1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-07 03:12:36 +01:00

Remove old file indexing system and IO handling

- Use FileIndex inside GameData to handle normalisation
- Remove old raw pointer API for loading data
This commit is contained in:
Daniel Evans 2015-03-06 01:40:29 +00:00 committed by Daniel Evans
parent c264e78696
commit ce4b8fc83a
12 changed files with 80 additions and 221 deletions

View File

@ -26,6 +26,12 @@ public:
*/ */
void indexDirectory(const std::string& directory); void indexDirectory(const std::string& directory);
/**
* Adds the files contained within the given directory tree to the
* file index.
*/
void indexTree(const std::string& root);
/** /**
* Adds the files contained within the given Archive file to the * Adds the files contained within the given Archive file to the
* file index. * file index.

View File

@ -16,6 +16,7 @@
#include <audio/MADStream.hpp> #include <audio/MADStream.hpp>
#include <render/TextureData.hpp> #include <render/TextureData.hpp>
#include <core/FileIndex.hpp>
#include <memory> #include <memory>
@ -41,17 +42,7 @@ private:
std::string splash; std::string splash;
public: public:
/**
* @struct FileInfo
* Stores information about a file the engine might want to load
*/
struct FileInfo
{
bool archived; /// Is the file inside an IMG or on the filesystem?
std::string path; /// Path to the file containing the file.
};
/** /**
* ctor * ctor
* @param path Path to the root of the game data. * @param path Path to the root of the game data.
@ -152,21 +143,7 @@ public:
void loadSplash(const std::string& name); void loadSplash(const std::string& name);
/** FileHandle openFile(const std::string& name);
* Returns a pointer to the named file if it is available,
* the memory must be freed by the caller.
* @param name the filename in the archive
* @return pointer to the data, NULL if it is not available
*/
char* openFile(const std::string& name);
FileHandle openFile2(const std::string& name);
/**
* @brief loadFile Marks a file as open, and opens it.
* @param name
* @return
*/
char* loadFile(const std::string& name);
/** /**
* @brief getAtlas Returns atlas i, creating it if the situation calls for it. * @brief getAtlas Returns atlas i, creating it if the situation calls for it.
@ -181,6 +158,8 @@ public:
return textures[{name, alpha}]; return textures[{name, alpha}];
} }
FileIndex index;
/** /**
* Files that have been loaded previously * Files that have been loaded previously
*/ */
@ -191,12 +170,7 @@ public:
*/ */
std::map<std::string, std::string> iplLocations; std::map<std::string, std::string> iplLocations;
std::map<std::string, std::string> ideLocations; std::map<std::string, std::string> ideLocations;
/**
* Maps file names to data about the file.
*/
std::map<std::string, FileInfo> _knownFiles;
/** /**
* Map of loaded archives * Map of loaded archives
*/ */

View File

@ -68,7 +68,7 @@ private:
GameData* _gameData; GameData* _gameData;
std::string _file; std::string _file;
ModelCallback _callback; ModelCallback _callback;
FileHandle _data; FileHandle data;
public: public:
LoadModelJob(WorkContext* context, GameData* gd, const std::string& file, ModelCallback cb); LoadModelJob(WorkContext* context, GameData* gd, const std::string& file, ModelCallback cb);

View File

