InventoryDialog::InventoryDialog() { // Determine the maximum size of the image of any item in the player's inventory int imgWidth = 0, imgHeight = 0; SynchronizedList<InvObject *>::iterator i; for (i = RING_INVENTORY._itemList.begin(); i != RING_INVENTORY._itemList.end(); ++i) { InvObject *invObject = *i; if (invObject->inInventory()) { // Get the image for the item GfxSurface itemSurface = surfaceFromRes(invObject->_displayResNum, invObject->_rlbNum, invObject->_cursorNum); // Maintain the dimensions of the largest item image imgWidth = MAX(imgWidth, (int)itemSurface.getBounds().width()); imgHeight = MAX(imgHeight, (int)itemSurface.getBounds().height()); // Add the item to the display list GfxInvImage *img = new GfxInvImage(); _images.push_back(img); img->setDetails(invObject->_displayResNum, invObject->_rlbNum, invObject->_cursorNum); img->_invObject = invObject; add(img); } } assert(_images.size() > 0); // Figure out the number of columns/rows to show all the items int cellsSize = 3; while ((cellsSize * cellsSize) < (int)_images.size()) ++cellsSize; // Set the position of each inventory item to be displayed int cellX = 0; Common::Point pt(0, 0); for (uint idx = 0; idx < _images.size(); ++idx) { if (cellX == cellsSize) { // Move to the start of the next line pt.x = 0; pt.y += imgHeight + 2; cellX = 0; } _images[idx]->_bounds.moveTo(pt.x, pt.y); pt.x += imgWidth + 2; ++cellX; } // Set up the buttons pt.y += imgHeight + 2; _btnOk.setText(OK_BTN_STRING); _btnOk._bounds.moveTo((imgWidth + 2) * cellsSize - _btnOk._bounds.width(), pt.y); _btnLook.setText(LOOK_BTN_STRING); _btnLook._bounds.moveTo(_btnOk._bounds.left - _btnLook._bounds.width() - 2, _btnOk._bounds.top); addElements(&_btnLook, &_btnOk, NULL); frame(); setCenter(SCREEN_CENTER_X, SCREEN_CENTER_Y); }
void EventsClass::setCursor(GfxSurface &cursor) { Graphics::Surface s = cursor.lockSurface(); const byte *cursorData = (const byte *)s.getPixels(); CursorMan.replaceCursor(cursorData, cursor.getBounds().width(), cursor.getBounds().height(), cursor._centroid.x, cursor._centroid.y, cursor._transColor); _lastCursor = CURSOR_NONE; }
void UIElements::add(UIElement *obj) { // Add object assert(_objList.size() < 12); _objList.push_back(obj); obj->setPosition(Common::Point(_bounds.left + obj->_position.x, _bounds.top + obj->_position.y)); obj->reposition(); GfxSurface s = obj->getFrame(); s.draw(obj->_position); }
/** * Translates a raw image resource into a graphics surface. The caller is then responsible * for managing and destroying the surface when done with it * * @imgData Raw image resource * @size Size of the resource */ GfxSurface surfaceFromRes(const byte *imgData) { Rect r(0, 0, READ_LE_UINT16(imgData), READ_LE_UINT16(imgData + 2)); GfxSurface s; s.create(r.width(), r.height()); s._centroid.x = READ_LE_UINT16(imgData + 4); s._centroid.y = READ_LE_UINT16(imgData + 6); s._transColor = *(imgData + 8); bool rleEncoded = (imgData[9] & 2) != 0; const byte *srcP = imgData + 10; Graphics::Surface destSurface = s.lockSurface(); byte *destP = (byte *)destSurface.getBasePtr(0, 0); if (!rleEncoded) { Common::copy(srcP, srcP + (r.width() * r.height()), destP); } else { Common::set_to(destP, destP + (r.width() * r.height()), s._transColor); for (int yp = 0; yp < r.height(); ++yp) { int width = r.width(); destP = (byte *)destSurface.getBasePtr(0, yp); while (width > 0) { uint8 controlVal = *srcP++; if ((controlVal & 0x80) == 0) { // Copy specified number of bytes Common::copy(srcP, srcP + controlVal, destP); width -= controlVal; srcP += controlVal; destP += controlVal; } else if ((controlVal & 0x40) == 0) { // Skip a specified number of output pixels destP += controlVal & 0x3f; width -= controlVal & 0x3f; } else { // Copy a specified pixel a given number of times controlVal &= 0x3f; int pixel = *srcP++; Common::set_to(destP, destP + controlVal, pixel); destP += controlVal; width -= controlVal; } } assert(width == 0); } } s.unlockSurface(); return s; }
void EventsClass::pushCursor(CursorType cursorType) { const byte *cursor; bool delFlag = true; uint size; switch (cursorType) { case CURSOR_NONE: // No cursor cursor = _resourceManager->getSubResource(4, 1, 6, &size); break; case CURSOR_LOOK: // Look cursor cursor = _resourceManager->getSubResource(4, 1, 5, &size); break; case CURSOR_USE: // Use cursor cursor = _resourceManager->getSubResource(4, 1, 4, &size); break; case CURSOR_TALK: // Talk cursor cursor = _resourceManager->getSubResource(4, 1, 3, &size); break; case CURSOR_ARROW: // Arrow cursor cursor = CURSOR_ARROW_DATA; delFlag = false; break; case CURSOR_WALK: default: // Walk cursor cursor = CURSOR_WALK_DATA; delFlag = false; break; } // Decode the cursor GfxSurface s = surfaceFromRes(cursor); Graphics::Surface surface = s.lockSurface(); const byte *cursorData = (const byte *)surface.getBasePtr(0, 0); CursorMan.pushCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor); s.unlockSurface(); if (delFlag) DEALLOCATE(cursor); }
/** * Resizes and positions a given rect based on raw image data and a passed scaling percentage * * @frame Raw image frame * @xp New x position * @yp New y position * @percent Scaling percentage */ void Rect::resize(const GfxSurface &surface, int xp, int yp, int percent) { int xe = surface.getBounds().width() * percent / 100; int ye = surface.getBounds().height() * percent / 100; this->set(0, 0, xe, ye); if (!right) ++right; if (!bottom) ++bottom; this->moveTo(xp, yp); int xd = surface._centroid.x * percent / 100; int yd = surface._centroid.y * percent / 100; this->translate(-xd, -yd); }
void Scene3700::Viewer::draw() { Region *priorityRegion = _globals->_sceneManager._scene->_priorities.find(1); for (int idx = 0; idx < 4; ++idx) { Visage &v = (idx == 0) ? _images1 : _images2; GfxSurface img = v.getFrame(_frameList[idx]); Rect destRect = img.getBounds(); destRect.resize(img, (_position.x - _globals->_sceneOffset.x), (_position.y - _globals->_sceneOffset.y - _yDiff), _percentList[idx]); destRect.translate(-_globals->_sceneManager._scene->_sceneBounds.left, -_globals->_sceneManager._scene->_sceneBounds.top); _globals->gfxManager().copyFrom(img, destRect, priorityRegion); } }
/** * Scales a passed surface, creating a new surface with the result * @param srcImage Source image to scale * @param NewWidth New width for scaled image * @param NewHeight New height for scaled image * @remarks Caller is responsible for freeing the returned surface */ static GfxSurface ResizeSurface(GfxSurface &src, int xSize, int ySize, int transIndex) { GfxSurface s; s.create(xSize, ySize); Graphics::Surface srcImage = src.lockSurface(); Graphics::Surface destImage = s.lockSurface(); int *horizUsage = scaleLine(xSize, srcImage.w); int *vertUsage = scaleLine(ySize, srcImage.h); // Loop to create scaled version for (int yp = 0; yp < ySize; ++yp) { byte *destP = (byte *)destImage.getBasePtr(0, yp); if (vertUsage[yp] == -1) { Common::set_to(destP, destP + xSize, transIndex); } else { const byte *srcP = (const byte *)srcImage.getBasePtr(0, vertUsage[yp]); for (int xp = 0; xp < xSize; ++xp) { if (horizUsage[xp] != -1) { const byte *tempSrcP = srcP + horizUsage[xp]; *destP++ = *tempSrcP++; } else { // Pixel overrun at the end of the line *destP++ = transIndex; } } } } // Unlock surfaces src.unlockSurface(); s.unlockSurface(); // Delete arrays and return surface delete[] horizUsage; delete[] vertUsage; return s; }
/** * Copys an area from one GfxSurface to another */ void GfxSurface::copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds, Region *priorityRegion) { GfxSurface srcImage; if (srcBounds.isEmpty()) return; if (srcBounds == src.getBounds()) srcImage = src; else { // Set the source image to be the subset specified by the source bounds Graphics::Surface srcSurface = src.lockSurface(); srcImage.create(srcBounds.width(), srcBounds.height()); Graphics::Surface destSurface = srcImage.lockSurface(); const byte *srcP = (const byte *)srcSurface.getBasePtr(srcBounds.left, srcBounds.top); byte *destP = (byte *)destSurface.pixels; for (int yp = srcBounds.top; yp < srcBounds.bottom; ++yp, srcP += srcSurface.pitch, destP += destSurface.pitch) { Common::copy(srcP, srcP + srcBounds.width(), destP); } srcImage.unlockSurface(); src.unlockSurface(); } if ((destBounds.width() != srcBounds.width()) || (destBounds.height() != srcBounds.height())) srcImage = ResizeSurface(srcImage, destBounds.width(), destBounds.height(), src._transColor); Graphics::Surface srcSurface = srcImage.lockSurface(); Graphics::Surface destSurface = lockSurface(); // Adjust bounds to ensure destination will be on-screen int srcX = 0, srcY = 0; if (destBounds.left < 0) { srcX = -destBounds.left; destBounds.left = 0; } if (destBounds.top < 0) { srcY = -destBounds.top; destBounds.top = 0; } if (destBounds.right > destSurface.w) destBounds.right = destSurface.w; if (destBounds.bottom > destSurface.h) destBounds.bottom = destSurface.h; if (destBounds.isValidRect()) { const byte *pSrc = (const byte *)srcSurface.getBasePtr(srcX, srcY); byte *pDest = (byte *)destSurface.getBasePtr(destBounds.left, destBounds.top); for (int y = 0; y < destBounds.height(); ++y, pSrc += srcSurface.pitch, pDest += destSurface.pitch) { if (!priorityRegion && (src._transColor == -1)) Common::copy(pSrc, pSrc + destBounds.width(), pDest); else { const byte *tempSrc = pSrc; byte *tempDest = pDest; int xp = destBounds.left; while (tempSrc < (pSrc + destBounds.width())) { if (!priorityRegion || !priorityRegion->contains(Common::Point( xp + _globals->_sceneManager._scene->_sceneBounds.left, destBounds.top + y + _globals->_sceneManager._scene->_sceneBounds.top))) { if (*tempSrc != src._transColor) *tempDest = *tempSrc; } ++tempSrc; ++tempDest; ++xp; } } } } unlockSurface(); srcImage.unlockSurface(); }
/** * Sets the specified cursor * * @cursorType Specified cursor number */ void EventsClass::setCursor(CursorType cursorType) { if (cursorType == _lastCursor) return; _lastCursor = cursorType; _globals->clearFlag(122); CursorMan.showMouse(true); const byte *cursor; bool delFlag = true; uint size; switch (cursorType) { case CURSOR_NONE: // No cursor _globals->setFlag(122); if (_vm->getFeatures() & GF_DEMO) { CursorMan.showMouse(false); return; } cursor = _resourceManager->getSubResource(4, 1, 6, &size); break; case CURSOR_LOOK: // Look cursor cursor = _resourceManager->getSubResource(4, 1, 5, &size); _currentCursor = CURSOR_LOOK; break; case CURSOR_USE: // Use cursor cursor = _resourceManager->getSubResource(4, 1, 4, &size); _currentCursor = CURSOR_USE; break; case CURSOR_TALK: // Talk cursor cursor = _resourceManager->getSubResource(4, 1, 3, &size); _currentCursor = CURSOR_TALK; break; case CURSOR_ARROW: // Arrow cursor cursor = CURSOR_ARROW_DATA; delFlag = false; break; case CURSOR_WALK: default: // Walk cursor cursor = CURSOR_WALK_DATA; _currentCursor = CURSOR_WALK; delFlag = false; break; } // Decode the cursor GfxSurface s = surfaceFromRes(cursor); Graphics::Surface surface = s.lockSurface(); const byte *cursorData = (const byte *)surface.getBasePtr(0, 0); CursorMan.replaceCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor); s.unlockSurface(); if (delFlag) DEALLOCATE(cursor); }
/** * Sets the specified cursor * * @cursorType Specified cursor number */ void EventsClass::setCursor(CursorType cursorType) { if (cursorType == _lastCursor) return; _lastCursor = cursorType; g_globals->clearFlag(122); CursorMan.showMouse(true); const byte *cursor; bool delFlag = true; uint size; bool questionEnabled = false; switch (cursorType) { case CURSOR_NONE: // No cursor g_globals->setFlag(122); if ((g_vm->getGameID() != GType_Ringworld) || ((g_vm->getGameID() == GType_Ringworld) && (g_vm->getFeatures() & GF_DEMO))) { CursorMan.showMouse(false); return; } cursor = g_resourceManager->getSubResource(4, 1, 6, &size); break; case CURSOR_LOOK: // Look cursor if (g_vm->getGameID() == GType_BlueForce) { cursor = g_resourceManager->getSubResource(1, 5, 3, &size); } else if (g_vm->getGameID() == GType_Ringworld2) { cursor = g_resourceManager->getSubResource(5, 1, 5, &size); } else { cursor = g_resourceManager->getSubResource(4, 1, 5, &size); } _currentCursor = CURSOR_LOOK; break; case CURSOR_USE: // Use cursor if (g_vm->getGameID() == GType_BlueForce) { cursor = g_resourceManager->getSubResource(1, 5, 2, &size); } else if (g_vm->getGameID() == GType_Ringworld2) { cursor = g_resourceManager->getSubResource(5, 1, 4, &size); } else { cursor = g_resourceManager->getSubResource(4, 1, 4, &size); } _currentCursor = CURSOR_USE; break; case CURSOR_TALK: // Talk cursor if (g_vm->getGameID() == GType_BlueForce) { cursor = g_resourceManager->getSubResource(1, 5, 4, &size); } else if (g_vm->getGameID() == GType_Ringworld2) { cursor = g_resourceManager->getSubResource(5, 1, 6, &size); } else { cursor = g_resourceManager->getSubResource(4, 1, 3, &size); } _currentCursor = CURSOR_TALK; break; case CURSOR_EXIT: // Exit cursor (Blue Force) assert(g_vm->getGameID() == GType_BlueForce); cursor = g_resourceManager->getSubResource(1, 5, 7, &size); _currentCursor = CURSOR_EXIT; break; case CURSOR_PRINTER: // Printer cursor (Blue Force) assert(g_vm->getGameID() == GType_BlueForce); cursor = g_resourceManager->getSubResource(1, 7, 6, &size); _currentCursor = CURSOR_PRINTER; break; case CURSOR_ARROW: // Arrow cursor cursor = CURSOR_ARROW_DATA; delFlag = false; break; case CURSOR_WALK: default: switch (g_vm->getGameID()) { case GType_BlueForce: if (cursorType == CURSOR_WALK) { cursor = g_resourceManager->getSubResource(1, 5, 1, &size); } else { // Inventory icon cursor = g_resourceManager->getSubResource(10, ((int)cursorType - 1) / 20 + 1, ((int)cursorType - 1) % 20 + 1, &size); questionEnabled = true; } _currentCursor = cursorType; break; case GType_Ringworld2: if (cursorType == CURSOR_WALK) { cursor = CURSOR_WALK_DATA; delFlag = false; } else { // Inventory icon InvObject *invObject = g_globals->_inventory->getItem((int)cursorType); cursor = g_resourceManager->getSubResource(6, invObject->_strip, invObject->_frame, &size); questionEnabled = true; } _currentCursor = cursorType; break; default: // For Ringworld, always treat as the walk cursor cursor = CURSOR_WALK_DATA; _currentCursor = CURSOR_WALK; delFlag = false; break; } break; // Ringworld 2 specific cursors case EXITCURSOR_N: case EXITCURSOR_S: case EXITCURSOR_W: case EXITCURSOR_E: case EXITCURSOR_LEFT_HAND: case CURSOR_INVALID: case EXITCURSOR_NE: case EXITCURSOR_SE: case EXITCURSOR_SW: case EXITCURSOR_NW: case SHADECURSOR_UP: case SHADECURSOR_DOWN: case SHADECURSOR_HAND: _currentCursor = cursorType; cursor = g_resourceManager->getSubResource(5, 1, cursorType - R2CURSORS_START, &size); break; case R2_CURSOR_ROPE: _currentCursor = cursorType; cursor = g_resourceManager->getSubResource(5, 4, 1, &size); break; } // Decode the cursor GfxSurface s = surfaceFromRes(cursor); Graphics::Surface surface = s.lockSurface(); const byte *cursorData = (const byte *)surface.getPixels(); CursorMan.replaceCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor); s.unlockSurface(); if (delFlag) DEALLOCATE(cursor); // For Blue Force and Return to Ringworld, enable the question button when an inventory icon is selected if (g_vm->getGameID() != GType_Ringworld) T2_GLOBALS._uiElements._question.setEnabled(questionEnabled); }
void ModalDialog::drawFrame() { Rect origRect = _bounds; _bounds.collapse(-10, -10); if (g_vm->getGameID() == GType_Ringworld2) { GfxElement::drawFrame(); } else { // Fill the dialog area g_globals->gfxManager().fillRect(origRect, 54); // Draw top line GfxSurface surface = surfaceFromRes(8, 1, 7); for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10) surface.draw(Common::Point(xp, _bounds.top)); surface.draw(Common::Point(_bounds.right - 20, _bounds.top)); surface = surfaceFromRes(8, 1, 1); surface.draw(Common::Point(_bounds.left, _bounds.top)); surface = surfaceFromRes(8, 1, 4); surface.draw(Common::Point(_bounds.right - 10, _bounds.top)); // Draw vertical edges surface = surfaceFromRes(8, 1, 2); for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10) surface.draw(Common::Point(_bounds.left, yp)); surface.draw(Common::Point(_bounds.left, _bounds.bottom - 20)); surface = surfaceFromRes(8, 1, 5); for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10) surface.draw(Common::Point(_bounds.right - 10, yp)); surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 20)); // Draw bottom line surface = surfaceFromRes(8, 1, 8); for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10) surface.draw(Common::Point(xp, _bounds.bottom - 10)); surface.draw(Common::Point(_bounds.right - 20, _bounds.bottom - 10)); surface = surfaceFromRes(8, 1, 3); surface.draw(Common::Point(_bounds.left, _bounds.bottom - 10)); surface = surfaceFromRes(8, 1, 6); surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 10)); } // Set the dialog's manager bounds _gfxManager._bounds = origRect; }