STARK: Initiate rework of the user interface code
A base class, Window, will be used to ensure all the UI containers work in a similar way.
This commit is contained in:
parent
4f52010182
commit
273a358ad3
36 changed files with 807 additions and 662 deletions
|
@ -24,12 +24,14 @@
|
|||
|
||||
#include "engines/stark/gfx/driver.h"
|
||||
|
||||
#include "engines/stark/resources/item.h"
|
||||
#include "engines/stark/resources/anim.h"
|
||||
#include "engines/stark/resources/level.h"
|
||||
#include "engines/stark/resources/item.h"
|
||||
#include "engines/stark/resources/knowledgeset.h"
|
||||
#include "engines/stark/resources/level.h"
|
||||
#include "engines/stark/resources/pattable.h"
|
||||
|
||||
#include "engines/stark/services/services.h"
|
||||
#include "engines/stark/services/userinterface.h"
|
||||
#include "engines/stark/services/staticprovider.h"
|
||||
#include "engines/stark/services/global.h"
|
||||
|
||||
|
@ -39,80 +41,106 @@
|
|||
|
||||
namespace Stark {
|
||||
|
||||
ActionMenu::ActionMenu(Gfx::Driver *gfx) : _gfx(gfx) {
|
||||
Global *global = StarkServices::instance().global;
|
||||
Resources::Object *inventory = global->getLevel()->findChildWithSubtype<Resources::KnowledgeSet>(Resources::KnowledgeSet::kInventory, true);
|
||||
_hand = inventory->findChildWithIndex<Resources::ItemSub2>(1);
|
||||
_eye = inventory->findChildWithIndex<Resources::ItemSub2>(2);
|
||||
_mouth = inventory->findChildWithIndex<Resources::ItemSub2>(3);
|
||||
|
||||
// TODO: Should these be hardcoded?
|
||||
_hand->setPosition(Common::Point(90, -21));
|
||||
_eye->setPosition(Common::Point(5, 40));
|
||||
_mouth->setPosition(Common::Point(43, 0));
|
||||
|
||||
_renderEntries.push_back(_hand->getRenderEntry(Common::Point(0, 0)));
|
||||
_renderEntries.push_back(_eye->getRenderEntry(Common::Point(0, 0)));
|
||||
_renderEntries.push_back(_mouth->getRenderEntry(Common::Point(0, 0)));
|
||||
|
||||
ActionMenu::ActionMenu(Gfx::Driver *gfx, Cursor *cursor) :
|
||||
Window(gfx, cursor) {
|
||||
StaticProvider *staticProvider = StarkServices::instance().staticProvider;
|
||||
// TODO: Shouldn't use a function called getCursorImage for this, also unhardcode
|
||||
_background = staticProvider->getCursorImage(5);
|
||||
|
||||
_unscaled = true;
|
||||
_item = nullptr;
|
||||
|
||||
_buttons[kActionHand].action = Resources::PATTable::kActionUse;
|
||||
_buttons[kActionHand].rect = Common::Rect(90, 15, 126, 63);
|
||||
_buttons[kActionEye].action = Resources::PATTable::kActionLook;
|
||||
_buttons[kActionEye].rect = Common::Rect(5, 77, 51, 110);
|
||||
_buttons[kActionMouth].action = Resources::PATTable::kActionTalk;
|
||||
_buttons[kActionMouth].rect = Common::Rect(42, 35, 83, 74);
|
||||
|
||||
clearActions();
|
||||
}
|
||||
|
||||
ActionMenu::~ActionMenu() {
|
||||
_renderEntries.clear();
|
||||
}
|
||||
|
||||
void ActionMenu::render(Common::Point pos) {
|
||||
_gfx->setScreenViewport(true); // Drawn unscaled
|
||||
_renderEntries.clear();
|
||||
void ActionMenu::open(Resources::Item *item, const Common::Point &itemClickPos) {
|
||||
UserInterface *ui = StarkServices::instance().userInterface;
|
||||
|
||||
if (_handEnabled) {
|
||||
_renderEntries.push_back(_hand->getRenderEntry(pos));
|
||||
_visible = true;
|
||||
|
||||
Common::Point screenMousePos = getScreenMousePosition();
|
||||
_position = Common::Rect::center(screenMousePos.x, screenMousePos.y, 160, 111);
|
||||
|
||||
_itemClickPos = itemClickPos;
|
||||
_item = item;
|
||||
|
||||
clearActions();
|
||||
|
||||
Resources::ActionArray possible = ui->getActionsPossibleForObject(_item, _itemClickPos);
|
||||
|
||||
for (uint i = 0; i < possible.size(); i++) {
|
||||
for (uint j = 0; j < ARRAYSIZE(_buttons); j++) {
|
||||
if (_buttons[j].action == possible[i]) {
|
||||
_buttons[j].enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_eyeEnabled) {
|
||||
_renderEntries.push_back(_eye->getRenderEntry(pos));
|
||||
}
|
||||
if (_mouthEnabled) {
|
||||
_renderEntries.push_back(_mouth->getRenderEntry(pos));
|
||||
}
|
||||
|
||||
Scene *scene = StarkServices::instance().scene;
|
||||
_background->render(pos);
|
||||
scene->render(_renderEntries);
|
||||
void ActionMenu::close() {
|
||||
_visible = false;
|
||||
_item = nullptr;
|
||||
}
|
||||
|
||||
void ActionMenu::onRender() {
|
||||
UserInterface *ui = StarkServices::instance().userInterface;
|
||||
Common::Point mousePos = getMousePosition();
|
||||
|
||||
_background->render(Common::Point(0, 0));
|
||||
|
||||
for (uint i = 0; i < ARRAYSIZE(_buttons); i++) {
|
||||
if (_buttons[i].enabled) {
|
||||
bool active = _buttons[i].rect.contains(mousePos);
|
||||
VisualImageXMG *visual = ui->getActionImage(_buttons[i].action, active);
|
||||
visual->render(Common::Point(_buttons[i].rect.left, _buttons[i].rect.top));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActionMenu::clearActions() {
|
||||
_handEnabled = _mouthEnabled = _eyeEnabled = false;
|
||||
for (uint i = 0; i < ARRAYSIZE(_buttons); i++) {
|
||||
_buttons[i].enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ActionMenu::enableAction(ActionMenuType action) {
|
||||
switch (action) {
|
||||
case kActionHand:
|
||||
_handEnabled = true;
|
||||
break;
|
||||
case kActionMouth:
|
||||
_mouthEnabled = true;
|
||||
break;
|
||||
case kActionEye:
|
||||
_eyeEnabled = true;
|
||||
break;
|
||||
default:
|
||||
error("Invalid action type in ActionMenu::enableAction");
|
||||
_buttons[action].enabled = true;
|
||||
}
|
||||
|
||||
void ActionMenu::onMouseMove(const Common::Point &pos) {
|
||||
bool hoveringAction = false;
|
||||
for (uint i = 0; i < ARRAYSIZE(_buttons); i++) {
|
||||
if (_buttons[i].enabled && _buttons[i].rect.contains(pos)) {
|
||||
hoveringAction = true;
|
||||
}
|
||||
}
|
||||
|
||||
int ActionMenu::isThisYourButton(Resources::Object *object) {
|
||||
Resources::Item *item = object->findParent<Resources::Item>();
|
||||
if (item == _mouth) {
|
||||
return kActionMouth;
|
||||
} else if (item == _eye) {
|
||||
return kActionEye;
|
||||
} else if (item == _hand) {
|
||||
return kActionHand;
|
||||
if (hoveringAction) {
|
||||
setCursor(Cursor::kActive);
|
||||
} else {
|
||||
return -1;
|
||||
setCursor(Cursor::kDefault);
|
||||
}
|
||||
}
|
||||
|
||||
void ActionMenu::onClick(const Common::Point &pos) {
|
||||
UserInterface *ui = StarkServices::instance().userInterface;
|
||||
|
||||
for (uint i = 0; i < ARRAYSIZE(_buttons); i++) {
|
||||
if (_buttons[i].enabled && _buttons[i].rect.contains(pos)) {
|
||||
ui->itemDoActionAt(_item, _buttons[i].action, _itemClickPos);
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,38 +25,52 @@
|
|||
|
||||
#include "engines/stark/gfx/renderentry.h"
|
||||
|
||||
#include "engines/stark/ui/window.h"
|
||||
|
||||
namespace Stark {
|
||||
|
||||
class Cursor;
|
||||
class VisualImageXMG;
|
||||
|
||||
namespace Resources {
|
||||
class ItemSub2;
|
||||
class Object;
|
||||
class Item;
|
||||
}
|
||||
|
||||
class ActionMenu {
|
||||
Resources::ItemSub2 *_eye;
|
||||
Resources::ItemSub2 *_hand;
|
||||
Resources::ItemSub2 *_mouth;
|
||||
VisualImageXMG *_background;
|
||||
bool _eyeEnabled;
|
||||
bool _handEnabled;
|
||||
bool _mouthEnabled;
|
||||
Gfx::RenderEntryArray _renderEntries;
|
||||
Gfx::Driver *_gfx;
|
||||
class ActionMenu : public Window {
|
||||
public:
|
||||
enum ActionMenuType {
|
||||
kActionHand,
|
||||
kActionMouth,
|
||||
kActionEye
|
||||
};
|
||||
ActionMenu(Gfx::Driver *gfx);
|
||||
ActionMenu(Gfx::Driver *gfx, Cursor *cursor);
|
||||
~ActionMenu();
|
||||
void render(Common::Point pos);
|
||||
|
||||
void open(Resources::Item *item, const Common::Point &itemClickPos);
|
||||
void close();
|
||||
|
||||
protected:
|
||||
void onMouseMove(const Common::Point &pos) override;
|
||||
void onClick(const Common::Point &pos) override;
|
||||
void onRender() override;
|
||||
|
||||
private:
|
||||
enum ActionMenuType {
|
||||
kActionHand = 0,
|
||||
kActionEye = 1,
|
||||
kActionMouth = 2
|
||||
};
|
||||
|
||||
struct ActionButton {
|
||||
bool enabled;
|
||||
uint32 action;
|
||||
Common::Rect rect;
|
||||
};
|
||||
|
||||
ActionButton _buttons[3];
|
||||
|
||||
VisualImageXMG *_background;
|
||||
|
||||
Common::Point _itemClickPos;
|
||||
Resources::Item *_item;
|
||||
|
||||
void clearActions();
|
||||
void enableAction(ActionMenuType action);
|
||||
Gfx::RenderEntryArray getRenderEntries() { return _renderEntries; }
|
||||
int isThisYourButton(Resources::Object *object);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ bool Console::Cmd_DumpKnowledge(int argc, const char **argv) {
|
|||
}
|
||||
|
||||
bool Console::Cmd_ChangeKnowledge(int argc, const char **argv) {
|
||||
int index = 0;
|
||||
uint index = 0;
|
||||
char type = 0;
|
||||
|
||||
if (argc >= 4) {
|
||||
|
@ -211,7 +211,7 @@ bool Console::Cmd_ListScripts(int argc, const char **argv) {
|
|||
}
|
||||
|
||||
bool Console::Cmd_EnableScript(int argc, const char **argv) {
|
||||
int index = 0;
|
||||
uint index = 0;
|
||||
|
||||
if (argc >= 2) {
|
||||
index = atoi(argv[1]);
|
||||
|
@ -243,7 +243,7 @@ bool Console::Cmd_EnableScript(int argc, const char **argv) {
|
|||
}
|
||||
|
||||
bool Console::Cmd_ForceScript(int argc, const char **argv) {
|
||||
int index = 0;
|
||||
uint index = 0;
|
||||
|
||||
if (argc >= 2) {
|
||||
index = atoi(argv[1]);
|
||||
|
|
|
@ -80,10 +80,14 @@ void Cursor::render() {
|
|||
}
|
||||
}
|
||||
|
||||
Common::Point Cursor::getMousePosition() const {
|
||||
// The rest of the engine expects 640x480 coordinates
|
||||
Common::Point Cursor::getMousePosition(bool unscaled) const {
|
||||
if (unscaled) {
|
||||
return _mousePos;
|
||||
} else {
|
||||
// Most of the engine expects 640x480 coordinates
|
||||
return _gfx->scalePoint(_mousePos);
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::setMouseHint(const Common::String &hint) {
|
||||
if (hint != _currentHint) {
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
/** Update the mouse position */
|
||||
void setMousePosition(Common::Point pos);
|
||||
|
||||
Common::Point getMousePosition() const;
|
||||
Common::Point getMousePosition(bool unscaled = false) const;
|
||||
|
||||
enum CursorType {
|
||||
kNone = -1,
|
||||
|
|
|
@ -44,8 +44,10 @@ public:
|
|||
|
||||
virtual void init() = 0;
|
||||
|
||||
virtual void setGameViewport() = 0;
|
||||
virtual void setScreenViewport(bool noScaling) = 0;
|
||||
virtual void setGameViewport() = 0; // deprecated
|
||||
virtual void setScreenViewport(bool noScaling) = 0; // deprecated
|
||||
|
||||
virtual void setViewport(Common::Rect rect, bool noScaling) = 0;
|
||||
|
||||
/** Get the screen viewport in actual resolution */
|
||||
Common::Rect getScreenViewport() { return _screenViewport; }
|
||||
|
|
|
@ -89,6 +89,27 @@ void OpenGLSDriver::setScreenViewport(bool noScaling) {
|
|||
glViewport(_viewport.left, _viewport.top, _viewport.width(), _viewport.height());
|
||||
}
|
||||
|
||||
void OpenGLSDriver::setViewport(Common::Rect rect, bool noScaling) {
|
||||
if (noScaling) {
|
||||
_viewport = rect;
|
||||
_unscaledViewport = rect;
|
||||
} else {
|
||||
_viewport = Common::Rect(
|
||||
_screenViewport.width() * rect.width() / kOriginalWidth,
|
||||
_screenViewport.height() * rect.height() / kOriginalHeight
|
||||
);
|
||||
|
||||
_viewport.translate(
|
||||
_screenViewport.left + _screenViewport.width() * rect.left / kOriginalWidth,
|
||||
_screenViewport.top + _screenViewport.height() * rect.top / kOriginalHeight
|
||||
);
|
||||
|
||||
_unscaledViewport = rect;
|
||||
}
|
||||
|
||||
glViewport(_viewport.left, g_system->getHeight() - _viewport.bottom, _viewport.width(), _viewport.height());
|
||||
}
|
||||
|
||||
Math::Vector2d OpenGLSDriver::scaled(float x, float y) const {
|
||||
return Math::Vector2d(x / (float) _unscaledViewport.width(), y / (float) _unscaledViewport.height());
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ public:
|
|||
|
||||
void setGameViewport() override;
|
||||
void setScreenViewport(bool noScaling) override;
|
||||
void setViewport(Common::Rect rect, bool noScaling) override;
|
||||
|
||||
void setupCamera(const Math::Matrix4 &projection, const Math::Matrix4 &view) override;
|
||||
|
||||
|
|
|
@ -28,15 +28,10 @@
|
|||
#include "engines/stark/visual/smacker.h"
|
||||
#include "engines/stark/visual/visual.h"
|
||||
|
||||
// TODO: Refactor this logic elsewhere
|
||||
#include "engines/stark/resources/item.h"
|
||||
#include "engines/stark/resources/anim.h"
|
||||
#include "engines/stark/resources/pattable.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Gfx {
|
||||
|
||||
RenderEntry::RenderEntry(Resources::Object *owner, const Common::String &name) :
|
||||
RenderEntry::RenderEntry(Resources::Item *owner, const Common::String &name) :
|
||||
_visual(nullptr),
|
||||
_name(name),
|
||||
_owner(owner),
|
||||
|
@ -87,51 +82,5 @@ bool RenderEntry::compare(const RenderEntry *x, const RenderEntry *y) {
|
|||
return x->_sortKey < y->_sortKey;
|
||||
}
|
||||
|
||||
bool RenderEntry::containsPoint(Common::Point point) {
|
||||
return indexForPoint(point) != -1;
|
||||
}
|
||||
|
||||
int RenderEntry::indexForPoint(Common::Point point) {
|
||||
// TODO: This doesn't consider 3D at all.
|
||||
// TODO: This is just a quick fix, we still need to calculate the position, after any scaling and 3D transforms.
|
||||
// TODO: We more or less ignore Y for now, since all we consider is the position-point.
|
||||
|
||||
// HACK: Since we lack Subtype2
|
||||
if (getOwner() && (getOwner()->getType() == Resources::Type::kItem || getOwner()->getType() == Resources::Type::kAnim)) {
|
||||
point.x -= _position.x;
|
||||
point.y -= _position.y;
|
||||
point.y -= Gfx::Driver::kTopBorderHeight; // Adjust for the top part.
|
||||
if (getOwner()->getType() == Resources::Type::kItem) {
|
||||
Resources::Item *item = (Resources::Item*)getOwner();
|
||||
int index = item->indexForPoint(point);
|
||||
// HACK For subtype 2, we get a PAT-index that is NOT inside the item.
|
||||
if (getOwner()->getSubType() == Resources::Item::kItemSub2) {
|
||||
return index;
|
||||
}
|
||||
if (index == -1) {
|
||||
return -1;
|
||||
} else {
|
||||
Resources::PATTable *table = item->findChildWithIndex<Resources::PATTable>(index);
|
||||
// Ignore any uninteractable Items
|
||||
// this should not be done when handling UI-buttons, as they have 0 actions.
|
||||
// For now that special case is handled in the Owner == Anim type below,
|
||||
// but in practice it should be done by way of checking for ItemSub2
|
||||
if (!table) {
|
||||
warning("Item %s has no PAT Table", item->getName().c_str());
|
||||
}
|
||||
if (!table || table->getNumActions() == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
// TODO: This is probably not necessary after introducing SubType2, but we keep it for the statics for now.
|
||||
} else if (getOwner()->getType() == Resources::Type::kAnim) { // HACK Until we get Subtype2
|
||||
Resources::Anim *anim = (Resources::Anim*)getOwner();
|
||||
return anim->indexForPoint(point);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // End of namespace Gfx
|
||||
} // End of namespace Stark
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace Stark {
|
|||
class Visual;
|
||||
|
||||
namespace Resources {
|
||||
class Object;
|
||||
class Item;
|
||||
}
|
||||
|
||||
namespace Gfx {
|
||||
|
@ -43,7 +43,7 @@ class Driver;
|
|||
|
||||
class RenderEntry {
|
||||
public:
|
||||
RenderEntry(Resources::Object *owner, const Common::String &name);
|
||||
RenderEntry(Resources::Item *owner, const Common::String &name);
|
||||
virtual ~RenderEntry() {};
|
||||
|
||||
void render(Driver *gfx);
|
||||
|
@ -53,17 +53,15 @@ public:
|
|||
void setPosition3D(const Math::Vector3d &position, float direction);
|
||||
void setSortKey(float sortKey);
|
||||
|
||||
/** Checks whether the render entry will draw anything to a specific point */
|
||||
bool containsPoint(Common::Point point);
|
||||
int indexForPoint(Common::Point point);
|
||||
/** Gets the owner-object */
|
||||
Resources::Object *getOwner() { return _owner; }
|
||||
Resources::Item *getOwner() const { return _owner; }
|
||||
|
||||
/** Compare two render entries by their sort keys */
|
||||
static bool compare(const RenderEntry *x, const RenderEntry *y);
|
||||
|
||||
protected:
|
||||
Common::String _name;
|
||||
Resources::Object *_owner;
|
||||
Resources::Item *_owner;
|
||||
|
||||
Visual *_visual;
|
||||
Common::Point _position;
|
||||
|
|
|
@ -65,6 +65,7 @@ MODULE_OBJS := \
|
|||
ui/dialoginterface.o \
|
||||
ui/inventoryinterface.o \
|
||||
ui/topmenu.o \
|
||||
ui/window.o \
|
||||
visual/actor.o \
|
||||
visual/image.o \
|
||||
visual/smacker.o
|
||||
|
|
|
@ -60,7 +60,7 @@ Anim::~Anim() {
|
|||
|
||||
Anim::Anim(Object *parent, byte subType, uint16 index, const Common::String &name) :
|
||||
Object(parent, subType, index, name),
|
||||
_field_30(0),
|
||||
_usage(0),
|
||||
_currentFrame(0),
|
||||
_numFrames(0),
|
||||
_refCount(0) {
|
||||
|
@ -68,7 +68,7 @@ Anim::Anim(Object *parent, byte subType, uint16 index, const Common::String &nam
|
|||
}
|
||||
|
||||
void Anim::readData(Formats::XRCReadStream *stream) {
|
||||
_field_30 = stream->readUint32LE();
|
||||
_usage = stream->readUint32LE();
|
||||
_numFrames = stream->readUint32LE();
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,10 @@ Visual *Anim::getVisual() {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 Anim::getUsage() const {
|
||||
return _usage;
|
||||
}
|
||||
|
||||
void Anim::applyToItem(Item *item) {
|
||||
_refCount++;
|
||||
}
|
||||
|
@ -91,7 +95,7 @@ bool Anim::isInUse() {
|
|||
}
|
||||
|
||||
void Anim::printData() {
|
||||
debug("field_30: %d", _field_30);
|
||||
debug("usage: %d", _usage);
|
||||
debug("numFrames: %d", _numFrames);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,23 @@ public:
|
|||
kAnimSkeleton = 4
|
||||
};
|
||||
|
||||
enum ActionUsage {
|
||||
kActionUsagePassive = 1,
|
||||
kActionUsageActive = 2
|
||||
};
|
||||
|
||||
enum UIUsage {
|
||||
kUIUsageInventory = 1,
|
||||
kUIUsageUseCursor = 4
|
||||
};
|
||||
|
||||
enum ActorUsage {
|
||||
kActorUsageIdle = 1,
|
||||
kActorUsageWalk = 2,
|
||||
kActorUsageTalk = 3,
|
||||
kActorUsageRun = 6
|
||||
};
|
||||
|
||||
/** Anim factory */
|
||||
static Object *construct(Object *parent, byte subType, uint16 index, const Common::String &name);
|
||||
|
||||
|
@ -84,12 +101,15 @@ public:
|
|||
/** Check is the animation is being used by an item */
|
||||
bool isInUse();
|
||||
|
||||
/** Obtain the purpose of this anim */
|
||||
uint32 getUsage() const;
|
||||
|
||||
virtual bool containsPoint(Common::Point point) { return false; }
|
||||
virtual int indexForPoint(Common::Point point) { return -1; }
|
||||
protected:
|
||||
virtual void printData() override;
|
||||
|
||||
uint32 _field_30;
|
||||
uint32 _usage;
|
||||
uint32 _currentFrame;
|
||||
uint32 _numFrames;
|
||||
int32 _refCount;
|
||||
|
|
|
@ -38,7 +38,7 @@ AnimHierarchy::~AnimHierarchy() {
|
|||
|
||||
AnimHierarchy::AnimHierarchy(Object *parent, byte subType, uint16 index, const Common::String &name) :
|
||||
Object(parent, subType, index, name),
|
||||
_animIndex(0),
|
||||
_animUsage(0),
|
||||
_currentAnim(nullptr),
|
||||
_animHierarchy(nullptr),
|
||||
_field_5C(0) {
|
||||
|
@ -76,9 +76,9 @@ void AnimHierarchy::onAllLoaded() {
|
|||
}
|
||||
}
|
||||
|
||||
void AnimHierarchy::setItemAnim(ItemVisual *item, int32 index) {
|
||||
void AnimHierarchy::setItemAnim(ItemVisual *item, int32 usage) {
|
||||
unselectItemAnim(item);
|
||||
_animIndex = index;
|
||||
_animUsage = usage;
|
||||
selectItemAnim(item);
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ void AnimHierarchy::unselectItemAnim(ItemVisual *item) {
|
|||
void AnimHierarchy::selectItemAnim(ItemVisual *item) {
|
||||
// Search for an animation with the appropriate index
|
||||
for (uint i = 0; i < _animations.size(); i++) {
|
||||
if (_animations[i]->getIndex() == _animIndex) {
|
||||
if (_animations[i]->getUsage() == _animUsage) {
|
||||
_currentAnim = _animations[i];
|
||||
break;
|
||||
}
|
||||
|
@ -125,6 +125,22 @@ TextureSet *AnimHierarchy::findTextureSet(uint32 textureType) {
|
|||
return findChildWithSubtype<TextureSet>(textureType);
|
||||
}
|
||||
|
||||
Anim *AnimHierarchy::getAnimForUsage(uint32 usage) {
|
||||
// Search for an animation with the appropriate use
|
||||
for (uint i = 0; i < _animations.size(); i++) {
|
||||
if (_animations[i]->getUsage() == usage) {
|
||||
return _animations[i];
|
||||
}
|
||||
}
|
||||
|
||||
error("No anim found for use '%d' in '%s'", usage, getName().c_str());
|
||||
}
|
||||
|
||||
Visual *AnimHierarchy::getVisualForUsage(uint32 usage) {
|
||||
Anim *anim = getAnimForUsage(usage);
|
||||
return anim->getVisual();
|
||||
}
|
||||
|
||||
void AnimHierarchy::printData() {
|
||||
for (uint i = 0; i < _animationReferences.size(); i++) {
|
||||
debug("anim %d: %s", i, _animationReferences[i].describe().c_str());
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#include "engines/stark/resourcereference.h"
|
||||
|
||||
namespace Stark {
|
||||
|
||||
class Visual;
|
||||
|
||||
namespace Formats {
|
||||
class XRCReadStream;
|
||||
}
|
||||
|
@ -57,8 +60,8 @@ public:
|
|||
void readData(Formats::XRCReadStream *stream) override;
|
||||
void onAllLoaded() override;
|
||||
|
||||
/** Set and apply the current animation for an item */
|
||||
void setItemAnim(ItemVisual *item, int32 index);
|
||||
/** Set and apply the current animation kind for an item */
|
||||
void setItemAnim(ItemVisual *item, int32 usage);
|
||||
|
||||
/** Unselect the current animation and remove it from an item */
|
||||
void unselectItemAnim(ItemVisual *item);
|
||||
|
@ -78,7 +81,10 @@ public:
|
|||
*/
|
||||
TextureSet *findTextureSet(uint32 textureType);
|
||||
|
||||
Visual *getVisualForUsage(uint32 usage);
|
||||
|
||||
protected:
|
||||
Anim *getAnimForUsage(uint32 usage);
|
||||
void printData() override;
|
||||
|
||||
Common::Array<ResourceReference> _animationReferences;
|
||||
|
@ -88,7 +94,7 @@ protected:
|
|||
AnimHierarchy * _animHierarchy;
|
||||
|
||||
float _field_5C;
|
||||
int32 _animIndex;
|
||||
uint32 _animUsage;
|
||||
Anim *_currentAnim;
|
||||
};
|
||||
|
||||
|
|
|
@ -26,12 +26,15 @@
|
|||
|
||||
#include "engines/stark/formats/xrc.h"
|
||||
#include "engines/stark/gfx/renderentry.h"
|
||||
|
||||
#include "engines/stark/resources/anim.h"
|
||||
#include "engines/stark/resources/animhierarchy.h"
|
||||
#include "engines/stark/resources/bonesmesh.h"
|
||||
#include "engines/stark/resources/bookmark.h"
|
||||
#include "engines/stark/resources/floor.h"
|
||||
#include "engines/stark/resources/pattable.h"
|
||||
#include "engines/stark/resources/textureset.h"
|
||||
|
||||
#include "engines/stark/services/global.h"
|
||||
#include "engines/stark/services/services.h"
|
||||
#include "engines/stark/services/stateprovider.h"
|
||||
|
@ -44,7 +47,7 @@ Object *Item::construct(Object *parent, byte subType, uint16 index, const Common
|
|||
case kItemSub1:
|
||||
return new ItemSub1(parent, subType, index, name);
|
||||
case kItemSub2:
|
||||
return new ItemSub2(parent, subType, index, name); // TODO
|
||||
return new ItemSub2(parent, subType, index, name);
|
||||
case kItemSub3:
|
||||
return new ItemSub3(parent, subType, index, name);
|
||||
case kItemSub5:
|
||||
|
@ -91,6 +94,10 @@ Item *Item::getSceneInstance() {
|
|||
return this;
|
||||
}
|
||||
|
||||
bool Item::isClickable() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Item::printData() {
|
||||
debug("enabled: %d", _enabled);
|
||||
debug("field_38: %d", _field_38);
|
||||
|
@ -103,6 +110,19 @@ void Item::saveLoad(ResourceSerializer *serializer) {
|
|||
serializer->syncAsSint32LE(_enabled);
|
||||
}
|
||||
|
||||
bool Item::doAction(uint32 action, uint32 hotspotIndex) {
|
||||
PATTable *table = findChildWithIndex<PATTable>(hotspotIndex);
|
||||
if (table && table->canPerformAction(action)) {
|
||||
return table->runScriptForAction(action);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Item::containsPoint(Common::Point point) {
|
||||
return indexForPoint(point) != -1;
|
||||
}
|
||||
|
||||
ItemVisual::~ItemVisual() {
|
||||
delete _renderEntry;
|
||||
}
|
||||
|
@ -111,15 +131,15 @@ ItemVisual::ItemVisual(Object *parent, byte subType, uint16 index, const Common:
|
|||
Item(parent, subType, index, name),
|
||||
_renderEntry(nullptr),
|
||||
_animHierarchy(nullptr),
|
||||
_currentAnimIndex(-1),
|
||||
_field_44(1) {
|
||||
_currentAnimKind(-1),
|
||||
_clickable(true) {
|
||||
_renderEntry = new Gfx::RenderEntry(this, getName());
|
||||
}
|
||||
|
||||
void ItemVisual::readData(Formats::XRCReadStream *stream) {
|
||||
Item::readData(stream);
|
||||
|
||||
_field_44 = stream->readUint32LE();
|
||||
_clickable = stream->readBool();
|
||||
}
|
||||
|
||||
void ItemVisual::onAllLoaded() {
|
||||
|
@ -128,7 +148,7 @@ void ItemVisual::onAllLoaded() {
|
|||
_animHierarchy = findChild<AnimHierarchy>(false);
|
||||
|
||||
if (_subType != kItemSub10) {
|
||||
setAnim(1);
|
||||
setAnimKind(Anim::kActionUsagePassive);
|
||||
}
|
||||
|
||||
if (!_enabled) {
|
||||
|
@ -146,19 +166,23 @@ void ItemVisual::setEnabled(bool enabled) {
|
|||
}
|
||||
}
|
||||
|
||||
void ItemVisual::setAnim(int32 index) {
|
||||
bool animNeedsUpdate = index != _currentAnimIndex;
|
||||
bool ItemVisual::isClickable() const {
|
||||
return _clickable;
|
||||
}
|
||||
|
||||
_currentAnimIndex = index;
|
||||
void ItemVisual::setAnimKind(int32 usage) {
|
||||
bool animNeedsUpdate = usage != _currentAnimKind;
|
||||
|
||||
_currentAnimKind = usage;
|
||||
if (animNeedsUpdate && _animHierarchy) {
|
||||
_animHierarchy->setItemAnim(this, index);
|
||||
_animHierarchy->setItemAnim(this, usage);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemVisual::printData() {
|
||||
Item::printData();
|
||||
|
||||
debug("field_44: %d", _field_44);
|
||||
debug("clickable: %d", _clickable);
|
||||
}
|
||||
|
||||
Anim *ItemVisual::getAnim() {
|
||||
|
@ -175,37 +199,6 @@ Visual *ItemVisual::getVisual() {
|
|||
return anim->getVisual();
|
||||
}
|
||||
|
||||
bool ItemVisual::containsPoint(Common::Point point) {
|
||||
Anim *anim = getAnim();
|
||||
if (anim) {
|
||||
return anim->containsPoint(point);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int ItemVisual::indexForPoint(Common::Point point) {
|
||||
// TODO: This breaks rather weirdly on subtype 6 and 10
|
||||
Anim *anim = getAnim();
|
||||
if (anim) {
|
||||
return anim->indexForPoint(point);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Gfx::RenderEntry *ItemSub2::getRenderEntry(const Common::Point &positionOffset) {
|
||||
if (_enabled) {
|
||||
Visual *visual = getVisual();
|
||||
|
||||
_renderEntry->setVisual(visual);
|
||||
_renderEntry->setPosition(_position + positionOffset);
|
||||
// _renderEntry->setSortKey(getSortKey());
|
||||
} else {
|
||||
_renderEntry->setVisual(nullptr);
|
||||
}
|
||||
|
||||
return _renderEntry;
|
||||
}
|
||||
|
||||
ItemSub13::~ItemSub13() {
|
||||
}
|
||||
|
||||
|
@ -292,6 +285,36 @@ AnimHierarchy *ItemSub1::findStockAnimHierarchy() {
|
|||
}
|
||||
}
|
||||
|
||||
ItemSub2::~ItemSub2() {
|
||||
}
|
||||
|
||||
ItemSub2::ItemSub2(Object *parent, byte subType, uint16 index, const Common::String &name) :
|
||||
ItemVisual(parent, subType, index, name) {
|
||||
}
|
||||
|
||||
Gfx::RenderEntry *ItemSub2::getRenderEntry(const Common::Point &positionOffset) {
|
||||
if (_enabled) {
|
||||
setAnimKind(Anim::kUIUsageInventory);
|
||||
|
||||
Visual *visual = getVisual();
|
||||
|
||||
_renderEntry->setVisual(visual);
|
||||
_renderEntry->setPosition(Common::Point());
|
||||
} else {
|
||||
_renderEntry->setVisual(nullptr);
|
||||
}
|
||||
|
||||
return _renderEntry;
|
||||
}
|
||||
|
||||
Visual *ItemSub2::getActionVisual(bool active) {
|
||||
if (active) {
|
||||
return _animHierarchy->getVisualForUsage(Anim::kActionUsageActive);
|
||||
} else {
|
||||
return _animHierarchy->getVisualForUsage(Anim::kActionUsagePassive);
|
||||
}
|
||||
}
|
||||
|
||||
ItemSub3::~ItemSub3() {
|
||||
}
|
||||
|
||||
|
@ -401,7 +424,7 @@ float ItemSub5610::getSortKey() const {
|
|||
Floor *floor = global->getCurrent()->getFloor();
|
||||
|
||||
if (_floorFaceIndex == -1) {
|
||||
warning("Undefined floor face index for item '%s'", getName().c_str());
|
||||
// warning("Undefined floor face index for item '%s'", getName().c_str());
|
||||
return floor->getDistanceFromCamera(0);
|
||||
}
|
||||
|
||||
|
@ -436,6 +459,15 @@ Gfx::RenderEntry *ItemSub56::getRenderEntry(const Common::Point &positionOffset)
|
|||
return _renderEntry;
|
||||
}
|
||||
|
||||
int ItemSub56::indexForPoint(Common::Point point) {
|
||||
// TODO: This breaks rather weirdly on subtype 6 and 10
|
||||
Anim *anim = getAnim();
|
||||
if (anim) {
|
||||
return anim->indexForPoint(point - _position);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ItemSub56::printData() {
|
||||
ItemSub5610::printData();
|
||||
|
||||
|
@ -470,6 +502,15 @@ Gfx::RenderEntry *ItemSub78::getRenderEntry(const Common::Point &positionOffset)
|
|||
return _renderEntry;
|
||||
}
|
||||
|
||||
int ItemSub78::indexForPoint(Common::Point point) {
|
||||
// TODO: This breaks rather weirdly on subtype 6 and 10
|
||||
Anim *anim = getAnim();
|
||||
if (anim) {
|
||||
return anim->indexForPoint(point - _position);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ItemSub78::printData() {
|
||||
ItemVisual::printData();
|
||||
|
||||
|
@ -525,7 +566,7 @@ void ItemSub10::onEnterLocation() {
|
|||
_animHierarchy = _referencedItem->findStockAnimHierarchy();
|
||||
}
|
||||
|
||||
setAnim(1);
|
||||
setAnimKind(Anim::kActorUsageIdle);
|
||||
}
|
||||
|
||||
BonesMesh *ItemSub10::findBonesMesh() {
|
||||
|
|
|
@ -79,6 +79,7 @@ public:
|
|||
|
||||
// Resource API
|
||||
virtual void readData(Formats::XRCReadStream *stream) override;
|
||||
void saveLoad(ResourceSerializer *serializer) override;
|
||||
|
||||
/** Is the item present in the scene */
|
||||
bool isEnabled() const;
|
||||
|
@ -92,8 +93,12 @@ public:
|
|||
/** Obtain the concrete instance of an item template */
|
||||
virtual Item *getSceneInstance();
|
||||
|
||||
void saveLoad(ResourceSerializer *serializer) override;
|
||||
virtual bool containsPoint(Common::Point point) { return false; };
|
||||
/** If this is false, the item is click through */
|
||||
virtual bool isClickable() const;
|
||||
|
||||
bool doAction(uint32 action, uint32 hotspotIndex);
|
||||
|
||||
bool containsPoint(Common::Point point);
|
||||
virtual int indexForPoint(Common::Point point) { return -1; };
|
||||
protected:
|
||||
void printData() override;
|
||||
|
@ -118,12 +123,11 @@ public:
|
|||
|
||||
// Item API
|
||||
void setEnabled(bool enabled) override;
|
||||
bool isClickable() const override;
|
||||
|
||||
/** Define the current animation index for the item */
|
||||
virtual void setAnim(int32 index); // TODO: Just virtual to allow hack in ItemSub2
|
||||
/** Define the current animation kind for the item */
|
||||
void setAnimKind(int32 usage);
|
||||
|
||||
bool containsPoint(Common::Point point) override;
|
||||
int indexForPoint(Common::Point point) override;
|
||||
protected:
|
||||
// Resource API
|
||||
void printData() override;
|
||||
|
@ -134,20 +138,8 @@ protected:
|
|||
Gfx::RenderEntry *_renderEntry;
|
||||
|
||||
AnimHierarchy *_animHierarchy;
|
||||
int32 _currentAnimIndex;
|
||||
uint32 _field_44;
|
||||
};
|
||||
|
||||
// Just a stub-class for now, to reduce the amount of hackery necessary elsewhere.
|
||||
class ItemSub2 : public ItemVisual {
|
||||
Common::Point _position;
|
||||
public:
|
||||
ItemSub2(Object *parent, byte subType, uint16 index, const Common::String &name) : ItemVisual(parent, subType, index, name), _position(0, 0) {};
|
||||
// This function does not actually need to be virtual in the super class, but
|
||||
// it's HACKED this way to work around the action-menu stuff for now.
|
||||
void setAnim(int32 index) override { ItemVisual::setAnim(0); }
|
||||
void setPosition(Common::Point pos) { _position = pos; }
|
||||
Gfx::RenderEntry *getRenderEntry(const Common::Point &positionOffset);
|
||||
int32 _currentAnimKind;
|
||||
bool _clickable;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -206,6 +198,23 @@ public:
|
|||
protected:
|
||||
};
|
||||
|
||||
/**
|
||||
* An inventory item
|
||||
*/
|
||||
class ItemSub2: public ItemVisual {
|
||||
public:
|
||||
ItemSub2(Object *parent, byte subType, uint16 index, const Common::String &name);
|
||||
virtual ~ItemSub2();
|
||||
|
||||
// Item API
|
||||
Gfx::RenderEntry *getRenderEntry(const Common::Point &positionOffset) override;
|
||||
|
||||
/** Obtain an action menu icon */
|
||||
Visual *getActionVisual(bool active);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
/**
|
||||
* A level item template
|
||||
*
|
||||
|
@ -279,6 +288,7 @@ public:
|
|||
|
||||
// Item API
|
||||
Gfx::RenderEntry *getRenderEntry(const Common::Point &positionOffset) override;
|
||||
int indexForPoint(Common::Point point) override;
|
||||
|
||||
protected:
|
||||
void printData() override;
|
||||
|
@ -333,6 +343,7 @@ public:
|
|||
|
||||
// Item API
|
||||
Gfx::RenderEntry *getRenderEntry(const Common::Point &positionOffset) override;
|
||||
int indexForPoint(Common::Point point) override;
|
||||
|
||||
protected:
|
||||
void printData() override;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "engines/stark/resources/knowledgeset.h"
|
||||
|
||||
#include "engines/stark/formats/xrc.h"
|
||||
#include "engines/stark/resources/item.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Resources {
|
||||
|
@ -38,5 +39,22 @@ KnowledgeSet::KnowledgeSet(Object *parent, byte subType, uint16 index, const Com
|
|||
void KnowledgeSet::printData() {
|
||||
}
|
||||
|
||||
Gfx::RenderEntryArray KnowledgeSet::getInventoryRenderEntries() {
|
||||
// TODO: Keep and persist inventory items order
|
||||
Common::Array<Resources::Item *> inventoryItems = listChildren<Resources::Item>(Resources::Item::kItemSub2);
|
||||
Common::Array<Resources::Item *>::iterator it = inventoryItems.begin();
|
||||
Gfx::RenderEntryArray result;
|
||||
|
||||
int i = 0;
|
||||
for (; it != inventoryItems.end(); ++it, ++i) {
|
||||
if (i < 4) continue; // HACK: The first 4 elements are UI elements, so skip them for now.
|
||||
if ((*it)->isEnabled()) {
|
||||
result.push_back((*it)->getRenderEntry(Common::Point(0, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // End of namespace Resources
|
||||
} // End of namespace Stark
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "common/str.h"
|
||||
|
||||
#include "engines/stark/gfx/renderentry.h"
|
||||
#include "engines/stark/resources/object.h"
|
||||
|
||||
namespace Stark {
|
||||
|
@ -35,6 +36,8 @@ class XRCReadStream;
|
|||
|
||||
namespace Resources {
|
||||
|
||||
class Item;
|
||||
|
||||
/**
|
||||
* A typed collection of Knowledge resources
|
||||
*/
|
||||
|
@ -53,6 +56,8 @@ public:
|
|||
KnowledgeSet(Object *parent, byte subType, uint16 index, const Common::String &name);
|
||||
virtual ~KnowledgeSet();
|
||||
|
||||
Gfx::RenderEntryArray getInventoryRenderEntries();
|
||||
|
||||
protected:
|
||||
void printData() override;
|
||||
};
|
||||
|
|
|
@ -59,18 +59,21 @@ void PATTable::printData() {
|
|||
debug("field_2C: %d", _field_2C);
|
||||
}
|
||||
|
||||
int PATTable::getNumActions() const {
|
||||
int count = 0;
|
||||
for (int i = 0; i < _entries.size(); i++) {
|
||||
ActionArray PATTable::listPossibleActions() const {
|
||||
ActionArray actions;
|
||||
|
||||
for (uint i = 0; i < _entries.size(); i++) {
|
||||
if (_entries[i]._scriptIndex != -1) {
|
||||
count++;
|
||||
// TODO: More rules
|
||||
actions.push_back(_entries[i]._actionType);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool PATTable::canPerformAction(ActionType action) const {
|
||||
for (int i = 0; i < _entries.size(); i++) {
|
||||
return actions;
|
||||
}
|
||||
|
||||
bool PATTable::canPerformAction(uint32 action) const {
|
||||
for (uint i = 0; i < _entries.size(); i++) {
|
||||
if (_entries[i]._actionType == action && _entries[i]._scriptIndex != -1) {
|
||||
return true;
|
||||
}
|
||||
|
@ -78,22 +81,14 @@ bool PATTable::canPerformAction(ActionType action) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
Script *PATTable::getScriptForAction(int action) {
|
||||
switch (action) {
|
||||
case kActionUse:
|
||||
case kActionLook:
|
||||
case kActionTalk:
|
||||
case kActionExit:
|
||||
break;
|
||||
default:
|
||||
break; // Not one of the 4 basic ones.
|
||||
}
|
||||
for (int i = 0; i < _entries.size(); i++) {
|
||||
bool PATTable::runScriptForAction(uint32 action) {
|
||||
for (uint i = 0; i < _entries.size(); i++) {
|
||||
if (_entries[i]._actionType == action) {
|
||||
Script *script = findChildWithIndex<Script>(_entries[i]._scriptIndex);
|
||||
return script;
|
||||
script->execute(Resources::Script::kCallModePlayerAction);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace Resources {
|
|||
|
||||
class Script;
|
||||
|
||||
typedef Common::Array<uint32> ActionArray;
|
||||
|
||||
class PATTable : public Object {
|
||||
public:
|
||||
static const Type::ResourceType TYPE = Type::kPATTable;
|
||||
|
@ -51,16 +53,17 @@ public:
|
|||
PATTable(Object *parent, byte subType, uint16 index, const Common::String &name);
|
||||
virtual ~PATTable();
|
||||
|
||||
Script *getScriptForAction(int action);
|
||||
ActionArray listPossibleActions() const;
|
||||
|
||||
int getNumActions() const;
|
||||
bool canPerformAction(ActionType action) const;
|
||||
bool runScriptForAction(uint32 action);
|
||||
|
||||
bool canPerformAction(uint32 action) const;
|
||||
// Resource API
|
||||
void readData(Formats::XRCReadStream *stream) override;
|
||||
|
||||
protected:
|
||||
struct Entry {
|
||||
int32 _actionType;
|
||||
uint32 _actionType;
|
||||
int32 _scriptIndex;
|
||||
};
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@ FMVPlayer::~FMVPlayer() {
|
|||
void FMVPlayer::play(const Common::String &name) {
|
||||
// TODO: Clear existing
|
||||
ArchiveLoader *archiveLoader = StarkServices::instance().archiveLoader;
|
||||
Gfx::Driver *gfx = StarkServices::instance().gfx;
|
||||
|
||||
Common::SeekableReadStream *stream = archiveLoader->getExternalFile(name, "Global/");
|
||||
if (!stream) {
|
||||
|
|
|
@ -36,7 +36,8 @@ Global::Global() :
|
|||
_level(nullptr),
|
||||
_current(nullptr),
|
||||
_debug(false),
|
||||
_fastForward(false) {
|
||||
_fastForward(false),
|
||||
_inventory(nullptr) {
|
||||
}
|
||||
|
||||
int32 Global::getCurrentChapter() {
|
||||
|
@ -52,8 +53,7 @@ void Global::setCurrentChapter(int32 value) {
|
|||
}
|
||||
|
||||
void Global::printInventory(bool printAll) {
|
||||
Resources::KnowledgeSet *inventory = _level->findChildWithSubtype<Resources::KnowledgeSet>(Resources::KnowledgeSet::kInventory);
|
||||
Common::Array<Resources::Item*> inventoryItems = inventory->listChildren<Resources::Item>(Resources::Item::kItemSub2);
|
||||
Common::Array<Resources::Item*> inventoryItems = _inventory->listChildren<Resources::Item>(Resources::Item::kItemSub2);
|
||||
Common::Array<Resources::Item*>::iterator it = inventoryItems.begin();
|
||||
for (int i = 0; it != inventoryItems.end(); ++it, i++) {
|
||||
if (printAll || (*it)->isEnabled()) {
|
||||
|
@ -63,25 +63,8 @@ void Global::printInventory(bool printAll) {
|
|||
}
|
||||
|
||||
void Global::enableInventoryItem(int32 num) {
|
||||
Resources::KnowledgeSet *inventory = _level->findChildWithSubtype<Resources::KnowledgeSet>(Resources::KnowledgeSet::kInventory);
|
||||
Common::Array<Resources::Item*> inventoryItems = inventory->listChildren<Resources::Item>(Resources::Item::kItemSub2);
|
||||
Common::Array<Resources::Item*> inventoryItems = _inventory->listChildren<Resources::Item>(Resources::Item::kItemSub2);
|
||||
inventoryItems[num]->setEnabled(true);
|
||||
}
|
||||
|
||||
Common::Array<Resources::Item*> Global::getInventoryContents() {
|
||||
Resources::KnowledgeSet *inventory = _level->findChildWithSubtype<Resources::KnowledgeSet>(Resources::KnowledgeSet::kInventory);
|
||||
Common::Array<Resources::Item*> inventoryItems = inventory->listChildren<Resources::Item>(Resources::Item::kItemSub2);
|
||||
Common::Array<Resources::Item*>::iterator it = inventoryItems.begin();
|
||||
Common::Array<Resources::Item*> result;
|
||||
|
||||
int i = 0;
|
||||
for (; it != inventoryItems.end(); ++it, ++i) {
|
||||
if (i < 4) continue; // HACK: The first 4 elements are UI elements, so skip them for now.
|
||||
if ((*it)->isEnabled()) {
|
||||
result.push_back(*it);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // End of namespace Stark
|
||||
|
|
|
@ -34,6 +34,7 @@ class Floor;
|
|||
class Item; // TODO: Should be ItemSub2
|
||||
class ItemSub1;
|
||||
class ItemSub10;
|
||||
class KnowledgeSet;
|
||||
class Level;
|
||||
class Location;
|
||||
class Root;
|
||||
|
@ -86,6 +87,7 @@ public:
|
|||
bool isFastForward() const { return _fastForward; }
|
||||
uint getMillisecondsPerGameloop() const { return _millisecondsPerGameloop; }
|
||||
Resources::ItemSub1 *getApril() const { return _april; }
|
||||
Resources::KnowledgeSet *getInventory() const { return _inventory; }
|
||||
|
||||
void setRoot(Resources::Root *root) { _root = root; }
|
||||
void setLevel(Resources::Level *level) { _level = level; }
|
||||
|
@ -94,13 +96,13 @@ public:
|
|||
void setFastForward(bool fastForward) { _fastForward = fastForward; }
|
||||
void setMillisecondsPerGameloop(uint millisecondsPerGameloop) { _millisecondsPerGameloop = millisecondsPerGameloop; }
|
||||
void setApril(Resources::ItemSub1 *april) { _april = april; }
|
||||
void setInventory(Resources::KnowledgeSet * inventory) { _inventory = inventory; }
|
||||
|
||||
/** Retrieve the current chapter number from the global resource tree */
|
||||
int32 getCurrentChapter();
|
||||
|
||||
/** Temporary HACK to allow us to query the inventory */
|
||||
void printInventory(bool printAll);
|
||||
Common::Array<Resources::Item*> getInventoryContents(); // TODO: Create a class for the inventory instead
|
||||
void enableInventoryItem(int32 num);
|
||||
|
||||
/** Change the current chapter */
|
||||
|
@ -109,7 +111,7 @@ private:
|
|||
uint _millisecondsPerGameloop;
|
||||
Resources::Root *_root;
|
||||
Resources::Level *_level;
|
||||
/* Inventory *_inventory; */
|
||||
Resources::KnowledgeSet *_inventory;
|
||||
Resources::ItemSub1 *_april;
|
||||
Current *_current;
|
||||
bool _debug;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "engines/stark/resources/camera.h"
|
||||
#include "engines/stark/resources/floor.h"
|
||||
#include "engines/stark/resources/item.h"
|
||||
#include "engines/stark/resources/knowledgeset.h"
|
||||
#include "engines/stark/resources/layer.h"
|
||||
#include "engines/stark/resources/level.h"
|
||||
#include "engines/stark/resources/location.h"
|
||||
|
@ -72,7 +73,7 @@ void ResourceProvider::initGlobal() {
|
|||
// Resources lifecycle update
|
||||
global->onAllLoaded();
|
||||
|
||||
//TODO: Retrieve the inventory from the global tree
|
||||
_global->setInventory(global->findChildWithSubtype<Resources::KnowledgeSet>(Resources::KnowledgeSet::kInventory));
|
||||
_global->setApril(global->findChildWithSubtype<Resources::ItemSub1>(Resources::Item::kItemSub1));
|
||||
}
|
||||
|
||||
|
@ -336,6 +337,8 @@ void ResourceProvider::shutdown() {
|
|||
_global->setLevel(nullptr);
|
||||
_global->setRoot(nullptr);
|
||||
_global->setCurrent(nullptr);
|
||||
_global->setInventory(nullptr);
|
||||
_global->setApril(nullptr);
|
||||
|
||||
_archiveLoader->unloadUnused();
|
||||
}
|
||||
|
|
|
@ -25,11 +25,10 @@
|
|||
#include "engines/stark/gfx/driver.h"
|
||||
#include "engines/stark/gfx/texture.h"
|
||||
|
||||
#include "engines/stark/resources/knowledgeset.h"
|
||||
#include "engines/stark/resources/level.h"
|
||||
#include "engines/stark/resources/location.h"
|
||||
#include "engines/stark/resources/speech.h"
|
||||
#include "engines/stark/services/global.h"
|
||||
#include "engines/stark/services/services.h"
|
||||
|
||||
#include "engines/stark/resources/floor.h"
|
||||
#include "engines/stark/resources/object.h"
|
||||
|
@ -37,26 +36,23 @@
|
|||
#include "engines/stark/resources/script.h"
|
||||
#include "engines/stark/resources/item.h"
|
||||
|
||||
#include "engines/stark/actionmenu.h"
|
||||
#include "engines/stark/services/global.h"
|
||||
#include "engines/stark/services/services.h"
|
||||
|
||||
#include "engines/stark/visual/image.h"
|
||||
|
||||
#include "engines/stark/cursor.h"
|
||||
#include "engines/stark/scene.h"
|
||||
#include "engines/stark/ui.h"
|
||||
|
||||
namespace Stark {
|
||||
|
||||
UserInterface::UserInterface(Gfx::Driver *driver, const Cursor *cursor) {
|
||||
_gfx = driver;
|
||||
_cursor = cursor;
|
||||
_actionMenuActive = false;
|
||||
UserInterface::UserInterface() {
|
||||
}
|
||||
|
||||
UserInterface::~UserInterface() {
|
||||
}
|
||||
|
||||
void UserInterface::init() {
|
||||
_actionMenu = new ActionMenu(_gfx);
|
||||
}
|
||||
|
||||
void UserInterface::skipCurrentSpeeches() {
|
||||
Global *global = StarkServices::instance().global;
|
||||
Current *current = global->getCurrent();
|
||||
|
@ -113,233 +109,79 @@ void UserInterface::walkTo(const Common::Point &mouse) {
|
|||
}
|
||||
}
|
||||
|
||||
void UserInterface::update() {
|
||||
VisualImageXMG *UserInterface::getActionImage(uint32 itemIndex, bool active) {
|
||||
// Lookup the action's item in the inventory
|
||||
Global *global = StarkServices::instance().global;
|
||||
Resources::KnowledgeSet *inventory = global->getLevel()->findChildWithSubtype<Resources::KnowledgeSet>(Resources::KnowledgeSet::kInventory, true);
|
||||
|
||||
// Get the visual for the action
|
||||
Resources::ItemSub2 *action = inventory->findChildWithIndex<Resources::ItemSub2>(itemIndex);
|
||||
Visual *visual = action->getActionVisual(active);
|
||||
|
||||
return visual->get<VisualImageXMG>();
|
||||
}
|
||||
|
||||
void UserInterface::activateActionMenuOn(Common::Point pos, Resources::Object *activeObject) {
|
||||
_actionMenuActive = true;
|
||||
_actionMenuPos = pos;
|
||||
_actionMenu->clearActions();
|
||||
int possible = getActionsPossibleForObject(activeObject);
|
||||
if (possible & kActionLookPossible) {
|
||||
_actionMenu->enableAction(ActionMenu::kActionEye);
|
||||
bool UserInterface::itemDoActionAt(Resources::Item *item, uint32 action, const Common::Point &position) {
|
||||
int32 hotspotIndex = item->indexForPoint(position);
|
||||
return item->doAction(action, hotspotIndex);
|
||||
}
|
||||
if (possible & kActionUsePossible) {
|
||||
_actionMenu->enableAction(ActionMenu::kActionHand);
|
||||
}
|
||||
if (possible & kActionTalkPossible) {
|
||||
_actionMenu->enableAction(ActionMenu::kActionMouth);
|
||||
|
||||
Resources::Item *UserInterface::getItemAtPosition(Common::Point pos, Gfx::RenderEntryArray entries) {
|
||||
// Render entries are sorted from the farthest to the camera to the nearest
|
||||
// Loop in reverse order
|
||||
for (int i = entries.size() - 1; i >= 0; i--) {
|
||||
Resources::Item *item = entries[i]->getOwner();
|
||||
|
||||
if (item->isClickable() && item->containsPoint(pos)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::RenderEntry *UserInterface::getEntryAtPosition(Common::Point pos, Gfx::RenderEntryArray entries) {
|
||||
Gfx::RenderEntryArray::iterator element = entries.begin();
|
||||
Gfx::RenderEntry *objectAtPos = nullptr;
|
||||
// We need this scaled. (Optionally, if we want to scale the cursor, we can move the scaling to the setMousePosition-function)
|
||||
while (element != entries.end()) {
|
||||
if ((*element)->containsPoint(pos)) {
|
||||
if (!objectAtPos) {
|
||||
objectAtPos = *element;
|
||||
// This assumes that lower sort keys are more important than higher sortkeys.
|
||||
} else if (Gfx::RenderEntry::compare(*element, objectAtPos)) {
|
||||
objectAtPos = *element;
|
||||
}
|
||||
}
|
||||
++element;
|
||||
}
|
||||
return objectAtPos;
|
||||
}
|
||||
|
||||
// To be specific, this returns the PATTable, so that the distinction on index is resolved,
|
||||
// any code that needs the item will thus have to traverse back up.
|
||||
Resources::Object *UserInterface::getObjectForRenderEntryAtPosition(Common::Point pos, Gfx::RenderEntry *entry) {
|
||||
if (entry == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
Resources::Object *owner = (Resources::Object*)entry->getOwner();
|
||||
if (owner->getType() != Resources::Type::kItem) {
|
||||
// HACK: We don't have ItemSub2 yet.
|
||||
if (owner->getType() != Resources::Type::kAnim) {
|
||||
error("Owner of render entry should be an item, was: %s", owner->getType().getName());
|
||||
} else if (owner->getType() == Resources::Type::kAnim) {
|
||||
// HACK
|
||||
owner = owner->findParent<Resources::Item>();
|
||||
}
|
||||
}
|
||||
int index = entry->indexForPoint(pos);
|
||||
// No table index
|
||||
if (index == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
Resources::PATTable *table = owner->findChildWithIndex<Resources::PATTable>(index);
|
||||
if (table) {
|
||||
return table;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Common::String UserInterface::getMouseHintForObject(Resources::Object *object) {
|
||||
if (object) {
|
||||
Resources::Item *item = object->findParent<Resources::Item>();
|
||||
Common::String UserInterface::getMouseHintForItem(Resources::Item *item) {
|
||||
if (item) {
|
||||
if (item->listChildrenRecursive<Resources::PATTable>().size() > 1) {
|
||||
// Use the PAT Table name if more than one defined in item.
|
||||
return object->getName();
|
||||
} else {
|
||||
//TODO: Items with multiple hotspots
|
||||
return item->getName();
|
||||
}
|
||||
} else {
|
||||
return object->getName();
|
||||
}
|
||||
} else {
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
Resources::ActionArray UserInterface::getActionsPossibleForObject(Resources::Item *item, const Common::Point &pos) {
|
||||
if (item == nullptr) {
|
||||
return Resources::ActionArray();
|
||||
}
|
||||
|
||||
int UserInterface::getActionsPossibleForObject(Resources::Object *object) {
|
||||
if (object == nullptr) {
|
||||
return kActionNonePossible;
|
||||
}
|
||||
if (object->getType() != Resources::Type::kPATTable) {
|
||||
error("getActionsPossibleForObject requires a PATTable");
|
||||
}
|
||||
Resources::PATTable *table = (Resources::PATTable*)object;
|
||||
int possible = UserInterface::kActionNonePossible;
|
||||
if (table->canPerformAction(Resources::PATTable::kActionLook)) {
|
||||
possible |= kActionLookPossible;
|
||||
}
|
||||
if (table->canPerformAction(Resources::PATTable::kActionUse) || isInventoryObject(object)) {
|
||||
possible |= kActionUsePossible;
|
||||
}
|
||||
if (table->canPerformAction(Resources::PATTable::kActionTalk)) {
|
||||
possible |= kActionTalkPossible;
|
||||
}
|
||||
if (table->canPerformAction(Resources::PATTable::kActionExit)) {
|
||||
possible |= kActionExitPossible;
|
||||
}
|
||||
return possible;
|
||||
int index = item->indexForPoint(pos);
|
||||
if (index < 0) {
|
||||
error("Position is outside of item '%s'", item->getName().c_str());
|
||||
}
|
||||
|
||||
bool UserInterface::isInventoryObject(Resources::Object *object) {
|
||||
if (object->getType() != Resources::Type::kPATTable) {
|
||||
error("isInventoryObject requires a PATTable");
|
||||
Resources::PATTable *table = item->findChildWithIndex<Resources::PATTable>(index);
|
||||
return table->listPossibleActions();
|
||||
}
|
||||
Resources::PATTable *table = (Resources::PATTable*)object;
|
||||
Resources::ItemSub2 *inventoryParent = table->findParent<Resources::ItemSub2>();
|
||||
if (_actionMenu->isThisYourButton(object) != -1 || inventoryParent->getSubType() != Resources::Item::kItemSub2) {
|
||||
|
||||
Resources::ActionArray UserInterface::getStockActionsPossibleForObject(Resources::Item *item, const Common::Point &pos) {
|
||||
Resources::ActionArray actions = getActionsPossibleForObject(item, pos);
|
||||
|
||||
Resources::ActionArray stockActions;
|
||||
for (uint i = 0; i < actions.size(); i++) {
|
||||
if (actions[i] < 4) {
|
||||
stockActions.push_back(actions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return stockActions;
|
||||
}
|
||||
|
||||
bool UserInterface::isInventoryObject(Resources::Item *item) {
|
||||
if (item->getIndex() < 4 || item->getSubType() != Resources::Item::kItemSub2) {
|
||||
// Do not explicitly add use on action-menu buttons.
|
||||
inventoryParent = nullptr;
|
||||
item = nullptr;
|
||||
}
|
||||
return inventoryParent != nullptr;
|
||||
}
|
||||
|
||||
bool UserInterface::performActionOnObject(Resources::Object *object, Resources::Object *activeObject, int action) {
|
||||
if (object->getType() != Resources::Type::kPATTable) {
|
||||
error("performActionOnObject requires a PATTable");
|
||||
}
|
||||
// PATTable of object under cursor
|
||||
Resources::PATTable *table = (Resources::PATTable*)object;
|
||||
// Possibilites:
|
||||
// * Click on something that doesn't take an action
|
||||
// * Click on something that takes exactly 1 action.
|
||||
// * Click on something that takes more than 1 action (open action menu)
|
||||
// * Click in the action menu, which has 0 available actions (TODO)
|
||||
if (action != -1) {
|
||||
Resources::Script *script = table->getScriptForAction(action);
|
||||
if (script != nullptr) {
|
||||
script->execute(Resources::Script::kCallModePlayerAction);
|
||||
return true;
|
||||
} else {
|
||||
warning("Could not perform action %d on %s", action, table->getName().c_str());
|
||||
}
|
||||
}
|
||||
// Assume all inventory objects need action menu.
|
||||
if (isInventoryObject(object)) {
|
||||
return false;
|
||||
}
|
||||
if (table->getNumActions() == 0) {
|
||||
|
||||
if (activeObject) {
|
||||
// HACK: presumably this can be resolved by adding SubItem2, and hooking up the item to the actionMenu directly.
|
||||
int menuResult = _actionMenu->isThisYourButton(object);
|
||||
Resources::Script *script = nullptr;
|
||||
if (menuResult != -1 && activeObject->getType() == Resources::Type::kPATTable) {
|
||||
Resources::PATTable *activeObjectTable = (Resources::PATTable *)activeObject;
|
||||
if (menuResult == ActionMenu::kActionHand) {
|
||||
if (isInventoryObject(activeObjectTable)) {
|
||||
StarkServices::instance().ui->notifySelectedInventoryItem(activeObject);
|
||||
return true;
|
||||
}
|
||||
script = activeObjectTable->getScriptForAction(Resources::PATTable::kActionUse);
|
||||
} else if (menuResult == ActionMenu::kActionEye) {
|
||||
script = activeObjectTable->getScriptForAction(Resources::PATTable::kActionLook);
|
||||
} else if (menuResult == ActionMenu::kActionMouth) {
|
||||
script = activeObjectTable->getScriptForAction(Resources::PATTable::kActionTalk);
|
||||
}
|
||||
if (script != nullptr) {
|
||||
script->execute(Resources::Script::kCallModePlayerAction);
|
||||
return true;
|
||||
} else {
|
||||
warning("No script, did the action menu buttons misalign again?");
|
||||
// Return true here too to clear the event as handled, even though we had a wrong PAT.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (table->getNumActions() == 1) {
|
||||
if (table->canPerformAction(Resources::PATTable::kActionLook)) {
|
||||
table->getScriptForAction(Resources::PATTable::kActionLook)->execute(Resources::Script::kCallModePlayerAction);
|
||||
}
|
||||
if (table->canPerformAction(Resources::PATTable::kActionUse)) {
|
||||
table->getScriptForAction(Resources::PATTable::kActionUse)->execute(Resources::Script::kCallModePlayerAction);
|
||||
}
|
||||
if (table->canPerformAction(Resources::PATTable::kActionTalk)) {
|
||||
table->getScriptForAction(Resources::PATTable::kActionTalk)->execute(Resources::Script::kCallModePlayerAction);
|
||||
}
|
||||
if (table->canPerformAction(Resources::PATTable::kActionExit)) {
|
||||
table->getScriptForAction(Resources::PATTable::kActionExit)->execute(Resources::Script::kCallModePlayerAction);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
// This is where we should trigger the Action Menu
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Gfx::RenderEntryArray UserInterface::getRenderEntries() {
|
||||
if (_actionMenuActive) {
|
||||
return _actionMenu->getRenderEntries();
|
||||
} else {
|
||||
return Gfx::RenderEntryArray();
|
||||
}
|
||||
}
|
||||
|
||||
void UserInterface::render() {
|
||||
// TODO: Move this elsewhere
|
||||
|
||||
Common::String debugStr;
|
||||
|
||||
Global *global = StarkServices::instance().global;
|
||||
Current *current = global->getCurrent();
|
||||
|
||||
int32 chapter = global->getCurrentChapter();
|
||||
|
||||
debugStr += Common::String::format("location: %02x %02x ", current->getLevel()->getIndex(), current->getLocation()->getIndex());
|
||||
debugStr += current->getLevel()->getName() + ", " + current->getLocation()->getName();
|
||||
debugStr += Common::String::format(" chapter: %d", chapter);
|
||||
|
||||
|
||||
Gfx::Texture *debugTexture = _gfx->createTextureFromString(debugStr, 0xF0FF0F00);
|
||||
|
||||
_gfx->setScreenViewport(false);
|
||||
_gfx->drawSurface(debugTexture, Common::Point(0,0));
|
||||
|
||||
if (_actionMenuActive) {
|
||||
_actionMenu->render(_actionMenuPos);
|
||||
}
|
||||
|
||||
delete debugTexture;
|
||||
return item != nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Stark
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include "engines/stark/gfx/renderentry.h"
|
||||
|
||||
#include "engines/stark/resources/pattable.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
|
@ -32,6 +34,7 @@ namespace Stark {
|
|||
|
||||
class ActionMenu;
|
||||
class Cursor;
|
||||
class VisualImageXMG;
|
||||
|
||||
namespace Resources {
|
||||
class Item;
|
||||
|
@ -49,11 +52,9 @@ class RenderEntry;
|
|||
*/
|
||||
class UserInterface {
|
||||
public:
|
||||
UserInterface(Gfx::Driver *driver, const Cursor *cursor);
|
||||
UserInterface();
|
||||
~UserInterface();
|
||||
|
||||
void init();
|
||||
|
||||
/** Skip currently playing speeches */
|
||||
void skipCurrentSpeeches();
|
||||
|
||||
|
@ -63,44 +64,18 @@ public:
|
|||
/** Make April try to go to the location under the cursor */
|
||||
void walkTo(const Common::Point &mouse);
|
||||
|
||||
/** Draw the mouse pointer, and any additional currently active UI */
|
||||
void render();
|
||||
VisualImageXMG *getActionImage(uint32 itemIndex, bool active);
|
||||
|
||||
/** Update the current state of the user interface */
|
||||
void update();
|
||||
bool itemDoActionAt(Resources::Item *item, uint32 action, const Common::Point &position);
|
||||
|
||||
Gfx::RenderEntry *getEntryAtPosition(Common::Point, Gfx::RenderEntryArray entries);
|
||||
Resources::Item *getItemAtPosition(Common::Point, Gfx::RenderEntryArray entries);
|
||||
|
||||
Resources::Object *getObjectForRenderEntryAtPosition(Common::Point pos, Gfx::RenderEntry *entry);
|
||||
Common::String getMouseHintForItem(Resources::Item *object);
|
||||
|
||||
Common::String getMouseHintForObject(Resources::Object *object);
|
||||
Resources::ActionArray getActionsPossibleForObject(Resources::Item *item, const Common::Point &pos);
|
||||
Resources::ActionArray getStockActionsPossibleForObject(Resources::Item *item, const Common::Point &pos);
|
||||
|
||||
enum ActionFlags {
|
||||
kActionNonePossible = 0,
|
||||
kActionUsePossible = 1,
|
||||
kActionLookPossible = 2,
|
||||
kActionTalkPossible = 4,
|
||||
kActionExitPossible = 8
|
||||
};
|
||||
|
||||
int getActionsPossibleForObject(Resources::Object *object);
|
||||
/** Attempt to run the relevant action on the object, returns true if action menu is needed, false if no action is possible */
|
||||
bool performActionOnObject(Resources::Object *object, Resources::Object *activeObject, int action = -1);
|
||||
void activateActionMenuOn(Common::Point pos, Resources::Object *activeObject);
|
||||
bool isActionMenuOpen() const { return _actionMenuActive; }
|
||||
void deactivateActionMenu() { _actionMenuActive = false; }
|
||||
bool isInventoryObject(Resources::Object *object);
|
||||
|
||||
Gfx::RenderEntryArray getRenderEntries();
|
||||
private:
|
||||
|
||||
int _indexForCurrentObject;
|
||||
Resources::Object *_object;
|
||||
bool _actionMenuActive;
|
||||
Common::Point _actionMenuPos;
|
||||
const Cursor *_cursor;
|
||||
ActionMenu *_actionMenu;
|
||||
Gfx::Driver *_gfx;
|
||||
bool isInventoryObject(Resources::Item *item);
|
||||
};
|
||||
|
||||
} // End of namespace Stark
|
||||
|
|
|
@ -110,7 +110,7 @@ Common::Error StarkEngine::run() {
|
|||
_scene = new Scene(_gfx);
|
||||
_dialogPlayer = new DialogPlayer();
|
||||
_cursor = new Cursor(_gfx);
|
||||
_userInterface = new UserInterface(_gfx, _cursor);
|
||||
_userInterface = new UserInterface();
|
||||
_ui = new UI(_gfx, _cursor);
|
||||
|
||||
// Setup the public services
|
||||
|
@ -131,7 +131,6 @@ Common::Error StarkEngine::run() {
|
|||
_staticProvider->init();
|
||||
_cursor->init();
|
||||
_dialogPlayer->init();
|
||||
_userInterface->init();
|
||||
// Initialize the UI
|
||||
_ui->init();
|
||||
|
||||
|
@ -199,7 +198,6 @@ void StarkEngine::mainLoop() {
|
|||
_resourceProvider->performLocationChange();
|
||||
}
|
||||
|
||||
_userInterface->update();
|
||||
updateDisplayScene();
|
||||
g_system->delayMillis(50);
|
||||
|
||||
|
|
|
@ -25,8 +25,10 @@
|
|||
|
||||
#include "engines/stark/ui.h"
|
||||
|
||||
#include "engines/stark/actionmenu.h"
|
||||
#include "engines/stark/cursor.h"
|
||||
|
||||
#include "engines/stark/gfx/driver.h"
|
||||
#include "engines/stark/gfx/renderentry.h"
|
||||
|
||||
#include "engines/stark/resources/object.h"
|
||||
|
@ -45,20 +47,20 @@ namespace Stark {
|
|||
UI::UI(Gfx::Driver *gfx, Cursor *cursor) :
|
||||
_gfx(gfx),
|
||||
_cursor(cursor),
|
||||
_currentObject(nullptr),
|
||||
_objectUnderCursor(nullptr),
|
||||
_hasClicked(false),
|
||||
_inventoryOpen(false),
|
||||
_topMenu(nullptr),
|
||||
_dialogInterface(nullptr),
|
||||
_inventoryInterface(nullptr),
|
||||
_selectedInventoryItem(-1),
|
||||
_exitGame(false),
|
||||
_fmvPlayer(nullptr)
|
||||
_fmvPlayer(nullptr),
|
||||
_actionMenu(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
UI::~UI() {
|
||||
delete _actionMenu;
|
||||
delete _topMenu;
|
||||
delete _dialogInterface;
|
||||
delete _inventoryInterface;
|
||||
|
@ -68,15 +70,21 @@ UI::~UI() {
|
|||
void UI::init() {
|
||||
_topMenu = new TopMenu();
|
||||
_dialogInterface = new DialogInterface();
|
||||
_inventoryInterface = new InventoryInterface();
|
||||
_inventoryInterface = new InventoryInterface(_gfx, _cursor);
|
||||
_fmvPlayer = new FMVPlayer();
|
||||
_actionMenu = new ActionMenu(_gfx, _cursor);
|
||||
}
|
||||
|
||||
void UI::update(Gfx::RenderEntryArray renderEntries, bool keepExisting) {
|
||||
void UI::update(Gfx::RenderEntryArray renderEntries) {
|
||||
Common::Point pos = _cursor->getMousePosition();
|
||||
|
||||
if (_actionMenu->isVisible() && _actionMenu->isMouseInside()) {
|
||||
_actionMenu->handleMouseMove();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for inventory to avoid mouse-overs from the world poking through.
|
||||
if (_inventoryOpen && _inventoryInterface->containsPoint(pos) && keepExisting == false) {
|
||||
if (_inventoryInterface->isVisible() && _inventoryInterface->isMouseInside()) {
|
||||
renderEntries = _inventoryInterface->getRenderEntries();
|
||||
}
|
||||
|
||||
|
@ -92,21 +100,17 @@ void UI::update(Gfx::RenderEntryArray renderEntries, bool keepExisting) {
|
|||
return;
|
||||
}
|
||||
|
||||
pos -= Common::Point(0, Gfx::Driver::kTopBorderHeight);
|
||||
|
||||
// Check for game world mouse overs
|
||||
UserInterface *ui = StarkServices::instance().userInterface;
|
||||
Gfx::RenderEntry *currentEntry = ui->getEntryAtPosition(pos, renderEntries);
|
||||
Resources::Object *object = ui->getObjectForRenderEntryAtPosition(pos, currentEntry);
|
||||
// So that we can run update multiple times, without resetting (i.e. after drawing the action menu)
|
||||
if (!object && keepExisting) {
|
||||
return;
|
||||
} else {
|
||||
// Subsequent runs ignore sort order of items drawn earlier.
|
||||
_objectUnderCursor = object;
|
||||
}
|
||||
Common::String mouseHint = ui->getMouseHintForObject(_objectUnderCursor);
|
||||
|
||||
_objectUnderCursor = ui->getItemAtPosition(pos, renderEntries);
|
||||
|
||||
Common::String mouseHint = ui->getMouseHintForItem(_objectUnderCursor);
|
||||
|
||||
if (_objectUnderCursor) {
|
||||
int actionsPossible = ui->getActionsPossibleForObject(_objectUnderCursor);
|
||||
Resources::ActionArray actionsPossible = ui->getActionsPossibleForObject(_objectUnderCursor, pos);
|
||||
setCursorDependingOnActionsAvailable(actionsPossible);
|
||||
} else {
|
||||
// Not an object
|
||||
|
@ -115,60 +119,99 @@ void UI::update(Gfx::RenderEntryArray renderEntries, bool keepExisting) {
|
|||
_cursor->setMouseHint(_selectedInventoryItemText + mouseHint);
|
||||
}
|
||||
|
||||
void UI::setCursorDependingOnActionsAvailable(int actionsAvailable) {
|
||||
bool moreThanOneActionPossible = false;
|
||||
switch (actionsAvailable) {
|
||||
case UserInterface::kActionLookPossible:
|
||||
_cursor->setCursorType(Cursor::kEye);
|
||||
break;
|
||||
case UserInterface::kActionTalkPossible:
|
||||
_cursor->setCursorType(Cursor::kMouth);
|
||||
break;
|
||||
case UserInterface::kActionUsePossible:
|
||||
_cursor->setCursorType(Cursor::kHand);
|
||||
break;
|
||||
case UserInterface::kActionExitPossible:
|
||||
_cursor->setCursorType(Cursor::kDefault); // TODO
|
||||
break;
|
||||
default:
|
||||
if (actionsAvailable != 0) {
|
||||
void UI::setCursorDependingOnActionsAvailable(Resources::ActionArray actionsAvailable) {
|
||||
if (actionsAvailable.empty()) {
|
||||
_cursor->setCursorType(Cursor::kPassive);
|
||||
moreThanOneActionPossible = true;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 count = 0;
|
||||
Cursor::CursorType cursorType;
|
||||
for (uint i = 0; i < actionsAvailable.size(); i++) {
|
||||
switch (actionsAvailable[i]) {
|
||||
case Resources::PATTable::kActionLook:
|
||||
cursorType = Cursor::kEye;
|
||||
count++;
|
||||
break;
|
||||
case Resources::PATTable::kActionTalk:
|
||||
cursorType = Cursor::kMouth;
|
||||
count++;
|
||||
break;
|
||||
case Resources::PATTable::kActionUse:
|
||||
cursorType = Cursor::kHand;
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
if (moreThanOneActionPossible) {
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
_cursor->setCursorType(cursorType);
|
||||
} else {
|
||||
_cursor->setCursorType(Cursor::kActive);
|
||||
}
|
||||
}
|
||||
|
||||
void UI::handleClick() {
|
||||
UserInterface *ui = StarkServices::instance().userInterface;
|
||||
if (_objectUnderCursor) {
|
||||
if (!ui->performActionOnObject(_objectUnderCursor, _currentObject, _selectedInventoryItem)) {
|
||||
_currentObject = _objectUnderCursor;
|
||||
ui->activateActionMenuOn(_cursor->getMousePosition(), _currentObject);
|
||||
// This currently potentially allows for click-through
|
||||
|
||||
if (_actionMenu->isVisible()) {
|
||||
if (_actionMenu->isMouseInside()) {
|
||||
_actionMenu->handleClick();
|
||||
} else {
|
||||
if (ui->isActionMenuOpen()) {
|
||||
// If the click resulted in a multi-action possibility, then it was outside the action menu.
|
||||
ui->deactivateActionMenu();
|
||||
_currentObject = nullptr;
|
||||
// If we were in the action menu, then retain the selected item.
|
||||
} else if (_selectedInventoryItem != -1) {
|
||||
_inventoryInterface->update();
|
||||
_selectedInventoryItem = -1;
|
||||
_selectedInventoryItemText = "";
|
||||
_actionMenu->close();
|
||||
}
|
||||
} else if (_objectUnderCursor) {
|
||||
Common::Point pos = _cursor->getMousePosition();
|
||||
pos -= Common::Point(0, Gfx::Driver::kTopBorderHeight);
|
||||
|
||||
// Possibilites:
|
||||
// * Click on something that doesn't take an action
|
||||
// * Click on something that takes exactly 1 action.
|
||||
// * Click on something that takes more than 1 action (open action menu)
|
||||
// * Click in the action menu, which has 0 available actions (TODO)
|
||||
if (_selectedInventoryItem != -1) {
|
||||
if (!ui->itemDoActionAt(_objectUnderCursor, _selectedInventoryItem, pos)) {
|
||||
warning("Could not perform action %d on %s", _selectedInventoryItem, _objectUnderCursor->getName().c_str());
|
||||
}
|
||||
} else {
|
||||
Resources::ActionArray actions = ui->getStockActionsPossibleForObject(_objectUnderCursor, pos);
|
||||
if (actions.size() == 1) {
|
||||
for (uint i = 0; i < actions.size(); i++) {
|
||||
if (actions[i] == Resources::PATTable::kActionLook) {
|
||||
ui->itemDoActionAt(_objectUnderCursor, Resources::PATTable::kActionLook, pos);
|
||||
break;
|
||||
} else if (actions[i] == Resources::PATTable::kActionTalk) {
|
||||
ui->itemDoActionAt(_objectUnderCursor, Resources::PATTable::kActionTalk, pos);
|
||||
break;
|
||||
} else if (actions[i] == Resources::PATTable::kActionUse) {
|
||||
ui->itemDoActionAt(_objectUnderCursor, Resources::PATTable::kActionUse, pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (actions.size() > 1) {
|
||||
_actionMenu->open(_objectUnderCursor, pos);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ui->walkTo(g_system->getEventManager()->getMousePos());
|
||||
|
||||
// // Assume all inventory objects need action menu.
|
||||
// if (isInventoryObject(item)) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// {
|
||||
// if (_selectedInventoryItem != -1) {
|
||||
// _inventoryInterface->update();
|
||||
// _selectedInventoryItem = -1;
|
||||
// _selectedInventoryItemText = "";
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// Check this before handling the menu clicks, otherwise it closes again on the same event.
|
||||
if (_inventoryOpen && !_inventoryInterface->containsPoint(_cursor->getMousePosition())) {
|
||||
_inventoryOpen = false;
|
||||
if (_inventoryInterface->isVisible() && !_inventoryInterface->isMouseInside()) {
|
||||
_inventoryInterface->close();
|
||||
}
|
||||
if (_topMenu->containsPoint(_cursor->getMousePosition())) {
|
||||
_topMenu->handleClick(_cursor->getMousePosition());
|
||||
|
@ -192,18 +235,17 @@ void UI::notifyDialogOptions(const Common::StringArray &options) {
|
|||
}
|
||||
|
||||
void UI::notifyShouldOpenInventory() {
|
||||
_inventoryOpen = true;
|
||||
// Make the inventory update it's contents.
|
||||
_inventoryInterface->update();
|
||||
_inventoryInterface->open();
|
||||
}
|
||||
|
||||
void UI::notifyFMVRequest(const Common::String &name) {
|
||||
_fmvPlayer->play(name);
|
||||
}
|
||||
|
||||
void UI::notifySelectedInventoryItem(Resources::Object *selectedItem) {
|
||||
_selectedInventoryItem = selectedItem->findParent<Resources::ItemSub2>()->getIndex();
|
||||
_selectedInventoryItemText = selectedItem->findParent<Resources::ItemSub2>()->getName() + " -> ";
|
||||
void UI::notifySelectedInventoryItem(Resources::Item *selectedItem) {
|
||||
_selectedInventoryItem = selectedItem->getIndex();
|
||||
_selectedInventoryItemText = selectedItem->getName() + " -> ";
|
||||
}
|
||||
|
||||
bool UI::isPlayingFMV() const {
|
||||
|
@ -219,8 +261,7 @@ void UI::render() {
|
|||
_fmvPlayer->render();
|
||||
return;
|
||||
}
|
||||
UserInterface *ui = StarkServices::instance().userInterface;
|
||||
update(ui->getRenderEntries(), true);
|
||||
|
||||
// Can't handle clicks before this point, since we need to have updated the mouse-over state to include the UI.
|
||||
if (_hasClicked) {
|
||||
handleClick();
|
||||
|
@ -231,12 +272,10 @@ void UI::render() {
|
|||
_topMenu->render();
|
||||
}
|
||||
|
||||
if (_inventoryOpen) {
|
||||
_inventoryInterface->render();
|
||||
}
|
||||
|
||||
_dialogInterface->render();
|
||||
ui->render();
|
||||
_actionMenu->render();
|
||||
}
|
||||
|
||||
} // End of namespace Stark
|
||||
|
|
|
@ -28,16 +28,19 @@
|
|||
|
||||
#include "engines/stark/gfx/renderentry.h"
|
||||
|
||||
#include "engines/stark/resources/pattable.h"
|
||||
|
||||
namespace Stark {
|
||||
|
||||
namespace Resources {
|
||||
class Object;
|
||||
class Item;
|
||||
}
|
||||
|
||||
namespace Gfx {
|
||||
class Driver;
|
||||
}
|
||||
|
||||
class ActionMenu;
|
||||
class DialogInterface;
|
||||
class InventoryInterface;
|
||||
class TopMenu;
|
||||
|
@ -45,31 +48,30 @@ class Cursor;
|
|||
class FMVPlayer;
|
||||
|
||||
class UI {
|
||||
ActionMenu *_actionMenu;
|
||||
FMVPlayer *_fmvPlayer;
|
||||
DialogInterface *_dialogInterface;
|
||||
InventoryInterface *_inventoryInterface;
|
||||
TopMenu *_topMenu;
|
||||
Resources::Object *_currentObject;
|
||||
Resources::Object *_objectUnderCursor;
|
||||
Resources::Item *_objectUnderCursor;
|
||||
int _selectedInventoryItem;
|
||||
Common::String _selectedInventoryItemText; // Just a temp HACK untill we get cursors sorted.
|
||||
Gfx::Driver *_gfx;
|
||||
Cursor *_cursor;
|
||||
bool _hasClicked;
|
||||
bool _exitGame;
|
||||
bool _inventoryOpen;
|
||||
void handleClick();
|
||||
void setCursorDependingOnActionsAvailable(int actionsAvailable);
|
||||
void setCursorDependingOnActionsAvailable(Resources::ActionArray actionsAvailable);
|
||||
public:
|
||||
UI(Gfx::Driver *gfx, Cursor *cursor);
|
||||
virtual ~UI();
|
||||
void init();
|
||||
void update(Gfx::RenderEntryArray renderEntries, bool keepExisting = false);
|
||||
void update(Gfx::RenderEntryArray renderEntries);
|
||||
void render();
|
||||
void notifyClick();
|
||||
void notifySubtitle(const Common::String &subtitle);
|
||||
void notifyDialogOptions(const Common::StringArray &options);
|
||||
void notifySelectedInventoryItem(Resources::Object *selectedItem);
|
||||
void notifySelectedInventoryItem(Resources::Item *selectedItem);
|
||||
void notifyShouldExit() { _exitGame = true; }
|
||||
void notifyShouldOpenInventory();
|
||||
void notifyFMVRequest(const Common::String &name);
|
||||
|
|
|
@ -40,7 +40,6 @@ Button::Button(const Common::String &text, Resources::Anim *image, Common::Point
|
|||
}
|
||||
|
||||
void Button::render() {
|
||||
Gfx::Driver *gfx = StarkServices::instance().gfx;
|
||||
_image->getVisual()->get<VisualImageXMG>()->render(_position);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ DialogInterface::~DialogInterface() {
|
|||
}
|
||||
|
||||
void DialogInterface::clearOptions() {
|
||||
for (int i = 0; i < _options.size(); i++) {
|
||||
for (uint i = 0; i < _options.size(); i++) {
|
||||
delete _options[i];
|
||||
}
|
||||
_options.clear();
|
||||
|
@ -55,7 +55,7 @@ void DialogInterface::clearOptions() {
|
|||
}
|
||||
|
||||
void DialogInterface::renderOptions() {
|
||||
for (int i = 0; i < _options.size(); i++) {
|
||||
for (uint i = 0; i < _options.size(); i++) {
|
||||
_options[i]->render();
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ void DialogInterface::notifyDialogOptions(const Common::StringArray &options) {
|
|||
_texture = nullptr;
|
||||
|
||||
int pos = 401;
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
for (uint i = 0; i < options.size(); i++) {
|
||||
ClickText *text = new ClickText(options[i], Common::Point(0, pos));
|
||||
_options.push_back(text);
|
||||
pos += text->getHeight();
|
||||
|
@ -105,7 +105,7 @@ void DialogInterface::notifyDialogOptions(const Common::StringArray &options) {
|
|||
|
||||
bool DialogInterface::containsPoint(Common::Point point) {
|
||||
if (_hasOptions && _options.size() > 0) {
|
||||
for (int i = 0; i < _options.size(); i++) {
|
||||
for (uint i = 0; i < _options.size(); i++) {
|
||||
if (_options[i]->containsPoint(point)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ bool DialogInterface::containsPoint(Common::Point point) {
|
|||
|
||||
void DialogInterface::handleMouseOver(Common::Point point) {
|
||||
if (_hasOptions && _options.size() > 0) {
|
||||
for (int i = 0; i < _options.size(); i++) {
|
||||
for (uint i = 0; i < _options.size(); i++) {
|
||||
if (_options[i]->containsPoint(point)) {
|
||||
_options[i]->handleMouseOver();
|
||||
} else {
|
||||
|
@ -128,7 +128,7 @@ void DialogInterface::handleMouseOver(Common::Point point) {
|
|||
|
||||
void DialogInterface::handleClick(Common::Point point) {
|
||||
if (_hasOptions && _options.size() > 0) {
|
||||
for (int i = 0; i < _options.size(); i++) {
|
||||
for (uint i = 0; i < _options.size(); i++) {
|
||||
if (_options[i]->containsPoint(point)) {
|
||||
DialogPlayer *dialogPlayer = StarkServices::instance().dialogPlayer;
|
||||
dialogPlayer->selectOption(i);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "engines/stark/gfx/driver.h"
|
||||
|
||||
#include "engines/stark/resources/anim.h"
|
||||
#include "engines/stark/resources/knowledgeset.h"
|
||||
#include "engines/stark/resources/item.h"
|
||||
|
||||
#include "engines/stark/services/global.h"
|
||||
|
@ -33,63 +34,54 @@
|
|||
|
||||
#include "engines/stark/visual/image.h"
|
||||
|
||||
#include "engines/stark/scene.h"
|
||||
|
||||
namespace Stark {
|
||||
|
||||
InventoryInterface::InventoryInterface() {
|
||||
InventoryInterface::InventoryInterface(Gfx::Driver *gfx, Cursor *cursor) :
|
||||
Window(gfx, cursor){
|
||||
StaticProvider *staticProvider = StarkServices::instance().staticProvider;
|
||||
_backgroundTexture = staticProvider->getUIItem(StaticProvider::kInventoryBg);
|
||||
_position = Common::Point(40, 50);
|
||||
|
||||
_position = Common::Rect(526, 315);
|
||||
_position.translate(40, 50);
|
||||
}
|
||||
|
||||
void InventoryInterface::render() {
|
||||
Gfx::Driver *gfx = StarkServices::instance().gfx;
|
||||
gfx->setScreenViewport(false);
|
||||
void InventoryInterface::open() {
|
||||
_visible = true;
|
||||
|
||||
_backgroundTexture->getVisual()->get<VisualImageXMG>()->render(_position);
|
||||
|
||||
Scene *scene = StarkServices::instance().scene;
|
||||
scene->render(_renderEntries);
|
||||
}
|
||||
|
||||
void InventoryInterface::update() {
|
||||
Global *global = StarkServices::instance().global;
|
||||
_items = global->getInventoryContents();
|
||||
_renderEntries = global->getInventory()->getInventoryRenderEntries();
|
||||
}
|
||||
|
||||
Common::Array<Resources::Item*>::iterator it = _items.begin();
|
||||
void InventoryInterface::close() {
|
||||
_visible = false;
|
||||
}
|
||||
|
||||
void InventoryInterface::onRender() {
|
||||
_backgroundTexture->getVisual()->get<VisualImageXMG>()->render(Common::Point(0, 0));
|
||||
|
||||
Gfx::RenderEntryArray::iterator it = _renderEntries.begin();
|
||||
// TODO: Unhardcode positions
|
||||
Common::Point pos = _position;
|
||||
Common::Point pos;
|
||||
int width =_backgroundTexture->getVisual()->get<VisualImageXMG>()->getWidth();
|
||||
pos.x += 40;
|
||||
for (;it != _items.end(); ++it) {
|
||||
_renderEntries.push_back((*it)->getRenderEntry(pos));
|
||||
pos.x += 40;
|
||||
if (pos.x > _position.x + width - 40) {
|
||||
pos.x = _position.x + 20;
|
||||
pos.y+= 40;
|
||||
for (;it != _renderEntries.end(); ++it) {
|
||||
(*it)->setPosition(pos);
|
||||
(*it)->render(_gfx);
|
||||
|
||||
pos.x += 36;
|
||||
if (pos.x > width - 40) {
|
||||
pos.x = 20;
|
||||
pos.y+= 36;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool InventoryInterface::containsPoint(Common::Point point) {
|
||||
Common::Rect r;
|
||||
r.left = _position.x;
|
||||
r.top = _position.y;
|
||||
r.setWidth(_backgroundTexture->getVisual()->get<VisualImageXMG>()->getWidth());
|
||||
r.setHeight(_backgroundTexture->getVisual()->get<VisualImageXMG>()->getHeight());
|
||||
return r.contains(point);
|
||||
void InventoryInterface::onMouseMove(const Common::Point &pos) {
|
||||
|
||||
}
|
||||
|
||||
Common::String InventoryInterface::getMouseHintAtPosition(Common::Point point) {
|
||||
for (int i = 0; i < _renderEntries.size(); i++) {
|
||||
int index = _renderEntries[i]->indexForPoint(point);
|
||||
if (index != -1) {
|
||||
// TODO: Care about index
|
||||
return _renderEntries[i]->getOwner()->getName();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
void InventoryInterface::onClick(const Common::Point &pos) {
|
||||
|
||||
}
|
||||
|
||||
} // End of namespace Stark
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include "engines/stark/gfx/renderentry.h"
|
||||
|
||||
#include "engines/stark/ui/window.h"
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/array.h"
|
||||
|
@ -43,19 +45,22 @@ namespace Gfx {
|
|||
class Texture;
|
||||
}
|
||||
|
||||
class InventoryInterface {
|
||||
class InventoryInterface : public Window {
|
||||
Resources::Anim *_backgroundTexture;
|
||||
Common::Point _position;
|
||||
Common::Array<Resources::Item*> _items;
|
||||
Gfx::RenderEntryArray _renderEntries;
|
||||
public:
|
||||
InventoryInterface();
|
||||
InventoryInterface(Gfx::Driver *gfx, Cursor *cursor);
|
||||
virtual ~InventoryInterface() {}
|
||||
void render();
|
||||
void update();
|
||||
bool containsPoint(Common::Point point);
|
||||
Common::String getMouseHintAtPosition(Common::Point point);
|
||||
|
||||
void open();
|
||||
void close();
|
||||
|
||||
Gfx::RenderEntryArray getRenderEntries() { return _renderEntries; }
|
||||
|
||||
protected:
|
||||
void onMouseMove(const Common::Point &pos) override;
|
||||
void onClick(const Common::Point &pos) override;
|
||||
void onRender() override;
|
||||
};
|
||||
|
||||
} // End of namespace Stark
|
||||
|
|
97
engines/stark/ui/window.cpp
Normal file
97
engines/stark/ui/window.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* ResidualVM - A 3D game interpreter
|
||||
*
|
||||
* ResidualVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the AUTHORS
|
||||
* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "engines/stark/ui/window.h"
|
||||
|
||||
#include "engines/stark/cursor.h"
|
||||
|
||||
#include "engines/stark/gfx/driver.h"
|
||||
|
||||
namespace Stark {
|
||||
|
||||
Window::Window(Gfx::Driver *gfx, Cursor *cursor) :
|
||||
_gfx(gfx),
|
||||
_cursor(cursor),
|
||||
_unscaled(false),
|
||||
_visible(false) {
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
}
|
||||
|
||||
void Window::render() {
|
||||
if (!_visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
_gfx->setViewport(_position, _unscaled);
|
||||
|
||||
onRender();
|
||||
}
|
||||
|
||||
bool Window::isMouseInside() const {
|
||||
if (!_visible) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::Point mousePos = _cursor->getMousePosition(_unscaled);
|
||||
return _position.contains(mousePos);
|
||||
}
|
||||
|
||||
bool Window::isVisible() const {
|
||||
return _visible;
|
||||
}
|
||||
|
||||
Common::Point Window::getMousePosition() const {
|
||||
Common::Point mousePos = _cursor->getMousePosition(_unscaled);
|
||||
return mousePos - Common::Point(_position.left, _position.top);
|
||||
}
|
||||
|
||||
Common::Point Window::getScreenMousePosition() const {
|
||||
return _cursor->getMousePosition(_unscaled);
|
||||
}
|
||||
|
||||
void Window::setCursor(Cursor::CursorType type) {
|
||||
_cursor->setCursorType(type);
|
||||
}
|
||||
|
||||
void Window::handleMouseMove() {
|
||||
if (!_visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isMouseInside()) {
|
||||
onMouseMove(getMousePosition());
|
||||
}
|
||||
}
|
||||
|
||||
void Window::handleClick() {
|
||||
if (!_visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isMouseInside()) {
|
||||
onClick(getMousePosition());
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Stark
|
72
engines/stark/ui/window.h
Normal file
72
engines/stark/ui/window.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* ResidualVM - A 3D game interpreter
|
||||
*
|
||||
* ResidualVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the AUTHORS
|
||||
* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STARK_UI_WINDOW_H
|
||||
#define STARK_UI_WINDOW_H
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
#include "engines/stark/cursor.h"
|
||||
|
||||
namespace Stark {
|
||||
|
||||
class Cursor;
|
||||
|
||||
namespace Gfx {
|
||||
class Driver;
|
||||
}
|
||||
|
||||
class Window {
|
||||
public:
|
||||
Window(Gfx::Driver *gfx, Cursor *cursor);
|
||||
virtual ~Window();
|
||||
|
||||
void handleMouseMove();
|
||||
void handleClick();
|
||||
|
||||
void render();
|
||||
|
||||
bool isMouseInside() const;
|
||||
bool isVisible() const;
|
||||
|
||||
protected:
|
||||
virtual void onMouseMove(const Common::Point &pos) = 0;
|
||||
virtual void onClick(const Common::Point &pos) = 0;
|
||||
virtual void onRender() = 0;
|
||||
|
||||
void setCursor(Cursor::CursorType type);
|
||||
Common::Point getMousePosition() const;
|
||||
Common::Point getScreenMousePosition() const;
|
||||
|
||||
Gfx::Driver *_gfx;
|
||||
|
||||
Common::Rect _position;
|
||||
bool _unscaled;
|
||||
bool _visible;
|
||||
|
||||
private:
|
||||
Cursor *_cursor;
|
||||
};
|
||||
|
||||
} // End of namespace Stark
|
||||
|
||||
#endif // STARK_UI_WINDOW_H
|
Loading…
Add table
Add a link
Reference in a new issue