Beispiel #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) {
					scene._backgroundSurface.transBlitFrom(*frame, pt, frame->getTransparencyIndex());
				} else if (scene._depthStyle == 0) {
					scene._backgroundSurface.copyFrom(*frame, pt, spriteSlot._depth, &scene._depthSurface,
						-1, false, frame->getTransparencyIndex());
				} else {
					scene._backgroundSurface.transBlitFrom(*frame, 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);
		}
	}
}
Beispiel #2
0
void EventsManager::changeCursor() {
    if (_cursorSprites) {
        MSprite *cursor = _cursorSprites->getFrame(_cursorId - 1);
        assert(cursor->w == cursor->h);
        byte transIndex = cursor->getTransparencyIndex();

        // Check for hotspot indication pixels along the right-hand and bottom
        // row. Put together, these give the cursor's hotspot x,y
        int hotspotX = 0, hotspotY = 0;
        byte *cursorData = cursor->getData();
        for (int idx = 0; idx < cursor->w; ++idx) {
            if (cursorData[(cursor->h - 1) * cursor->w + idx] != transIndex)
                hotspotX = idx;

            if (cursorData[(idx + 1) * cursor->w - 1] != transIndex)
                hotspotY = idx;
        }

        // Reduce the cursor data to remove the last column from each row, since
        // the cursor routines don't have a pitch option
        byte *destCursor = new byte[(cursor->w - 1) * (cursor->h - 1)];
        byte *srcP = cursorData;
        byte *destP = destCursor;

        for (int idx = 0; idx < (cursor->h - 1); ++idx) {
            Common::copy(srcP, srcP + cursor->w - 1, destP);
            srcP += cursor->w;
            destP += cursor->w - 1;
        }

        // Set the raw cursor data to use
        CursorMan.replaceCursor(destCursor, cursor->w - 1, cursor->h - 1,
                                hotspotX, hotspotY, transIndex);
        showCursor();
        delete[] destCursor;
    }
}
Beispiel #3
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;
		}
	}
}
Beispiel #4
0
void SpriteSlots::drawSprites(MSurface *s) {
	DepthList depthList;
	Scene &scene = _vm->_game->_scene;

	// Get a list of sprite object depths for active objects
	for (uint i = 0; i < size(); ++i) {
		SpriteSlot &spriteSlot = (*this)[i];
		if (spriteSlot._flags >= IMG_STATIC) {
			DepthEntry rec(16 - spriteSlot._depth, i);
			depthList.push_back(rec);
		}
	}

	// Sort the list in order of the depth
	Common::sort(depthList.begin(), depthList.end(), sortHelper);

	// Loop through each of the objects
	DepthList::iterator i;
	for (i = depthList.begin(); i != depthList.end(); ++i) {
		DepthEntry &de = *i;
		SpriteSlot &slot = (*this)[de.index];
		assert(slot._spritesIndex < (int)scene._sprites.size());
		SpriteAsset &spriteSet = *scene._sprites[slot._spritesIndex];

		// Get the sprite frame
		int frameNumber = ABS(slot._frameNumber);
		bool flipped = slot._frameNumber < 0;

		assert(frameNumber > 0);
		MSprite *sprite = spriteSet.getFrame(frameNumber - 1);

		if ((slot._scale < 100) && (slot._scale != -1)) {
			// Scaled drawing
			s->copyFrom(*sprite, slot._position, slot._depth, &scene._depthSurface,
				slot._scale, flipped, sprite->getTransparencyIndex());
		} else {
			int xp, yp;

			if (slot._scale == -1) {
				xp = slot._position.x - scene._posAdjust.x;
				yp = slot._position.y - scene._posAdjust.y;
			} else {
				xp = slot._position.x - (sprite->w / 2) - scene._posAdjust.x;
				yp = slot._position.y - sprite->h - scene._posAdjust.y + 1;
			}

			if (slot._depth > 1) {
				// Draw the frame with depth processing
				s->copyFrom(*sprite, Common::Point(xp, yp), slot._depth, &scene._depthSurface,
					-1, flipped, sprite->getTransparencyIndex());
			} else {
				MSurface *spr = sprite;
				if (flipped) {
					// Create a flipped copy of the sprite temporarily
					spr = sprite->flipHorizontal();
				}

				// No depth, so simply draw the image
				s->transBlitFrom(*spr, Common::Point(xp, yp), sprite->getTransparencyIndex());

				// Free sprite if it was a flipped one
				if (flipped) {
					spr->free();
					delete spr;
				}
			}
		}
	}
}