Ejemplo n.º 1
0
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);
        }
    }
}
Ejemplo n.º 2
0
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;
		}
	}
}