refactor: Prefer dependency injection to callbacks in concrete GUIs

This commit is contained in:
Vsevolod Kremianskii 2020-10-22 07:54:52 +07:00
parent fce658500b
commit fe1ab7a424
20 changed files with 286 additions and 361 deletions

View file

@ -250,28 +250,13 @@ void Game::drawCursor() {
}
void Game::loadHUD() {
_hud.reset(new HUD(_version, _options.graphics));
_hud.reset(new HUD(this, _version, _options.graphics));
_hud->load();
_hud->setOnEquipmentClick(bind(&Game::onEquipmentClick, this));
}
void Game::onEquipmentClick() {
_hud->resetFocus();
shared_ptr<SpatialObject> player(_module->area()->player());
_equipment->open(player.get());
_screen = GameScreen::Equipment;
}
void Game::loadDialogGui() {
_dialog.reset(new Dialog(_version, this, _options.graphics));
_dialog.reset(new Dialog(this, _version, _options.graphics));
_dialog->load();
_dialog->setOnDialogFinished(bind(&Game::onDialogFinished, this));
}
void Game::onDialogFinished() {
_screen = GameScreen::InGame;
}
void Game::loadContainerGui() {
@ -280,12 +265,8 @@ void Game::loadContainerGui() {
}
void Game::loadEquipmentGui() {
_equipment.reset(new Equipment(_version, _options.graphics));
_equipment.reset(new Equipment(this, _version, _options.graphics));
_equipment->load();
_equipment->setOnClose([this]() {
_equipment->resetFocus();
_screen = GameScreen::InGame;
});
}
GUI *Game::getScreenGUI() const {
@ -430,6 +411,12 @@ void Game::onCameraChanged(CameraType camera) {
_window.setRelativeMouseMode(camera == CameraType::FirstPerson);
}
void Game::openEquipment() {
shared_ptr<SpatialObject> player(_module->area()->player());
_equipment->open(player.get());
_screen = GameScreen::Equipment;
}
bool Game::handle(const SDL_Event &event) {
GUI *gui = getScreenGUI();
if (gui && gui->handle(event)) {

View file

@ -72,6 +72,7 @@ public:
void openContainer(SpatialObject *container);
void scheduleModuleTransition(const std::string &moduleName, const std::string &entry);
void onCameraChanged(CameraType camera);
void openEquipment();
bool handle(const SDL_Event &event) override;
@ -206,7 +207,6 @@ private:
// Event handlers
void onDialogFinished();
void onEquipmentClick();
// END Event handlers
};

View file

@ -70,157 +70,34 @@ void CharacterGeneration::load() {
loadClassSelection();
loadQuickOrCustom();
loadQuickCharacterGeneration();
loadQuick();
loadPortraitSelection();
loadNameEntry();
}
void CharacterGeneration::loadClassSelection() {
_classSelection = make_unique<ClassSelection>(_game, _version, _gfxOpts);
_classSelection = make_unique<ClassSelection>(_game, this, _version, _gfxOpts);
_classSelection->load();
_classSelection->setOnClassSelected([this](const CreatureConfiguration &config) {
_classSelection->resetFocus();
_portraitSelection->loadPortraits(config);
loadCharacter(config);
showControl("MODEL_LBL");
_screen = CharGenScreen::QuickOrCustom;
});
_classSelection->setOnCancel([this]() {
_classSelection->resetFocus();
_game->openMainMenu();
});
}
void CharacterGeneration::loadCharacter(const CreatureConfiguration &config) {
_character = config;
Control &lblModel = getControl("MODEL_LBL");
const Control::Extent &extent = lblModel.extent();
float aspect = extent.width / static_cast<float>(extent.height);
glm::mat4 cameraTransform(1.0f);
cameraTransform = glm::translate(cameraTransform, glm::vec3(0.0f, 1.0f, 0.0f));
cameraTransform = glm::rotate(cameraTransform, glm::half_pi<float>(), glm::vec3(1.0f, 0.0f, 0.0f));
cameraTransform = glm::rotate(cameraTransform, glm::pi<float>(), glm::vec3(0.0f, 1.0f, 0.0f));
unique_ptr<Control::Scene3D> scene(SceneBuilder(_gfxOpts)
.aspect(aspect)
.depth(0.1f, 10.0f)
.modelSupplier(bind(&CharacterGeneration::getCharacterModel, this, config, _1))
.modelScale(kModelScale)
.modelOffset(glm::vec2(0.0f, kModelOffsetY))
.cameraTransform(cameraTransform)
.ambientLightColor(glm::vec3(1.0f))
.build());
lblModel.setScene3D(move(scene));
string portrait(findPortrait(config.appearance));
Control &lblPortrait = getControl("PORTRAIT_LBL");
if (!portrait.empty()) {
lblPortrait.setBorderFill(portrait);
}
}
shared_ptr<ModelSceneNode> CharacterGeneration::getCharacterModel(const CreatureConfiguration &config, SceneGraph &sceneGraph) {
unique_ptr<ObjectFactory> objectFactory(new ObjectFactory(_version, _game, &sceneGraph, _gfxOpts));
unique_ptr<Creature> creature(objectFactory->newCreature());
creature->load(config);
return creature->model();
}
void CharacterGeneration::loadQuickOrCustom() {
_quickOrCustom = make_unique<QuickOrCustom>(_version, _gfxOpts);
_quickOrCustom = make_unique<QuickOrCustom>(this, _version, _gfxOpts);
_quickOrCustom->load();
_quickOrCustom->setOnQuickCharacter([this]() {
_quickOrCustom->resetFocus();
_screen = CharGenScreen::Quick;
});
_quickOrCustom->setOnBack([this]() {
_quickOrCustom->resetFocus();
hideControl("MODEL_LBL");
_screen = CharGenScreen::ClassSelection;
});
}
void CharacterGeneration::loadQuickCharacterGeneration() {
_quick = make_unique<QuickCharacterGeneration>(_version, _gfxOpts);
void CharacterGeneration::loadQuick() {
_quick = make_unique<QuickCharacterGeneration>(this, _version, _gfxOpts);
_quick->load();
if (_version == GameVersion::KotOR) {
_quick->configureControl("LBL_DECORATION", [](Control &ctrl) { ctrl.setDiscardColor(glm::vec3(0.0f, 0.0f, 0.082353f)); });
}
_quick->setOnStepSelected([this](int step) {
_quick->resetFocus();
switch (step) {
case 1:
hideControl("MODEL_LBL");
_portraitSelection->loadPortraits(_character);
_screen = CharGenScreen::PortraitSelection;
break;
case 2:
hideControl("MODEL_LBL");
_screen = CharGenScreen::Name;
break;
default:
finishCharacterGeneration();
break;
}
});
_quick->setOnCancel([this]() {
_quick->resetFocus();
_screen = CharGenScreen::QuickOrCustom;
});
}
void CharacterGeneration::finishCharacterGeneration() {
string moduleName(_version == GameVersion::KotOR ? "end_m01aa" : "001ebo");
CreatureConfiguration config(_character);
config.equipment.clear();
PartyConfiguration party;
party.memberCount = 1;
party.leader = config;
_game->loadModule(moduleName, party);
}
void CharacterGeneration::loadPortraitSelection() {
_portraitSelection = make_unique<PortraitSelection>(_version, _gfxOpts);
_portraitSelection = make_unique<PortraitSelection>(this, _version, _gfxOpts);
_portraitSelection->load();
_portraitSelection->setOnPortraitSelected([this](const CreatureConfiguration &config) {
_portraitSelection->resetFocus();
loadCharacter(config);
showControl("MODEL_LBL");
_screen = CharGenScreen::Quick;
_quick->setStep(1);
});
_portraitSelection->setOnCancel([this]() {
_portraitSelection->resetFocus();
showControl("MODEL_LBL");
_screen = CharGenScreen::Quick;
});
}
void CharacterGeneration::loadNameEntry() {
_nameEntry = make_unique<NameEntry>(_version, _gfxOpts);
_nameEntry = make_unique<NameEntry>(this, _version, _gfxOpts);
_nameEntry->load();
_nameEntry->setOnEnd([this]() {
_nameEntry->resetFocus();
showControl("MODEL_LBL");
_screen = CharGenScreen::Quick;
_quick->setStep(2);
});
_nameEntry->setOnBack([this]() {
_nameEntry->resetFocus();
showControl("MODEL_LBL");
_screen = CharGenScreen::Quick;
});
}
bool CharacterGeneration::handle(const SDL_Event &event) {
@ -262,6 +139,100 @@ void CharacterGeneration::render3D() const {
getSubGUI()->render3D();
}
void CharacterGeneration::finish() {
string moduleName(_version == GameVersion::KotOR ? "end_m01aa" : "001ebo");
CreatureConfiguration config(_character);
config.equipment.clear();
PartyConfiguration party;
party.memberCount = 1;
party.leader = config;
_game->loadModule(moduleName, party);
}
void CharacterGeneration::cancel() {
_game->openMainMenu();
}
void CharacterGeneration::openClassSelection() {
hideControl("MODEL_LBL");
_screen = CharGenScreen::ClassSelection;
}
void CharacterGeneration::openNameEntry() {
hideControl("MODEL_LBL");
_screen = CharGenScreen::Name;
}
void CharacterGeneration::openPortraitSelection() {
hideControl("MODEL_LBL");
_screen = CharGenScreen::PortraitSelection;
}
void CharacterGeneration::openQuick() {
showControl("MODEL_LBL");
_screen = CharGenScreen::Quick;
}
void CharacterGeneration::openQuickOrCustom() {
showControl("MODEL_LBL");
_screen = CharGenScreen::QuickOrCustom;
}
void CharacterGeneration::loadCharacterModel() {
Control &lblModel = getControl("MODEL_LBL");
const Control::Extent &extent = lblModel.extent();
float aspect = extent.width / static_cast<float>(extent.height);
glm::mat4 cameraTransform(1.0f);
cameraTransform = glm::translate(cameraTransform, glm::vec3(0.0f, 1.0f, 0.0f));
cameraTransform = glm::rotate(cameraTransform, glm::half_pi<float>(), glm::vec3(1.0f, 0.0f, 0.0f));
cameraTransform = glm::rotate(cameraTransform, glm::pi<float>(), glm::vec3(0.0f, 1.0f, 0.0f));
unique_ptr<Control::Scene3D> scene(SceneBuilder(_gfxOpts)
.aspect(aspect)
.depth(0.1f, 10.0f)
.modelSupplier(bind(&CharacterGeneration::getCharacterModel, this, _1))
.modelScale(kModelScale)
.modelOffset(glm::vec2(0.0f, kModelOffsetY))
.cameraTransform(cameraTransform)
.ambientLightColor(glm::vec3(1.0f))
.build());
lblModel.setScene3D(move(scene));
string portrait(findPortrait(_character.appearance));
if (!portrait.empty()) {
Control &lblPortrait = getControl("PORTRAIT_LBL");
lblPortrait.setBorderFill(portrait);
}
}
shared_ptr<ModelSceneNode> CharacterGeneration::getCharacterModel(SceneGraph &sceneGraph) {
unique_ptr<ObjectFactory> objectFactory(new ObjectFactory(_version, _game, &sceneGraph, _gfxOpts));
unique_ptr<Creature> creature(objectFactory->newCreature());
creature->load(_character);
return creature->model();
}
const CreatureConfiguration &CharacterGeneration::character() const {
return _character;
}
void CharacterGeneration::setCharacter(const CreatureConfiguration &config) {
_character = config;
loadCharacterModel();
_portraitSelection->updatePortraits();
}
void CharacterGeneration::setQuickStep(int step) {
_quick->setStep(step);
}
} // namespace game
} // namespace reone

View file

@ -48,12 +48,24 @@ public:
CharacterGeneration(Game *game, resource::GameVersion, const render::GraphicsOptions &opts);
void load() override;
bool handle(const SDL_Event &event) override;
void update(float dt) override;
void render() const override;
void render3D() const override;
void finish();
void cancel();
void openClassSelection();
void openNameEntry();
void openPortraitSelection();
void openQuick();
void openQuickOrCustom();
const CreatureConfiguration &character() const;
void setCharacter(const CreatureConfiguration &config);
void setQuickStep(int step);
private:
Game *_game { nullptr };
CharGenScreen _screen { CharGenScreen::ClassSelection };
@ -70,26 +82,20 @@ private:
// END Sub GUI
void loadCharacterModel();
gui::GUI *getSubGUI() const;
std::shared_ptr<scene::ModelSceneNode> getCharacterModel(const CreatureConfiguration &config, scene::SceneGraph &sceneGraph);
std::shared_ptr<scene::ModelSceneNode> getCharacterModel(scene::SceneGraph &sceneGraph);
// Loading
void loadClassSelection();
void loadQuickOrCustom();
void loadQuickCharacterGeneration();
void loadQuick();
void loadPortraitSelection();
void loadNameEntry();
void loadCharacter(const CreatureConfiguration &config);
// END Loading
// Event handling
void finishCharacterGeneration();
// END Event handling
};
} // namespace game

View file

@ -25,6 +25,8 @@
#include "../colors.h"
#include "chargen.h"
using namespace std;
using namespace reone::gui;
@ -62,8 +64,10 @@ static map<ClassType, int> g_classDescStrRefs {
{ ClassType::JediGuardian, 48033 }
};
ClassSelection::ClassSelection(Game *game, GameVersion version, const GraphicsOptions &opts) :
GUI(version, opts), _game(game) {
ClassSelection::ClassSelection(Game *game, CharacterGeneration *charGen, GameVersion version, const GraphicsOptions &opts) :
GUI(version, opts),
_game(game),
_charGen(charGen) {
_resRef = getResRef("classsel");
@ -240,27 +244,19 @@ int ClassSelection::getClassButtonIndexByTag(const string &tag) const {
}
void ClassSelection::onClick(const string &control) {
resetFocus();
int idx = getClassButtonIndexByTag(control);
if (idx != -1) {
ClassButton &button = _classButtons[idx];
if (_onClassSelected) {
_onClassSelected(button.config);
}
_charGen->setCharacter(_classButtons[idx].config);
_charGen->openQuickOrCustom();
return;
}
if (control == "BTN_BACK") {
if (_onCancel) _onCancel();
_charGen->cancel();
}
}
void ClassSelection::setOnClassSelected(const function<void(const CreatureConfiguration &)> &fn) {
_onClassSelected = fn;
}
void ClassSelection::setOnCancel(const function<void()> &fn) {
_onCancel = fn;
}
} // namespace game
} // namespace reone

View file

@ -28,17 +28,15 @@ namespace reone {
namespace game {
class CharacterGeneration;
class Game;
class ClassSelection : public gui::GUI {
public:
ClassSelection(Game *game, resource::GameVersion version, const render::GraphicsOptions &opts);
ClassSelection(Game *game, CharacterGeneration *charGen, resource::GameVersion version, const render::GraphicsOptions &opts);
void load() override;
void setOnClassSelected(const std::function<void(const CreatureConfiguration &)> &fn);
void setOnCancel(const std::function<void()> &fn);
private:
struct ClassButton {
gui::Control *control { nullptr };
@ -47,12 +45,11 @@ private:
};
Game *_game { nullptr };
CharacterGeneration *_charGen { nullptr };
resource::GameVersion _version { resource::GameVersion::KotOR };
glm::ivec2 _defaultButtonSize { 0 };
glm::ivec2 _enlargedButtonSize { 0 };
std::vector<ClassButton> _classButtons;
std::function<void(const CreatureConfiguration &)> _onClassSelected;
std::function<void()> _onCancel;
void configureClassButtons();
void configureClassModels();

View file

@ -19,6 +19,8 @@
#include "../colors.h"
#include "chargen.h"
using namespace std;
using namespace reone::gui;
@ -29,8 +31,9 @@ namespace reone {
namespace game {
NameEntry::NameEntry(GameVersion version, const GraphicsOptions &opts) :
NameEntry::NameEntry(CharacterGeneration *charGen, GameVersion version, const GraphicsOptions &opts) :
GUI(version, opts),
_charGen(charGen),
_input(kTextInputLetters | kTextInputWhitespace) {
_resRef = getResRef("name");
@ -62,25 +65,17 @@ bool NameEntry::handle(const SDL_Event &event) {
}
void NameEntry::onClick(const string &control) {
resetFocus();
if (control == "END_BTN") {
if (_onEnd) {
_onEnd();
}
_charGen->setQuickStep(2);
_charGen->openQuick();
} else if (control == "BTN_BACK") {
if (_onBack) {
_onBack();
}
_charGen->openQuick();
}
}
void NameEntry::setOnEnd(const function<void()> &fn) {
_onEnd = fn;
}
void NameEntry::setOnBack(const function<void()> &fn) {
_onBack = fn;
}
} // namespace game
} // namespace reone

View file

@ -24,20 +24,18 @@ namespace reone {
namespace game {
class CharacterGeneration;
class NameEntry : public gui::GUI {
public:
NameEntry(resource::GameVersion version, const render::GraphicsOptions &opts);
NameEntry(CharacterGeneration *charGen, resource::GameVersion version, const render::GraphicsOptions &opts);
void load() override;
bool handle(const SDL_Event &event) override;
void setOnEnd(const std::function<void()> &fn);
void setOnBack(const std::function<void()> &fn);
private:
CharacterGeneration *_charGen { nullptr };
gui::TextInput _input;
std::function<void()> _onEnd;
std::function<void()> _onBack;
void onClick(const std::string &control) override;
};

View file

@ -22,6 +22,8 @@
#include "../colors.h"
#include "chargen.h"
using namespace std;
using namespace reone::gui;
@ -32,7 +34,10 @@ namespace reone {
namespace game {
PortraitSelection::PortraitSelection(GameVersion version, const GraphicsOptions &opts) : GUI(version, opts) {
PortraitSelection::PortraitSelection(CharacterGeneration *charGen, GameVersion version, const GraphicsOptions &opts) :
GUI(version, opts),
_charGen(charGen) {
_resRef = getResRef("portcust");
switch (version) {
@ -65,15 +70,12 @@ void PortraitSelection::setButtonColors(const string &tag) {
control.setHilight(move(hilight));
}
void PortraitSelection::loadPortraits(const CreatureConfiguration &config) {
if (!_portraits.empty() && _character == config) return;
_character = config;
void PortraitSelection::updatePortraits() {
_portraits.clear();
shared_ptr<TwoDaTable> portraits(Resources.find2DA("portraits"));
int sex = _character.gender == Gender::Female ? 1 : 0;
_portraits.clear();
const CreatureConfiguration &character = _charGen->character();
int sex = character.gender == Gender::Female ? 1 : 0;
for (auto &row : portraits->rows()) {
if (row.getInt("forpc") == 1 && row.getInt("sex") == sex) {
@ -94,14 +96,18 @@ void PortraitSelection::loadPortraits(const CreatureConfiguration &config) {
_portraits.push_back(move(portrait));
}
}
auto maybePortrait = find_if(_portraits.begin(), _portraits.end(), [&config](const Portrait &portrait) {
resetCurrentPortrait();
}
void PortraitSelection::resetCurrentPortrait() {
const CreatureConfiguration &character = _charGen->character();
auto maybePortrait = find_if(_portraits.begin(), _portraits.end(), [&character](const Portrait &portrait) {
return
portrait.appearanceNumber == config.appearance ||
portrait.appearanceS == config.appearance ||
portrait.appearanceL == config.appearance;
portrait.appearanceNumber == character.appearance ||
portrait.appearanceS == character.appearance ||
portrait.appearanceL == character.appearance;
});
_currentPortrait = static_cast<int>(distance(_portraits.begin(), maybePortrait));
loadCurrentPortrait();
}
@ -115,6 +121,8 @@ void PortraitSelection::loadCurrentPortrait() {
}
void PortraitSelection::onClick(const string &control) {
resetFocus();
int portraitCount = static_cast<int>(_portraits.size());
if (control == "BTN_ARRL") {
@ -129,37 +137,30 @@ void PortraitSelection::onClick(const string &control) {
loadCurrentPortrait();
} else if (control == "BTN_ACCEPT") {
if (_onPortraitSelected) {
int appearance;
switch (_character.clazz) {
case ClassType::Scoundrel:
appearance = _portraits[_currentPortrait].appearanceS;
break;
case ClassType::Soldier:
appearance = _portraits[_currentPortrait].appearanceL;
break;
default:
appearance = _portraits[_currentPortrait].appearanceNumber;
break;
}
CreatureConfiguration charGenInfo(_character);
charGenInfo.appearance = appearance;
_onPortraitSelected(charGenInfo);
CreatureConfiguration character(_charGen->character());
int appearance;
switch (character.clazz) {
case ClassType::Scoundrel:
appearance = _portraits[_currentPortrait].appearanceS;
break;
case ClassType::Soldier:
appearance = _portraits[_currentPortrait].appearanceL;
break;
default:
appearance = _portraits[_currentPortrait].appearanceNumber;
break;
}
character.appearance = appearance;
_charGen->setQuickStep(1);
_charGen->setCharacter(character);
_charGen->openQuick();
} else if (control == "BTN_BACK") {
if (_onCancel) _onCancel();
resetCurrentPortrait();
_charGen->openQuick();
}
}
void PortraitSelection::setOnPortraitSelected(const function<void(const CreatureConfiguration &)> &fn) {
_onPortraitSelected = fn;
}
void PortraitSelection::setOnCancel(const function<void()> &fn) {
_onCancel = fn;
}
} // namespace game
} // namespace reone

View file

@ -26,26 +26,26 @@ namespace reone {
namespace game {
class CharacterGeneration;
class PortraitSelection : public gui::GUI {
public:
PortraitSelection(resource::GameVersion version, const render::GraphicsOptions &opts);
PortraitSelection(CharacterGeneration *charGen, resource::GameVersion version, const render::GraphicsOptions &opts);
void load() override;
void loadPortraits(const CreatureConfiguration &config);
void setOnPortraitSelected(const std::function<void(const CreatureConfiguration &)> &fn);
void setOnCancel(const std::function<void()> &fn);
void updatePortraits();
void resetCurrentPortrait();
private:
CreatureConfiguration _character;
CharacterGeneration *_charGen { nullptr };
std::vector<Portrait> _portraits;
int _currentPortrait { 0 };
std::function<void(const CreatureConfiguration &)> _onPortraitSelected;
std::function<void()> _onCancel;
void setButtonColors(const std::string &tag);
void loadCurrentPortrait();
void onClick(const std::string &control) override;
void loadCurrentPortrait();
void setButtonColors(const std::string &tag);
};
} // namespace game

View file

@ -21,6 +21,8 @@
#include "../colors.h"
#include "chargen.h"
using namespace std;
using namespace reone::gui;
@ -31,7 +33,10 @@ namespace reone {
namespace game {
QuickCharacterGeneration::QuickCharacterGeneration(GameVersion version, const GraphicsOptions &opts) : GUI(version, opts) {
QuickCharacterGeneration::QuickCharacterGeneration(CharacterGeneration *charGen, GameVersion version, const GraphicsOptions &opts) :
GUI(version, opts),
_charGen(charGen) {
_resRef = getResRef("quickpnl");
if (_version == GameVersion::TheSithLords) {
@ -42,10 +47,20 @@ QuickCharacterGeneration::QuickCharacterGeneration(GameVersion version, const Gr
void QuickCharacterGeneration::load() {
GUI::load();
setStep(0);
doSetStep(0);
if (_version == GameVersion::KotOR) {
configureControl("LBL_DECORATION", [](Control &ctrl) { ctrl.setDiscardColor(glm::vec3(0.0f, 0.0f, 0.082353f)); });
}
}
void QuickCharacterGeneration::setStep(int step) {
if (_step != step) {
doSetStep(step);
}
}
void QuickCharacterGeneration::doSetStep(int step) {
_step = step;
setControlFocusable("LBL_1", false);
@ -84,36 +99,34 @@ void QuickCharacterGeneration::setStep(int step) {
}
void QuickCharacterGeneration::onClick(const string &control) {
resetFocus();
if (control == "BTN_CANCEL") {
setStep(0);
_charGen->openQuickOrCustom();
if (_onCancel) {
_onCancel();
}
} else if (control == "BTN_BACK") {
if (_step == 0) {
if (_onCancel) {
_onCancel();
}
_charGen->openQuickOrCustom();
} else {
setStep(_step - 1);
}
} else if (boost::starts_with(control, "BTN_STEPNAME")) {
int step = control[12] - '0';
if (_onStepSelected) {
_onStepSelected(step);
switch (step) {
case 1:
_charGen->openPortraitSelection();
break;
case 2:
_charGen->openNameEntry();
break;
default:
_charGen->finish();
break;
}
}
}
void QuickCharacterGeneration::setOnStepSelected(const function<void(int)> &fn) {
_onStepSelected = fn;
}
void QuickCharacterGeneration::setOnCancel(const function<void()> &fn) {
_onCancel = fn;
}
} // namespace game
} // namespace reone

View file

@ -23,24 +23,23 @@ namespace reone {
namespace game {
class CharacterGeneration;
class QuickCharacterGeneration : public gui::GUI {
public:
QuickCharacterGeneration(resource::GameVersion version, const render::GraphicsOptions &opts);
QuickCharacterGeneration(CharacterGeneration *charGen, resource::GameVersion version, const render::GraphicsOptions &opts);
void load() override;
void setStep(int step);
void setOnStepSelected(const std::function<void(int)> &fn);
void setOnCancel(const std::function<void()> &fn);
private:
CharacterGeneration *_charGen { nullptr };
int _step { 0 };
std::function<void(int)> _onStepSelected;
std::function<void()> _onCancel;
void onClick(const std::string &control) override;
void doSetStep(int step);
};
} // namespace game

View file

@ -19,6 +19,8 @@
#include "../colors.h"
#include "chargen.h"
using namespace std;
using namespace reone::gui;
@ -29,7 +31,10 @@ namespace reone {
namespace game {
QuickOrCustom::QuickOrCustom(GameVersion version, const GraphicsOptions &opts) : GUI(version, opts) {
QuickOrCustom::QuickOrCustom(CharacterGeneration *charGen, GameVersion version, const GraphicsOptions &opts) :
GUI(version, opts),
_charGen(charGen) {
_resRef = getResRef("qorcpnl");
if (version == GameVersion::TheSithLords) {
@ -49,25 +54,16 @@ void QuickOrCustom::load() {
}
void QuickOrCustom::onClick(const string &control) {
resetFocus();
if (control == "QUICK_CHAR_BTN") {
if (_onQuickChar) {
_onQuickChar();
}
_charGen->setQuickStep(0);
_charGen->openQuick();
} else if (control == "BTN_BACK") {
if (_onBack) {
_onBack();
}
_charGen->openClassSelection();
}
}
void QuickOrCustom::setOnQuickCharacter(const function<void()> &fn) {
_onQuickChar = fn;
}
void QuickOrCustom::setOnBack(const function<void()> &fn) {
_onBack = fn;
}
} // namespace game
} // namespace reone

View file

@ -23,18 +23,16 @@ namespace reone {
namespace game {
class CharacterGeneration;
class QuickOrCustom : public gui::GUI {
public:
QuickOrCustom(resource::GameVersion version, const render::GraphicsOptions &opts);
QuickOrCustom(CharacterGeneration *charGen, resource::GameVersion version, const render::GraphicsOptions &opts);
void load() override;
void setOnQuickCharacter(const std::function<void()> &fn);
void setOnBack(const std::function<void()> &fn);
private:
std::function<void()> _onQuickChar;
std::function<void()> _onBack;
CharacterGeneration *_charGen { nullptr };
void onClick(const std::string &control) override;
};

View file

@ -53,8 +53,9 @@ enum EndEntryFlags {
kEndEntryOnAudioStop = 2
};
Dialog::Dialog(GameVersion version, Game *game, const GraphicsOptions &opts) :
GUI(version, opts), _game(game) {
Dialog::Dialog(Game *game, GameVersion version, const GraphicsOptions &opts) :
GUI(version, opts),
_game(game) {
_resRef = getResRef("dialog");
_scaling = ScalingMode::Stretch;
@ -119,18 +120,13 @@ void Dialog::configureReplies() {
}
void Dialog::onReplyClicked(int index) {
if (!_pickReplyEnabled) return;
if (_onReplyPicked) {
_onReplyPicked(index);
}
pickReply(index);
}
void Dialog::startDialog(SpatialObject &owner, const string &resRef) {
shared_ptr<GffStruct> dlg(Resources.findGFF(resRef, ResourceType::Conversation));
if (!dlg) {
if (_onDialogFinished) _onDialogFinished();
_game->openInGame();
return;
}
_owner = &owner;
@ -164,7 +160,7 @@ void Dialog::loadStartEntry() {
}
}
if (entryIdx == -1) {
if (_onDialogFinished) _onDialogFinished();
_game->openInGame();
return;
}
_currentEntry.reset(new DlgFile::EntryReply(_dialog->getEntry(entryIdx)));
@ -234,9 +230,7 @@ void Dialog::finish() {
if (_currentSpeaker) {
static_cast<Creature &>(*_currentSpeaker).setTalking(false);
}
if (_onDialogFinished) {
_onDialogFinished();
}
_game->openInGame();
}
void Dialog::loadCurrentSpeaker() {
@ -459,18 +453,6 @@ Camera &Dialog::camera() const {
return cameraModel.empty() ? area->dialogCamera() : static_cast<Camera &>(area->animatedCamera());
}
void Dialog::setPickReplyEnabled(bool enabled) {
_pickReplyEnabled = enabled;
}
void Dialog::setOnReplyPicked(const function<void(uint32_t)> &fn) {
_onReplyPicked = fn;
}
void Dialog::setOnDialogFinished(const function<void()> &fn) {
_onDialogFinished = fn;
}
} // namespace game
} // namespace reone

View file

@ -33,7 +33,7 @@ class Game;
class Dialog : public gui::GUI {
public:
Dialog(resource::GameVersion version, Game *game, const render::GraphicsOptions &opts);
Dialog(Game *game, resource::GameVersion version, const render::GraphicsOptions &opts);
void load() override;
void startDialog(SpatialObject &owner, const std::string &resRef);
@ -44,10 +44,6 @@ public:
Camera &camera() const;
void setPickReplyEnabled(bool enabled);
void setOnReplyPicked(const std::function<void(uint32_t)> &fn);
void setOnDialogFinished(const std::function<void()> &fn);
private:
Game *_game { nullptr };
SpatialObject *_owner { nullptr };
@ -55,19 +51,11 @@ private:
std::shared_ptr<resource::DlgFile::EntryReply> _currentEntry;
std::shared_ptr<audio::SoundInstance> _currentVoice;
SpatialObject *_currentSpeaker { nullptr };
bool _pickReplyEnabled { true };
int _autoPickReplyIdx { -1 };
int _endEntryFlags { 0 };
uint32_t _endEntryTimestamp { 0 };
bool _entryEnded { false };
// Callbacks
std::function<void(uint32_t)> _onReplyPicked;
std::function<void()> _onDialogFinished;
// END Callbacks
bool handleKeyDown(SDL_Scancode key) override;
bool handleKeyUp(SDL_Scancode key) override;

View file

@ -23,6 +23,7 @@
#include "../../system/gui/control/listbox.h"
#include "../../system/resource/resources.h"
#include "../game.h"
#include "../object/creature.h"
#include "../object/item.h"
@ -55,7 +56,10 @@ static unordered_map<Equipment::Slot, string> g_slotNames = {
{ Equipment::Slot::WeapR2, "WEAP_R2"}
};
Equipment::Equipment(GameVersion version, const GraphicsOptions &opts) : GUI(version, opts) {
Equipment::Equipment(Game *game, GameVersion version, const GraphicsOptions &opts) :
GUI(version, opts),
_game(game) {
_resRef = getResRef("equip");
_backgroundType = BackgroundType::Menu;
@ -129,10 +133,6 @@ void Equipment::open(SpatialObject *owner) {
selectSlot(Slot::None);
}
void Equipment::setOnClose(const function<void()> &fn) {
_onClose = fn;
}
void Equipment::preloadControl(Control &control) {
if (control.tag() == "LB_ITEMS") {
static_cast<ListBox &>(control).setProtoItemType(ControlType::ImageButton);
@ -142,9 +142,7 @@ void Equipment::preloadControl(Control &control) {
void Equipment::onClick(const string &control) {
if (control == "BTN_EQUIP" || control == "BTN_BACK") {
if (_selectedSlot == Slot::None) {
if (_onClose) {
_onClose();
}
_game->openInGame();
} else {
selectSlot(Slot::None);
}

View file

@ -26,6 +26,8 @@ namespace reone {
namespace game {
class Game;
class Equipment : public gui::GUI {
public:
enum class Slot {
@ -43,18 +45,16 @@ public:
WeapR2
};
Equipment(resource::GameVersion version, const render::GraphicsOptions &opts);
Equipment(Game *game, resource::GameVersion version, const render::GraphicsOptions &opts);
void load() override;
void open(SpatialObject *owner);
void setOnClose(const std::function<void()> &fn);
private:
Game *_game { nullptr };
SpatialObject *_owner { nullptr };
Slot _selectedSlot { Slot::None };
int _selectedItemIdx { -1 };
std::function<void()> _onClose;
static resource::InventorySlot getInventorySlot(Slot slot);
static std::shared_ptr<render::Texture> getEmptySlotIcon(Slot slot);

View file

@ -20,6 +20,8 @@
#include "../../system/log.h"
#include "../../system/gui/control/label.h"
#include "../game.h"
using namespace std;
using namespace reone::gui;
@ -30,8 +32,11 @@ namespace reone {
namespace game {
HUD::HUD(GameVersion version, const GraphicsOptions &opts) :
GUI(version, opts), _debug(opts), _select(opts) {
HUD::HUD(Game *game, GameVersion version, const GraphicsOptions &opts) :
GUI(version, opts),
_game(game),
_debug(opts),
_select(opts) {
_resRef = getResRef("mipc28x6");
_resolutionX = 800;
@ -144,9 +149,8 @@ void HUD::render() const {
void HUD::onClick(const string &control) {
if (control == "BTN_EQU") {
if (_onEquipmentClick) {
_onEquipmentClick();
}
resetFocus();
_game->openEquipment();
}
}
@ -187,10 +191,6 @@ void HUD::setContext(const GuiContext &ctx) {
_debug.setContext(ctx.debug);
}
void HUD::setOnEquipmentClick(const function<void()> &fn) {
_onEquipmentClick = fn;
}
} // namespace game
} // namespace reone

View file

@ -29,23 +29,23 @@ namespace reone {
namespace game {
class Game;
class HUD : public gui::GUI {
public:
HUD(resource::GameVersion version, const render::GraphicsOptions &opts);
HUD(Game *game, resource::GameVersion version, const render::GraphicsOptions &opts);
void load() override;
void render() const override;
void setContext(const GuiContext &ctx);
void setOnEquipmentClick(const std::function<void()> &fn);
private:
Game *_game { nullptr };
DebugOverlay _debug;
SelectionOverlay _select;
std::function<void()> _onEquipmentClick;
void onClick(const std::string &control) override;
};