Initial commit
This commit is contained in:
756
engines/saga2/floating.cpp
Normal file
756
engines/saga2/floating.cpp
Normal file
@@ -0,0 +1,756 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* aint32 with this program; if not, write to the Free Software
|
||||
*
|
||||
*
|
||||
* Based on the original sources
|
||||
* Faery Tale II -- The Halls of the Dead
|
||||
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
|
||||
*/
|
||||
|
||||
#include "saga2/saga2.h"
|
||||
#include "saga2/detection.h"
|
||||
#include "saga2/floating.h"
|
||||
#include "saga2/objects.h"
|
||||
#include "saga2/imagcach.h"
|
||||
#include "saga2/grabinfo.h"
|
||||
#include "saga2/display.h"
|
||||
|
||||
namespace Saga2 {
|
||||
|
||||
/* classes:
|
||||
containerWindow
|
||||
mindWindow
|
||||
smallContainerWindow
|
||||
enchanetmentWindow
|
||||
|
||||
floatingWindow
|
||||
*/
|
||||
|
||||
/* ===================================================================== *
|
||||
Prototypes
|
||||
* ===================================================================== */
|
||||
|
||||
void updateWindowSection(const Rect16 &r);
|
||||
|
||||
/* ===================================================================== *
|
||||
Imports
|
||||
* ===================================================================== */
|
||||
|
||||
// These externs are imported because the window update routines
|
||||
// need to know about the scrolling tile area.
|
||||
|
||||
extern StaticPoint16 fineScroll;
|
||||
extern gFont *mainFont;
|
||||
extern bool allPlayerActorsDead;
|
||||
|
||||
|
||||
/* ===================================================================== *
|
||||
DecoratedWindow member functions
|
||||
* ===================================================================== */
|
||||
|
||||
// Constructor for a background window
|
||||
DecoratedWindow::DecoratedWindow(const Rect16 &r, uint16 ident, const char saveas[], AppFunc *cmd)
|
||||
: gWindow(r, ident, saveas, cmd) {
|
||||
_decorations = nullptr;
|
||||
_numDecorations = 0;
|
||||
}
|
||||
|
||||
// destructor for decorated windows
|
||||
DecoratedWindow::~DecoratedWindow() {
|
||||
removeDecorations();
|
||||
}
|
||||
|
||||
// Redraw the window, but only a small clipped section,
|
||||
// and perhaps drawn onto an off-screen map.
|
||||
|
||||
void DecoratedWindow::drawClipped(
|
||||
gPort &port,
|
||||
const Point16 &offset,
|
||||
const Rect16 &clipRect) {
|
||||
WindowDecoration *dec;
|
||||
int16 i;
|
||||
|
||||
if (displayEnabled())
|
||||
if (_extent.overlap(clipRect)) {
|
||||
// For each "decorative panel" within the frame of the window
|
||||
|
||||
for (dec = _decorations, i = 0; i < _numDecorations; i++, dec++) {
|
||||
// If the decorative panel overlaps the area we are
|
||||
// rendering
|
||||
|
||||
if (dec->extent.overlap(clipRect)) {
|
||||
Point16 pos(dec->extent.x - offset.x,
|
||||
dec->extent.y - offset.y);
|
||||
|
||||
drawCompressedImage(port, pos, dec->image);
|
||||
}
|
||||
}
|
||||
|
||||
gWindow::drawClipped(port, offset, clipRect);
|
||||
}
|
||||
|
||||
// REM: We should also draw the scrolling tiles at this time???
|
||||
}
|
||||
|
||||
// Set up the _decorations for the window, and load them into the
|
||||
// memory pool
|
||||
|
||||
void DecoratedWindow::setDecorations(
|
||||
WindowDecoration *dec,
|
||||
int16 count,
|
||||
hResContext *con) {
|
||||
int16 i;
|
||||
|
||||
_numDecorations = count;
|
||||
|
||||
if (_decorations)
|
||||
delete[] _decorations;
|
||||
|
||||
_decorations = new WindowDecoration[_numDecorations];
|
||||
|
||||
// For each "decorative panel" within the frame of the window
|
||||
|
||||
for (i = 0; i < _numDecorations; i++, dec++) {
|
||||
// request an image pointer from the image Cache
|
||||
dec->image = g_vm->_imageCache->requestImage(con,
|
||||
MKTAG('B', 'R', 'D', dec->imageNumber));
|
||||
_decorations[i].extent = dec->extent;
|
||||
_decorations[i].image = dec->image;
|
||||
_decorations[i].imageNumber = dec->imageNumber;
|
||||
}
|
||||
}
|
||||
|
||||
void DecoratedWindow::setDecorations(
|
||||
WindowDecoration *dec,
|
||||
int16 count,
|
||||
hResContext *con,
|
||||
hResID id_) {
|
||||
int16 i;
|
||||
|
||||
_numDecorations = count;
|
||||
|
||||
if (_decorations)
|
||||
delete[] _decorations;
|
||||
|
||||
_decorations = new WindowDecoration[_numDecorations];
|
||||
|
||||
// For each "decorative panel" within the frame of the window
|
||||
|
||||
for (i = 0; i < _numDecorations; i++, dec++) {
|
||||
// request an image pointer from the image Cache
|
||||
dec->image = g_vm->_imageCache->requestImage(con, id_ | MKTAG(0, 0, 0, dec->imageNumber));
|
||||
_decorations[i].extent = dec->extent;
|
||||
_decorations[i].image = dec->image;
|
||||
_decorations[i].imageNumber = dec->imageNumber;
|
||||
}
|
||||
}
|
||||
|
||||
void DecoratedWindow::setDecorations(
|
||||
WindowDecoration *dec,
|
||||
int16 count,
|
||||
hResContext *con,
|
||||
char a, char b, char c) {
|
||||
setDecorations(dec, count, con, MKTAG(a, b, c, 0));
|
||||
}
|
||||
|
||||
void DecoratedWindow::setDecorations(
|
||||
const StaticWindow *dec,
|
||||
int16 count,
|
||||
hResContext *con) {
|
||||
int16 i;
|
||||
|
||||
_numDecorations = count;
|
||||
|
||||
if (_decorations)
|
||||
delete[] _decorations;
|
||||
|
||||
_decorations = new WindowDecoration[_numDecorations];
|
||||
|
||||
if (g_vm->getGameId() == GID_DINO) {
|
||||
warning("TODO: setDecorations() for Dino");
|
||||
return;
|
||||
}
|
||||
|
||||
// For each "decorative panel" within the frame of the window
|
||||
|
||||
for (i = 0; i < _numDecorations; i++, dec++) {
|
||||
// request an image pointer from the image Cache
|
||||
_decorations[i].extent = dec->extent;
|
||||
_decorations[i].image = g_vm->_imageCache->requestImage(con,
|
||||
MKTAG('B', 'R', 'D', dec->imageNumber));
|
||||
_decorations[i].imageNumber = dec->imageNumber;
|
||||
}
|
||||
}
|
||||
|
||||
void DecoratedWindow::setDecorations(
|
||||
const StaticWindow *dec,
|
||||
int16 count,
|
||||
hResContext *con,
|
||||
hResID id_) {
|
||||
int16 i;
|
||||
|
||||
_numDecorations = count;
|
||||
|
||||
if (_decorations)
|
||||
delete[] _decorations;
|
||||
|
||||
_decorations = new WindowDecoration[_numDecorations];
|
||||
|
||||
// For each "decorative panel" within the frame of the window
|
||||
|
||||
for (i = 0; i < _numDecorations; i++, dec++) {
|
||||
// request an image pointer from the image Cache
|
||||
_decorations[i].extent = dec->extent;
|
||||
_decorations[i].image = g_vm->_imageCache->requestImage(con, id_ | MKTAG(0, 0, 0, dec->imageNumber));
|
||||
_decorations[i].imageNumber = dec->imageNumber;
|
||||
}
|
||||
}
|
||||
|
||||
void DecoratedWindow::setDecorations(
|
||||
const StaticWindow *dec,
|
||||
int16 count,
|
||||
hResContext *con,
|
||||
char a, char b, char c) {
|
||||
setDecorations(dec, count, con, MKTAG(a, b, c, 0));
|
||||
}
|
||||
|
||||
// Free the _decorations from the memory pool
|
||||
|
||||
void DecoratedWindow::removeDecorations() {
|
||||
WindowDecoration *dec;
|
||||
int16 i;
|
||||
|
||||
// release requests made to the Image Cache
|
||||
for (dec = _decorations, i = 0; i < _numDecorations; i++, dec++) {
|
||||
g_vm->_imageCache->releaseImage(dec->image);
|
||||
}
|
||||
|
||||
if (_decorations) {
|
||||
delete[] _decorations;
|
||||
_decorations = nullptr;
|
||||
}
|
||||
|
||||
_numDecorations = 0;
|
||||
}
|
||||
|
||||
// Redraw all of the _decorations, on the main port only...
|
||||
|
||||
void DecoratedWindow::draw() { // redraw the window
|
||||
g_vm->_pointer->hide();
|
||||
if (displayEnabled())
|
||||
drawClipped(g_vm->_mainPort, Point16(0, 0), _extent);
|
||||
g_vm->_pointer->show();
|
||||
}
|
||||
|
||||
// Return true if window floats above animated are
|
||||
|
||||
bool DecoratedWindow::isBackdrop() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update a region of a window, and all floaters which
|
||||
// might be above that window.
|
||||
void DecoratedWindow::update(const Rect16 &updateRect) {
|
||||
Rect16 r = updateRect;
|
||||
|
||||
r.x += _extent.x;
|
||||
r.y += _extent.y;
|
||||
|
||||
updateWindowSection(r);
|
||||
}
|
||||
|
||||
void DecoratedWindow::update(const StaticRect &updateRect) {
|
||||
Rect16 r = updateRect;
|
||||
|
||||
r.x += _extent.x;
|
||||
r.y += _extent.y;
|
||||
|
||||
updateWindowSection(r);
|
||||
}
|
||||
|
||||
/* ===================================================================== *
|
||||
BackWindow member functions
|
||||
* ===================================================================== */
|
||||
|
||||
// Constructor for a background window
|
||||
|
||||
BackWindow::BackWindow(const Rect16 &r, uint16 ident, AppFunc *cmd)
|
||||
: DecoratedWindow(r, ident, "", cmd) {
|
||||
}
|
||||
|
||||
void BackWindow::invalidate(Rect16 *area) {
|
||||
if (displayEnabled())
|
||||
_window.update(*area);
|
||||
}
|
||||
|
||||
void BackWindow::invalidate(const StaticRect *area) {
|
||||
if (displayEnabled())
|
||||
_window.update(*area);
|
||||
}
|
||||
|
||||
// Return true if window floats above animated are
|
||||
|
||||
bool BackWindow::isBackdrop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// A backdrop window can never go to front.
|
||||
|
||||
void BackWindow::toFront() {}
|
||||
|
||||
/* ===================================================================== *
|
||||
DragBar class member functions
|
||||
* ===================================================================== */
|
||||
|
||||
StaticPoint16 DragBar::_dragOffset = {0, 0};
|
||||
StaticPoint16 DragBar::_dragPos = {0, 0};
|
||||
bool DragBar::_update;
|
||||
FloatingWindow *DragBar::_dragWindow;
|
||||
|
||||
DragBar::DragBar(gPanelList &list, const Rect16 &r)
|
||||
: gControl(list, r, nullptr, 0, nullptr) {
|
||||
}
|
||||
|
||||
bool DragBar::activate(gEventType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void DragBar::deactivate() {
|
||||
gPanel::deactivate();
|
||||
}
|
||||
|
||||
bool DragBar::pointerHit(gPanelMessage &msg) {
|
||||
Rect16 wExtent = _window.getExtent();
|
||||
|
||||
_dragPos.x = wExtent.x;
|
||||
_dragPos.y = wExtent.y;
|
||||
_dragOffset.set(msg._pickAbsPos.x, msg._pickAbsPos.y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Inform the main drawing loop that a floating window needs to
|
||||
// be dragged...
|
||||
|
||||
void DragBar::pointerDrag(gPanelMessage &msg) {
|
||||
Rect16 ext = _window.getExtent();
|
||||
Point16 pos;
|
||||
|
||||
// Calculate new window position
|
||||
|
||||
pos.x = msg._pickAbsPos.x + ext.x - _dragOffset.x;
|
||||
pos.y = msg._pickAbsPos.y + ext.y - _dragOffset.y;
|
||||
|
||||
// If window position has changed, then signal the drawing loop
|
||||
|
||||
if (pos != _dragPos) {
|
||||
_dragPos.set(pos.x, pos.y);
|
||||
_update = true;
|
||||
_dragWindow = (FloatingWindow *)&_window;
|
||||
}
|
||||
}
|
||||
|
||||
void DragBar::pointerRelease(gPanelMessage &) {
|
||||
deactivate();
|
||||
_update = false; // just in case
|
||||
_dragWindow = nullptr;
|
||||
}
|
||||
|
||||
|
||||
/* ===================================================================== *
|
||||
gButton class member functions
|
||||
* ===================================================================== */
|
||||
|
||||
void gButton::deactivate() {
|
||||
_selected = 0;
|
||||
draw();
|
||||
gPanel::deactivate();
|
||||
}
|
||||
|
||||
bool gButton::activate(gEventType why) {
|
||||
_selected = 1;
|
||||
draw();
|
||||
|
||||
if (why == kEventKeyDown) { // momentarily depress
|
||||
deactivate();
|
||||
notify(kEventNewValue, 1); // notify App of successful hit
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gButton::pointerHit(gPanelMessage &) {
|
||||
activate(kEventMouseDown);
|
||||
return true;
|
||||
}
|
||||
|
||||
void gButton::pointerRelease(gPanelMessage &) {
|
||||
// We have to test selected first because deactivate clears it.
|
||||
|
||||
if (_selected) {
|
||||
deactivate(); // give back input focus
|
||||
notify(kEventNewValue, 1); // notify App of successful hit
|
||||
} else deactivate();
|
||||
}
|
||||
|
||||
void gButton::pointerDrag(gPanelMessage &msg) {
|
||||
if (_selected != msg._inPanel) {
|
||||
_selected = msg._inPanel;
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
void gButton::draw() {
|
||||
gPort &port = _window._windowPort;
|
||||
Rect16 rect = _window.getExtent();
|
||||
|
||||
g_vm->_pointer->hide(port, _extent); // hide mouse pointer
|
||||
if (displayEnabled())
|
||||
drawClipped(port, Point16(0, 0), Rect16(0, 0, rect.width, rect.height));
|
||||
g_vm->_pointer->show(port, _extent); // show mouse pointer
|
||||
}
|
||||
|
||||
|
||||
/* ===================================================================== *
|
||||
gImageButton class member functions
|
||||
* ===================================================================== */
|
||||
|
||||
void gImageButton::drawClipped(gPort &port, const Point16 &offset, const Rect16 &r) {
|
||||
gPixelMap *currentImage = _selected ? _selImage : _deselImage;
|
||||
|
||||
if (displayEnabled())
|
||||
if (_extent.overlap(r))
|
||||
port.bltPixels(*currentImage,
|
||||
0,
|
||||
0,
|
||||
_extent.x - offset.x,
|
||||
_extent.y - offset.y,
|
||||
currentImage->_size.x,
|
||||
currentImage->_size.y);
|
||||
}
|
||||
|
||||
/* ===================================================================== *
|
||||
gToggleButton class member functions
|
||||
* ===================================================================== */
|
||||
|
||||
bool gToggleButton::activate(gEventType why) {
|
||||
if (why == kEventKeyDown || why == kEventMouseDown) {
|
||||
_selected = !_selected;
|
||||
draw();
|
||||
gPanel::deactivate();
|
||||
notify(kEventNewValue, _selected); // notify App of successful hit
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gToggleButton::pointerHit(gPanelMessage &) {
|
||||
return activate(kEventMouseDown);
|
||||
}
|
||||
|
||||
/* ===================================================================== *
|
||||
LabeledButton class member functions
|
||||
* ===================================================================== */
|
||||
|
||||
LabeledButton::LabeledButton(gPanelList &list,
|
||||
const Rect16 &box,
|
||||
gPixelMap &img1,
|
||||
gPixelMap &img2,
|
||||
char *buttonLabel,
|
||||
uint16 ident,
|
||||
AppFunc *cmd) :
|
||||
gImageButton(list,
|
||||
box,
|
||||
img1,
|
||||
img2,
|
||||
buttonLabel,
|
||||
ident,
|
||||
cmd) {
|
||||
const char *underscore;
|
||||
|
||||
if ((underscore = strchr(_title, '_')) != nullptr)
|
||||
_accelKey = toupper(underscore[1]);
|
||||
}
|
||||
|
||||
void LabeledButton::drawClipped(
|
||||
gPort &port,
|
||||
const Point16 &offset,
|
||||
const Rect16 &r) {
|
||||
if (!displayEnabled()) return;
|
||||
if (!_extent.overlap(r)) return;
|
||||
|
||||
Point16 origin,
|
||||
textOrigin;
|
||||
gFont *textFont = mainFont;
|
||||
|
||||
origin.x = _extent.x - offset.x;
|
||||
origin.y = _extent.y - offset.y;
|
||||
|
||||
SAVE_GPORT_STATE(port);
|
||||
|
||||
port.setColor(14);
|
||||
port.fillRect(origin.x, origin.y, _extent.width, _extent.height);
|
||||
|
||||
gImageButton::drawClipped(port, offset, r);
|
||||
|
||||
textOrigin.x = origin.x + ((_extent.width -
|
||||
TextWidth(textFont, _title, -1, kTextStyleUnderBar)) >> 1);
|
||||
textOrigin.y = origin.y + ((_extent.height - textFont->height) >> 1);
|
||||
|
||||
port.setColor(2);
|
||||
port.moveTo(textOrigin);
|
||||
port.setFont(textFont);
|
||||
port.setStyle(kTextStyleUnderBar);
|
||||
port.drawText(_title, -1);
|
||||
}
|
||||
|
||||
|
||||
/* ===================================================================== *
|
||||
Floating Window class member functions
|
||||
* ===================================================================== */
|
||||
|
||||
FloatingWindow::FloatingWindow(const Rect16 &r, uint16 ident, const char saveas[], AppFunc *cmd)
|
||||
: DecoratedWindow(r, ident, saveas, cmd) {
|
||||
_db = new DragBar(*this, Rect16(0, 0, r.width, r.height));
|
||||
|
||||
_origPos.x = r.x;
|
||||
_origPos.y = r.y;
|
||||
|
||||
#if 0
|
||||
decOffset.x = 0;
|
||||
decOffset.y = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Redraw the window, but only a small clipped section,
|
||||
// and perhaps drawn onto an off-screen map.
|
||||
void FloatingWindow::drawClipped(
|
||||
gPort &port,
|
||||
const Point16 &offset,
|
||||
const Rect16 &r) {
|
||||
Rect16 rect = _extent;
|
||||
WindowDecoration *dec;
|
||||
int16 i;
|
||||
|
||||
if (displayEnabled())
|
||||
if (_extent.overlap(r)) {
|
||||
// do'nt do the temp stuff if there are _decorations present
|
||||
if (_numDecorations == 0) {
|
||||
rect.x -= offset.x;
|
||||
rect.y -= offset.y;
|
||||
|
||||
port.setColor(2);
|
||||
port.frameRect(rect, 2);
|
||||
rect.expand(-2, -2);
|
||||
port.setColor(12);
|
||||
port.fillRect(rect);
|
||||
}
|
||||
|
||||
// For each "decorative panel" within the frame of the window
|
||||
for (dec = _decorations, i = 0; i < _numDecorations; i++, dec++) {
|
||||
Point16 pos(dec->extent.x /* - decOffset.x */ - offset.x + _extent.x,
|
||||
dec->extent.y /* - decOffset.y */ - offset.y + _extent.y);
|
||||
|
||||
drawCompressedImage(port, pos, dec->image);
|
||||
}
|
||||
|
||||
gWindow::drawClipped(port, offset, r);
|
||||
}
|
||||
}
|
||||
|
||||
void FloatingWindow::setExtent(const Rect16 &r) {
|
||||
// set an offset from the original position of the window
|
||||
// for the _decorations to use in drawing themselves
|
||||
#if 0
|
||||
decOffset.x = _origPos.x - r.x;
|
||||
decOffset.y = _origPos.y - r.y;
|
||||
#endif
|
||||
|
||||
// now reset the extent
|
||||
_extent.height = r.height;
|
||||
_extent.width = r.width;
|
||||
setPos(Point16(r.x, r.y));
|
||||
}
|
||||
|
||||
bool FloatingWindow::open() {
|
||||
_db->moveToBack(*this);
|
||||
|
||||
g_vm->_mouseInfo->replaceObject();
|
||||
g_vm->_mouseInfo->clearGauge();
|
||||
g_vm->_mouseInfo->setText(nullptr);
|
||||
g_vm->_mouseInfo->setIntent(GrabInfo::kIntWalkTo);
|
||||
|
||||
return gWindow::open();
|
||||
}
|
||||
|
||||
// Close this window and redraw the screen under it.
|
||||
void FloatingWindow::close() {
|
||||
gWindow::close();
|
||||
updateWindowSection(_extent);
|
||||
}
|
||||
|
||||
|
||||
// This routine is used by the floating window dragger. It's job
|
||||
// is to completely re-render all of the pixels in a rectangular
|
||||
// area, includuing any floating windows which might overlap that
|
||||
// area, and including the scrolling animated area which might
|
||||
// overlap that area.
|
||||
|
||||
bool checkTileAreaPort();
|
||||
|
||||
void updateWindowSection(const Rect16 &r) {
|
||||
gPixelMap tempMap;
|
||||
gPort tempPort;
|
||||
Point16 offset(r.x, r.y);
|
||||
Rect16 clip,
|
||||
animClip;
|
||||
Point16 animOffset(kTileRectX - fineScroll.x, kTileRectY);
|
||||
|
||||
// Detects that program is shutting down and aborts the blit
|
||||
if (g_vm->_tileDrawMap._data == nullptr)
|
||||
return;
|
||||
|
||||
if (!checkTileAreaPort()) return;
|
||||
|
||||
// Since the floating windows can be dragged partly offscreen
|
||||
// we should make sure we're rendering only to on-screen pixels.
|
||||
|
||||
clip = intersect(r, Rect16(0, 0, kScreenWidth, kScreenHeight));
|
||||
|
||||
// Allocate a temporary pixel map and gPort
|
||||
|
||||
tempMap._size.x = clip.width;
|
||||
tempMap._size.y = clip.height;
|
||||
tempMap._data = new uint8[tempMap.bytes()]();
|
||||
if (tempMap._data == nullptr)
|
||||
return;
|
||||
|
||||
tempPort.setMap(&tempMap);
|
||||
tempPort.setMode(kDrawModeReplace);
|
||||
|
||||
// Compute the intersection of the animated area with the clip
|
||||
// rectangle. If they overlap, then copy part of the animated
|
||||
// area into the temporary bitmap.
|
||||
|
||||
animClip = intersect(Rect16(kTileRectX, kTileRectY, kTileRectWidth, kTileRectHeight), clip);
|
||||
if (!animClip.empty() && !allPlayerActorsDead) {
|
||||
// Compute which pixel on the animated pixel map is the
|
||||
// upper left corner of the clip area
|
||||
|
||||
Point16 localOrg;
|
||||
|
||||
// Compute which pixel on the animated pixel map is the
|
||||
// upper left corner of the clip area
|
||||
|
||||
localOrg.x = animClip.x - animOffset.x;
|
||||
localOrg.y = animClip.y - animOffset.y;
|
||||
|
||||
// Translate the clip area to the coordinate system of
|
||||
// the temporary map, which is relative to the clip.
|
||||
|
||||
animClip.x -= clip.x;
|
||||
animClip.y -= clip.y;
|
||||
|
||||
// Blit the animated pixels into the temp map.
|
||||
|
||||
tempPort.bltPixels(g_vm->_tileDrawMap,
|
||||
localOrg.x,
|
||||
localOrg.y,
|
||||
animClip.x, animClip.y,
|
||||
animClip.width, animClip.height);
|
||||
}
|
||||
|
||||
// Compute the offset of the local blits (used by drawClipped)
|
||||
|
||||
offset = Point16(clip.x, clip.y);
|
||||
|
||||
// For each window, both background and float, that overlaps
|
||||
// the clip, draw the window's imagery
|
||||
if (g_vm->_userControlsSetup) {
|
||||
for (Common::List<gWindow *>::iterator it = g_vm->_toolBase->bottomWindowIterator(); it != g_vm->_toolBase->topWindowIterator(); --it)
|
||||
(*it)->drawClipped(tempPort, offset, clip);
|
||||
}
|
||||
// Now, blit the temporary bitmap to the main screen.
|
||||
|
||||
g_vm->_mainPort.setMode(kDrawModeReplace);
|
||||
g_vm->_pointer->hide(g_vm->_mainPort, clip);
|
||||
g_vm->_mainPort.bltPixels(tempMap,
|
||||
0, 0,
|
||||
clip.x, clip.y, clip.width, clip.height);
|
||||
g_vm->_pointer->show(g_vm->_mainPort, clip);
|
||||
g_vm->_mainPort.setMode(kDrawModeMatte);
|
||||
delete[] tempMap._data;
|
||||
}
|
||||
|
||||
void drawFloatingWindows(gPort &port, const Point16 &offset, const Rect16 &clip) {
|
||||
DecoratedWindow *dw;
|
||||
|
||||
// If a floating window is in the process of being dragged,
|
||||
// then things get a little more complex...
|
||||
|
||||
if (DragBar::_update) {
|
||||
Rect16 oldExtent,
|
||||
newExtent;
|
||||
|
||||
// Calculate the new and old position of the window
|
||||
|
||||
oldExtent = DragBar::_dragWindow->getExtent();
|
||||
newExtent = oldExtent;
|
||||
newExtent.x = DragBar::_dragPos.x;
|
||||
newExtent.y = DragBar::_dragPos.y;
|
||||
|
||||
// Move the window to the new position
|
||||
|
||||
DragBar::_dragWindow->setExtent(newExtent);
|
||||
DragBar::_update = false;
|
||||
|
||||
if (newExtent.overlap(oldExtent)) {
|
||||
// If the positions overlap, update them as a single
|
||||
// unit.
|
||||
|
||||
oldExtent = bound(newExtent, oldExtent);
|
||||
updateWindowSection(oldExtent);
|
||||
} else {
|
||||
// Otherwise, update new and old positions separately
|
||||
|
||||
updateWindowSection(newExtent);
|
||||
updateWindowSection(oldExtent);
|
||||
}
|
||||
}
|
||||
|
||||
for (Common::List<gWindow *>::iterator it = g_vm->_toolBase->bottomWindowIterator(); it != g_vm->_toolBase->topWindowIterator(); --it) {
|
||||
dw = (DecoratedWindow *)(*it);
|
||||
if (!dw->isBackdrop())
|
||||
dw->drawClipped(port, offset, clip);
|
||||
}
|
||||
}
|
||||
|
||||
void FloatingWindow::toFront() {
|
||||
gWindow::toFront();
|
||||
draw();
|
||||
}
|
||||
|
||||
/* ===================================================================== *
|
||||
Misc functions
|
||||
* ===================================================================== */
|
||||
|
||||
void closeAllFloatingWindows() {
|
||||
}
|
||||
|
||||
extern APPFUNC(cmdWindowFunc);
|
||||
|
||||
} // end of namespace Saga2
|
||||
Reference in New Issue
Block a user