Refactor resource management
- Move GameID into libgame - Move resource provider registration into Game - Move GUI background loading into GameGUI
This commit is contained in:
parent
32bc207b14
commit
9c5be9b87a
69 changed files with 457 additions and 533 deletions
|
@ -96,7 +96,6 @@ set_target_properties(libcommon PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINA
|
|||
|
||||
set(RESOURCE_HEADERS
|
||||
src/resource/2da.h
|
||||
src/resource/gameidutil.h
|
||||
src/resource/gffstruct.h
|
||||
src/resource/folder.h
|
||||
src/resource/format/2dareader.h
|
||||
|
@ -125,7 +124,6 @@ set(RESOURCE_HEADERS
|
|||
|
||||
set(RESOURCE_SOURCES
|
||||
src/resource/2da.cpp
|
||||
src/resource/gameidutil.cpp
|
||||
src/resource/gffstruct.cpp
|
||||
src/resource/folder.cpp
|
||||
src/resource/format/2dareader.cpp
|
||||
|
@ -181,7 +179,6 @@ set(RENDER_HEADERS
|
|||
src/render/model/emitter.h
|
||||
src/render/model/mdlreader.h
|
||||
src/render/model/model.h
|
||||
src/render/model/modelloader.h
|
||||
src/render/model/modelmesh.h
|
||||
src/render/model/modelnode.h
|
||||
src/render/model/models.h
|
||||
|
@ -442,6 +439,7 @@ set(GAME_HEADERS
|
|||
src/game/enginetype/event.h
|
||||
src/game/enginetype/location.h
|
||||
src/game/game.h
|
||||
src/game/gameidutil.h
|
||||
src/game/gui/barkbubble.h
|
||||
src/game/gui/chargen/abilities.h
|
||||
src/game/gui/chargen/chargen.h
|
||||
|
@ -557,6 +555,9 @@ set(GAME_SOURCES
|
|||
src/game/cursors.cpp
|
||||
src/game/dialog.cpp
|
||||
src/game/game.cpp
|
||||
src/game/game_kotor.cpp
|
||||
src/game/game_tsl.cpp
|
||||
src/game/gameidutil.cpp
|
||||
src/game/gui/barkbubble.cpp
|
||||
src/game/gui/chargen/abilities.cpp
|
||||
src/game/gui/chargen/chargen.cpp
|
||||
|
|
|
@ -43,14 +43,14 @@ AudioFiles::AudioFiles() : MemoryCache(bind(&AudioFiles::doGet, this, _1)) {
|
|||
shared_ptr<AudioStream> AudioFiles::doGet(string resRef) {
|
||||
shared_ptr<AudioStream> result;
|
||||
|
||||
shared_ptr<ByteArray> mp3Data(Resources::instance().get(resRef, ResourceType::Mp3, false));
|
||||
shared_ptr<ByteArray> mp3Data(Resources::instance().getRaw(resRef, ResourceType::Mp3, false));
|
||||
if (mp3Data) {
|
||||
Mp3Reader mp3;
|
||||
mp3.load(wrap(mp3Data));
|
||||
result = mp3.stream();
|
||||
}
|
||||
if (!result) {
|
||||
shared_ptr<ByteArray> wavData(Resources::instance().get(resRef, ResourceType::Wav));
|
||||
shared_ptr<ByteArray> wavData(Resources::instance().getRaw(resRef, ResourceType::Wav));
|
||||
if (wavData) {
|
||||
WavReader wav;
|
||||
wav.load(wrap(wavData));
|
||||
|
|
|
@ -44,13 +44,13 @@ public:
|
|||
|
||||
~Cursors();
|
||||
|
||||
void init(resource::GameID gameId);
|
||||
void init(GameID gameId);
|
||||
void deinit();
|
||||
|
||||
std::shared_ptr<render::Cursor> get(CursorType type);
|
||||
|
||||
private:
|
||||
resource::GameID _gameId { resource::GameID::KotOR };
|
||||
GameID _gameId { GameID::KotOR };
|
||||
std::unordered_map<CursorType, std::shared_ptr<render::Cursor>> _cache;
|
||||
|
||||
const std::pair<uint32_t, uint32_t> &getCursorNames(CursorType type);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#include "game.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "SDL2/SDL_timer.h"
|
||||
|
||||
#include "../audio/files.h"
|
||||
|
@ -34,7 +36,6 @@
|
|||
#include "../render/textures.h"
|
||||
#include "../render/walkmesh/walkmeshes.h"
|
||||
#include "../render/window.h"
|
||||
#include "../resource/gameidutil.h"
|
||||
#include "../resource/resources.h"
|
||||
#include "../resource/strings.h"
|
||||
#include "../script/scripts.h"
|
||||
|
@ -43,6 +44,7 @@
|
|||
|
||||
#include "blueprint/blueprints.h"
|
||||
#include "cursors.h"
|
||||
#include "gameidutil.h"
|
||||
#include "reputes.h"
|
||||
#include "gui/sounds.h"
|
||||
#include "script/routines.h"
|
||||
|
@ -65,6 +67,9 @@ namespace reone {
|
|||
|
||||
namespace game {
|
||||
|
||||
static constexpr char kDataDirectoryName[] = "data";
|
||||
static constexpr char kModulesDirectoryName[] = "modules";
|
||||
|
||||
static bool g_conversationsEnabled = true;
|
||||
|
||||
Game::Game(const fs::path &path, const Options &opts) :
|
||||
|
@ -99,25 +104,23 @@ int Game::run() {
|
|||
}
|
||||
|
||||
void Game::init() {
|
||||
initResourceProviders();
|
||||
loadModuleNames();
|
||||
|
||||
RenderWindow::instance().init(_options.graphics, this);
|
||||
Strings::instance().init(_gameId, _path);
|
||||
Resources::instance().init(_gameId, _path);
|
||||
Strings::instance().init(_path);
|
||||
Meshes::instance().init();
|
||||
Textures::instance().init(_gameId);
|
||||
Textures::instance().init();
|
||||
Materials::instance().init();
|
||||
PBRIBL::instance().init();
|
||||
Shaders::instance().init();
|
||||
AudioPlayer::instance().init(_options.audio);
|
||||
GUISounds::instance().init();
|
||||
Routines::instance().init(_gameId, this);
|
||||
Routines::instance().init(this);
|
||||
Reputes::instance().init();
|
||||
|
||||
Surfaces::instance().init();
|
||||
Walkmeshes::instance().init(Surfaces::instance().getWalkableSurfaceIndices(), Surfaces::instance().getGrassSurfaceIndices());
|
||||
|
||||
Models::instance().init(_gameId);
|
||||
registerModelLoaders();
|
||||
|
||||
Cursors::instance().init(_gameId);
|
||||
setCursorType(CursorType::Default);
|
||||
|
||||
|
@ -126,8 +129,27 @@ void Game::init() {
|
|||
_profileOverlay.init();
|
||||
}
|
||||
|
||||
void Game::registerModelLoaders() {
|
||||
Models::instance().registerLoader(ResourceType::Mdl, make_shared<MdlModelLoader>());
|
||||
void Game::initResourceProviders() {
|
||||
if (isTSL(_gameId)) {
|
||||
initResourceProvidersForTSL();
|
||||
} else {
|
||||
initResourceProvidersForKotOR();
|
||||
}
|
||||
Resources::instance().indexDirectory(getPathIgnoreCase(fs::current_path(), kDataDirectoryName));
|
||||
}
|
||||
|
||||
void Game::loadModuleNames() {
|
||||
fs::path modules(getPathIgnoreCase(_path, kModulesDirectoryName));
|
||||
|
||||
for (auto &entry : fs::directory_iterator(modules)) {
|
||||
string filename(boost::to_lower_copy(entry.path().filename().string()));
|
||||
if (!boost::ends_with(filename, ".rim") || boost::ends_with(filename, "_s.rim")) continue;
|
||||
|
||||
string moduleName(boost::to_lower_copy(filename.substr(0, filename.size() - 4)));
|
||||
_moduleNames.push_back(move(moduleName));
|
||||
}
|
||||
|
||||
sort(_moduleNames.begin(), _moduleNames.end());
|
||||
}
|
||||
|
||||
void Game::setCursorType(CursorType type) {
|
||||
|
@ -232,7 +254,7 @@ void Game::loadModule(const string &name, string entry) {
|
|||
SoundSets::instance().invalidate();
|
||||
Lips::instance().invalidate();
|
||||
|
||||
Resources::instance().loadModule(name);
|
||||
loadModuleResources(name);
|
||||
|
||||
if (_module) {
|
||||
_module->area()->runOnExitScript();
|
||||
|
@ -280,6 +302,22 @@ void Game::withLoadingScreen(const string &imageResRef, const function<void()> &
|
|||
block();
|
||||
}
|
||||
|
||||
void Game::loadModuleResources(const string &moduleName) {
|
||||
Resources::instance().invalidateCache();
|
||||
Resources::instance().clearTransientProviders();
|
||||
|
||||
fs::path modulesPath(getPathIgnoreCase(_path, kModulesDirectoryName));
|
||||
Resources::instance().indexRimFile(getPathIgnoreCase(modulesPath, moduleName + ".rim"), true);
|
||||
Resources::instance().indexRimFile(getPathIgnoreCase(modulesPath, moduleName + "_s.rim"), true);
|
||||
|
||||
fs::path lipsPath(getPathIgnoreCase(_path, kLipsDirectoryName));
|
||||
Resources::instance().indexErfFile(getPathIgnoreCase(lipsPath, moduleName + "_loc.mod"), true);
|
||||
|
||||
if (isTSL(_gameId)) {
|
||||
Resources::instance().indexErfFile(getPathIgnoreCase(modulesPath, moduleName + "_dlg.erf"), true);
|
||||
}
|
||||
}
|
||||
|
||||
void Game::drawAll() {
|
||||
// Compute derived PBR IBL textures from queued environment maps
|
||||
PBRIBL::instance().refresh();
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include "SDL2/SDL_events.h"
|
||||
|
||||
#include "../resource/types.h"
|
||||
#include "../scene/pipeline/world.h"
|
||||
#include "../scene/scenegraph.h"
|
||||
|
||||
|
@ -66,6 +65,15 @@ class Video;
|
|||
|
||||
namespace game {
|
||||
|
||||
constexpr char kKeyFilename[] = "chitin.key";
|
||||
constexpr char kTexturePackDirectoryName[] = "texturepacks";
|
||||
constexpr char kGUITexturePackFilename[] = "swpc_tex_gui.erf";
|
||||
constexpr char kTexturePackFilename[] = "swpc_tex_tpa.erf";
|
||||
constexpr char kMusicDirectoryName[] = "streammusic";
|
||||
constexpr char kSoundsDirectoryName[] = "streamsounds";
|
||||
constexpr char kLipsDirectoryName[] = "lips";
|
||||
constexpr char kOverrideDirectoryName[] = "override";
|
||||
|
||||
/**
|
||||
* Entry point for the game logic: contains the main game loop and delegates
|
||||
* work to the instances of Module and GUI. Serves as a Service Locator.
|
||||
|
@ -76,7 +84,6 @@ namespace game {
|
|||
class Game : public render::IEventHandler, boost::noncopyable {
|
||||
public:
|
||||
Game(const boost::filesystem::path &path, const Options &opts);
|
||||
virtual ~Game() = default;
|
||||
|
||||
/**
|
||||
* Initialize the engine, run the main game loop and clean up on exit.
|
||||
|
@ -100,7 +107,7 @@ public:
|
|||
int getRunScriptVar() const;
|
||||
std::shared_ptr<Object> getObjectById(uint32_t id) const;
|
||||
|
||||
resource::GameID gameId() const { return _gameId; }
|
||||
GameID gameId() const { return _gameId; }
|
||||
const Options &options() const { return _options; }
|
||||
scene::SceneGraph &sceneGraph() { return _sceneGraph; }
|
||||
ObjectFactory &objectFactory() { return *_objectFactory; }
|
||||
|
@ -111,6 +118,7 @@ public:
|
|||
CameraType cameraType() const { return _cameraType; }
|
||||
ScriptRunner &scriptRunner() { return _scriptRunner; }
|
||||
Conversation &conversation() { return *_conversation; }
|
||||
const std::vector<std::string> &moduleNames() const { return _moduleNames; }
|
||||
|
||||
void setCursorType(CursorType type);
|
||||
void setLoadFromSaveGame(bool load);
|
||||
|
@ -205,7 +213,7 @@ private:
|
|||
scene::SceneGraph _sceneGraph;
|
||||
scene::WorldRenderPipeline _worldPipeline;
|
||||
Console _console;
|
||||
resource::GameID _gameId { resource::GameID::KotOR };
|
||||
GameID _gameId { GameID::KotOR };
|
||||
std::unique_ptr<ObjectFactory> _objectFactory;
|
||||
GameScreen _screen { GameScreen::MainMenu };
|
||||
Party _party;
|
||||
|
@ -221,6 +229,7 @@ private:
|
|||
bool _paused { false };
|
||||
Conversation *_conversation { nullptr }; /**< pointer to either DialogGUI or ComputerGUI */
|
||||
ProfileOverlay _profileOverlay;
|
||||
std::vector<std::string> _moduleNames;
|
||||
|
||||
// Modules
|
||||
|
||||
|
@ -282,12 +291,22 @@ private:
|
|||
void changeScreen(GameScreen screen);
|
||||
void updateVideo(float dt);
|
||||
void updateMusic();
|
||||
void registerModelLoaders();
|
||||
|
||||
std::string getMainMenuMusic() const;
|
||||
std::string getCharacterGenerationMusic() const;
|
||||
gui::GUI *getScreenGUI() const;
|
||||
|
||||
// Resource management
|
||||
|
||||
void initResourceProviders();
|
||||
void initResourceProvidersForKotOR();
|
||||
void initResourceProvidersForTSL();
|
||||
|
||||
void loadModuleNames();
|
||||
void loadModuleResources(const std::string &moduleName);
|
||||
|
||||
// END Resource management
|
||||
|
||||
// Loading
|
||||
|
||||
void loadCharacterGeneration();
|
||||
|
|
68
src/game/game_kotor.cpp
Normal file
68
src/game/game_kotor.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2021 The reone project contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Game functions specific to KotOR.
|
||||
*/
|
||||
|
||||
#include "game.h"
|
||||
|
||||
#include "../common/pathutil.h"
|
||||
|
||||
#include "../resource/keybifprovider.h"
|
||||
#include "../resource/resources.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
using namespace reone::resource;
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
||||
static constexpr char kPatchFilename[] = "patch.erf";
|
||||
static constexpr char kWavesDirectoryName[] = "streamwaves";
|
||||
static constexpr char kExeFilename[] = "swkotor.exe";
|
||||
|
||||
static vector<string> g_nonTransientLipFiles { "global.mod", "localization.mod" };
|
||||
|
||||
void Game::initResourceProvidersForKotOR() {
|
||||
Resources::instance().indexKeyFile(getPathIgnoreCase(_path, kKeyFilename));
|
||||
Resources::instance().indexErfFile(getPathIgnoreCase(_path, kPatchFilename));
|
||||
|
||||
fs::path texPacksPath(getPathIgnoreCase(_path, kTexturePackDirectoryName));
|
||||
Resources::instance().indexErfFile(getPathIgnoreCase(texPacksPath, kGUITexturePackFilename));
|
||||
Resources::instance().indexErfFile(getPathIgnoreCase(texPacksPath, kTexturePackFilename));
|
||||
|
||||
Resources::instance().indexDirectory(getPathIgnoreCase(_path, kMusicDirectoryName));
|
||||
Resources::instance().indexDirectory(getPathIgnoreCase(_path, kSoundsDirectoryName));
|
||||
Resources::instance().indexDirectory(getPathIgnoreCase(_path, kWavesDirectoryName));
|
||||
|
||||
fs::path lipsPath(getPathIgnoreCase(_path, kLipsDirectoryName));
|
||||
for (auto &filename : g_nonTransientLipFiles) {
|
||||
Resources::instance().indexErfFile(getPathIgnoreCase(lipsPath, filename));
|
||||
}
|
||||
|
||||
Resources::instance().indexExeFile(getPathIgnoreCase(_path, kExeFilename));
|
||||
Resources::instance().indexDirectory(getPathIgnoreCase(_path, kOverrideDirectoryName));
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
63
src/game/game_tsl.cpp
Normal file
63
src/game/game_tsl.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2021 The reone project contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Game functions specific to TSL.
|
||||
*/
|
||||
|
||||
#include "game.h"
|
||||
|
||||
#include "../common/pathutil.h"
|
||||
|
||||
#include "../resource/keybifprovider.h"
|
||||
#include "../resource/resources.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
using namespace reone::resource;
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
||||
static constexpr char kVoiceDirectoryName[] = "streamvoice";
|
||||
static constexpr char kLocalizationLipFilename[] = "localization";
|
||||
static constexpr char kExeFilename[] = "swkotor2.exe";
|
||||
|
||||
void Game::initResourceProvidersForTSL() {
|
||||
Resources::instance().indexKeyFile(getPathIgnoreCase(_path, kKeyFilename));
|
||||
|
||||
fs::path texPacksPath(getPathIgnoreCase(_path, kTexturePackDirectoryName));
|
||||
Resources::instance().indexErfFile(getPathIgnoreCase(texPacksPath, kGUITexturePackFilename));
|
||||
Resources::instance().indexErfFile(getPathIgnoreCase(texPacksPath, kTexturePackFilename));
|
||||
|
||||
Resources::instance().indexDirectory(getPathIgnoreCase(_path, kMusicDirectoryName));
|
||||
Resources::instance().indexDirectory(getPathIgnoreCase(_path, kSoundsDirectoryName));
|
||||
Resources::instance().indexDirectory(getPathIgnoreCase(_path, kVoiceDirectoryName));
|
||||
|
||||
fs::path lipsPath(getPathIgnoreCase(_path, kLipsDirectoryName));
|
||||
Resources::instance().indexErfFile(getPathIgnoreCase(lipsPath, kLocalizationLipFilename));
|
||||
|
||||
Resources::instance().indexExeFile(getPathIgnoreCase(_path, kExeFilename));
|
||||
Resources::instance().indexDirectory(getPathIgnoreCase(_path, kOverrideDirectoryName));
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
|
@ -23,7 +23,7 @@ namespace fs = boost::filesystem;
|
|||
|
||||
namespace reone {
|
||||
|
||||
namespace resource {
|
||||
namespace game {
|
||||
|
||||
GameID determineGameID(const fs::path &gameDir) {
|
||||
// If there is no swkotor2 executable, then this is KotOR
|
||||
|
@ -47,6 +47,6 @@ bool isTSL(GameID gameId) {
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace resource
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
namespace reone {
|
||||
|
||||
namespace resource {
|
||||
namespace game {
|
||||
|
||||
/**
|
||||
* @return GameID determined from the specified game directory
|
||||
|
@ -32,6 +32,6 @@ GameID determineGameID(const boost::filesystem::path &gameDir);
|
|||
|
||||
bool isTSL(GameID gameId);
|
||||
|
||||
} // namespace resource
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
|
@ -29,7 +29,7 @@ class CharacterGeneration;
|
|||
|
||||
class CharGenAbilities : public GameGUI {
|
||||
public:
|
||||
CharGenAbilities(CharacterGeneration *charGen, resource::GameID gameId, const render::GraphicsOptions &opts);
|
||||
CharGenAbilities(CharacterGeneration *charGen, GameID gameId, const render::GraphicsOptions &opts);
|
||||
|
||||
void load() override;
|
||||
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
|
||||
#include "../../../gui/scenebuilder.h"
|
||||
#include "../../../render/model/models.h"
|
||||
#include "../../../resource/gameidutil.h"
|
||||
#include "../../../resource/resources.h"
|
||||
|
||||
#include "../../game.h"
|
||||
#include "../../gameidutil.h"
|
||||
#include "../../portraitutil.h"
|
||||
#include "../../rp/classes.h"
|
||||
|
||||
|
@ -56,9 +56,9 @@ CharacterGeneration::CharacterGeneration(Game *game) :
|
|||
_game(game) {
|
||||
|
||||
_resRef = getResRef("maincg");
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
|
||||
initForGame();
|
||||
loadBackground(BackgroundType::Menu);
|
||||
};
|
||||
|
||||
void CharacterGeneration::load() {
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
|
||||
#include "../../../gui/scenebuilder.h"
|
||||
#include "../../../render/model/models.h"
|
||||
#include "../../../resource/gameidutil.h"
|
||||
#include "../../../resource/strings.h"
|
||||
|
||||
#include "../../characterutil.h"
|
||||
#include "../../game.h"
|
||||
#include "../../gameidutil.h"
|
||||
#include "../../object/creature.h"
|
||||
#include "../../rp/classes.h"
|
||||
|
||||
|
@ -65,7 +65,7 @@ ClassSelection::ClassSelection(Game *game) :
|
|||
_resRef = getResRef("classsel");
|
||||
|
||||
if (_gameId == GameID::KotOR) {
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
|
||||
initForGame();
|
||||
|
|
|
@ -27,7 +27,7 @@ class CharacterGeneration;
|
|||
|
||||
class CustomCharacterGeneration : public GameGUI {
|
||||
public:
|
||||
CustomCharacterGeneration(CharacterGeneration *charGen, resource::GameID gameId, const render::GraphicsOptions &opts);
|
||||
CustomCharacterGeneration(CharacterGeneration *charGen, GameID gameId, const render::GraphicsOptions &opts);
|
||||
|
||||
void load() override;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class CharacterGeneration;
|
|||
|
||||
class CharGenFeats : public GameGUI {
|
||||
public:
|
||||
CharGenFeats(CharacterGeneration *charGen, resource::GameID gameId, const render::GraphicsOptions &opts);
|
||||
CharGenFeats(CharacterGeneration *charGen, GameID gameId, const render::GraphicsOptions &opts);
|
||||
|
||||
void load() override;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class CharacterGeneration;
|
|||
|
||||
class LevelUpMenu : public GameGUI {
|
||||
public:
|
||||
LevelUpMenu(CharacterGeneration *charGen, resource::GameID gameId, const render::GraphicsOptions &options);
|
||||
LevelUpMenu(CharacterGeneration *charGen, GameID gameId, const render::GraphicsOptions &options);
|
||||
|
||||
void load() override;
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ void NameEntry::load() {
|
|||
}
|
||||
|
||||
void NameEntry::loadLtrFile(const string &resRef, LtrReader <r) {
|
||||
shared_ptr<ByteArray> data(Resources::instance().get(resRef, ResourceType::Ltr));
|
||||
shared_ptr<ByteArray> data(Resources::instance().getRaw(resRef, ResourceType::Ltr));
|
||||
ltr.load(wrap(data));
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class CharacterGeneration;
|
|||
|
||||
class NameEntry : public GameGUI {
|
||||
public:
|
||||
NameEntry(CharacterGeneration *charGen, resource::GameID gameId, const render::GraphicsOptions &opts);
|
||||
NameEntry(CharacterGeneration *charGen, GameID gameId, const render::GraphicsOptions &opts);
|
||||
|
||||
void load() override;
|
||||
bool handle(const SDL_Event &event) override;
|
||||
|
|
|
@ -53,11 +53,11 @@ PortraitSelection::PortraitSelection(Game *game, CharacterGeneration *charGen) :
|
|||
|
||||
_resRef = getResRef("portcust");
|
||||
|
||||
if (_gameId == GameID::KotOR) {
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
}
|
||||
|
||||
initForGame();
|
||||
|
||||
if (_gameId == GameID::KotOR) {
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
}
|
||||
|
||||
void PortraitSelection::load() {
|
||||
|
|
|
@ -27,7 +27,7 @@ class CharacterGeneration;
|
|||
|
||||
class QuickCharacterGeneration : public GameGUI {
|
||||
public:
|
||||
QuickCharacterGeneration(CharacterGeneration *charGen, resource::GameID gameId, const render::GraphicsOptions &opts);
|
||||
QuickCharacterGeneration(CharacterGeneration *charGen, GameID gameId, const render::GraphicsOptions &opts);
|
||||
|
||||
void load() override;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class CharacterGeneration;
|
|||
|
||||
class QuickOrCustom : public GameGUI {
|
||||
public:
|
||||
QuickOrCustom(CharacterGeneration *charGen, resource::GameID gameId, const render::GraphicsOptions &opts);
|
||||
QuickOrCustom(CharacterGeneration *charGen, GameID gameId, const render::GraphicsOptions &opts);
|
||||
|
||||
void load() override;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ class CharacterGeneration;
|
|||
|
||||
class CharGenSkills : public GameGUI {
|
||||
public:
|
||||
CharGenSkills(CharacterGeneration *charGen, resource::GameID gameId, const render::GraphicsOptions &opts);
|
||||
CharGenSkills(CharacterGeneration *charGen, GameID gameId, const render::GraphicsOptions &opts);
|
||||
|
||||
void load() override;
|
||||
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
|
||||
#include "colorutil.h"
|
||||
|
||||
#include "../../resource/gameidutil.h"
|
||||
|
||||
using namespace reone::resource;
|
||||
#include "../gameidutil.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
|
|
|
@ -19,15 +19,15 @@
|
|||
|
||||
#include "glm/vec3.hpp"
|
||||
|
||||
#include "../../resource/types.h"
|
||||
#include "../types.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
||||
glm::vec3 getBaseColor(resource::GameID gameId);
|
||||
glm::vec3 getHilightColor(resource::GameID gameId);
|
||||
glm::vec3 getDisabledColor(resource::GameID gameId);
|
||||
glm::vec3 getBaseColor(GameID gameId);
|
||||
glm::vec3 getHilightColor(GameID gameId);
|
||||
glm::vec3 getDisabledColor(GameID gameId);
|
||||
|
||||
} // namespace game
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
#include "computer.h"
|
||||
|
||||
#include "../../gui/control/listbox.h"
|
||||
#include "../../resource/gameidutil.h"
|
||||
|
||||
#include "../gameidutil.h"
|
||||
|
||||
#include "colorutil.h"
|
||||
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
#include "../../gui/control/imagebutton.h"
|
||||
#include "../../gui/control/listbox.h"
|
||||
#include "../../render/textures.h"
|
||||
#include "../../resource/gameidutil.h"
|
||||
#include "../../resource/strings.h"
|
||||
|
||||
#include "../game.h"
|
||||
#include "../gameidutil.h"
|
||||
#include "../object/item.h"
|
||||
#include "../objectconverter.h"
|
||||
|
||||
|
|
|
@ -17,8 +17,12 @@
|
|||
|
||||
#include "gui.h"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include "../../audio/player.h"
|
||||
#include "../../resource/gameidutil.h"
|
||||
#include "../../render/textures.h"
|
||||
|
||||
#include "../gameidutil.h"
|
||||
|
||||
#include "colorutil.h"
|
||||
#include "sounds.h"
|
||||
|
@ -34,7 +38,7 @@ namespace reone {
|
|||
|
||||
namespace game {
|
||||
|
||||
GameGUI::GameGUI(GameID gameId, const GraphicsOptions &options) : GUI(gameId, options) {
|
||||
GameGUI::GameGUI(GameID gameId, const GraphicsOptions &options) : GUI(options), _gameId(gameId) {
|
||||
}
|
||||
|
||||
void GameGUI::onClick(const string &control) {
|
||||
|
@ -57,6 +61,53 @@ void GameGUI::initForGame() {
|
|||
}
|
||||
}
|
||||
|
||||
string GameGUI::getResRef(const std::string &base) const {
|
||||
return isTSL(_gameId) ? base + "_p" : base;
|
||||
}
|
||||
|
||||
void GameGUI::loadBackground(BackgroundType type) {
|
||||
string resRef;
|
||||
|
||||
if (isTSL(_gameId)) {
|
||||
switch (type) {
|
||||
case BackgroundType::Computer0:
|
||||
case BackgroundType::Computer1:
|
||||
resRef = "pnl_computer_pc";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ((_gfxOpts.width == 1600 && _gfxOpts.height == 1200) ||
|
||||
(_gfxOpts.width == 1280 && _gfxOpts.height == 960) ||
|
||||
(_gfxOpts.width == 1024 && _gfxOpts.height == 768) ||
|
||||
(_gfxOpts.width == 800 && _gfxOpts.height == 600)) {
|
||||
|
||||
resRef = str(boost::format("%dx%d") % _gfxOpts.width % _gfxOpts.height);
|
||||
} else {
|
||||
resRef = "1600x1200";
|
||||
}
|
||||
switch (type) {
|
||||
case BackgroundType::Menu:
|
||||
resRef += "back";
|
||||
break;
|
||||
case BackgroundType::Load:
|
||||
resRef += "load";
|
||||
break;
|
||||
case BackgroundType::Computer0:
|
||||
resRef += "comp0";
|
||||
break;
|
||||
case BackgroundType::Computer1:
|
||||
resRef += "comp1";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_background = Textures::instance().get(resRef, TextureUsage::Diffuse);
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace reone
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "../../gui/gui.h"
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace game {
|
||||
|
@ -28,12 +30,19 @@ namespace game {
|
|||
*/
|
||||
class GameGUI : public gui::GUI {
|
||||
protected:
|
||||
GameGUI(resource::GameID gameId, const render::GraphicsOptions &options);
|
||||
GameGUI(GameID gameId, const render::GraphicsOptions &options);
|
||||
|
||||
void onClick(const std::string &control) override;
|
||||
void onFocusChanged(const std::string &control, bool focus) override;
|
||||
|
||||
void initForGame();
|
||||
|
||||
std::string getResRef(const std::string &base) const;
|
||||
|
||||
protected:
|
||||
GameID _gameId;
|
||||
|
||||
void loadBackground(BackgroundType type);
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
#include "../../gui/control/label.h"
|
||||
#include "../../render/meshes.h"
|
||||
#include "../../render/window.h"
|
||||
#include "../../resource/gameidutil.h"
|
||||
|
||||
#include "../game.h"
|
||||
#include "../gameidutil.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
|
||||
#include "../../../gui/control/listbox.h"
|
||||
#include "../../../render/textures.h"
|
||||
#include "../../../resource/gameidutil.h"
|
||||
#include "../../../resource/resources.h"
|
||||
#include "../../../resource/strings.h"
|
||||
|
||||
#include "../../game.h"
|
||||
#include "../../gameidutil.h"
|
||||
|
||||
#include "../colorutil.h"
|
||||
|
||||
|
@ -46,9 +46,9 @@ AbilitiesMenu::AbilitiesMenu(Game *game) :
|
|||
_game(game) {
|
||||
|
||||
_resRef = getResRef("abilities");
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
|
||||
initForGame();
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
|
||||
void AbilitiesMenu::load() {
|
||||
|
|
|
@ -39,9 +39,9 @@ CharacterMenu::CharacterMenu(Game *game) :
|
|||
_game(game) {
|
||||
|
||||
_resRef = getResRef("character");
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
|
||||
initForGame();
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
|
||||
void CharacterMenu::load() {
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
#include "../../../gui/control/imagebutton.h"
|
||||
#include "../../../gui/control/listbox.h"
|
||||
#include "../../../render/textures.h"
|
||||
#include "../../../resource/gameidutil.h"
|
||||
#include "../../../resource/strings.h"
|
||||
|
||||
#include "../../blueprint/blueprints.h"
|
||||
#include "../../game.h"
|
||||
#include "../../gameidutil.h"
|
||||
#include "../../object/creature.h"
|
||||
#include "../../object/item.h"
|
||||
|
||||
|
@ -78,9 +78,9 @@ Equipment::Equipment(Game *game) :
|
|||
_game(game) {
|
||||
|
||||
_resRef = getResRef("equip");
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
|
||||
initForGame();
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
|
||||
void Equipment::load() {
|
||||
|
|
|
@ -19,9 +19,8 @@
|
|||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "../../../resource/gameidutil.h"
|
||||
|
||||
#include "../../game.h"
|
||||
#include "../../gameidutil.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
|
@ -36,9 +36,9 @@ InventoryMenu::InventoryMenu(Game *game) :
|
|||
_game(game) {
|
||||
|
||||
_resRef = getResRef("inventory");
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
|
||||
initForGame();
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
|
||||
void InventoryMenu::load() {
|
||||
|
|
|
@ -35,9 +35,9 @@ JournalMenu::JournalMenu(Game *game) :
|
|||
_game(game) {
|
||||
|
||||
_resRef = getResRef("journal");
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
|
||||
initForGame();
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
|
||||
void JournalMenu::load() {
|
||||
|
|
|
@ -42,9 +42,9 @@ MapMenu::MapMenu(Game *game) :
|
|||
_game(game) {
|
||||
|
||||
_resRef = getResRef("map");
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
|
||||
initForGame();
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
|
||||
void MapMenu::load() {
|
||||
|
|
|
@ -35,9 +35,9 @@ MessagesMenu::MessagesMenu(Game *game) :
|
|||
_game(game) {
|
||||
|
||||
_resRef = getResRef("messages");
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
|
||||
initForGame();
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
|
||||
void MessagesMenu::load() {
|
||||
|
|
|
@ -35,9 +35,9 @@ OptionsMenu::OptionsMenu(Game *game) :
|
|||
_game(game) {
|
||||
|
||||
_resRef = getResRef("optionsingame");
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
|
||||
initForGame();
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
|
||||
void OptionsMenu::load() {
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
#include "loadscreen.h"
|
||||
|
||||
#include "../../gui/control/progressbar.h"
|
||||
#include "../../resource/gameidutil.h"
|
||||
#include "../../resource/resources.h"
|
||||
|
||||
#include "../game.h"
|
||||
#include "../gameidutil.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -33,8 +33,7 @@ namespace reone {
|
|||
namespace game {
|
||||
|
||||
LoadingScreen::LoadingScreen(Game *game) :
|
||||
GUI(game->gameId(), game->options().graphics),
|
||||
_game(game) {
|
||||
GameGUI(game->gameId(), game->options().graphics) {
|
||||
|
||||
_resRef = getResRef("loadscreen");
|
||||
|
||||
|
@ -42,7 +41,7 @@ LoadingScreen::LoadingScreen(Game *game) :
|
|||
_resolutionX = 800;
|
||||
_resolutionY = 600;
|
||||
} else {
|
||||
_backgroundType = BackgroundType::Load;
|
||||
loadBackground(BackgroundType::Load);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../../gui/gui.h"
|
||||
#include "gui.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace game {
|
|||
|
||||
class Game;
|
||||
|
||||
class LoadingScreen : public gui::GUI {
|
||||
class LoadingScreen : public GameGUI {
|
||||
public:
|
||||
LoadingScreen(Game *game);
|
||||
|
||||
|
|
|
@ -24,12 +24,12 @@
|
|||
#include "../../gui/control/listbox.h"
|
||||
#include "../../gui/scenebuilder.h"
|
||||
#include "../../render/model/models.h"
|
||||
#include "../../resource/gameidutil.h"
|
||||
#include "../../resource/resources.h"
|
||||
#include "../../scene/types.h"
|
||||
|
||||
#include "../blueprint/blueprints.h"
|
||||
#include "../game.h"
|
||||
#include "../gameidutil.h"
|
||||
|
||||
#include "colorutil.h"
|
||||
|
||||
|
@ -61,7 +61,7 @@ MainMenu::MainMenu(Game *game) :
|
|||
_resRef = "mainmenu8x6_p";
|
||||
} else {
|
||||
_resRef = "mainmenu16x12";
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
|
||||
_resolutionX = 800;
|
||||
|
@ -166,7 +166,7 @@ void MainMenu::startModuleSelection() {
|
|||
|
||||
void MainMenu::loadModuleNames() {
|
||||
auto &modules = getControl<ListBox>("LB_MODULES");
|
||||
for (auto &module : Resources::instance().moduleNames()) {
|
||||
for (auto &module : _game->moduleNames()) {
|
||||
ListBox::Item item;
|
||||
item.tag = module;
|
||||
item.text = module;
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
#include "../../gui/control/label.h"
|
||||
#include "../../gui/control/togglebutton.h"
|
||||
#include "../../render/textures.h"
|
||||
#include "../../resource/gameidutil.h"
|
||||
#include "../../resource/strings.h"
|
||||
#include "../../script/types.h"
|
||||
|
||||
#include "../blueprint/blueprints.h"
|
||||
#include "../game.h"
|
||||
#include "../gameidutil.h"
|
||||
#include "../portraitutil.h"
|
||||
|
||||
#include "colorutil.h"
|
||||
|
@ -63,7 +63,7 @@ PartySelection::PartySelection(Game *game) :
|
|||
_resRef = "partyselect_p";
|
||||
} else {
|
||||
_resRef = "partyselection";
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
|
||||
initForGame();
|
||||
|
|
|
@ -53,11 +53,11 @@ SaveLoad::SaveLoad(Game *game) :
|
|||
|
||||
_resRef = getResRef("saveload");
|
||||
|
||||
if (_gameId == GameID::KotOR) {
|
||||
_backgroundType = BackgroundType::Menu;
|
||||
}
|
||||
|
||||
initForGame();
|
||||
|
||||
if (_gameId == GameID::KotOR) {
|
||||
loadBackground(BackgroundType::Menu);
|
||||
}
|
||||
}
|
||||
|
||||
void SaveLoad::load() {
|
||||
|
|
|
@ -30,10 +30,10 @@
|
|||
#include "../render/stateutil.h"
|
||||
#include "../render/textures.h"
|
||||
#include "../render/window.h"
|
||||
#include "../resource/gameidutil.h"
|
||||
#include "../resource/types.h"
|
||||
|
||||
#include "game.h"
|
||||
#include "gameidutil.h"
|
||||
#include "gui/colorutil.h"
|
||||
|
||||
using namespace std;
|
||||
|
|
|
@ -115,7 +115,7 @@ void Area::load(const string &name, const GffStruct &are, const GffStruct &git)
|
|||
|
||||
void Area::loadLYT() {
|
||||
LytReader lyt;
|
||||
lyt.load(wrap(Resources::instance().get(_name, ResourceType::Lyt)));
|
||||
lyt.load(wrap(Resources::instance().getRaw(_name, ResourceType::Lyt)));
|
||||
|
||||
for (auto &lytRoom : lyt.rooms()) {
|
||||
shared_ptr<Model> model(Models::instance().get(lytRoom.name));
|
||||
|
@ -140,7 +140,7 @@ void Area::loadLYT() {
|
|||
|
||||
void Area::loadVIS() {
|
||||
VisReader vis;
|
||||
vis.load(wrap(Resources::instance().get(_name, ResourceType::Vis)));
|
||||
vis.load(wrap(Resources::instance().getRaw(_name, ResourceType::Vis)));
|
||||
|
||||
_visibility = fixVisibility(vis.visibility());
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ shared_ptr<ModelSceneNode> CreatureModelBuilder::build() {
|
|||
string modelName(getBodyModelName());
|
||||
if (modelName.empty()) return nullptr;
|
||||
|
||||
shared_ptr<Model> model(Models::instance().get(modelName, ResourceType::Mdl));
|
||||
shared_ptr<Model> model(Models::instance().get(modelName));
|
||||
if (!model) return nullptr;
|
||||
|
||||
auto modelSceneNode = make_unique<ModelSceneNode>(ModelSceneNode::Classification::Creature, model, &_creature->sceneGraph());
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
#include "routines.h"
|
||||
|
||||
#include "../../common/log.h"
|
||||
#include "../../resource/gameidutil.h"
|
||||
|
||||
#include "../enginetype/event.h"
|
||||
#include "../enginetype/location.h"
|
||||
|
||||
#include "../game.h"
|
||||
#include "../gameidutil.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -39,10 +39,10 @@ Routines &Routines::instance() {
|
|||
return instance;
|
||||
}
|
||||
|
||||
void Routines::init(GameID gameId, Game *game) {
|
||||
void Routines::init(Game *game) {
|
||||
_game = game;
|
||||
|
||||
if (isTSL(gameId)) {
|
||||
if (isTSL(game->gameId())) {
|
||||
addTslRoutines();
|
||||
} else {
|
||||
addKotorRoutines();
|
||||
|
|
|
@ -47,7 +47,7 @@ class Routines : public script::IRoutineProvider, boost::noncopyable {
|
|||
public:
|
||||
static Routines &instance();
|
||||
|
||||
void init(resource::GameID gameId, Game *game);
|
||||
void init(Game *game);
|
||||
void deinit();
|
||||
|
||||
const script::Routine &get(int index) override;
|
||||
|
|
|
@ -44,7 +44,7 @@ SoundSets::SoundSets() : MemoryCache(bind(&SoundSets::doGet, this, _1)) {
|
|||
}
|
||||
|
||||
shared_ptr<SoundSet> SoundSets::doGet(string resRef) {
|
||||
auto data = Resources::instance().get(resRef, ResourceType::Ssf);
|
||||
auto data = Resources::instance().getRaw(resRef, ResourceType::Ssf);
|
||||
if (!data) return nullptr;
|
||||
|
||||
auto result = make_shared<SoundSet>();
|
||||
|
|
|
@ -32,6 +32,20 @@ constexpr float kDefaultFollowDistance = 5.0f;
|
|||
constexpr char kObjectTagPlayer[] = "player";
|
||||
constexpr float kDefaultRaycastDistance = 8.0f;
|
||||
|
||||
enum class GameID {
|
||||
KotOR,
|
||||
TSL,
|
||||
TSL_Steam
|
||||
};
|
||||
|
||||
enum class BackgroundType {
|
||||
None,
|
||||
Menu,
|
||||
Load,
|
||||
Computer0,
|
||||
Computer1
|
||||
};
|
||||
|
||||
enum class CursorType {
|
||||
None,
|
||||
Default,
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "../render/stateutil.h"
|
||||
#include "../render/textures.h"
|
||||
#include "../render/window.h"
|
||||
#include "../resource/gameidutil.h"
|
||||
#include "../resource/resources.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -38,16 +37,12 @@ namespace reone {
|
|||
|
||||
namespace gui {
|
||||
|
||||
GUI::GUI(GameID gameId, const GraphicsOptions &opts) : _gameId(gameId), _gfxOpts(opts) {
|
||||
GUI::GUI(const GraphicsOptions &opts) : _gfxOpts(opts) {
|
||||
_aspect = _gfxOpts.width / static_cast<float>(_gfxOpts.height);
|
||||
_screenCenter.x = _gfxOpts.width / 2;
|
||||
_screenCenter.y = _gfxOpts.height / 2;
|
||||
}
|
||||
|
||||
string GUI::getResRef(const string &base) const {
|
||||
return isTSL(_gameId) ? base + "_p" : base;
|
||||
}
|
||||
|
||||
void GUI::load() {
|
||||
if (_resRef.empty()) {
|
||||
throw logic_error("resRef must not be empty");
|
||||
|
@ -55,8 +50,6 @@ void GUI::load() {
|
|||
debug("GUI: load " + _resRef, 1, DebugChannels::gui);
|
||||
|
||||
shared_ptr<GffStruct> gui(Resources::instance().getGFF(_resRef, ResourceType::Gui));
|
||||
loadBackground(_backgroundType);
|
||||
|
||||
ControlType type = Control::getType(*gui);
|
||||
string tag(Control::getTag(*gui));
|
||||
|
||||
|
@ -84,49 +77,6 @@ void GUI::load() {
|
|||
}
|
||||
}
|
||||
|
||||
void GUI::loadBackground(BackgroundType type) {
|
||||
string resRef;
|
||||
|
||||
if (isTSL(_gameId)) {
|
||||
switch (type) {
|
||||
case BackgroundType::Computer0:
|
||||
case BackgroundType::Computer1:
|
||||
resRef = "pnl_computer_pc";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ((_gfxOpts.width == 1600 && _gfxOpts.height == 1200) ||
|
||||
(_gfxOpts.width == 1280 && _gfxOpts.height == 960) ||
|
||||
(_gfxOpts.width == 1024 && _gfxOpts.height == 768) ||
|
||||
(_gfxOpts.width == 800 && _gfxOpts.height == 600)) {
|
||||
|
||||
resRef = str(boost::format("%dx%d") % _gfxOpts.width % _gfxOpts.height);
|
||||
} else {
|
||||
resRef = "1600x1200";
|
||||
}
|
||||
switch (type) {
|
||||
case BackgroundType::Menu:
|
||||
resRef += "back";
|
||||
break;
|
||||
case BackgroundType::Load:
|
||||
resRef += "load";
|
||||
break;
|
||||
case BackgroundType::Computer0:
|
||||
resRef += "comp0";
|
||||
break;
|
||||
case BackgroundType::Computer1:
|
||||
resRef += "comp1";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_background = Textures::instance().get(resRef, TextureUsage::Diffuse);
|
||||
}
|
||||
|
||||
void GUI::stretchControl(Control &control) {
|
||||
float aspectX = _gfxOpts.width / static_cast<float>(_resolutionX);
|
||||
float aspectY = _gfxOpts.height / static_cast<float>(_resolutionY);
|
||||
|
|
|
@ -72,10 +72,8 @@ protected:
|
|||
Stretch
|
||||
};
|
||||
|
||||
resource::GameID _gameId { resource::GameID::KotOR };
|
||||
render::GraphicsOptions _gfxOpts;
|
||||
std::string _resRef;
|
||||
BackgroundType _backgroundType { BackgroundType::None };
|
||||
int _resolutionX { kDefaultResolutionX };
|
||||
int _resolutionY { kDefaultResolutionY };
|
||||
ScalingMode _scaling { ScalingMode::Center };
|
||||
|
@ -92,15 +90,13 @@ protected:
|
|||
glm::vec3 _defaultHilightColor { 0.0f };
|
||||
std::unordered_map<std::string, ScalingMode> _scalingByControlTag;
|
||||
|
||||
GUI(resource::GameID gameId, const render::GraphicsOptions &opts);
|
||||
GUI(const render::GraphicsOptions &opts);
|
||||
|
||||
void loadBackground(BackgroundType type);
|
||||
void loadControl(const resource::GffStruct &gffs);
|
||||
virtual void onFocusChanged(const std::string &control, bool focus);
|
||||
virtual void preloadControl(Control &control);
|
||||
|
||||
Control &getControl(const std::string &tag) const;
|
||||
std::string getResRef(const std::string &base) const;
|
||||
|
||||
template <class T>
|
||||
T &getControl(const std::string &tag) const {
|
||||
|
|
|
@ -33,14 +33,6 @@ enum class ControlType {
|
|||
ListBox = 11
|
||||
};
|
||||
|
||||
enum class BackgroundType {
|
||||
None,
|
||||
Menu,
|
||||
Load,
|
||||
Computer0,
|
||||
Computer1
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
} // namespace reone
|
||||
|
|
|
@ -41,7 +41,7 @@ Lips::Lips() : MemoryCache(bind(&Lips::doGet, this, _1)) {
|
|||
}
|
||||
|
||||
shared_ptr<LipAnimation> Lips::doGet(string resRef) {
|
||||
shared_ptr<ByteArray> lipData(Resources::instance().get(resRef, ResourceType::Lip));
|
||||
shared_ptr<ByteArray> lipData(Resources::instance().getRaw(resRef, ResourceType::Lip));
|
||||
if (!lipData) return nullptr;
|
||||
|
||||
LipReader lip;
|
||||
|
|
|
@ -25,9 +25,7 @@
|
|||
|
||||
#include "../../common/collectionutil.h"
|
||||
#include "../../common/log.h"
|
||||
#include "../../common/streamutil.h"
|
||||
#include "../../common/stringutil.h"
|
||||
#include "../../resource/resources.h"
|
||||
|
||||
#include "../textures.h"
|
||||
|
||||
|
@ -573,7 +571,6 @@ unique_ptr<ModelNode> MdlReader::readNode(uint32_t offset, ModelNode *parent) {
|
|||
transform = glm::translate(transform, position);
|
||||
transform *= glm::mat4_cast(orientation);
|
||||
|
||||
|
||||
auto node = make_unique<ModelNode>(_nodeIndex++, parent);
|
||||
node->_flags = header.flags;
|
||||
node->_nodeNumber = header.nodeNumber;
|
||||
|
@ -996,20 +993,6 @@ unique_ptr<Animation> MdlReader::readAnimation(uint32_t offset) {
|
|||
return make_unique<Animation>(name, header.length, header.transitionTime, move(events), move(rootNode));
|
||||
}
|
||||
|
||||
shared_ptr<Model> MdlModelLoader::loadModel(GameID gameId, const string &resRef) {
|
||||
shared_ptr<ByteArray> mdlData(Resources::instance().get(resRef, ResourceType::Mdl));
|
||||
shared_ptr<ByteArray> mdxData(Resources::instance().get(resRef, ResourceType::Mdx));
|
||||
shared_ptr<Model> model;
|
||||
|
||||
if (mdlData && mdxData) {
|
||||
MdlReader mdl;
|
||||
mdl.load(wrap(mdlData), wrap(mdxData));
|
||||
model = mdl.model();
|
||||
}
|
||||
|
||||
return move(model);
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace reone
|
||||
|
|
|
@ -18,11 +18,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../resource/format/binreader.h"
|
||||
#include "../../resource/types.h"
|
||||
|
||||
#include "aabbnode.h"
|
||||
#include "model.h"
|
||||
#include "modelloader.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
|
@ -272,11 +270,6 @@ private:
|
|||
std::shared_ptr<AABBNode> readAABBNode(uint32_t offset);
|
||||
};
|
||||
|
||||
class MdlModelLoader : public IModelLoader {
|
||||
public:
|
||||
std::shared_ptr<Model> loadModel(resource::GameID gameId, const std::string &resRef) override;
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace reone
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2021 The reone project contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "../../resource/types.h"
|
||||
|
||||
#include "model.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace render {
|
||||
|
||||
/**
|
||||
* An interface to abstract loading models from different formats.
|
||||
*/
|
||||
class IModelLoader {
|
||||
public:
|
||||
virtual std::shared_ptr<Model> loadModel(resource::GameID gameId, const std::string &resRef) = 0;
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace reone
|
|
@ -36,39 +36,34 @@ Models &Models::instance() {
|
|||
return instance;
|
||||
}
|
||||
|
||||
void Models::init(GameID gameId) {
|
||||
_gameId = gameId;
|
||||
}
|
||||
|
||||
void Models::invalidateCache() {
|
||||
_cache.clear();
|
||||
}
|
||||
|
||||
void Models::registerLoader(ResourceType type, shared_ptr<IModelLoader> loader) {
|
||||
_loaders.insert(make_pair(type, move(loader)));
|
||||
}
|
||||
|
||||
shared_ptr<Model> Models::get(const string &resRef, ResourceType type) {
|
||||
shared_ptr<Model> Models::get(const string &resRef) {
|
||||
if (resRef.empty()) return nullptr;
|
||||
|
||||
auto maybeModel = _cache.find(resRef);
|
||||
if (maybeModel != _cache.end()) return maybeModel->second;
|
||||
|
||||
auto inserted = _cache.insert(make_pair(resRef, doGet(resRef, type)));
|
||||
auto inserted = _cache.insert(make_pair(resRef, doGet(resRef)));
|
||||
return inserted.first->second;
|
||||
}
|
||||
|
||||
shared_ptr<Model> Models::doGet(const string &resRef, ResourceType type) {
|
||||
auto maybeLoader = _loaders.find(type);
|
||||
if (maybeLoader == _loaders.end()) {
|
||||
warn("Model loader not found by ResType: " + to_string(static_cast<int>(type)));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<Model> Models::doGet(const string &resRef) {
|
||||
debug("Load model " + resRef);
|
||||
shared_ptr<Model> model(maybeLoader->second->loadModel(_gameId, resRef));
|
||||
if (model) {
|
||||
model->init();
|
||||
|
||||
shared_ptr<ByteArray> mdlData(Resources::instance().getRaw(resRef, ResourceType::Mdl));
|
||||
shared_ptr<ByteArray> mdxData(Resources::instance().getRaw(resRef, ResourceType::Mdx));
|
||||
shared_ptr<Model> model;
|
||||
|
||||
if (mdlData && mdxData) {
|
||||
MdlReader mdl;
|
||||
mdl.load(wrap(mdlData), wrap(mdxData));
|
||||
model = mdl.model();
|
||||
if (model) {
|
||||
model->init();
|
||||
}
|
||||
}
|
||||
|
||||
return move(model);
|
||||
|
|
|
@ -23,12 +23,8 @@
|
|||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include "../../resource/types.h"
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
#include "modelloader.h"
|
||||
|
||||
namespace reone {
|
||||
|
||||
namespace render {
|
||||
|
@ -39,22 +35,14 @@ class Models : boost::noncopyable {
|
|||
public:
|
||||
static Models &instance();
|
||||
|
||||
void init(resource::GameID gameId);
|
||||
void invalidateCache();
|
||||
|
||||
/**
|
||||
* Associates the specified model loader with the specified ResType.
|
||||
*/
|
||||
void registerLoader(resource::ResourceType type, std::shared_ptr<IModelLoader> loader);
|
||||
|
||||
std::shared_ptr<Model> get(const std::string &resRef, resource::ResourceType type = resource::ResourceType::Mdl);
|
||||
std::shared_ptr<Model> get(const std::string &resRef);
|
||||
|
||||
private:
|
||||
resource::GameID _gameId { resource::GameID::KotOR };
|
||||
std::unordered_map<resource::ResourceType, std::shared_ptr<IModelLoader>> _loaders;
|
||||
std::unordered_map<std::string, std::shared_ptr<Model>> _cache;
|
||||
|
||||
std::shared_ptr<Model> doGet(const std::string &resRef, resource::ResourceType type);
|
||||
std::shared_ptr<Model> doGet(const std::string &resRef);
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
|
|
|
@ -44,9 +44,7 @@ Textures &Textures::instance() {
|
|||
return instance;
|
||||
}
|
||||
|
||||
void Textures::init(GameID gameId) {
|
||||
_gameId = gameId;
|
||||
|
||||
void Textures::init() {
|
||||
// Initialize default texture
|
||||
_default = make_shared<Texture>("default", getTextureProperties(TextureUsage::Default));
|
||||
_default->init();
|
||||
|
@ -109,14 +107,14 @@ shared_ptr<Texture> Textures::get(const string &resRef, TextureUsage usage) {
|
|||
shared_ptr<Texture> Textures::doGet(const string &resRef, TextureUsage usage) {
|
||||
shared_ptr<Texture> texture;
|
||||
|
||||
shared_ptr<ByteArray> tgaData(Resources::instance().get(resRef, ResourceType::Tga, false));
|
||||
shared_ptr<ByteArray> tgaData(Resources::instance().getRaw(resRef, ResourceType::Tga, false));
|
||||
if (tgaData) {
|
||||
TgaReader tga(resRef, usage);
|
||||
tga.load(wrap(tgaData));
|
||||
texture = tga.texture();
|
||||
|
||||
if (texture) {
|
||||
shared_ptr<ByteArray> txiData(Resources::instance().get(resRef, ResourceType::Txi, false));
|
||||
shared_ptr<ByteArray> txiData(Resources::instance().getRaw(resRef, ResourceType::Txi, false));
|
||||
if (txiData) {
|
||||
TxiReader txi;
|
||||
txi.load(wrap(txiData));
|
||||
|
@ -126,7 +124,7 @@ shared_ptr<Texture> Textures::doGet(const string &resRef, TextureUsage usage) {
|
|||
}
|
||||
|
||||
if (!texture) {
|
||||
shared_ptr<ByteArray> tpcData(Resources::instance().get(resRef, ResourceType::Tpc, false));
|
||||
shared_ptr<ByteArray> tpcData(Resources::instance().getRaw(resRef, ResourceType::Tpc, false));
|
||||
if (tpcData) {
|
||||
TpcReader tpc(resRef, usage);
|
||||
tpc.load(wrap(tpcData));
|
||||
|
|
|
@ -37,7 +37,7 @@ class Textures : boost::noncopyable {
|
|||
public:
|
||||
static Textures &instance();
|
||||
|
||||
void init(resource::GameID gameId);
|
||||
void init();
|
||||
void invalidateCache();
|
||||
|
||||
/**
|
||||
|
@ -48,7 +48,6 @@ public:
|
|||
std::shared_ptr<Texture> get(const std::string &resRef, TextureUsage usage = TextureUsage::Default);
|
||||
|
||||
private:
|
||||
resource::GameID _gameId { resource::GameID::KotOR };
|
||||
std::shared_ptr<render::Texture> _default;
|
||||
std::shared_ptr<render::Texture> _defaultCubemap;
|
||||
std::unordered_map<std::string, std::shared_ptr<Texture>> _cache;
|
||||
|
|
|
@ -55,7 +55,7 @@ shared_ptr<Walkmesh> Walkmeshes::get(const string &resRef, ResourceType type) {
|
|||
}
|
||||
|
||||
shared_ptr<Walkmesh> Walkmeshes::doGet(const string &resRef, ResourceType type) {
|
||||
shared_ptr<ByteArray> data(Resources::instance().get(resRef, type));
|
||||
shared_ptr<ByteArray> data(Resources::instance().getRaw(resRef, type));
|
||||
shared_ptr<Walkmesh> walkmesh;
|
||||
|
||||
if (data) {
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "format/gffreader.h"
|
||||
#include "format/rimreader.h"
|
||||
#include "folder.h"
|
||||
#include "gameidutil.h"
|
||||
#include "keybifprovider.h"
|
||||
#include "typeutil.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -40,114 +40,55 @@ namespace reone {
|
|||
|
||||
namespace resource {
|
||||
|
||||
static const char kPatchFileName[] = "patch.erf";
|
||||
static const char kExeFileNameKotor[] = "swkotor.exe";
|
||||
static const char kExeFileNameTsl[] = "swkotor2.exe";
|
||||
|
||||
static const char kModulesDirectoryName[] = "modules";
|
||||
static const char kOverrideDirectoryName[] = "override";
|
||||
static const char kMusicDirectoryName[] = "streammusic";
|
||||
static const char kSoundsDirectoryName[] = "streamsounds";
|
||||
static const char kVoiceDirectoryName[] = "streamvoice";
|
||||
static const char kWavesDirectoryName[] = "streamwaves";
|
||||
static const char kTexturePackDirectoryName[] = "texturepacks";
|
||||
static const char kLipsDirectoryName[] = "lips";
|
||||
|
||||
static const char kGUITexturePackFilename[] = "swpc_tex_gui.erf";
|
||||
static const char kTexturePackFilename[] = "swpc_tex_tpa.erf";
|
||||
|
||||
Resources &Resources::instance() {
|
||||
static Resources instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void Resources::init(GameID gameId, const fs::path &gamePath) {
|
||||
_gameId = gameId;
|
||||
_gamePath = gamePath;
|
||||
|
||||
indexKeyBifFiles();
|
||||
indexTexturePacks();
|
||||
indexAudioFiles();
|
||||
indexLipModFiles();
|
||||
indexExeReader();
|
||||
indexOverrideDirectory();
|
||||
indexDataDirectory();
|
||||
|
||||
loadModuleNames();
|
||||
}
|
||||
|
||||
void Resources::indexKeyBifFiles() {
|
||||
fs::path keyPath(getPathIgnoreCase(_gamePath, "chitin.key"));
|
||||
void Resources::indexKeyFile(const fs::path &path) {
|
||||
if (!fs::exists(path)) return;
|
||||
|
||||
auto keyBif = make_unique<KeyBifResourceProvider>();
|
||||
keyBif->init(keyPath);
|
||||
keyBif->init(path);
|
||||
|
||||
_providers.push_back(move(keyBif));
|
||||
|
||||
debug("Indexed " + keyPath.string());
|
||||
}
|
||||
|
||||
void Resources::indexTexturePacks() {
|
||||
if (_gameId == GameID::KotOR) {
|
||||
fs::path patchPath(getPathIgnoreCase(_gamePath, kPatchFileName));
|
||||
indexErfFile(patchPath);
|
||||
}
|
||||
fs::path texPacksPath(getPathIgnoreCase(_gamePath, kTexturePackDirectoryName));
|
||||
fs::path guiTexPackPath(getPathIgnoreCase(texPacksPath, kGUITexturePackFilename));
|
||||
fs::path texPackPath(getPathIgnoreCase(texPacksPath, kTexturePackFilename));
|
||||
|
||||
indexErfFile(guiTexPackPath);
|
||||
indexErfFile(texPackPath);
|
||||
}
|
||||
|
||||
void Resources::indexErfFile(const fs::path &path) {
|
||||
auto erf = make_unique<ErfReader>();
|
||||
erf->load(path);
|
||||
|
||||
_providers.push_back(move(erf));
|
||||
|
||||
debug("Indexed " + path.string());
|
||||
}
|
||||
|
||||
void Resources::indexAudioFiles() {
|
||||
fs::path musicPath(getPathIgnoreCase(_gamePath, kMusicDirectoryName));
|
||||
fs::path soundsPath(getPathIgnoreCase(_gamePath, kSoundsDirectoryName));
|
||||
void Resources::indexErfFile(const fs::path &path, bool transient) {
|
||||
if (!fs::exists(path)) return;
|
||||
|
||||
indexDirectory(musicPath);
|
||||
indexDirectory(soundsPath);
|
||||
auto erf = make_unique<ErfReader>();
|
||||
erf->load(path);
|
||||
|
||||
if (isTSL(_gameId)) {
|
||||
fs::path voicePath(getPathIgnoreCase(_gamePath, kVoiceDirectoryName));
|
||||
indexDirectory(voicePath);
|
||||
if (transient) {
|
||||
_transientProviders.push_back(move(erf));
|
||||
} else {
|
||||
fs::path wavesPath(getPathIgnoreCase(_gamePath, kWavesDirectoryName));
|
||||
indexDirectory(wavesPath);
|
||||
_providers.push_back(move(erf));
|
||||
}
|
||||
|
||||
debug("Indexed " + path.string());
|
||||
}
|
||||
|
||||
void Resources::indexLipModFiles() {
|
||||
static vector<string> kotorMods { "global", "localization" };
|
||||
static vector<string> tslMods { "localization" };
|
||||
void Resources::indexRimFile(const fs::path &path, bool transient) {
|
||||
if (!fs::exists(path)) return;
|
||||
|
||||
const vector<string> &mods = _gameId == GameID::KotOR ? kotorMods : tslMods;
|
||||
fs::path lipsPath(getPathIgnoreCase(_gamePath, "lips"));
|
||||
|
||||
for (auto &mod : mods) {
|
||||
fs::path modPath(getPathIgnoreCase(lipsPath, mod + ".mod"));
|
||||
indexErfFile(modPath);
|
||||
}
|
||||
}
|
||||
|
||||
void Resources::indexRimFile(const fs::path &path) {
|
||||
auto rim = make_unique<RimReader>();
|
||||
rim->load(path);
|
||||
|
||||
_providers.push_back(move(rim));
|
||||
if (transient) {
|
||||
_transientProviders.push_back(move(rim));
|
||||
} else {
|
||||
_providers.push_back(move(rim));
|
||||
}
|
||||
|
||||
debug("Indexed " + path.string());
|
||||
}
|
||||
|
||||
void Resources::indexDirectory(const fs::path &path) {
|
||||
if (!fs::exists(path)) return;
|
||||
|
||||
auto folder = make_unique<Folder>();
|
||||
folder->load(path);
|
||||
|
||||
|
@ -156,117 +97,59 @@ void Resources::indexDirectory(const fs::path &path) {
|
|||
debug("Indexed " + path.string());
|
||||
}
|
||||
|
||||
void Resources::indexOverrideDirectory() {
|
||||
fs::path path(getPathIgnoreCase(_gamePath, kOverrideDirectoryName));
|
||||
indexDirectory(path);
|
||||
}
|
||||
|
||||
void Resources::indexDataDirectory() {
|
||||
fs::path path(getPathIgnoreCase(fs::current_path(), "data", false));
|
||||
if (!path.empty()) {
|
||||
indexDirectory(path);
|
||||
}
|
||||
}
|
||||
|
||||
void Resources::indexExeReader() {
|
||||
string filename(isTSL(_gameId) ? kExeFileNameTsl : kExeFileNameKotor);
|
||||
fs::path path(getPathIgnoreCase(_gamePath, filename));
|
||||
void Resources::indexExeFile(const fs::path &path) {
|
||||
if (!fs::exists(path)) return;
|
||||
|
||||
_exeFile.load(path);
|
||||
|
||||
debug("Indexed " + path.string());
|
||||
}
|
||||
|
||||
void Resources::loadModuleNames() {
|
||||
fs::path modules(getPathIgnoreCase(_gamePath, kModulesDirectoryName));
|
||||
|
||||
for (auto &entry : fs::directory_iterator(modules)) {
|
||||
string filename(entry.path().filename().string());
|
||||
boost::to_lower(filename);
|
||||
|
||||
if (!boost::ends_with(filename, ".rim") || boost::ends_with(filename, "_s.rim")) continue;
|
||||
|
||||
string moduleName(filename.substr(0, filename.size() - 4));
|
||||
boost::to_lower(moduleName);
|
||||
|
||||
_moduleNames.push_back(moduleName);
|
||||
}
|
||||
|
||||
sort(_moduleNames.begin(), _moduleNames.end());
|
||||
}
|
||||
|
||||
Resources::~Resources() {
|
||||
deinit();
|
||||
}
|
||||
|
||||
void Resources::deinit() {
|
||||
invalidateCache();
|
||||
|
||||
_transientProviders.clear();
|
||||
_providers.clear();
|
||||
}
|
||||
|
||||
void Resources::invalidateCache() {
|
||||
_rawCache.clear();
|
||||
_2daCache.clear();
|
||||
_gffCache.clear();
|
||||
_resCache.clear();
|
||||
}
|
||||
|
||||
void Resources::loadModule(const string &name) {
|
||||
invalidateCache();
|
||||
void Resources::clearTransientProviders() {
|
||||
_transientProviders.clear();
|
||||
|
||||
fs::path modulesPath(getPathIgnoreCase(_gamePath, kModulesDirectoryName));
|
||||
fs::path moduleRimPath(getPathIgnoreCase(modulesPath, name + ".rim"));
|
||||
fs::path moduleRimSPath(getPathIgnoreCase(modulesPath, name + "_s.rim"));
|
||||
|
||||
fs::path lipsPath(getPathIgnoreCase(_gamePath, kLipsDirectoryName));
|
||||
fs::path lipModPath(getPathIgnoreCase(lipsPath, name + "_loc.mod"));
|
||||
|
||||
indexTransientRimFile(moduleRimPath);
|
||||
indexTransientRimFile(moduleRimSPath);
|
||||
|
||||
if (fs::exists(lipModPath)) {
|
||||
indexTransientErfFile(lipModPath);
|
||||
}
|
||||
if (isTSL(_gameId)) {
|
||||
fs::path dlgPath(getPathIgnoreCase(modulesPath, name + "_dlg.erf"));
|
||||
indexTransientErfFile(dlgPath);
|
||||
}
|
||||
}
|
||||
|
||||
void Resources::indexTransientRimFile(const fs::path &path) {
|
||||
auto rim = make_unique<RimReader>();
|
||||
rim->load(path);
|
||||
|
||||
_transientProviders.push_back(move(rim));
|
||||
|
||||
debug("Indexed " + path.string());
|
||||
}
|
||||
|
||||
void Resources::indexTransientErfFile(const fs::path &path) {
|
||||
auto erf = make_unique<ErfReader>();
|
||||
erf->load(path);
|
||||
|
||||
_transientProviders.push_back(move(erf));
|
||||
|
||||
debug("Indexed " + path.string());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static shared_ptr<T> findResource(const string &key, unordered_map<string, shared_ptr<T>> &cache, const function<shared_ptr<T>()> &getter) {
|
||||
static shared_ptr<T> getResource(const string &key, unordered_map<string, shared_ptr<T>> &cache, const function<shared_ptr<T>()> &getter) {
|
||||
auto maybeResource = cache.find(key);
|
||||
if (maybeResource != cache.end()) {
|
||||
return maybeResource->second;
|
||||
};
|
||||
auto inserted = cache.insert(make_pair(key, getter()));
|
||||
if (maybeResource != cache.end()) return maybeResource->second;
|
||||
|
||||
auto inserted = cache.insert(make_pair(key, getter()));
|
||||
return inserted.first->second;
|
||||
}
|
||||
|
||||
shared_ptr<ByteArray> Resources::getRaw(const string &resRef, ResourceType type, bool logNotFound) {
|
||||
if (resRef.empty()) return nullptr;
|
||||
|
||||
string cacheKey(getCacheKey(resRef, type));
|
||||
auto res = _rawCache.find(cacheKey);
|
||||
if (res != _rawCache.end()) return res->second;
|
||||
|
||||
shared_ptr<ByteArray> data = doGetRaw(_transientProviders, resRef, type);
|
||||
if (!data) {
|
||||
data = doGetRaw(_providers, resRef, type);
|
||||
}
|
||||
if (!data && logNotFound) {
|
||||
warn("Resource not found: " + cacheKey);
|
||||
}
|
||||
auto pair = _rawCache.insert(make_pair(cacheKey, move(data)));
|
||||
|
||||
return pair.first->second;
|
||||
}
|
||||
|
||||
string Resources::getCacheKey(const string &resRef, ResourceType type) const {
|
||||
return str(boost::format("%s.%s") % resRef % getExtByResType(type));
|
||||
}
|
||||
|
||||
shared_ptr<TwoDA> Resources::get2DA(const string &resRef, bool logNotFound) {
|
||||
return findResource<TwoDA>(resRef, _2daCache, [&]() {
|
||||
shared_ptr<ByteArray> data(get(resRef, ResourceType::TwoDa, logNotFound));
|
||||
return getResource<TwoDA>(resRef, _2daCache, [&]() {
|
||||
shared_ptr<ByteArray> data(getRaw(resRef, ResourceType::TwoDa, logNotFound));
|
||||
shared_ptr<TwoDA> twoDa;
|
||||
|
||||
if (data) {
|
||||
|
@ -279,37 +162,12 @@ shared_ptr<TwoDA> Resources::get2DA(const string &resRef, bool logNotFound) {
|
|||
});
|
||||
}
|
||||
|
||||
shared_ptr<ByteArray> Resources::get(const string &resRef, ResourceType type, bool logNotFound) {
|
||||
if (resRef.empty()) return nullptr;
|
||||
|
||||
string cacheKey(getCacheKey(resRef, type));
|
||||
auto res = _resCache.find(cacheKey);
|
||||
if (res != _resCache.end()) return res->second;
|
||||
|
||||
shared_ptr<ByteArray> data = get(_transientProviders, resRef, type);
|
||||
if (!data) {
|
||||
data = get(_providers, resRef, type);
|
||||
}
|
||||
if (!data && logNotFound) {
|
||||
warn("Resource not found: " + cacheKey);
|
||||
}
|
||||
auto pair = _resCache.insert(make_pair(cacheKey, move(data)));
|
||||
|
||||
return pair.first->second;
|
||||
}
|
||||
|
||||
string Resources::getCacheKey(const string &resRef, resource::ResourceType type) const {
|
||||
return str(boost::format("%s.%s") % resRef % getExtByResType(type));
|
||||
}
|
||||
|
||||
shared_ptr<ByteArray> Resources::get(const vector<unique_ptr<IResourceProvider>> &providers, const string &resRef, ResourceType type) {
|
||||
shared_ptr<ByteArray> Resources::doGetRaw(const vector<unique_ptr<IResourceProvider>> &providers, const string &resRef, ResourceType type) {
|
||||
for (auto provider = providers.rbegin(); provider != providers.rend(); ++provider) {
|
||||
if (!(*provider)->supports(type)) continue;
|
||||
|
||||
shared_ptr<ByteArray> data((*provider)->find(resRef, type));
|
||||
if (data) {
|
||||
return data;
|
||||
}
|
||||
if (data) return data;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -318,8 +176,8 @@ shared_ptr<ByteArray> Resources::get(const vector<unique_ptr<IResourceProvider>>
|
|||
shared_ptr<GffStruct> Resources::getGFF(const string &resRef, ResourceType type) {
|
||||
string cacheKey(getCacheKey(resRef, type));
|
||||
|
||||
return findResource<GffStruct>(cacheKey, _gffCache, [this, &resRef, &type]() {
|
||||
shared_ptr<ByteArray> data(get(resRef, type));
|
||||
return getResource<GffStruct>(cacheKey, _gffCache, [this, &resRef, &type]() {
|
||||
shared_ptr<ByteArray> data(getRaw(resRef, type));
|
||||
shared_ptr<GffStruct> gffs;
|
||||
|
||||
if (data) {
|
||||
|
|
|
@ -27,10 +27,8 @@
|
|||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include "2da.h"
|
||||
#include "format/keyreader.h"
|
||||
#include "format/pereader.h"
|
||||
#include "gffstruct.h"
|
||||
#include "keybifprovider.h"
|
||||
#include "resourceprovider.h"
|
||||
#include "types.h"
|
||||
|
||||
|
@ -47,67 +45,40 @@ class Resources : boost::noncopyable {
|
|||
public:
|
||||
static Resources &instance();
|
||||
|
||||
void init(GameID gameId, const boost::filesystem::path &gamePath);
|
||||
void deinit();
|
||||
void indexKeyFile(const boost::filesystem::path &path);
|
||||
void indexErfFile(const boost::filesystem::path &path, bool transient = false);
|
||||
void indexRimFile(const boost::filesystem::path &path, bool transient = false);
|
||||
void indexDirectory(const boost::filesystem::path &path);
|
||||
void indexExeFile(const boost::filesystem::path &path);
|
||||
|
||||
void loadModule(const std::string &name);
|
||||
void invalidateCache();
|
||||
void clearTransientProviders();
|
||||
|
||||
std::shared_ptr<ByteArray> getRaw(const std::string &resRef, ResourceType type, bool logNotFound = true);
|
||||
std::shared_ptr<TwoDA> get2DA(const std::string &resRef, bool logNotFound = true);
|
||||
std::shared_ptr<GffStruct> getGFF(const std::string &resRef, ResourceType type);
|
||||
std::shared_ptr<ByteArray> getFromExe(uint32_t name, PEResourceType type);
|
||||
|
||||
/**
|
||||
* Searches for the raw resource data by ResRef and ResType.
|
||||
*/
|
||||
std::shared_ptr<ByteArray> get(const std::string &resRef, ResourceType type, bool logNotFound = true);
|
||||
|
||||
/**
|
||||
* @return list of available module names
|
||||
*/
|
||||
const std::vector<std::string> &moduleNames() const { return _moduleNames; }
|
||||
|
||||
private:
|
||||
GameID _gameId { GameID::KotOR };
|
||||
boost::filesystem::path _gamePath;
|
||||
std::vector<std::string> _moduleNames;
|
||||
|
||||
// Resource providers
|
||||
// Providers
|
||||
|
||||
PEReader _exeFile;
|
||||
std::vector<std::unique_ptr<IResourceProvider>> _providers;
|
||||
std::vector<std::unique_ptr<IResourceProvider>> _transientProviders; /**< transient providers are replaced when switching between modules */
|
||||
|
||||
// END Resource providers
|
||||
// END Providers
|
||||
|
||||
// Resource caches
|
||||
// Caches
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<ByteArray>> _rawCache;
|
||||
std::unordered_map<std::string, std::shared_ptr<TwoDA>> _2daCache;
|
||||
std::unordered_map<std::string, std::shared_ptr<GffStruct>> _gffCache;
|
||||
std::unordered_map<std::string, std::shared_ptr<ByteArray>> _resCache;
|
||||
|
||||
// END Resource caches
|
||||
// END Caches
|
||||
|
||||
~Resources();
|
||||
|
||||
void indexKeyBifFiles();
|
||||
void indexTexturePacks();
|
||||
void indexAudioFiles();
|
||||
void indexLipModFiles();
|
||||
void indexExeReader();
|
||||
void indexOverrideDirectory();
|
||||
void indexDataDirectory();
|
||||
|
||||
void indexErfFile(const boost::filesystem::path &path);
|
||||
void indexTransientErfFile(const boost::filesystem::path &path);
|
||||
void indexRimFile(const boost::filesystem::path &path);
|
||||
void indexTransientRimFile(const boost::filesystem::path &path);
|
||||
void indexDirectory(const boost::filesystem::path &path);
|
||||
|
||||
void invalidateCache();
|
||||
void loadModuleNames();
|
||||
|
||||
std::shared_ptr<ByteArray> get(const std::vector<std::unique_ptr<IResourceProvider>> &providers, const std::string &resRef, ResourceType type);
|
||||
std::string getCacheKey(const std::string &resRef, ResourceType type) const;
|
||||
|
||||
std::shared_ptr<ByteArray> doGetRaw(const std::vector<std::unique_ptr<IResourceProvider>> &providers, const std::string &resRef, ResourceType type);
|
||||
};
|
||||
|
||||
} // namespace resource
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
#include "../common/pathutil.h"
|
||||
|
||||
#include "gameidutil.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
@ -34,9 +32,7 @@ Strings &Strings::instance() {
|
|||
return instance;
|
||||
}
|
||||
|
||||
void Strings::init(GameID gameId, const fs::path &gameDir) {
|
||||
_gameId = gameId;
|
||||
|
||||
void Strings::init(const fs::path &gameDir) {
|
||||
fs::path tlkPath(getPathIgnoreCase(gameDir, "dialog.tlk"));
|
||||
_tlk.load(tlkPath);
|
||||
}
|
||||
|
@ -59,9 +55,7 @@ string Strings::getSound(int strRef) {
|
|||
}
|
||||
|
||||
void Strings::process(string &str) {
|
||||
if (isTSL(_gameId)) {
|
||||
stripDeveloperNotes(str);
|
||||
}
|
||||
stripDeveloperNotes(str);
|
||||
}
|
||||
|
||||
void Strings::stripDeveloperNotes(string &str) {
|
||||
|
|
|
@ -33,7 +33,7 @@ class Strings {
|
|||
public:
|
||||
static Strings &instance();
|
||||
|
||||
void init(GameID gameId, const boost::filesystem::path &gameDir);
|
||||
void init(const boost::filesystem::path &gameDir);
|
||||
|
||||
/**
|
||||
* Searches for a string in the global talktable by StrRef.
|
||||
|
@ -50,7 +50,6 @@ public:
|
|||
std::string getSound(int strRef);
|
||||
|
||||
private:
|
||||
GameID _gameId { GameID::KotOR };
|
||||
TlkReader _tlk;
|
||||
|
||||
void process(std::string &str);
|
||||
|
|
|
@ -26,12 +26,6 @@ namespace reone {
|
|||
|
||||
namespace resource {
|
||||
|
||||
enum class GameID {
|
||||
KotOR,
|
||||
TSL,
|
||||
TSL_Steam
|
||||
};
|
||||
|
||||
/**
|
||||
* Used together with a ResRef to locate game resources.
|
||||
*/
|
||||
|
|
|
@ -40,7 +40,7 @@ Scripts::Scripts() : MemoryCache(bind(&Scripts::doGet, this, _1)) {
|
|||
}
|
||||
|
||||
shared_ptr<ScriptProgram> Scripts::doGet(string resRef) {
|
||||
shared_ptr<ByteArray> data(Resources::instance().get(resRef, ResourceType::Ncs));
|
||||
shared_ptr<ByteArray> data(Resources::instance().getRaw(resRef, ResourceType::Ncs));
|
||||
if (!data) return nullptr;
|
||||
|
||||
NcsReader ncs(resRef);
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <boost/program_options.hpp>
|
||||
|
||||
#include "../src/common/pathutil.h"
|
||||
#include "../src/resource/gameidutil.h"
|
||||
|
||||
#include "tools.h"
|
||||
#include "types.h"
|
||||
|
@ -61,9 +60,6 @@ Program::Program(int argc, char **argv) : _argc(argc), _argv(argv) {
|
|||
int Program::run() {
|
||||
initOptions();
|
||||
loadOptions();
|
||||
|
||||
_gameId = determineGameID(_gamePath);
|
||||
|
||||
loadTools();
|
||||
|
||||
switch (_operation) {
|
||||
|
|
|
@ -50,7 +50,6 @@ private:
|
|||
boost::filesystem::path _destPath;
|
||||
std::string _target;
|
||||
Operation _operation { Operation::None };
|
||||
resource::GameID _gameId { resource::GameID::KotOR };
|
||||
std::vector<std::shared_ptr<ITool>> _tools;
|
||||
|
||||
void initOptions();
|
||||
|
|
Loading…
Reference in a new issue