1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-22 02:12:45 +01:00

Refactor Object Definition information to GameData

This commit is contained in:
Daniel Evans 2015-04-24 18:09:21 +01:00
parent a4f0ef7f44
commit 5db4c28f04
18 changed files with 164 additions and 127 deletions

View File

@ -30,7 +30,7 @@ class SCMFile;
/**
* @brief Loads and stores all "static" data such as loaded models, handling
* information, weather etc.
* information, weather, object definitions etc.
*
* @todo Move parsing of one-off data files from this class.
* @todo Improve how Loaders and written and used
@ -73,10 +73,15 @@ public:
}
/**
* Loads the data contained in the given file
* Stores the given IDE file in the list of item definitions to load.
*/
void loadIDE(const std::string& name);
void addIDE(const std::string& name);
/**
* Loads the object definitions from the given IDE file
*/
bool loadObjects(const std::string& name);
/**
* Handles the parsing of a COL file.
*/
@ -184,7 +189,31 @@ public:
* Map Zones
*/
std::map<std::string, ZoneData> zones;
/**
* Object Definitions
*/
std::map<ObjectID, ObjectInformationPtr> objectTypes;
uint16_t findModelObject(const std::string model);
template<class T> std::shared_ptr<T> findObjectType(ObjectID id)
{
auto f = objectTypes.find(id);
/// @TODO don't instanciate an object here just to read .type
T tmp;
if( f != objectTypes.end() && f->second->class_type == tmp.class_type )
{
return std::static_pointer_cast<T>(f->second);
}
return nullptr;
}
/**
* Paths associated with each object definition.
*/
std::map<uint16_t, std::vector<std::shared_ptr<PathData>>> objectNodes;
/**
* The vehicle colour palettes
*/

View File