@ -7,6 +7,9 @@
#include <loaders/rwbinarystream.h> #include <loaders/rwbinarystream.h>
#include <WorkContext.hpp>
#include <core/FileHandle.hpp>
#include <functional>
#include <string> #include <string>
#include <map> #include <map>
@ -15,20 +18,16 @@ class GameData;
class TextureLoader class TextureLoader
{ {
public: public:
bool loadFromFile(std::string filename, GameData* gameData); bool loadFromMemory(FileHandle file, GameData* gameData);
bool loadFromMemory(char *data, GameData* gameData);
}; };
#include <WorkContext.hpp>
#include <functional>
// TODO: refactor this interface to be more like ModelLoader so they can be rolled into one. // TODO: refactor this interface to be more like ModelLoader so they can be rolled into one.
class LoadTextureArchiveJob : public WorkJob class LoadTextureArchiveJob : public WorkJob
{ {
private: private:
GameData* _gameData; GameData* _gameData;
std::string _file; std::string _file;
char* _data; FileHandle data;
public: public:
LoadTextureArchiveJob(WorkContext* context, GameData* gd, const std::string& file); LoadTextureArchiveJob(WorkContext* context, GameData* gd, const std::string& file);

View File

@ -29,6 +29,27 @@ void FileIndex::indexDirectory(const std::string& directory)
}; };
} }
} }
closedir(dp);
}
void FileIndex::indexTree(const std::string& root)
{
indexDirectory(root);
DIR* dp = opendir(root.c_str());
dirent* ep;
if ( dp == NULL ) {
throw std::runtime_error("Unable to open directory: " + root);
}
while( (ep = readdir(dp)) )
{
if( ep->d_type == DT_DIR && ep->d_name[0] != '.' )
{
std::string path = root + "/" + ep->d_name;
indexTree(path);
}
}
closedir(dp);
} }
void FileIndex::indexArchive(const std::string& archive) void FileIndex::indexArchive(const std::string& archive)
@ -120,11 +141,16 @@ FileHandle FileIndex::openFile(const std::string& filename)
} }
dfile.seekg(0, std::ios_base::end); dfile.seekg(0, std::ios_base::end);
size_t length = dfile.tellg(); length = dfile.tellg();
dfile.seekg(0); dfile.seekg(0);
char *data = new char[length]; data = new char[length];
dfile.read(data, length); dfile.read(data, length);
} }
if( data == nullptr )
{
return nullptr;
}
return FileHandle( new FileContentsInfo{ data, length } ); return FileHandle( new FileContentsInfo{ data, length } );
} }

View File

