refactor: Store and reuse loaded modules

This is how global game state will be tracked.
This commit is contained in:
Vsevolod Kremianskii 2020-10-27 11:34:37 +07:00
parent 52ad37ea25
commit b638551c00
6 changed files with 81 additions and 54 deletions

View file

@ -136,26 +136,8 @@ void Game::loadMainMenu() {
void Game::loadModule(const string &name, const PartyConfiguration &party, string entry) {
info("Game: load module: " + name);
_partyConfig = party;
withLoadingScreen([this, &name, &party, &entry]() {
Resources::instance().loadModule(name);
Models::instance().invalidateCache();
Walkmeshes::instance().invalidateCache();
Textures::instance().invalidateCache();
AudioFiles::instance().invalidateCache();
Scripts::instance().invalidateCache();
Blueprints::instance().invalidateCache();
shared_ptr<GffStruct> ifo(Resources::instance().getGFF("module", ResourceType::ModuleInfo));
_module = _objectFactory->newModule();
_module->load(name, *ifo);
_module->loadParty(_partyConfig, entry);
string musicName(_module->area()->music());
playMusic(musicName);
if (!_hud) {
loadHUD();
}
@ -171,6 +153,37 @@ void Game::loadModule(const string &name, const PartyConfiguration &party, strin
if (!_partySelection) {
loadPartySelection();
}
Models::instance().invalidateCache();
Walkmeshes::instance().invalidateCache();
Textures::instance().invalidateCache();
AudioFiles::instance().invalidateCache();
Scripts::instance().invalidateCache();
Blueprints::instance().invalidateCache();
Resources::instance().loadModule(name);
_party.clear();
auto maybeModule = _loadedModules.find(name);
if (maybeModule != _loadedModules.end()) {
_module = maybeModule->second;
} else {
shared_ptr<GffStruct> ifo(Resources::instance().getGFF("module", ResourceType::ModuleInfo));
_module = _objectFactory->newModule();
_module->load(name, *ifo);
_loadedModules.insert(make_pair(name, _module));
}
_module->loadParty(party, entry);
_module->area()->fill(_sceneGraph);
_partyConfig = party;
string musicName(_module->area()->music());
playMusic(musicName);
_ticks = SDL_GetTicks();
_screen = GameScreen::InGame;
});
@ -345,7 +358,6 @@ void Game::loadNextModule() {
JobExecutor::instance().cancel();
JobExecutor::instance().await();
_sceneGraph.clear();
loadModule(_nextModule, _partyConfig, _nextEntry);
_nextModule.clear();

View file

@ -62,6 +62,8 @@ public:
Game(const boost::filesystem::path &path, const Options &opts);
virtual ~Game() = default;
bool handle(const SDL_Event &event) override;
int run();
void loadModule(const std::string &name, const PartyConfiguration &party, std::string entry = "");
@ -76,8 +78,6 @@ public:
void startDialog(SpatialObject &owner, const std::string &resRef);
void quit();
bool handle(const SDL_Event &event) override;
resource::GameVersion version() const;
const Options &options() const;
scene::SceneGraph &sceneGraph();
@ -126,15 +126,21 @@ private:
resource::GameVersion _version { resource::GameVersion::KotOR };
std::unique_ptr<ObjectFactory> _objectFactory;
GameScreen _screen { GameScreen::MainMenu };
std::string _nextModule;
std::string _nextEntry;
std::shared_ptr<Module> _module;
Party _party;
PartyConfiguration _partyConfig;
std::shared_ptr<audio::SoundInstance> _music;
uint32_t _ticks { 0 };
bool _quit { false };
// Modules
std::string _nextModule;
std::string _nextEntry;
std::shared_ptr<Module> _module;
std::map<std::string, std::shared_ptr<Module>> _loadedModules;
// END Modules
// GUI
std::unique_ptr<MainMenu> _mainMenu;

View file

@ -92,15 +92,11 @@ void Area::loadLYT() {
LytFile lyt;
lyt.load(wrap(Resources::instance().get(_name, ResourceType::AreaLayout)));
SceneGraph *sceneGraph = &_game->sceneGraph();
for (auto &lytRoom : lyt.rooms()) {
shared_ptr<ModelSceneNode> model(new ModelSceneNode(sceneGraph, Models::instance().get(lytRoom.name)));
shared_ptr<ModelSceneNode> model(new ModelSceneNode(&_game->sceneGraph(), Models::instance().get(lytRoom.name)));
model->setLocalTransform(glm::translate(glm::mat4(1.0f), lytRoom.position));
model->playAnimation("animloop1", kAnimationLoop);
sceneGraph->addRoot(model);
shared_ptr<Walkmesh> walkmesh(Walkmeshes::instance().get(lytRoom.name, ResourceType::Walkmesh));
unique_ptr<Room> room(new Room(lytRoom.name, lytRoom.position, model, walkmesh));
@ -124,8 +120,6 @@ void Area::loadPTH() {
const vector<PthFile::Point> &points = path.points();
unordered_map<int, float> pointZ;
SceneGraph *sceneGraph = &_game->sceneGraph();
for (int i = 0; i < points.size(); ++i) {
const PthFile::Point &point = points[i];
Room *room = nullptr;
@ -136,11 +130,6 @@ void Area::loadPTH() {
continue;
}
pointZ.insert(make_pair(i, z));
shared_ptr<CubeSceneNode> aabb(new CubeSceneNode(sceneGraph, 0.5f));
aabb->setLocalTransform(glm::translate(glm::mat4(1.0f), glm::vec3(point.x, point.y, z + 0.25f)));
sceneGraph->addRoot(aabb);
}
_pathfinder.load(points, pointZ);
@ -314,11 +303,6 @@ void Area::add(const shared_ptr<SpatialObject> &object) {
_objectById.insert(make_pair(object->id(), object));
_objectsByTag[object->tag()].push_back(object);
shared_ptr<ModelSceneNode> sceneNode(object->model());
if (sceneNode) {
_game->sceneGraph().addRoot(sceneNode);
}
determineObjectRoom(*object);
}
@ -410,7 +394,17 @@ void Area::loadParty(const PartyConfiguration &config, const glm::vec3 &position
Party &party = _game->party();
bool firstLoad = party.empty();
if (!firstLoad) {
if (firstLoad) {
if (config.memberCount > 0) {
shared_ptr<Creature> partyLeader(makeCharacter(config.leader, kPartyLeaderTag, position, heading));
landObject(*partyLeader);
add(partyLeader);
_player = partyLeader;
_partyLeader = partyLeader;
party.addMember(partyLeader.get());
_game->module()->player().setCreature(static_cast<Creature *>(_player.get()));
}
} else {
if (_partyMember1) {
destroyObject(*_partyMember1);
}
@ -422,15 +416,6 @@ void Area::loadParty(const PartyConfiguration &config, const glm::vec3 &position
party.clear();
party.addMember(static_cast<Creature *>(_partyLeader.get()));
}
if (firstLoad && config.memberCount > 0) {
shared_ptr<Creature> partyLeader(makeCharacter(config.leader, kPartyLeaderTag, position, heading));
landObject(*partyLeader);
add(partyLeader);
_player = partyLeader;
_partyLeader = partyLeader;
party.addMember(partyLeader.get());
_game->module()->player().setCreature(static_cast<Creature *>(_player.get()));
}
if (config.memberCount > 1) {
shared_ptr<Creature> partyMember(makeCharacter(config.member1, kPartyMember1Tag, position, heading));
landObject(*partyMember);
@ -587,6 +572,23 @@ void Area::destroyObject(const SpatialObject &object) {
_objectsToDestroy.insert(object.id());
}
void Area::fill(SceneGraph &sceneGraph) {
sceneGraph.clear();
for (auto &room : _rooms) {
shared_ptr<ModelSceneNode> sceneNode(room.second->model());
if (sceneNode) {
sceneGraph.addRoot(sceneNode);
}
}
for (auto &object : _objects) {
shared_ptr<ModelSceneNode> sceneNode(object->model());
if (sceneNode) {
sceneGraph.addRoot(sceneNode);
}
}
}
void Area::fill(const UpdateContext &updateCtx, GuiContext &guiCtx) {
addPartyMemberPortrait(_partyLeader, guiCtx);
addPartyMemberPortrait(_partyMember1, guiCtx);

View file

@ -42,6 +42,12 @@
namespace reone {
namespace scene {
class SceneGraph;
}
namespace game {
typedef std::unordered_map<std::string, std::shared_ptr<Room>> RoomMap;
@ -54,6 +60,7 @@ public:
Area(uint32_t id, Game *game);
void destroyObject(const SpatialObject &object);
void fill(scene::SceneGraph &sceneGraph);
void fill(const UpdateContext &updateCtx, GuiContext &guiCtx);
bool handle(const SDL_Event &event);
void load(const std::string &name, const resource::GffStruct &are, const resource::GffStruct &git);

View file

@ -59,8 +59,8 @@ const glm::vec3 &Room::position() const {
return _position;
}
const ModelSceneNode *Room::model() const {
return _model.get();
shared_ptr<ModelSceneNode> Room::model() const {
return _model;
}
const Walkmesh *Room::walkmesh() const {

View file

@ -45,7 +45,7 @@ public:
const std::string &name() const;
const glm::vec3 &position() const;
const scene::ModelSceneNode *model() const;
std::shared_ptr<scene::ModelSceneNode> model() const;
const render::Walkmesh *walkmesh() const;
bool visible() const;