@ -67,11 +67,6 @@ public:
Logger* logger;
/**
* Loads an IDE into the game
*/
bool defineItems(const std::string& name);
/**
* Loads an IPL into the game.
* @param name The name of the IPL as it appears in the games' gta.dat
@ -85,7 +80,6 @@ public:
* Creates an instance
*/
InstanceObject *createInstance(const uint16_t id, const glm::vec3& pos, const glm::quat& rot = glm::quat());
uint16_t findModelDefinition(const std::string model);
/**
* @brief Creates an InstanceObject for use in the current Cutscene.
@ -163,28 +157,6 @@ public:
* State of playing sounds
*/
SoundManager sound;
/**
* Object Definitions
*/
std::map<ObjectID, ObjectInformationPtr> objectTypes;
template<class T> std::shared_ptr<T> findObjectType(ObjectID id)
{
auto f = objectTypes.find(id);
/// @TODO don't instanciate an object here just to read .type
T tmp;
if( f != objectTypes.end() && f->second->class_type == tmp.class_type )
{
return std::static_pointer_cast<T>(f->second);
}
return nullptr;
}
/**
* Paths associated with each object definition.
*/
std::map<uint16_t, std::vector<std::shared_ptr<PathData>>> objectNodes;
/**
* @brief objects All active GameObjects in the world.

View File

@ -139,7 +139,7 @@ void GameData::parseDAT(const std::string& path)
cmd = line.substr(0, space);
if(cmd == "IDE")
{
loadIDE(line.substr(space+1));
addIDE(line.substr(space+1));
}
else if(cmd == "SPLASH")
{
@ -174,7 +174,7 @@ void GameData::parseDAT(const std::string& path)
}
}
void GameData::loadIDE(const std::string& name)
void GameData::addIDE(const std::string& name)
{
std::string lowername = name;
for(size_t t = 0; t < lowername.size(); ++t)
@ -188,6 +188,55 @@ void GameData::loadIDE(const std::string& name)
ideLocations.insert({lowername, datpath+"/"+lowername});
}
bool GameData::loadObjects(const std::string& name)
{
auto i = ideLocations.find(name);
std::string path = name;
LoaderIDE idel;
if(idel.load(path)) {
objectTypes.insert(idel.objects.begin(), idel.objects.end());
// Load AI information.
for( size_t a = 0; a < idel.PATHs.size(); ++a ) {
auto pathit = objectNodes.find(idel.PATHs[a]->ID);
if( pathit == objectNodes.end() ) {
objectNodes.insert({
idel.PATHs[a]->ID,
{idel.PATHs[a]}
});
}
else {
pathit->second.push_back(idel.PATHs[a]);
}
}
}
else {
logger->error("Data", "Failed to load IDE " + path);
}
return false;
}
#include <strings.h>
uint16_t GameData::findModelObject(const std::string model)
{
// Dear C++ Why do I have to resort to strcasecmp this isn't C.
auto defit = std::find_if(objectTypes.begin(), objectTypes.end(),
[&](const decltype(objectTypes)::value_type& d)
{
if(d.second->class_type == ObjectInformation::_class("OBJS"))
{
auto dat = static_cast<ObjectData*>(d.second.get());
return strcasecmp(dat->modelName.c_str(), model.c_str()) == 0;
}
return false;
});
if( defit != objectTypes.end() ) return defit->first;
return -1;
}
void GameData::loadCOL(const size_t zone, const std::string& name)
{
LoaderCOL col;

View File

@ -109,37 +109,6 @@ GameWorld::~GameWorld()
/// @todo delete other things.
}
bool GameWorld::defineItems(const std::string& name)
{
auto i = data->ideLocations.find(name);
std::string path = name;
LoaderIDE idel;
if(idel.load(path)) {
objectTypes.insert(idel.objects.begin(), idel.objects.end());
// Load AI information.
for( size_t a = 0; a < idel.PATHs.size(); ++a ) {
auto pathit = objectNodes.find(idel.PATHs[a]->ID);
if( pathit == objectNodes.end() ) {
objectNodes.insert({
idel.PATHs[a]->ID,
{idel.PATHs[a]}
});
}
else {
pathit->second.push_back(idel.PATHs[a]);
}
}
}
else {
logger->error("Data", "Failed to load IDE " + path);
}
return false;
}
bool GameWorld::placeItems(const std::string& name)
{
auto i = data->iplLocations.find(name);
@ -183,7 +152,7 @@ bool GameWorld::placeItems(const std::string& name)
InstanceObject *GameWorld::createInstance(const uint16_t id, const glm::vec3& pos, const glm::quat& rot)
{
auto oi = findObjectType<ObjectData>(id);
auto oi = data->findObjectType<ObjectData>(id);
if( oi ) {
std::string modelname = oi->modelName;
@ -266,24 +235,6 @@ void GameWorld::cleanupTraffic(const glm::vec3& focus)
destroyQueuedObjects();
}
#include <strings.h>
uint16_t GameWorld::findModelDefinition(const std::string model)
{
// Dear C++ Why do I have to resort to strcasecmp this isn't C.
auto defit = std::find_if(objectTypes.begin(), objectTypes.end(),
[&](const decltype(objectTypes)::value_type& d)
{
if(d.second->class_type == ObjectInformation::_class("OBJS"))
{
auto dat = static_cast<ObjectData*>(d.second.get());
return strcasecmp(dat->modelName.c_str(), model.c_str()) == 0;
}
return false;
});
if( defit != objectTypes.end() ) return defit->first;
return -1;
}
#include <ai/PlayerController.hpp>
#include <core/Logger.hpp>
CutsceneObject *GameWorld::createCutsceneObject(const uint16_t id, const glm::vec3 &pos, const glm::quat &rot)
@ -291,8 +242,8 @@ CutsceneObject *GameWorld::createCutsceneObject(const uint16_t id, const glm::ve
std::string modelname;
std::string texturename;
auto type = objectTypes.find(id);
if( type != objectTypes.end() )
auto type = data->objectTypes.find(id);
if( type != data->objectTypes.end() )
{
if( type->second->class_type == ObjectInformation::_class("HIER") )
{
@ -359,7 +310,7 @@ CutsceneObject *GameWorld::createCutsceneObject(const uint16_t id, const glm::ve
VehicleObject *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos, const glm::quat& rot)
{
auto vti = findObjectType<VehicleData>(id);
auto vti = data->findObjectType<VehicleData>(id);
if( vti ) {
logger->info("World", "Creating Vehicle ID " + std::to_string(id) + " (" + vti->gameName + ")");
@ -382,7 +333,7 @@ VehicleObject *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos,
logger->warning("World", "No colour palette for vehicle " + vti->modelName);
}
auto wi = findObjectType<ObjectData>(vti->wheelModelID);
auto wi = data->findObjectType<ObjectData>(vti->wheelModelID);
if( wi )
{
if(! wi->textureName.empty()) {
@ -424,7 +375,7 @@ VehicleObject *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos,
CharacterObject* GameWorld::createPedestrian(const uint16_t id, const glm::vec3 &pos, const glm::quat& rot)
{
auto pt = findObjectType<CharacterData>(id);
auto pt = data->findObjectType<CharacterData>(id);
if( pt ) {
std::string modelname = pt->modelName;

View File

@ -19,8 +19,8 @@ InstanceObject::InstanceObject(GameWorld* engine,
if( obj ) {
changeModel(obj);
auto pathit = engine->objectNodes.find(obj->ID);
if( pathit != engine->objectNodes.end() ) {
auto pathit = engine->data->objectNodes.find(obj->ID);
if( pathit != engine->data->objectNodes.end() ) {
auto& pathlist = pathit->second;
for( size_t p = 0; p < pathlist.size(); ++p ) {
auto& path = pathlist[p];

View File

@ -561,7 +561,7 @@ void GameRenderer::renderVehicle(VehicleObject *vehicle)
// Draw wheels n' stuff
for( size_t w = 0; w < vehicle->info->wheels.size(); ++w) {
auto woi = engine->findObjectType<ObjectData>(vehicle->vehicle->wheelModelID);
auto woi = engine->data->findObjectType<ObjectData>(vehicle->vehicle->wheelModelID);
if( woi ) {
Model* wheelModel = engine->data->models["wheels"]->resource;
auto& wi = vehicle->physVehicle->getWheelInfo(w);
@ -705,7 +705,7 @@ void GameRenderer::renderPickup(PickupObject *pickup)
glm::mat4 modelMatrix = glm::translate(glm::mat4(), pickup->getPosition());
modelMatrix = glm::rotate(modelMatrix, engine->gameTime, glm::vec3(0.f, 0.f, 1.f));
auto odata = engine->findObjectType<ObjectData>(pickup->getModelID());
auto odata = engine->data->findObjectType<ObjectData>(pickup->getModelID());
Model* model = nullptr;
ModelFrame* itemModel = nullptr;
@ -793,7 +793,7 @@ void GameRenderer::renderProjectile(ProjectileObject *projectile)
{
glm::mat4 modelMatrix = projectile->getTimeAdjustedTransform(_renderAlpha);
auto odata = engine->findObjectType<ObjectData>(projectile->getProjectileInfo().weapon->modelID);
auto odata = engine->data->findObjectType<ObjectData>(projectile->getProjectileInfo().weapon->modelID);
auto weapons = engine->data->models["weapons"];
if( weapons && weapons->resource ) {
auto itemModel = weapons->resource->findFrame(odata->modelName + "_l0");
@ -837,7 +837,7 @@ void GameRenderer::renderWheel(Model* model, const glm::mat4 &matrix, const std:
void GameRenderer::renderItem(InventoryItem *item, const glm::mat4 &modelMatrix)
{
// srhand
std::shared_ptr<ObjectData> odata = engine->findObjectType<ObjectData>(item->getModelID());
std::shared_ptr<ObjectData> odata = engine->data->findObjectType<ObjectData>(item->getModelID());
auto weapons = engine->data->models["weapons"];
if( weapons && weapons->resource ) {
auto itemModel = weapons->resource->findFrame(odata->modelName + "_l0");

View File

@ -407,7 +407,7 @@ void game_load_special_char(const ScriptArguments& args)
}
bool game_special_char_loaded(const ScriptArguments& args)
{
auto chartype = args.getVM()->getWorld()->findObjectType<CharacterData>(args[0].integer);
auto chartype = args.getVM()->getWorld()->data->findObjectType<CharacterData>(args[0].integer);
if( chartype ) {
auto modelfind = args.getVM()->getWorld()->data->models.find(chartype->modelName);
if( modelfind != args.getVM()->getWorld()->data->models.end() && modelfind->second->resource != nullptr ) {

View File

@ -197,7 +197,7 @@ bool game_character_in_vehicle(const ScriptArguments& args)
bool game_character_in_model(const ScriptArguments& args)
{
auto vdata = args.getVM()->getWorld()->findObjectType<VehicleData>(args[1].integer);
auto vdata = args.getVM()->getWorld()->data->findObjectType<VehicleData>(args[1].integer);
if( vdata )
{
auto controller = (CharacterController*)(*args[0].handle);
@ -665,13 +665,13 @@ void game_create_pickup(const ScriptArguments& args)
auto model = args.getVM()->getFile()->getModels()[id];
std::transform(model.begin(), model.end(), model.begin(), ::tolower);
id = args.getVM()->getWorld()->findModelDefinition(model);
id = args.getVM()->getWorld()->data->findModelObject(model);
args.getVM()->getWorld()->data->loadDFF(model+".dff");
args.getVM()->getWorld()->data->loadTXD("icons.txd");
}
else
{
auto data = args.getVM()->getWorld()->findObjectType<ObjectData>(id);
auto data = args.getVM()->getWorld()->data->findObjectType<ObjectData>(id);
if ( ! ( id >= 170 && id <= 184 ) )
{
@ -779,17 +779,16 @@ void game_create_object_world(const ScriptArguments& args)
if( id < 0 ) {
auto& modelname = args.getVM()->getFile()->getModels()[-id];
id = args.getVM()->getWorld()->findModelDefinition(modelname);
id = args.getVM()->getWorld()->data->findModelObject(modelname);
if( id == (uint16_t)-1 ) {
args.getVM()->getWorld()->logger->error("SCM", "Failed to find model " + modelname);
}
}
auto& object = args.getVM()->getWorld()->objectTypes[id];
glm::vec3 position(args[1].real, args[2].real, args[3].real);
auto inst = args.getVM()->getWorld()->createInstance(object->ID, position);
auto inst = args.getVM()->getWorld()->createInstance(id, position);
*args[4].handle = inst;
}
@ -897,8 +896,8 @@ void game_change_nearest_model(const ScriptArguments& args)
std::transform(newmodel.begin(), newmodel.end(), newmodel.begin(), ::tolower);
std::transform(oldmodel.begin(), oldmodel.end(), oldmodel.begin(), ::tolower);
auto newobjectid = args.getVM()->getWorld()->findModelDefinition(newmodel);
auto nobj = args.getVM()->getWorld()->findObjectType<ObjectData>(newobjectid);
auto newobjectid = args.getVM()->getWorld()->data->findModelObject(newmodel);
auto nobj = args.getVM()->getWorld()->data->findObjectType<ObjectData>(newobjectid);
/// @todo Objects need to adopt the new object ID, not just the model.
for(auto o : args.getVM()->getWorld()->objects) {

View File

@ -0,0 +1,31 @@
#include <boost/test/unit_test.hpp>
#include <engine/GameData.hpp>
#include <test_globals.hpp>
BOOST_AUTO_TEST_SUITE(GameDataTests)
BOOST_AUTO_TEST_CASE(test_object_data)
{
GameData gd(&Global::get().log, Global::getGamePath());
GameWorld gw(&Global::get().log, &gd);
gd.load();
gd.loadObjects(Global::getGamePath() + "/data/maps/generic.ide");
{
auto def = gd.findObjectType<ObjectData>(1100);
BOOST_REQUIRE( def );
BOOST_ASSERT(def->class_type == ObjectInformation::_class("OBJS"));
BOOST_CHECK_EQUAL( def->modelName, "rd_Corner1" );
BOOST_CHECK_EQUAL( def->textureName, "generic" );
BOOST_CHECK_EQUAL( def->numClumps, 1 );
BOOST_CHECK_EQUAL( def->drawDistance[0], 220 );
BOOST_CHECK_EQUAL( def->flags, 0 );
}
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -44,7 +44,7 @@ void IngameState::startTest()
auto carRot = glm::angleAxis(glm::radians(90.f), glm::vec3(0.f, 0.f, 1.f));
//auto boatPos = glm::vec3( -1000.f, -1040.f, 5.f );
int i = 0;
for( auto& vi : getWorld()->objectTypes ) {
for( auto& vi : getWorld()->data->objectTypes ) {
switch( vi.first ) {
case 140: continue;
case 141: continue;

View File

@ -16,7 +16,7 @@ void LoadingState::enter()
for(std::map<std::string, std::string>::iterator it = world->data->ideLocations.begin();
it != world->data->ideLocations.end();
++it) {
world->defineItems(it->second);
world->data->loadObjects(it->second);
}
// Load IPLs

View File

@ -1,8 +1,9 @@
#include "ItemListModel.hpp"
#include <engine/GameData.hpp>
qint16 ItemListModel::getIDOf(unsigned int row) const
{
if( row < world()->objectTypes.size() )
if( row < world()->data->objectTypes.size() )
{
return row;
}
@ -17,7 +18,7 @@ ItemListModel::ItemListModel(GameWorld *world, QObject *parent) :
int ItemListModel::rowCount(const QModelIndex &parent) const
{
return _world->objectTypes.size();
return _world->data->objectTypes.size();
}
int ItemListModel::columnCount(const QModelIndex &parent) const

View File

@ -171,7 +171,7 @@ void ViewerWidget::showObject(qint16 item)
if( dummyObject ) gworld->destroyObject( dummyObject );
auto def = world()->objectTypes[item];
auto def = world()->data->objectTypes[item];
if( def )
{

View File

@ -1,13 +1,13 @@
#include "ObjectListModel.hpp"
ObjectListModel::ObjectListModel(GameWorld *world, QObject *parent) :
QAbstractTableModel(parent), _world( world )
ObjectListModel::ObjectListModel(GameData *dat, QObject *parent) :
QAbstractTableModel(parent), _gameData( dat )
{
}
int ObjectListModel::rowCount(const QModelIndex &parent) const
{
return _world->objectTypes.size();
return _gameData->objectTypes.size();
}
int ObjectListModel::columnCount(const QModelIndex &parent) const
@ -34,7 +34,7 @@ QVariant ObjectListModel::data(const QModelIndex &index, int role) const
}
else if ( index.column() == 1 )
{
auto object = world()->objectTypes[id];
auto object = _gameData->objectTypes[id];
if( gDataType[object->class_type].isEmpty() )
{
return QString("Unknown");
@ -43,7 +43,7 @@ QVariant ObjectListModel::data(const QModelIndex &index, int role) const
}
else if( index.column() == 2 )
{
auto object = world()->objectTypes[id];
auto object = _gameData->objectTypes[id];
if(object->class_type == ObjectData::class_id)
{
auto v = std::static_pointer_cast<ObjectData>(object);
@ -81,7 +81,7 @@ QVariant ObjectListModel::headerData(int section, Qt::Orientation orientation, i
QModelIndex ObjectListModel::index(int row, int column, const QModelIndex &parent) const
{
auto it = world()->objectTypes.begin();
auto it = _gameData->objectTypes.begin();
for(int i = 0; i < row; i++) it++;
auto id = it->second->ID;

View File

@ -3,18 +3,18 @@
#include <QAbstractItemModel>
#include <engine/GameWorld.hpp>
#include <engine/GameData.hpp>
class ObjectListModel : public QAbstractTableModel
{
Q_OBJECT
GameWorld* _world;
GameData* _gameData;
public:
explicit ObjectListModel(GameWorld* _world, QObject *parent = 0);
explicit ObjectListModel(GameData* gameDat, QObject *parent = 0);
GameWorld* world() const { return _world; }
GameData* gameData() const { return _gameData; }
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;

View File

@ -60,7 +60,7 @@ static std::map<ObjectInformation::ObjectClass, QString> gDataType =
void ObjectViewer::showItem(qint16 item)
{
auto def = world()->objectTypes[item];
auto def = world()->data->objectTypes[item];
if( def )
{
@ -95,7 +95,7 @@ void ObjectViewer::showData(GameWorld *world)
for(std::map<std::string, std::string>::iterator it = world->data->ideLocations.begin();
it != world->data->ideLocations.end();
++it) {
world->defineItems(it->second);
world->data->loadObjects(it->second);
}
if( objectList->model() )
@ -103,7 +103,7 @@ void ObjectViewer::showData(GameWorld *world)
delete objectList->model();
}
objectList->setModel(new ObjectListModel(world, objectList));
objectList->setModel(new ObjectListModel(world->data, objectList));
connect(objectList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(showItem(QModelIndex)));
}

View File

@ -52,7 +52,7 @@ public:
for(std::map<std::string, std::string>::iterator it = e->data->ideLocations.begin();
it != e->data->ideLocations.end();
++it) {
e->defineItems(it->second);
d->loadObjects(it->second);
}
e->dynamicsWorld->setGravity(btVector3(0.f, 0.f, 0.f));

View File

@ -50,4 +50,9 @@ BOOST_AUTO_TEST_CASE(test_object_data)
}
}
BOOST_AUTO_TEST_CASE(test_gamedata_data)
{
}
BOOST_AUTO_TEST_SUITE_END()