@ -41,7 +41,7 @@ std::string findPathRealCase(const std::string& base, const std::string& path)
// Open the current "base" path (i.e. the real path) // Open the current "base" path (i.e. the real path)
DIR* dp = opendir(base.c_str()); DIR* dp = opendir(base.c_str());
dirent* ep; dirent* ep;
if( dp != NULL) { if( dp != NULL) {
while( (ep = readdir(dp)) ) { while( (ep = readdir(dp)) ) {
realName = ep->d_name; realName = ep->d_name;
@ -96,25 +96,12 @@ GameData::~GameData()
void GameData::load() void GameData::load()
{ {
index.indexTree(datpath);
parseDAT(datpath+"/data/default.dat"); parseDAT(datpath+"/data/default.dat");
parseDAT(datpath+"/data/gta3.dat"); parseDAT(datpath+"/data/gta3.dat");
_knownFiles.insert({"wheels.DFF", {false, datpath+"/models/Generic/wheels.DFF"}}); loadDFF("wheels.dff");
_knownFiles.insert({"loplyguy.dff", {false, datpath+"/models/Generic/loplyguy.dff"}});
_knownFiles.insert({"weapons.dff", {false, datpath+"/models/Generic/weapons.dff"}});
_knownFiles.insert({"arrow.dff", {false, datpath+"/models/Generic/arrow.DFF"}});
_knownFiles.insert({"particle.txd", {false, datpath+"/models/particle.txd"}});
_knownFiles.insert({"hud.txd", {false, datpath+"/models/hud.txd"}});
_knownFiles.insert({"english.gxt", {false, datpath+"/TEXT/english.gxt"}});
_knownFiles.insert({"ped.ifp", {false, datpath+"/anim/ped.ifp"}});
_knownFiles.insert({"fonts.txd", {false, datpath+"/models/fonts.txd"}});
_knownFiles.insert({"news.txd", {false, datpath+"/txd/NEWS.TXD"}});
_knownFiles.insert({"splash1.txd", {false, datpath+"/txd/SPLASH1.TXD"}});
_knownFiles.insert({"splash2.txd", {false, datpath+"/txd/SPLASH2.TXD"}});
_knownFiles.insert({"splash3.txd", {false, datpath+"/txd/SPLASH3.TXD"}});
loadDFF("wheels.DFF");
loadDFF("weapons.dff"); loadDFF("weapons.dff");
loadDFF("arrow.dff"); loadDFF("arrow.dff");
loadTXD("particle.txd"); loadTXD("particle.txd");
@ -179,9 +166,7 @@ void GameData::parseDAT(const std::string& path)
texpath[t] = '/'; texpath[t] = '/';
} }
} }
texpath = findPathRealCase(datpath, texpath);
std::string texname = texpath.substr(texpath.find_last_of("/")+1); std::string texname = texpath.substr(texpath.find_last_of("/")+1);
_knownFiles.insert({ texname, { false, texpath }});
loadTXD(texname); loadTXD(texname);
} }
} }
@ -219,32 +204,7 @@ void GameData::loadCOL(const size_t zone, const std::string& name)
void GameData::loadIMG(const std::string& name) void GameData::loadIMG(const std::string& name)
{ {
LoaderIMG imgLoader; index.indexArchive(datpath + name);
std::string archivePath = datpath + name;
if (imgLoader.load(archivePath)) {
for (size_t i = 0; i < imgLoader.getAssetCount(); i++) {
auto &asset = imgLoader.getAssetInfoByIndex(i);
std::string filename = asset.name;
if(asset.size == 0)
{
engine->logger.warning("Data", "Ignoring asset " + filename + " with size 0");
}
else
{
// Enter the asset twice..
_knownFiles.insert({ filename, { true, archivePath }});
for(size_t t = 0; t < filename.size(); ++t)
{
filename[t] = tolower(filename[t]);
}
_knownFiles.insert({ filename, { true, archivePath }});
}
}
archives.insert({archivePath, imgLoader});
}
} }
void GameData::loadIPL(const std::string& name) void GameData::loadIPL(const std::string& name)
@ -364,7 +324,7 @@ SCMFile *GameData::loadSCM(const std::string &path)
void GameData::loadGXT(const std::string &name) void GameData::loadGXT(const std::string &name)
{ {
auto d = openFile2(name); auto d = openFile(name);
LoaderGXT loader; LoaderGXT loader;
@ -470,7 +430,7 @@ void GameData::loadDFF(const std::string& name, bool async)
void GameData::loadIFP(const std::string &name) void GameData::loadIFP(const std::string &name)
{ {
auto f = openFile2(name); auto f = openFile(name);
if(f) if(f)
{ {
@ -563,109 +523,14 @@ void GameData::loadSplash(const std::string &name)
engine->state.currentSplash = lower; engine->state.currentSplash = lower;
} }
char* GameData::openFile(const std::string& name) FileHandle GameData::openFile(const std::string &name)
{ {
auto i = _knownFiles.find(name); auto file = index.openFile(name);
if(i != _knownFiles.end()) if( file == nullptr )
{ {
if(i->second.archived) engine->logger.error("Data", "Unable to open file: " + name);
{
// Find the archive
auto ai = archives.find(i->second.path);
if(ai != archives.end())
{
return ai->second.loadToMemory(name);
}
else
{
engine->logger.error("Data", "Archive not found " + i->second.path);
}
}
else
{
std::ifstream dfile(i->second.path);
if ( ! dfile.is_open()) {
engine->logger.error("Data", "Error opening file " + i->second.path);
return nullptr;
}
dfile.seekg(0, std::ios_base::end);
size_t length = dfile.tellg();
dfile.seekg(0);
char *data = new char[length];
dfile.read(data, length);
return data;
}
} }
else return file;
{
engine->logger.error("Data", "Unable to locate file: " + name);
}
return nullptr;
}
FileHandle GameData::openFile2(const std::string &name)
{
auto i = _knownFiles.find(name);
if(i != _knownFiles.end())
{
char* data = nullptr;
size_t length = 0;
if(i->second.archived)
{
// Find the archive
auto ai = archives.find(i->second.path);
if(ai != archives.end())
{
LoaderIMGFile asset;
if( ai->second.findAssetInfo(name, asset) )
{
data = ai->second.loadToMemory(name);
length = asset.size * 2048;
}
}
else
{
engine->logger.error("Data", "Archive not found " + i->second.path);
}
}
else
{
std::ifstream dfile(i->second.path);
if ( ! dfile.is_open()) {
engine->logger.error("Data", "Error opening file " + i->second.path);
return nullptr;
}
dfile.seekg(0, std::ios_base::end);
length = dfile.tellg();
dfile.seekg(0);
data = new char[length];
dfile.read(data, length);
}
return FileHandle( new FileContentsInfo{ data, length } );
}
else
{
engine->logger.error("Data", "Unable to locate file: " + name);
}
return nullptr;
}
char* GameData::loadFile(const std::string &name)
{
auto it = loadedFiles.find(name);
if( it != loadedFiles.end() ) {
engine->logger.warning("Data", "File " + name + " already loaded");
}
loadedFiles[name] = true;
return openFile(name);
} }
TextureAtlas* GameData::getAtlas(size_t i) TextureAtlas* GameData::getAtlas(size_t i)

View File

@ -215,6 +215,9 @@ InstanceObject *GameWorld::createInstance(const uint16_t id, const glm::vec3& po
std::string modelname = oi->modelName; std::string modelname = oi->modelName;
std::string texturename = oi->textureName; std::string texturename = oi->textureName;
std::transform(std::begin(modelname), std::end(modelname), std::begin(modelname), tolower);
std::transform(std::begin(texturename), std::end(texturename), std::begin(texturename), tolower);
// Ensure the relevant data is loaded. // Ensure the relevant data is loaded.
if(! oi->modelName.empty()) { if(! oi->modelName.empty()) {
if( modelname != "null" ) { if( modelname != "null" ) {
@ -660,7 +663,7 @@ void GameWorld::loadCutscene(const std::string &name)
std::string lowerName(name); std::string lowerName(name);
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower); std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower);
auto datfile = gameData.openFile2(lowerName + ".dat"); auto datfile = gameData.openFile(lowerName + ".dat");
CutsceneData* cutscene = new CutsceneData; CutsceneData* cutscene = new CutsceneData;

View File

@ -456,26 +456,26 @@ Model* LoaderDFF::loadFromMemory(FileHandle file, GameData *gameData)
} }
LoadModelJob::LoadModelJob(WorkContext *context, GameData* gd, const std::string &file, ModelCallback cb) LoadModelJob::LoadModelJob(WorkContext *context, GameData* gd, const std::string &file, ModelCallback cb)
: WorkJob(context), _gameData(gd), _file(file), _callback(cb), _data(nullptr) : WorkJob(context), _gameData(gd), _file(file), _callback(cb)
{ {
} }
void LoadModelJob::work() void LoadModelJob::work()
{ {
_data = _gameData->openFile2(_file); data = _gameData->openFile(_file);
} }
void LoadModelJob::complete() void LoadModelJob::complete()
{ {
Model* m = nullptr; Model* m = nullptr;
// TODO error status // TODO error status
if( _data ) { if( data ) {
// TODO allow some of the loading to process in a seperate thread. // TODO allow some of the loading to process in a seperate thread.
LoaderDFF loader; LoaderDFF loader;
m = loader.loadFromMemory(_data, _gameData); m = loader.loadFromMemory(data, _gameData);
} }
_callback(m); _callback(m);

View File

@ -7,23 +7,6 @@
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
bool TextureLoader::loadFromFile(std::string filename, GameData* gameData)
{
std::ifstream dfile(filename);
if ( ! dfile.is_open()) {
std::cerr << "Error opening file " << filename << std::endl;
return false;
}
dfile.seekg(0, std::ios_base::end);
size_t length = dfile.tellg();
dfile.seekg(0);
char *data = new char[length];
dfile.read(data, length);
return loadFromMemory(data, gameData);
}
GLuint gErrorTextureData[] = { 0xFFFF00FF, 0xFF000000, 0xFF000000, 0xFFFF00FF }; GLuint gErrorTextureData[] = { 0xFFFF00FF, 0xFF000000, 0xFF000000, 0xFFFF00FF };
GLuint gDebugTextureData[] = {0xFF0000FF, 0xFF00FF00}; GLuint gDebugTextureData[] = {0xFF0000FF, 0xFF00FF00};
GLuint gTextureRed[] = {0xFF0000FF}; GLuint gTextureRed[] = {0xFF0000FF};
@ -201,8 +184,9 @@ TextureData::Handle createTexture(RW::BSTextureNative& texNative, RW::BinaryStre
return TextureData::create( textureName, { texNative.width, texNative.height }, transparent ); return TextureData::create( textureName, { texNative.width, texNative.height }, transparent );
} }
bool TextureLoader::loadFromMemory(char *data, GameData *gameData) bool TextureLoader::loadFromMemory(FileHandle file, GameData *gameData)
{ {
auto data = file->data;
RW::BinaryStreamSection root(data); RW::BinaryStreamSection root(data);
/*auto texDict =*/ root.readStructure<RW::BSTextureDictionary>(); /*auto texDict =*/ root.readStructure<RW::BSTextureDictionary>();
@ -218,7 +202,7 @@ bool TextureLoader::loadFromMemory(char *data, GameData *gameData)
std::string alpha = std::string(texNative.alphaName); std::string alpha = std::string(texNative.alphaName);
std::transform(name.begin(), name.end(), name.begin(), ::tolower ); std::transform(name.begin(), name.end(), name.begin(), ::tolower );
std::transform(alpha.begin(), alpha.end(), alpha.begin(), ::tolower ); std::transform(alpha.begin(), alpha.end(), alpha.begin(), ::tolower );
auto texture = createTexture(texNative, rootSection); auto texture = createTexture(texNative, rootSection);
gameData->textures[{name, alpha}] = texture; gameData->textures[{name, alpha}] = texture;
@ -233,23 +217,21 @@ bool TextureLoader::loadFromMemory(char *data, GameData *gameData)
LoadTextureArchiveJob::LoadTextureArchiveJob(WorkContext *context, GameData *gd, const std::string &file) LoadTextureArchiveJob::LoadTextureArchiveJob(WorkContext *context, GameData *gd, const std::string &file)
: WorkJob(context), _gameData(gd), _file(file), _data(nullptr) : WorkJob(context), _gameData(gd), _file(file)
{ {
} }
void LoadTextureArchiveJob::work() void LoadTextureArchiveJob::work()
{ {
_data = _gameData->openFile(_file); data = _gameData->openFile(_file);
} }
void LoadTextureArchiveJob::complete() void LoadTextureArchiveJob::complete()
{ {
// TODO error status // TODO error status
if(_data) { if(data) {
TextureLoader loader; TextureLoader loader;
loader.loadFromMemory(_data, _gameData); loader.loadFromMemory(data, _gameData);
} }
delete[] _data;
} }

View File

@ -647,7 +647,7 @@ void GameRenderer::renderInstance(InstanceObject *instance)
} }
glm::mat4 matrixModel; glm::mat4 matrixModel;
if( instance->body ) { if( instance->body && instance->body->body ) {
instance->body->body->getWorldTransform().getOpenGLMatrix(glm::value_ptr(matrixModel)); instance->body->body->getWorldTransform().getOpenGLMatrix(glm::value_ptr(matrixModel));
} }
else { else {
@ -917,6 +917,10 @@ void GameRenderer::renderGeometry(Model* model, size_t g, const glm::mat4& model
auto& tC = mat.textures[0].name; auto& tC = mat.textures[0].name;
auto& tA = mat.textures[0].alphaName; auto& tA = mat.textures[0].alphaName;
tex = engine->gameData.findTexture(tC, tA); tex = engine->gameData.findTexture(tC, tA);
if( ! tex )
{
//engine->logger.warning("Renderer", "Missing texture: " + tC + " " + tA);
}
mat.textures[0].texture = tex; mat.textures[0].texture = tex;
} }
if( tex ) if( tex )

View File

@ -257,6 +257,6 @@ void main()
{ {
vec4 c = texture2D(texture, TexCoords); vec4 c = texture2D(texture, TexCoords);
// Set colour to 0, 0, 0, 1 for textured mode. // Set colour to 0, 0, 0, 1 for textured mode.
outColour = colour + c.rgba; outColour = vec4(colour.rgb + c.rgb, colour.a);
})"; })";
} }

View File

@ -70,7 +70,7 @@ RWGame::RWGame(const std::string& gamepath, int argc, char* argv[])
// Initalize all the archives. // Initalize all the archives.
engine->gameData.loadIMG("/models/gta3"); engine->gameData.loadIMG("/models/gta3");
engine->gameData.loadIMG("/models/txd"); //engine->gameData.loadIMG("/models/txd");
engine->gameData.loadIMG("/anim/cuts"); engine->gameData.loadIMG("/anim/cuts");
// Initialize renderer // Initialize renderer