Refactor Dialog and Computer GUI to use control binding

This commit is contained in:
Vsevolod Kremianskii 2021-06-13 10:14:07 +07:00
parent 9ee347f725
commit e2f6ee3b7a
6 changed files with 181 additions and 88 deletions

View file

@ -17,8 +17,6 @@
#include "computer.h"
#include "../../gui/control/listbox.h"
#include "../game.h"
#include "../gameidutil.h"
@ -33,13 +31,9 @@ namespace reone {
namespace game {
static const char kControlTagMessage[] = "LB_MESSAGE";
static const char kControlTagReplies[] = "LB_REPLIES";
ComputerGUI::ComputerGUI(Game *game) : Conversation(game) {
_resRef = getResRef("computer");
_scaling = ScalingMode::Stretch;
_repliesControlTag = kControlTagReplies;
if (isTSL(game->gameId())) {
_resolutionX = 800;
@ -49,36 +43,79 @@ ComputerGUI::ComputerGUI(Game *game) : Conversation(game) {
void ComputerGUI::load() {
Conversation::load();
bindControls();
configureMessage();
configureReplies();
}
void ComputerGUI::configureMessage() {
auto &message = getControl<ListBox>(kControlTagMessage);
message.setProtoMatchContent(true);
void ComputerGUI::bindControls() {
_binding.lblCompSkill = getControlPtr<Label>("LBL_COMP_SKILL");
_binding.lblCompSkillVal = getControlPtr<Label>("LBL_COMP_SKILL_VAL");
_binding.lblCompSpikes = getControlPtr<Label>("LBL_COMP_SPIKES");
_binding.lblCompSpikesVal = getControlPtr<Label>("LBL_COMP_SPIKES_VAL");
_binding.lblRepSkill = getControlPtr<Label>("LBL_REP_SKILL");
_binding.lblRepSkillVal = getControlPtr<Label>("LBL_REP_SKILL_VAL");
_binding.lblRepUnits = getControlPtr<Label>("LBL_REP_UNITS");
_binding.lblRepUnitsVal = getControlPtr<Label>("LBL_REP_UNITS_VAL");
_binding.lbMessage = getControlPtr<ListBox>("LB_MESSAGE");
_binding.lbReplies = getControlPtr<ListBox>("LB_REPLIES");
Control &protoItem = message.protoItem();
protoItem.setHilightColor(getHilightColor(_game->gameId()));
protoItem.setTextColor(getBaseColor(_game->gameId()));
if (isTSL(_game->gameId())) {
_binding.lblBar1 = getControlPtr<Label>("LBL_BAR1");
_binding.lblBar2 = getControlPtr<Label>("LBL_BAR2");
_binding.lblBar3 = getControlPtr<Label>("LBL_BAR3");
_binding.lblBar4 = getControlPtr<Label>("LBL_BAR4");
_binding.lblBar5 = getControlPtr<Label>("LBL_BAR5");
_binding.lblBar6 = getControlPtr<Label>("LBL_BAR6");
} else {
_binding.lblCompSkillIcon = getControlPtr<Label>("LBL_COMP_SKILL_ICON");
_binding.lblCompSpikesIcon = getControlPtr<Label>("LBL_COMP_SPIKES_ICON");
_binding.lblRepSkillIcon = getControlPtr<Label>("LBL_REP_SKILL_ICON");
_binding.lblRepUnitsIcon = getControlPtr<Label>("LBL_REP_UNITS_ICON");
_binding.lblStatic1 = getControlPtr<Label>("LBL_STATIC1");
_binding.lblStatic2 = getControlPtr<Label>("LBL_STATIC2");
_binding.lblStatic3 = getControlPtr<Label>("LBL_STATIC3");
_binding.lblStatic4 = getControlPtr<Label>("LBL_STATIC4");
_binding.lblObscure = getControlPtr<Label>("LBL_OBSCURE");
}
}
void ComputerGUI::configureMessage() {
_binding.lbMessage->setProtoMatchContent(true);
_binding.lbMessage->protoItem().setHilightColor(getHilightColor(_game->gameId()));
_binding.lbMessage->protoItem().setTextColor(getBaseColor(_game->gameId()));
}
void ComputerGUI::configureReplies() {
auto &replies = getControl<ListBox>(kControlTagReplies);
replies.setProtoMatchContent(true);
Control &protoItem = replies.protoItem();
protoItem.setHilightColor(getHilightColor(_game->gameId()));
protoItem.setTextColor(getBaseColor(_game->gameId()));
_binding.lbReplies->setProtoMatchContent(true);
_binding.lbReplies->protoItem().setHilightColor(getHilightColor(_game->gameId()));
_binding.lbReplies->protoItem().setTextColor(getBaseColor(_game->gameId()));
}
void ComputerGUI::setMessage(string message) {
ListBox::Item item;
item.text = message;
item.text = move(message);
ListBox &listBox = getControl<ListBox>(kControlTagMessage);
listBox.clearItems();
listBox.addItem(move(item));
_binding.lbMessage->clearItems();
_binding.lbMessage->addItem(move(item));
}
void ComputerGUI::setReplyLines(vector<string> lines) {
_binding.lbReplies->clearItems();
for (size_t i = 0; i < lines.size(); ++i) {
ListBox::Item item;
item.tag = to_string(i);
item.text = lines[i];
_binding.lbReplies->addItem(move(item));
}
}
void ComputerGUI::onListBoxItemClick(const string &control, const string &item) {
if (control == "LB_REPLIES") {
int replyIdx = stoi(item);
pickReply(replyIdx);
}
}
} // namespace game

View file

@ -17,6 +17,9 @@
#pragma once
#include "../../gui/control/label.h"
#include "../../gui/control/listbox.h"
#include "conversation.h"
namespace reone {
@ -30,10 +33,48 @@ public:
void load() override;
private:
void setMessage(std::string message) override;
struct Binding {
std::shared_ptr<gui::Label> lblCompSkill;
std::shared_ptr<gui::Label> lblCompSkillVal;
std::shared_ptr<gui::Label> lblCompSpikes;
std::shared_ptr<gui::Label> lblCompSpikesVal;
std::shared_ptr<gui::Label> lblRepSkill;
std::shared_ptr<gui::Label> lblRepSkillVal;
std::shared_ptr<gui::Label> lblRepUnits;
std::shared_ptr<gui::Label> lblRepUnitsVal;
std::shared_ptr<gui::ListBox> lbMessage;
std::shared_ptr<gui::ListBox> lbReplies;
// KotOR only
std::shared_ptr<gui::Label> lblCompSkillIcon;
std::shared_ptr<gui::Label> lblCompSpikesIcon;
std::shared_ptr<gui::Label> lblRepSkillIcon;
std::shared_ptr<gui::Label> lblRepUnitsIcon;
std::shared_ptr<gui::Label> lblStatic1;
std::shared_ptr<gui::Label> lblStatic2;
std::shared_ptr<gui::Label> lblStatic3;
std::shared_ptr<gui::Label> lblStatic4;
std::shared_ptr<gui::Label> lblObscure;
// END KotOR only
// TSL only
std::shared_ptr<gui::Label> lblBar1;
std::shared_ptr<gui::Label> lblBar2;
std::shared_ptr<gui::Label> lblBar3;
std::shared_ptr<gui::Label> lblBar4;
std::shared_ptr<gui::Label> lblBar5;
std::shared_ptr<gui::Label> lblBar6;
// END TSL only
} _binding;
void bindControls();
void configureMessage();
void configureReplies();
void setMessage(std::string message) override;
void setReplyLines(std::vector<std::string> lines) override;
void onListBoxItemClick(const std::string &control, const std::string &item) override;
};
} // namespace game

View file

@ -216,24 +216,13 @@ static string getReplyText(const Dialog::EntryReply &reply, int index) {
}
void Conversation::refreshReplies() {
ListBox &listBox = getControl<ListBox>(_repliesControlTag);
listBox.clearItems();
if (_autoPickFirstReply) return;
vector<string> lines;
if (!_autoPickFirstReply) {
for (size_t i = 0; i < _replies.size(); ++i) {
ListBox::Item item;
item.tag = to_string(i);
item.text = getReplyText(*_replies[i], static_cast<int>(i));
listBox.addItem(move(item));
lines.push_back(getReplyText(*_replies[i], static_cast<int>(i)));
}
}
void Conversation::onListBoxItemClick(const string &control, const string &item) {
if (control == _repliesControlTag) {
int replyIdx = stoi(item);
pickReply(replyIdx);
}
setReplyLines(move(lines));
}
void Conversation::pickReply(int index) {

View file

@ -67,8 +67,6 @@ public:
void resume();
protected:
std::string _repliesControlTag;
std::shared_ptr<Dialog> _dialog;
std::shared_ptr<SpatialObject> _owner;
std::shared_ptr<graphics::Model> _cameraModel;
@ -77,17 +75,21 @@ protected:
bool _entryEnded { false };
bool _paused { false };
virtual void onStart();
virtual void onFinish();
virtual void onLoadEntry();
virtual void onEntryEnded();
/**
* @param index index of the entry in the DLG file
* @param start true if this is a starting entry, false otherwise
*/
virtual void loadEntry(int index, bool start = false);
void pickReply(int index);
virtual void setReplyLines(std::vector<std::string> lines) = 0;
virtual void onStart();
virtual void onFinish();
virtual void onLoadEntry();
virtual void onEntryEnded();
private:
std::shared_ptr<audio::SoundHandle> _currentVoice;
Timer _endEntryTimer;
@ -95,8 +97,6 @@ private:
std::vector<const Dialog::EntryReply *> _replies;
bool _autoPickFirstReply { false };
void onListBoxItemClick(const std::string &control, const std::string &item) override;
void loadConversationBackground();
void loadCameraModel();
void loadStartEntry();
@ -106,11 +106,6 @@ private:
bool isSkippableEntry() const;
/**
* Replaces text in the message control.
*/
virtual void setMessage(std::string message) = 0;
/**
* Recreates items in the replies list box.
*/
@ -118,7 +113,6 @@ private:
void finish();
void endCurrentEntry();
void pickReply(int index);
/**
* @return index of the first active entry/reply from the specified list, -1 otherwise
@ -132,6 +126,11 @@ private:
*/
bool evaluateCondition(const std::string &scriptResRef);
/**
* Replaces text in the message control.
*/
virtual void setMessage(std::string message) = 0;
// Event handlers
bool handleMouseButtonDown(const SDL_MouseButtonEvent &event);

View file

@ -22,7 +22,6 @@
#include "../../audio/soundhandle.h"
#include "../../common/log.h"
#include "../../common/random.h"
#include "../../gui/control/listbox.h"
#include "../../gui/control/panel.h"
#include "../../graphics/model/models.h"
#include "../../resource/resources.h"
@ -50,9 +49,6 @@ namespace game {
static const char kControlTagTopFrame[] = "TOP";
static const char kControlTagBottomFrame[] = "BOTTOM";
static const char kControlTagMessage[] = "LBL_MESSAGE";
static const char kControlTagReplies[] = "LB_REPLIES";
static const char kObjectTagOwner[] = "owner";
static const unordered_map<string, AnimationType> g_animTypeByName {
@ -92,20 +88,24 @@ static const unordered_map<string, AnimationType> g_animTypeByName {
DialogGUI::DialogGUI(Game *game) : Conversation(game) {
_resRef = getResRef("dialog");
_scaling = ScalingMode::Stretch;
_repliesControlTag = kControlTagReplies;
}
void DialogGUI::load() {
Conversation::load();
bindControls();
configureMessage();
configureReplies();
loadFrames();
}
void DialogGUI::bindControls() {
_binding.lblMessage = getControlPtr<Label>("LBL_MESSAGE");
_binding.lbReplies = getControlPtr<ListBox>("LB_REPLIES");
}
void DialogGUI::loadFrames() {
int rootTop = _rootControl->extent().top;
int messageHeight = getControl(kControlTagMessage).extent().height;
int messageHeight = _binding.lblMessage->extent().height;
addFrame(kControlTagTopFrame, -rootTop, messageHeight);
addFrame(kControlTagBottomFrame, 0, _options.height - rootTop);
@ -128,18 +128,14 @@ void DialogGUI::addFrame(string tag, int top, int height) {
}
void DialogGUI::configureMessage() {
auto &message = getControl(kControlTagMessage);
message.setExtentTop(-_rootControl->extent().top);
message.setTextColor(getBaseColor(_game->gameId()));
_binding.lblMessage->setExtentTop(-_rootControl->extent().top);
_binding.lblMessage->setTextColor(getBaseColor(_game->gameId()));
}
void DialogGUI::configureReplies() {
auto &replies = getControl<ListBox>(kControlTagReplies);
replies.setProtoMatchContent(true);
Control &protoItem = replies.protoItem();
protoItem.setHilightColor(getHilightColor(_game->gameId()));
protoItem.setTextColor(getBaseColor(_game->gameId()));
_binding.lbReplies->setProtoMatchContent(true);
_binding.lbReplies->protoItem().setHilightColor(getHilightColor(_game->gameId()));
_binding.lbReplies->protoItem().setTextColor(getBaseColor(_game->gameId()));
}
void DialogGUI::onStart() {
@ -188,7 +184,8 @@ void DialogGUI::onLoadEntry() {
updateCamera();
updateParticipantAnimations();
repositionMessage();
hideControl(kControlTagReplies);
_binding.lbReplies->setVisible(false);
}
void DialogGUI::loadCurrentSpeaker() {
@ -319,8 +316,7 @@ AnimationType DialogGUI::getStuntAnimationType(int ordinal) const {
}
void DialogGUI::repositionMessage() {
Control &message = getControl(kControlTagMessage);
Control::Text text(message.text());
Control::Text text(_binding.lblMessage->text());
int top;
if (_entryEnded) {
@ -328,11 +324,11 @@ void DialogGUI::repositionMessage() {
top = -_rootControl->extent().top;
} else {
text.align = Control::TextAlign::CenterTop;
top = getControl(kControlTagReplies).extent().top;
top = _binding.lbReplies->extent().top;
}
message.setText(move(text));
message.setExtentTop(top);
_binding.lblMessage->setText(move(text));
_binding.lblMessage->setExtentTop(top);
}
void DialogGUI::onFinish() {
@ -354,13 +350,25 @@ void DialogGUI::releaseStuntParticipants() {
}
void DialogGUI::onEntryEnded() {
showControl(kControlTagReplies);
_binding.lbReplies->setVisible(true);
updateCamera();
repositionMessage();
}
void DialogGUI::setMessage(string message) {
setControlText(kControlTagMessage, message);
_binding.lblMessage->setTextMessage(message);
}
void DialogGUI::setReplyLines(vector<string> lines) {
_binding.lbReplies->clearItems();
for (size_t i = 0; i < lines.size(); ++i) {
ListBox::Item item;
item.tag = to_string(i);
item.text = lines[i];
_binding.lbReplies->addItem(move(item));
}
}
void DialogGUI::update(float dt) {
@ -373,6 +381,13 @@ void DialogGUI::update(float dt) {
}
}
void DialogGUI::onListBoxItemClick(const string &control, const string &item) {
if (control == "LB_REPLIES") {
int replyIdx = stoi(item);
pickReply(replyIdx);
}
}
} // namespace game
} // namespace reone

View file

@ -17,6 +17,9 @@
#pragma once
#include "../../gui/control/label.h"
#include "../../gui/control/listbox.h"
#include "../camera/dialogcamera.h"
#include "../object/creature.h"
@ -39,16 +42,15 @@ private:
std::shared_ptr<Creature> creature;
};
struct Binding {
std::shared_ptr<gui::Label> lblMessage;
std::shared_ptr<gui::ListBox> lbReplies;
} _binding;
std::shared_ptr<SpatialObject> _currentSpeaker;
std::map<std::string, Participant> _participantByTag;
void onStart() override;
void onFinish() override;
void onLoadEntry() override;
void onEntryEnded() override;
void setMessage(std::string message) override;
void bindControls();
void addFrame(std::string tag, int top, int height);
void configureMessage();
void configureReplies();
@ -62,6 +64,16 @@ private:
std::string getStuntAnimationName(int ordinal) const;
AnimationType getStuntAnimationType(int ordinal) const;
void setMessage(std::string message) override;
void setReplyLines(std::vector<std::string> lines) override;
void onStart() override;
void onFinish() override;
void onLoadEntry() override;
void onEntryEnded() override;
void onListBoxItemClick(const std::string &control, const std::string &item) override;
// Loading
void loadFrames();