188 lines
4.7 KiB
C++
188 lines
4.7 KiB
C++
/* 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
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "ultima/ultima8/gumps/item_relative_gump.h"
|
|
#include "ultima/ultima8/gumps/game_map_gump.h"
|
|
#include "ultima/ultima8/world/container.h"
|
|
#include "ultima/ultima8/world/get_object.h"
|
|
|
|
namespace Ultima {
|
|
namespace Ultima8 {
|
|
|
|
DEFINE_RUNTIME_CLASSTYPE_CODE(ItemRelativeGump)
|
|
|
|
ItemRelativeGump::ItemRelativeGump() : Gump(), _ix(0), _iy(0) {
|
|
}
|
|
|
|
ItemRelativeGump::ItemRelativeGump(int32 x, int32 y, int32 width, int32 height,
|
|
uint16 owner, uint32 flags, int32 layer)
|
|
: Gump(x, y, width, height, owner, flags, layer), _ix(0), _iy(0) {
|
|
}
|
|
|
|
ItemRelativeGump::~ItemRelativeGump(void) {
|
|
}
|
|
|
|
void ItemRelativeGump::InitGump(Gump *newparent, bool take_focus) {
|
|
Gump::InitGump(newparent, take_focus);
|
|
|
|
GetItemLocation(0);
|
|
|
|
if (!newparent && _parent)
|
|
MoveOnScreen();
|
|
}
|
|
|
|
void ItemRelativeGump::MoveOnScreen() {
|
|
assert(_parent);
|
|
Common::Rect32 sd = _parent->getDims();
|
|
|
|
// first move back to our desired location
|
|
_x = 0;
|
|
_y = 0;
|
|
|
|
// get rectangle that gump occupies in desktops's coordinate space
|
|
int32 left, right, top, bottom;
|
|
left = -_dims.left;
|
|
right = left + _dims.width();
|
|
top = -_dims.top;
|
|
bottom = top + _dims.height();
|
|
GumpToParent(left, top);
|
|
GumpToParent(right, bottom);
|
|
|
|
int32 movex = 0, movey = 0;
|
|
|
|
if (left < -sd.left)
|
|
movex = -sd.left - left;
|
|
else if (right > -sd.left + sd.width())
|
|
movex = -sd.left + sd.width() - right;
|
|
|
|
if (top < -sd.top)
|
|
movey = -sd.top - top;
|
|
else if (bottom > -sd.top + sd.height())
|
|
movey = -sd.top + sd.height() - bottom;
|
|
|
|
Move(left + movex, top + movey);
|
|
}
|
|
|
|
// Paint the Gump (RenderSurface is relative to parent).
|
|
// Calls PaintThis and PaintChildren
|
|
void ItemRelativeGump::Paint(RenderSurface *surf, int32 lerp_factor, bool scaled) {
|
|
GetItemLocation(lerp_factor);
|
|
Gump::Paint(surf, lerp_factor, scaled);
|
|
}
|
|
|
|
|
|
// Convert a parent relative point to a gump point
|
|
void ItemRelativeGump::ParentToGump(int32 &px, int32 &py, PointRoundDir r) {
|
|
px -= _ix;
|
|
py -= _iy;
|
|
Gump::ParentToGump(px, py, r);
|
|
}
|
|
|
|
// Convert a gump point to parent relative point
|
|
void ItemRelativeGump::GumpToParent(int32 &gx, int32 &gy, PointRoundDir r) {
|
|
Gump::GumpToParent(gx, gy, r);
|
|
gx += _ix;
|
|
gy += _iy;
|
|
}
|
|
|
|
void ItemRelativeGump::GetItemLocation(int32 lerp_factor) {
|
|
Gump *gump = nullptr;
|
|
|
|
Item *it = getItem(_owner);
|
|
|
|
if (!it) {
|
|
// This shouldn't ever happen, the GumpNotifyProcess should
|
|
// close us before we get here
|
|
Close();
|
|
return;
|
|
}
|
|
|
|
Item *next;
|
|
Item *prev = nullptr;
|
|
while ((next = it->getParentAsContainer()) != nullptr) {
|
|
prev = it;
|
|
it = next;
|
|
gump = getGump(it->getGump());
|
|
if (gump) break;
|
|
}
|
|
|
|
int32 gx, gy;
|
|
bool found;
|
|
|
|
if (!gump) {
|
|
gump = GetRootGump()->FindGump<GameMapGump>();
|
|
|
|
if (!gump) {
|
|
warning("ItemRelativeGump::GetItemLocation(): Unable to find GameMapGump");
|
|
return;
|
|
}
|
|
|
|
found = gump->GetLocationOfItem(_owner, gx, gy, lerp_factor);
|
|
} else {
|
|
assert(prev);
|
|
found = gump->GetLocationOfItem(prev->getObjId(), gx, gy, lerp_factor);
|
|
}
|
|
|
|
if (found) {
|
|
// Convert the GumpSpaceCoord relative to the world/item gump
|
|
// into screenspace coords
|
|
gy = gy - it->getShapeInfo()->_z * 8 - 16;
|
|
} else {
|
|
// If location not found show near bottom center
|
|
Common::Rect32 r = gump->getDims();
|
|
gx = (r.left + r.right) / 2;
|
|
gy = r.bottom - 8;
|
|
}
|
|
|
|
gump->GumpToScreenSpace(gx, gy);
|
|
|
|
// Convert the screenspace coords into the coords of us
|
|
if (_parent)
|
|
_parent->ScreenSpaceToGump(gx, gy);
|
|
|
|
// Set x and y, and center us over it
|
|
_ix = gx - _dims.width() / 2;
|
|
_iy = gy - _dims.height();
|
|
|
|
|
|
if (_flags & FLAG_KEEP_VISIBLE)
|
|
MoveOnScreen();
|
|
}
|
|
|
|
void ItemRelativeGump::Move(int32 x, int32 y) {
|
|
ParentToGump(x, y);
|
|
_x += x;
|
|
_y += y;
|
|
}
|
|
|
|
void ItemRelativeGump::saveData(Common::WriteStream *ws) {
|
|
Gump::saveData(ws);
|
|
}
|
|
|
|
bool ItemRelativeGump::loadData(Common::ReadStream *rs, uint32 version) {
|
|
if (!Gump::loadData(rs, version)) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
} // End of namespace Ultima8
|
|
} // End of namespace Ultima
|