void SpriteSlots::drawBackground() { Scene &scene = _vm->_game->_scene; // Initial draw loop for any active sprites in the background for (uint i = 0; i < size(); ++i) { SpriteSlot &spriteSlot = (*this)[i]; DirtyArea &dirtyArea = scene._dirtyAreas[i]; if (spriteSlot._flags >= IMG_STATIC) { // Foreground sprite, so we can ignore it dirtyArea._active = false; } else { dirtyArea._active = true; dirtyArea.setSpriteSlot(&spriteSlot); if (spriteSlot._flags == IMG_DELTA) { // Background object, so need to draw it assert(spriteSlot._frameNumber > 0); SpriteAsset *asset = scene._sprites[spriteSlot._spritesIndex]; MSprite *frame = asset->getFrame(spriteSlot._frameNumber - 1); Common::Point pt = spriteSlot._position; if (spriteSlot._scale != -1) { // Adjust the drawing position pt.x -= frame->w / 2; pt.y -= frame->h - 1; } if (spriteSlot._depth <= 1) { frame->copyTo(&scene._backgroundSurface, pt, frame->getTransparencyIndex()); } else if (scene._depthStyle == 0) { scene._backgroundSurface.copyFrom(frame, pt, spriteSlot._depth, &scene._depthSurface, -1, false, frame->getTransparencyIndex()); } else { frame->copyTo(&scene._backgroundSurface, pt, frame->getTransparencyIndex()); } } } } // Mark any remaning sprite slot dirty areas as inactive for (uint i = size(); i < SPRITE_SLOTS_MAX_SIZE; ++i) scene._dirtyAreas[i]._active = false; // Flag any active text display for (uint i = 0; i < scene._textDisplay.size(); ++i) { TextDisplay &textDisplay = scene._textDisplay[i]; DirtyArea &dirtyArea = scene._dirtyAreas[i + SPRITE_SLOTS_MAX_SIZE]; if (textDisplay._expire >= 0 || !textDisplay._active) { dirtyArea._active = false; } else { dirtyArea._active = true; dirtyArea.setTextDisplay(&textDisplay); } } }
void UISlots::draw(bool updateFlag, bool delFlag) { Scene &scene = _vm->_game->_scene; UserInterface &userInterface = scene._userInterface; DirtyArea *dirtyAreaPtr = nullptr; // Loop through setting up the dirty areas for (uint idx = 0; idx < size(); ++idx) { DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; UISlot &slot = (*this)[idx]; if (slot._flags >= IMG_STATIC) { dirtyArea._active = false; } else { dirtyArea.setUISlot(&slot); dirtyArea._textActive = true; if (slot._segmentId == IMG_SPINNING_OBJECT && slot._flags == IMG_FULL_UPDATE) { dirtyArea._active = false; dirtyAreaPtr = &dirtyArea; } } } userInterface._dirtyAreas.merge(1, userInterface._uiSlots.size()); if (dirtyAreaPtr) dirtyAreaPtr->_active = true; // Copy parts of the user interface background that need to be erased for (uint idx = 0; idx < size(); ++idx) { DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; UISlot &slot = (*this)[idx]; if (dirtyArea._active && dirtyArea._bounds.width() > 0 && dirtyArea._bounds.height() > 0 && slot._flags > -20) { if (slot._flags >= IMG_ERASE) { // Merge area userInterface.mergeFrom(&userInterface._surface, dirtyArea._bounds, Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top)); } else { // Copy area userInterface._surface.copyTo(&userInterface, dirtyArea._bounds, Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top)); } } } for (uint idx = 0; idx < size(); ++idx) { DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; UISlot &slot = (*this)[idx]; int slotType = slot._flags; if (slotType >= IMG_STATIC) { dirtyArea.setUISlot(&slot); if (!updateFlag) slotType &= ~0x40; dirtyArea._textActive = slotType > 0; slot._flags &= 0x40; } } userInterface._dirtyAreas.merge(1, userInterface._uiSlots.size()); for (uint idx = 0; idx < size(); ++idx) { DirtyArea *dirtyArea = &userInterface._dirtyAreas[idx]; UISlot &slot = (*this)[idx]; if (slot._flags >= IMG_STATIC && !(slot._flags & 0x40)) { if (!dirtyArea->_active) { do { dirtyArea = dirtyArea->_mergedArea; } while (!dirtyArea->_active); } if (dirtyArea->_textActive) { SpriteAsset *asset = scene._sprites[slot._spritesIndex]; // Get the frame details int frameNumber = ABS(slot._frameNumber); bool flipped = slot._frameNumber < 0; if (slot._segmentId == IMG_SPINNING_OBJECT) { MSprite *sprite = asset->getFrame(frameNumber - 1); sprite->copyTo(&userInterface, slot._position, sprite->getTransparencyIndex()); } else { MSprite *sprite = asset->getFrame(frameNumber - 1); if (flipped) { MSurface *spr = sprite->flipHorizontal(); userInterface.mergeFrom(spr, spr->getBounds(), slot._position, sprite->getTransparencyIndex()); delete spr; } else { userInterface.mergeFrom(sprite, sprite->getBounds(), slot._position, sprite->getTransparencyIndex()); } } } } } // Mark areas of the screen surface for updating if (updateFlag) { for (uint idx = 0; idx < size(); ++idx) { DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; if (dirtyArea._active && dirtyArea._textActive && dirtyArea._bounds.width() > 0 && dirtyArea._bounds.height() > 0) { // Flag area of screen as needing update Common::Rect r = dirtyArea._bounds; r.translate(0, scene._interfaceY); _vm->_screen.copyRectToScreen(r); } } } // Post-processing to remove slots no longer needed for (int idx = (int)size() - 1; idx >= 0; --idx) { UISlot &slot = (*this)[idx]; if (slot._flags < IMG_STATIC) { if (delFlag || updateFlag) remove_at(idx); else if (slot._flags > -20) slot._flags -= 20; } else { if (updateFlag) slot._flags &= ~0x40; else slot._flags |= 0x40; } } }