Revision: 1381
          http://rigsofrods.svn.sourceforge.net/rigsofrods/?rev=1381&view=rev
Author:   rorthomas
Date:     2010-05-08 22:13:25 +0000 (Sat, 08 May 2010)

Log Message:
-----------
added serializer basics, NOT WORKING YET!

Added Paths:
-----------
    trunk/source/serializer/
    trunk/source/serializer/CMakeLists.txt
    trunk/source/serializer/serializationmodules.h
    trunk/source/serializer/serializer.cpp
    trunk/source/serializer/serializer.h
    trunk/source/serializer/tests/
    trunk/source/serializer/tests/main.cpp

Added: trunk/source/serializer/CMakeLists.txt
===================================================================
--- trunk/source/serializer/CMakeLists.txt                              (rev 0)
+++ trunk/source/serializer/CMakeLists.txt      2010-05-08 22:13:25 UTC (rev 
1381)
@@ -0,0 +1,26 @@
+project(rorserializer)
+
+add_definitions("-D_UNICODE -DNOLANG")
+
+include_directories(${Ogre_INCLUDE_DIRS})
+link_directories   (${Ogre_LIBRARY_DIRS})
+
+include_directories(.)
+include_directories(../main)
+
+# the lib
+FILE(GLOB sources "*.cpp")
+FILE(GLOB headers "*.h")
+add_library(serializer STATIC ${sources} ${headers} ../main/BeamData.h)
+windows_hacks(serializer)
+target_link_libraries(serializer ${Ogre_LIBRARIES})
+
+# the tests
+FILE(GLOB test_sources "tests/*.cpp")
+add_executable(serializer_test ${test_sources})
+windows_hacks(serializer_test)
+target_link_libraries(serializer_test ${Ogre_LIBRARIES} "serializer")
+
+
+
+

Added: trunk/source/serializer/serializationmodules.h
===================================================================
--- trunk/source/serializer/serializationmodules.h                              
(rev 0)
+++ trunk/source/serializer/serializationmodules.h      2010-05-08 22:13:25 UTC 
(rev 1381)
@@ -0,0 +1,995 @@
+
+#include "serializer.h"
+
+#include "OgreLogManager.h"
+#include "Ogre.h"
+
+
+using namespace Ogre;
+
+// format description:
+// http://wiki.rigsofrods.com/pages/Truck_Description_File
+
+
+// global functions
+int add_beam(rig_t *rig, node_t *p1, node_t *p2, int type, float strength, 
float spring, float damp, float length=-1, float shortbound=-1, float 
longbound=-1, float precomp=1, float diameter=DEFAULT_BEAM_DIAMETER);
+void init_node(rig_t *rig, int pos, float x, float y, float z, int type, float 
m=10, int iswheel=0, float friction=CHASSIS_FRICTION_COEF, int id=-1, int 
wheelid=-1, float nfriction=NODE_FRICTION_COEF_DEFAULT, float 
nvolume=NODE_VOLUME_COEF_DEFAULT, float nsurface=NODE_SURFACE_COEF_DEFAULT, 
float nloadweight=NODE_LOADWEIGHT_DEFAULT);
+
+// the serialization modules
+
+class GlobalsSerializer : public RoRSerializationModule
+{
+public:
+       GlobalsSerializer(RoRSerializer *s) :
+               RoRSerializationModule(s)
+       {
+               // setup the base descriptions, etc, then register ourself
+               name = sectionTrigger = "globals";
+               s->registerModuleSerializer(this);
+       }
+
+       void initData(rig_t *rig)
+       {
+               rig->globals = new globalssection_t();
+               memset(rig->globals, 0, sizeof(globalssection_t));
+               initiated = true;
+       }
+
+       int deserialize(char *line, rig_t *rig)
+       {
+               // ignore section header
+               if(!strcmp(line, "globals"))
+                       return 1;
+               
+               if(!initiated) initData(rig);
+       
+               // shortcuts    
+               globalssection_t *g = rig->globals;
+
+               return checkRes(2, sscanf(line,"%f, %f, %s", &g->truckmass, 
&g->loadmass, g->texname));
+       }
+       
+       int serialize(char *line, rig_t *rig)
+       {
+               // XXX: TODO
+               return -1;
+       }
+};
+
+class NodeSerializer : public RoRSerializationModule
+{
+public:
+       NodeSerializer(RoRSerializer *s) :
+               RoRSerializationModule(s)
+       {
+               // setup the base descriptions, etc, then register ourself
+               name = sectionTrigger = "nodes";
+               s->registerModuleSerializer(this);
+       }
+
+       void initData(rig_t *rig)
+       {
+               rig->nodes = new nodessection_t();
+               memset(rig->nodes, 0, sizeof(nodessection_t));
+               // set some defaults, important!
+               rig->nodes->gravitation = -9.81f;
+               initiated = true;
+       }
+
+       int deserialize(char *line, rig_t *rig)
+       {
+               // ignore section header
+               if(!strcmp(line, "nodes"))
+                       return 1;
+
+               if(!initiated) initData(rig);
+               
+               // shortcuts
+               nodessection_t *n = rig->nodes;
+
+               if(!rig->globals)
+               {
+                       LogManager::getSingleton().logMessage("Nodes section 
must come after the globals section");
+                       return -1;
+               }
+
+
+               // XXX: TOFIX: logging!
+               // parse nodes
+               int id = 0;
+               float x = 0, y = 0, z = 0, mass = 0;
+               char options[255] = "n";
+               int result = sscanf(line,"%i, %f, %f, %f, %s %f", &id, &x, &y, 
&z, options, &mass);
+               // catch some errors
+               if (result < 4 || result == EOF)
+               {
+                       //LogManager::getSingleton().logMessage("Error parsing 
File " + String(fname) +" line " + StringConverter::toString(linecounter) + ". 
trying to continue ...");
+                       return 0;
+               }
+               if (id != n->free_node)
+               {
+                       //LogManager::getSingleton().logMessage("Error parsing 
File (Node) " + String(fname) +" line " + 
StringConverter::toString(linecounter) + ":");
+                       //LogManager::getSingleton().logMessage("Error: lost 
sync in nodes numbers after node " + StringConverter::toString(free_node) + 
"(got " + StringConverter::toString(id) + " instead)");
+                       exit(2);
+               };
+
+               if(n->free_node >= MAX_NODES)
+               {
+                       //LogManager::getSingleton().logMessage("nodes limit 
reached ("+StringConverter::toString(MAX_NODES)+"): " + String(fname) +" line " 
+ StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return 0;
+               }
+
+               Vector3 npos = n->startPos + n->startRot * Vector3(x, y, z);
+               init_node(rig, id, npos.x, npos.y, npos.z, NODE_NORMAL, 10, 0, 
0, n->free_node, -1, n->default_node_friction, n->default_node_volume, 
n->default_node_surface, n->default_node_loadweight);
+               n->nodes[id].iIsSkin = true;
+
+               if      (n->default_node_loadweight >= 0.0f)
+               {
+                       n->nodes[id].masstype     = NODE_LOADED;
+                       n->nodes[id].overrideMass = true;
+                       n->nodes[id].mass         = n->default_node_loadweight;
+               }
+
+               // merge options and default_node_options
+               strncpy(options, ((String(n->default_node_options) + 
String(options)).c_str()), 250);
+
+               // now 'parse' the options
+               char *options_pointer = options;
+               while (*options_pointer != 0)
+               {
+                       switch (*options_pointer)
+                       {
+                               case 'l':       // load node
+                                       if(mass != 0)
+                                       {
+                                               n->nodes[id].masstype     = 
NODE_LOADED;
+                                               n->nodes[id].overrideMass = 
true;
+                                               n->nodes[id].mass         = 
mass;
+                                       }
+                                       else
+                                       {
+                                               n->nodes[id].masstype     = 
NODE_LOADED;
+                                               n->masscount++;
+                                       }
+                                       break;
+                               case 'x':       //exhaust
+                                       // XXX: TOFIX
+                                       //if (disable_smoke)
+                                       //      break;
+                                       /*
+                                       if(s->smokeId == 0 && s->smokeRef != 0)
+                                       {
+                                               exhaust_t e;
+                                               e.emitterNode = id;
+                                               e.directionNode = smokeRef;
+                                               e.isOldFormat = true;
+                                               //smokeId=id;
+                                               e.smokeNode = 
parent->createChildSceneNode();
+                                               //ParticleSystemManager 
*pSysM=ParticleSystemManager::getSingletonPtr();
+                                               char wname[256];
+                                               sprintf(wname, 
"exhaust-%zu-%s", exhausts.size(), truckname);
+                                               //if (pSysM) 
smoker=pSysM->createSystem(wname, "tracks/Smoke");
+                                               
e.smoker=manager->createParticleSystem(wname, "tracks/Smoke");
+                                               // ParticleSystem* pSys = 
ParticleSystemManager::getSingleton().createSystem("exhaust", "tracks/Smoke");
+                                               if (!e.smoker)
+                                                       continue;
+                                               
e.smokeNode->attachObject(e.smoker);
+                                               
e.smokeNode->setPosition(nodes[e.emitterNode].AbsPosition);
+                                               exhausts.push_back(e);
+
+                                       }
+                                       */
+                                       n->nodes[n->smokeId].isHot = true;
+                                       n->nodes[id].isHot      = true;
+                                       n->smokeId = id;
+                                       break;
+                               case 'y':       //exhaust reference
+                                       // XXX: TOFIX
+                                       //if (disable_smoke)
+                                       //      break;
+                                       /*
+                                       if(smokeId != 0 && smokeRef == 0)
+                                       {
+                                               exhaust_t e;
+                                               e.emitterNode = smokeId;
+                                               e.directionNode = id;
+                                               e.isOldFormat = true;
+                                               //smokeId=id;
+                                               e.smokeNode = 
parent->createChildSceneNode();
+                                               //ParticleSystemManager 
*pSysM=ParticleSystemManager::getSingletonPtr();
+                                               char wname[256];
+                                               sprintf(wname, 
"exhaust-%zu-%s", exhausts.size(), truckname);
+                                               //if (pSysM) 
smoker=pSysM->createSystem(wname, "tracks/Smoke");
+                                               
e.smoker=manager->createParticleSystem(wname, "tracks/Smoke");
+                                               // ParticleSystem* pSys = 
ParticleSystemManager::getSingleton().createSystem("exhaust", "tracks/Smoke");
+                                               if (!e.smoker)
+                                                       continue;
+                                               
e.smokeNode->attachObject(e.smoker);
+                                               
e.smokeNode->setPosition(nodes[e.emitterNode].AbsPosition);
+                                               exhausts.push_back(e);
+
+                                               nodes[smokeId].isHot=true;
+                                               nodes[id].isHot=true;
+                                       }
+                                       */
+                                       n->smokeRef = id;
+                                       break;
+                               case 'c':       //contactless
+                                       n->nodes[id].contactless = 1;
+                                       break;
+                               case 'h':       //hook
+                                       // emulate the old behaviour using new 
fancy hookgroups
+                                       // XXX: TOFIX
+                                       /*
+                                       hook_t h;
+                                       h.hookNode=&nodes[id];
+                                       h.locked=UNLOCKED;
+                                       h.lockNode=0;
+                                       h.lockTruck=0;
+                                       h.lockNodes=true;
+                                       h.group=-1;
+                                       hooks.push_back(h);
+                                       */
+                                       break;
+                               case 'e':       //editor
+                                       n->editorId = id;
+                                       break;
+                               case 'b':       //buoy
+                                       n->nodes[id].buoyancy = 10000.0f;
+                                       break;
+                               case 'p':       //diasble particles
+                                       n->nodes[id].disable_particles = true;
+                               break;
+                               case 'L':       //Log data:
+                                       
LogManager::getSingleton().logMessage("Node " + StringConverter::toString(id) + 
"  settings. Node load mass: " \
+                                               + 
StringConverter::toString(n->nodes[id].mass) + ", friction coefficient: " + 
StringConverter::toString(n->default_node_friction) \
+                                               + " and buoyancy volume 
coefficient: " + StringConverter::toString(n->default_node_volume) + " Fluid 
drag surface coefficient: " \
+                                               + 
StringConverter::toString(n->default_node_surface)+ " Particle mode: " + 
StringConverter::toString(n->nodes[id].disable_particles));
+                               break;
+                       }
+                       options_pointer++;
+               }
+               n->free_node++;
+               return result;
+       }
+       int serialize(char *line, rig_t *rig)
+       {
+               // XXX: TODO
+               return -1;
+       }
+};
+
+class BeamSerializer : public RoRSerializationModule
+{
+public:
+       BeamSerializer(RoRSerializer *s) :
+               RoRSerializationModule(s)
+       {
+               // setup the base descriptions, etc, then register ourself
+               name = sectionTrigger = "beams";
+               s->registerModuleSerializer(this);
+       }
+
+       void initData(rig_t *rig)
+       {
+               rig->beams = new beamssection_t();
+               memset(rig->beams, 0, sizeof(beamssection_t));
+               initiated = true;
+       }
+
+       int deserialize(char *line, rig_t *rig)
+       {
+               // ignore section header
+               if(!strcmp(line, "beams"))
+                       return 1;
+               
+               if(!initiated) initData(rig);
+               
+               // shortcuts
+               nodessection_t *n = rig->nodes;
+               beamssection_t *b = rig->beams;
+               if(!n)
+               {
+                       LogManager::getSingleton().logMessage("Beams section 
must come after the nodes section");
+                       return -1;
+               }
+
+               // XXX: TOFIX: logging!
+               //parse beams
+               int id1, id2;
+               char options[50] = "v";
+               int type = BEAM_NORMAL;
+               int result = sscanf(line, "%i, %i, %s", &id1, &id2, options);
+               if (result < 2 || result == EOF)
+               {
+                       //LogManager::getSingleton().logMessage("Error parsing 
File (Beam) " + String(fname) +" line " + 
StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return -1;
+               }
+
+               if (id1 >= n->free_node || id2 >= n->free_node)
+               {
+                       LogManager::getSingleton().logMessage("Error: unknown 
node number in beams section ("
+                               
+StringConverter::toString(id1)+","+StringConverter::toString(id2)+")");
+                       exit(3);
+               };
+
+               if(b->free_beam >= MAX_BEAMS)
+               {
+                       //LogManager::getSingleton().logMessage("beams limit 
reached ("+StringConverter::toString(MAX_BEAMS)+"): " + String(fname) +" line " 
+ StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return -1;
+               }
+
+               //skip if a beam already exists
+               int i;
+               for (i=0; i < b->free_beam; i++)
+               {
+                       if ((b->beams[i].p1 == &n->nodes[id1] && b->beams[i].p2 
== &n->nodes[id2]) \
+                               || (b->beams[i].p1 == &n->nodes[id2] && 
b->beams[i].p2 == &n->nodes[id1]))
+                       {
+                               LogManager::getSingleton().logMessage("Skipping 
duplicate beams: from node "+StringConverter::toString(id1)+" to node 
"+StringConverter::toString(id2));
+                               return 0;
+                       }
+               }
+
+               // FIXME: separate init_beam and setup_beam to be able to set 
all parameters after creation
+               // this is just ugly:
+               char *options_pointer = options;
+               while (*options_pointer != 0)
+               {
+                       if(*options_pointer=='i')
+                       {
+                               type = BEAM_INVISIBLE;
+                               break;
+                       }
+                       options_pointer++;
+               }
+
+               int pos = add_beam(rig, &n->nodes[id1], &n->nodes[id2], type, \
+                       b->default_break  * b->default_break_scale, \
+                       b->default_spring * b->default_spring_scale, \
+                       b->default_damp   * b->default_damp_scale, \
+                       -1, -1, -1, 1, \
+                       b->default_beam_diameter);
+
+               // now 'parse' the options
+               options_pointer = options;
+               while (*options_pointer != 0)
+               {
+                       switch (*options_pointer)
+                       {
+                               case 'i':       // invisible
+                                       b->beams[pos].type = BEAM_INVISIBLE;
+                                       break;
+                               case 'v':       // visible
+                                       b->beams[pos].type = BEAM_NORMAL;
+                                       break;
+                               case 'r':
+                                       b->beams[pos].bounded = ROPE;
+                                       break;
+                               case 's':
+                                       b->beams[pos].bounded = SUPPORTBEAM;
+                                       break;
+                       }
+                       options_pointer++;
+               }
+
+               return result;
+       }
+       int serialize(char *line, rig_t *rig)
+       {
+               // XXX: TODO
+               return -1;
+       }
+};
+
+
+class FileInfoSerializer : public RoRSerializationModule
+{
+public:
+       FileInfoSerializer(RoRSerializer *s) :
+               RoRSerializationModule(s)
+       {
+               // setup the base descriptions, etc, then register ourself
+               name = commandTrigger = "fileinfo";
+               s->registerModuleSerializer(this);
+       }
+
+       void initData(rig_t *rig)
+       {
+               rig->fileinfo = new fileinfo_t();
+               memset(rig->fileinfo, 0, sizeof(fileinfo_t));
+               initiated = true;
+       }
+       
+       int deserialize(char *line, rig_t *rig)
+       {
+               if(!initiated) initData(rig);
+               return checkRes(1, sscanf(line, "fileinfo %s, %i, %i", 
rig->fileinfo->uniquetruckid, &rig->fileinfo->categoryid, 
&rig->fileinfo->truckversion));
+       }
+       int serialize(char *line, rig_t *rig)
+       {
+               return sprintf(line, "fileinfo %s, %i, %i\n", 
rig->fileinfo->uniquetruckid, rig->fileinfo->categoryid, 
rig->fileinfo->truckversion);
+       }
+};
+
+
+class AuthorSerializer : public RoRSerializationModule
+{
+public:
+       AuthorSerializer(RoRSerializer *s) :
+               RoRSerializationModule(s)
+       {
+               // setup the base descriptions, etc, then register ourself
+               name = commandTrigger = "author";
+               s->registerModuleSerializer(this);
+       }
+
+       void initData(rig_t *rig)
+       {
+               rig->fileauthors = new fileauthors_t();
+               // beware or memsetting std::* !
+               rig->fileauthors->authors.clear();
+               initiated = true;
+       }
+
+       int deserialize(char *line, rig_t *rig)
+       {
+               if(!initiated) initData(rig);
+               fileauthors_t *a = rig->fileauthors;
+               
+               int authorid;
+               char authorname[255], authoremail[255], authortype[255];
+               authorinfo_t author;
+               author.id = -1;
+               strcpy(author.email, "unknown");
+               strcpy(author.name,  "unknown");
+               strcpy(author.type,  "unknown");
+
+               int result = sscanf(line,"author %s %i %s %s", authortype, 
&authorid, authorname, authoremail);
+               if (result < 1 || result == EOF)
+               {
+                       //LogManager::getSingleton().logMessage("Error parsing 
File (author) " + String(fname) +" line " + 
StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return 0;
+               }
+               //replace '_' with ' '
+               char *tmp = authorname;
+               while (*tmp!=0) {if (*tmp=='_') *tmp=' ';tmp++;};
+               //fill the struct now
+               author.id = authorid;
+               if(strnlen(authortype, 250) > 0)
+                       strncpy(author.type, authortype, 255);
+               if(strnlen(authorname, 250) > 0)
+                       strncpy(author.name, authorname, 255);
+               if(strnlen(authoremail, 250) > 0)
+                       strncpy(author.email, authoremail, 255);
+
+               a->authors.push_back(author);
+               return result;
+       }
+       int serialize(char *line, rig_t *rig)
+       {
+               // XXX: TODO
+               return -1;
+       }
+};
+
+
+class EngineSerializer : public RoRSerializationModule
+{
+public:
+       EngineSerializer(RoRSerializer *s) :
+               RoRSerializationModule(s)
+       {
+               // setup the base descriptions, etc, then register ourself
+               name = sectionTrigger = "engine";
+               s->registerModuleSerializer(this);
+       }
+
+       void initData(rig_t *rig)
+       {
+               rig->engine = new enginesection_t();
+               memset(rig->engine, 0, sizeof(enginesection_t));
+               initiated = true;
+       }
+
+       int deserialize(char *line, rig_t *rig)
+       {
+               // ignore section header
+               if(!strcmp(line, "engine"))
+                       return 1;
+
+               if(!initiated) initData(rig);
+
+               // shortcuts
+               enginesection_t *e = rig->engine;
+               
+               //parse engine
+               int numgears;
+               if(rig->driveable == MACHINE)
+                       // ignore engine section on machines
+                       return 1;
+
+               rig->driveable = TRUCK;
+               int result = sscanf(line, "%f, %f, %f, %f, %f, %f, %f, %f, %f, 
%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f", \
+                       &e->minrpm, \
+                       &e->maxrpm, \
+                       &e->torque, \
+                       &e->dratio, \
+                       &e->rear, \
+                       
&e->gears[0],&e->gears[1],&e->gears[2],&e->gears[3],&e->gears[4],&e->gears[5],&e->gears[6],&e->gears[7],&e->gears[8],&e->gears[9],&e->gears[10],&e->gears[11],&e->gears[12],&e->gears[13],&e->gears[14],&e->gears[15]
+                       );
+               
+               if (result < 7 || result == EOF)
+               {
+                       //LogManager::getSingleton().logMessage("Error parsing 
File (Engine) " + String(fname) +" line " + 
StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return 0;
+               }
+               for (numgears = 0; numgears < MAX_GEARS; numgears++)
+                       if (e->gears[numgears] <= 0)
+                               break;
+               if (numgears < 3)
+               {
+                       //LogManager::getSingleton().logMessage("Trucks with 
less than 3 gears are not supported! " + String(fname) +" line " + 
StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return -1;
+               }
+               e->numgears = numgears;
+               return result;
+       }
+       int serialize(char *line, rig_t *rig)
+       {
+               // XXX: TODO
+               return -1;
+       }
+};
+
+
+class CamerasSerializer : public RoRSerializationModule
+{
+public:
+       CamerasSerializer(RoRSerializer *s) :
+               RoRSerializationModule(s)
+       {
+               // setup the base descriptions, etc, then register ourself
+               name = sectionTrigger = "cameras";
+               s->registerModuleSerializer(this);
+       }
+
+       void initData(rig_t *rig)
+       {
+               rig->cameras = new camerassection_t();
+               memset(rig->cameras, 0, sizeof(camerassection_t));
+               initiated = true;
+       }
+
+       int deserialize(char *line, rig_t *rig)
+       {
+               // ignore section header
+               if(!strcmp(line, "cameras"))
+                       return 1;
+
+               if(!initiated) initData(rig);
+
+               // shortcuts
+               camerassection_t *c = rig->cameras;
+               
+               int nodepos, nodedir, dir;
+               int result = sscanf(line,"%i, %i, %i",&nodepos,&nodedir,&dir);
+               if (result < 3 || result == EOF)
+               {
+                       //LogManager::getSingleton().logMessage("Error parsing 
File (Camera) " + String(fname) +" line " + 
StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return 0;
+               }
+
+               if(c->free_camera > MAX_CAMERAS)
+               {
+                       return -1;
+               }
+
+               c->cameras[c->free_camera].nodepos = nodepos;
+               c->cameras[c->free_camera].nodedir = nodedir;
+               c->cameras[c->free_camera].dir = dir;
+               c->free_camera++;
+               return result;
+       }
+       int serialize(char *line, rig_t *rig)
+       {
+               // XXX: TODO
+               return -1;
+       }
+};
+
+
+class ShocksSerializer : public RoRSerializationModule
+{
+public:
+       ShocksSerializer(RoRSerializer *s) :
+               RoRSerializationModule(s)
+       {
+               // setup the base descriptions, etc, then register ourself
+               name = sectionTrigger = "shocks";
+               s->registerModuleSerializer(this);
+       }
+
+       void initData(rig_t *rig)
+       {
+               rig->shocks = new shockssection_t();
+               memset(rig->shocks, 0, sizeof(shockssection_t));
+               initiated = true;
+       }
+
+       int deserialize(char *line, rig_t *rig)
+       {
+               // ignore section header
+               if(!strcmp(line, "shocks"))
+                       return 1;
+
+               if(!rig->beams)
+               {
+                       LogManager::getSingleton().logMessage("Nodes section 
must come after the beams section");
+                       return -1;
+               }
+
+               if(!initiated) initData(rig);
+
+               // shortcuts
+               shockssection_t *s = rig->shocks;
+               beamssection_t  *b = rig->beams;
+               nodessection_t  *n = rig->nodes;
+
+               int id1, id2;
+               float sp, d, sbound,lbound,precomp;
+               char options[50] = "n";
+               int result = sscanf(line, "%i, %i, %f, %f, %f, %f, %f, %s", 
&id1, &id2, &sp, &d, &sbound, &lbound, &precomp, options);
+               if (result < 7 || result == EOF)
+               {
+                       //LogManager::getSingleton().logMessage("Error parsing 
File (Shock) " + String(fname) +" line " + 
StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return 0;
+               }
+
+               // checks ...
+               if(b->free_beam >= MAX_BEAMS)
+               {
+                       //LogManager::getSingleton().logMessage("beams limit 
reached ("+StringConverter::toString(MAX_BEAMS)+"): " + String(fname) +" line " 
+ StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return -1;
+               }
+               if(s->free_shock >= MAX_BEAMS)
+               {
+                       //LogManager::getSingleton().logMessage("shock limit 
reached ("+StringConverter::toString(MAX_SHOCKS)+"): " + String(fname) +" line 
" + StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return -1;
+               }
+               if (id1 >= n->free_node || id2 >= n->free_node)
+               {
+                       LogManager::getSingleton().logMessage("Error: unknown 
node number in shocks section 
("+StringConverter::toString(id1)+","+StringConverter::toString(id2)+")");
+                       exit(4);
+               }
+
+               // options
+               int htype = BEAM_HYDRO;
+               int shockflag = SHOCK_FLAG_NORMAL;
+
+               // now 'parse' the options
+               char *options_pointer = options;
+               while (*options_pointer != 0)
+               {
+                       switch (*options_pointer)
+                       {
+                               case 'i':       // invisible
+                                       htype      = BEAM_INVISIBLE_HYDRO;
+                                       shockflag |= SHOCK_FLAG_INVISIBLE;
+                                       break;
+                               case 'l':
+                               case 'L':
+                                       shockflag &= ~SHOCK_FLAG_NORMAL; // not 
normal anymore
+                                       shockflag |= SHOCK_FLAG_LACTIVE;
+                                       s->free_active_shock++; // this has no 
array associated with it. its just to determine if there are active shocks!
+                                       break;
+                               case 'r':
+                               case 'R':
+                                       shockflag &= ~SHOCK_FLAG_NORMAL; // not 
normal anymore
+                                       shockflag |= SHOCK_FLAG_RACTIVE;
+                                       s->free_active_shock++; // this has no 
array associated with it. its just to determine if there are active shocks!
+                                       break;
+                               case 'm':
+                                       {
+                                               // metric values: calculate 
sbound and lbound now
+                                               float beam_length = 
n->nodes[id1].AbsPosition.distance(n->nodes[id2].AbsPosition);
+                                               sbound = sbound / beam_length;
+                                               lbound = lbound / beam_length;
+                                       }
+                                       break;
+                       }
+                       options_pointer++;
+               }
+               int pos = add_beam(rig, &n->nodes[id1], &n->nodes[id2], htype, 
b->default_break * 4.0f, sp, d, -1.0f, sbound, lbound, precomp);
+               b->beams[pos].shock = &s->shocks[s->free_shock];
+               s->shocks[s->free_shock].beamid = pos;
+               s->shocks[s->free_shock].flags = shockflag;
+               s->free_shock++;
+
+               return result;
+       }
+       int serialize(char *line, rig_t *rig)
+       {
+               // XXX: TODO
+               return -1;
+       }
+};
+
+
+class HydrosSerializer : public RoRSerializationModule
+{
+public:
+       HydrosSerializer(RoRSerializer *s) :
+               RoRSerializationModule(s)
+       {
+               // setup the base descriptions, etc, then register ourself
+               name = sectionTrigger = "hydros";
+               s->registerModuleSerializer(this);
+       }
+
+       void initData(rig_t *rig)
+       {
+               rig->hydros = new hydrossection_t();
+               memset(rig->hydros, 0, sizeof(hydrossection_t));
+               initiated = true;
+       }
+
+       int deserialize(char *line, rig_t *rig)
+       {
+               // ignore section header
+               if(!strcmp(line, "hydros"))
+                       return 1;
+
+               if(!rig->beams)
+               {
+                       LogManager::getSingleton().logMessage("Hydros section 
must come after the beams section");
+                       return -1;
+               }
+
+               if(!initiated) initData(rig);
+
+               // shortcuts
+               hydrossection_t *h = rig->hydros;
+               beamssection_t  *b = rig->beams;
+               nodessection_t  *n = rig->nodes;
+
+               //parse hydros
+               int id1, id2;
+               float ratio;
+               char options[50] = "n";
+               float startDelay=0;
+               float stopDelay=0;
+               char startFunction[50]="";
+               char stopFunction[50]="";
+
+               int result = sscanf(line, "%i, %i, %f, %s %f, %f, %s 
%s",&id1,&id2,&ratio,options,&startDelay,&stopDelay,startFunction,stopFunction);
+               if (result < 3 || result == EOF)
+               {
+                       //LogManager::getSingleton().logMessage("Error parsing 
File (Hydro) " + String(fname) +" line " + 
StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return 0;
+               }
+
+               int htype = BEAM_HYDRO;
+
+               // FIXME: separate init_beam and setup_beam to be able to set 
all parameters after creation
+               // this is just ugly:
+               char *options_pointer = options;
+               while (*options_pointer != 0)
+               {
+                       if(*options_pointer=='i')
+                       {
+                               htype = BEAM_INVISIBLE_HYDRO;
+                               break;
+                       }
+                       options_pointer++;
+               }
+
+               if (id1 >= n->free_node || id2 >= n->free_node)
+               {
+                       LogManager::getSingleton().logMessage("Error: unknown 
node number in hydros section 
("+StringConverter::toString(id1)+","+StringConverter::toString(id2)+")");
+                       exit(6);
+               };
+
+               if(b->free_beam >= MAX_BEAMS)
+               {
+                       //LogManager::getSingleton().logMessage("beams limit 
reached ("+StringConverter::toString(MAX_BEAMS)+"): " + String(fname) +" line " 
+ StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return -1;
+               }
+               if(h->free_hydro >= MAX_HYDROS)
+               {
+                       //LogManager::getSingleton().logMessage("hydros limit 
reached ("+StringConverter::toString(MAX_HYDROS)+"): " + String(fname) +" line 
" + StringConverter::toString(linecounter) + ". trying to continue ...");
+                       return -1;
+               }
+
+               int pos = add_beam(rig, &n->nodes[id1], &n->nodes[id2], htype, 
b->default_break * b->default_break_scale, b->default_spring * 
b->default_spring_scale, b->default_damp * b->default_damp_scale);
+               h->hydro[h->free_hydro]=pos;
+               h->free_hydro++;
+               b->beams[pos].Lhydro = b->beams[pos].L;
+               b->beams[pos].hydroRatio = ratio;
+               b->beams[pos].animOption = 0;
+
+
+               // now 'parse' the options
+               options_pointer = options;
+               while (*options_pointer != 0)
+               {
+                       switch (*options_pointer)
+                       {
+                               case 'i':       // invisible
+                                       b->beams[pos].type        = 
BEAM_INVISIBLE_HYDRO;
+                                       break;
+                               case 'n':       // normal
+                                       b->beams[pos].type        = BEAM_HYDRO;
+                                       b->beams[pos].hydroFlags |= 
HYDRO_FLAG_DIR;
+                                       break;
+                               case 's': // speed changing hydro
+                                       b->beams[pos].hydroFlags |= 
HYDRO_FLAG_SPEED;
+                                       break;
+                               case 'a':
+                                       b->beams[pos].hydroFlags |= 
HYDRO_FLAG_AILERON;
+                                       break;
+                               case 'r':
+                                       b->beams[pos].hydroFlags |= 
HYDRO_FLAG_RUDDER;
+                                       break;
+                               case 'e':
+                                       b->beams[pos].hydroFlags |= 
HYDRO_FLAG_ELEVATOR;
+                                       break;
+                               case 'u':
+                                       b->beams[pos].hydroFlags |= 
(HYDRO_FLAG_AILERON | HYDRO_FLAG_ELEVATOR);
+                                       break;
+                               case 'v':
+                                       b->beams[pos].hydroFlags |= 
(HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_ELEVATOR);
+                                       break;
+                               case 'x':
+                                       b->beams[pos].hydroFlags |= 
(HYDRO_FLAG_AILERON | HYDRO_FLAG_RUDDER);
+                                       break;
+                               case 'y':
+                                       b->beams[pos].hydroFlags |= 
(HYDRO_FLAG_REV_AILERON | HYDRO_FLAG_RUDDER);
+                                       break;
+                               case 'g':
+                                       b->beams[pos].hydroFlags |= 
(HYDRO_FLAG_ELEVATOR | HYDRO_FLAG_RUDDER);
+                                       break;
+                               case 'h':
+                                       b->beams[pos].hydroFlags |= 
(HYDRO_FLAG_REV_ELEVATOR | HYDRO_FLAG_RUDDER);
+                                       break;
+                       }
+                       options_pointer++;
+                       // if you use the i flag on its own, add the direction 
to it
+                       if(b->beams[pos].type == BEAM_INVISIBLE_HYDRO && 
!b->beams[pos].hydroFlags)
+                               b->beams[pos].hydroFlags |= HYDRO_FLAG_DIR;
+               }
+               return result;
+       }
+       int serialize(char *line, rig_t *rig)
+       {
+               // XXX: TODO
+               return -1;
+       }
+};
+
+
+
+
+
+
+//////// HELPER functions below
+int add_beam(rig_t *rig, node_t *p1, node_t *p2, int type, float strength, 
float spring, float damp, float length, float shortbound, float longbound, 
float precomp, float diameter)
+{
+       // shortcuts
+       nodessection_t *n = rig->nodes;
+       beamssection_t *b = rig->beams;
+       
+       int pos = b->free_beam;
+
+       b->beams[pos].p1 = p1;
+       b->beams[pos].p2 = p2;
+       b->beams[pos].p2truck = 0;
+       b->beams[pos].type = type;
+       if (length < 0)
+       {
+               //calculate the length
+               Vector3 t = p1->RelPosition - p2->RelPosition;
+               b->beams[pos].L = precomp * t.length();
+       } else
+       {
+               b->beams[pos].L = length;
+       }
+       b->beams[pos].k                 = spring;
+       b->beams[pos].d                 = damp;
+       b->beams[pos].broken            = 0;
+       b->beams[pos].Lhydro            = b->beams[pos].L;
+       b->beams[pos].refL              = b->beams[pos].L;
+       b->beams[pos].hydroRatio        = 0;
+       b->beams[pos].hydroFlags        = 0;
+       b->beams[pos].animFlags         = 0;
+       b->beams[pos].stress            = 0;
+       b->beams[pos].lastforce         = Vector3::ZERO;
+       b->beams[pos].iscentering       = false;
+       b->beams[pos].isOnePressMode    = 0;
+       b->beams[pos].isforcerestricted = false;
+       b->beams[pos].autoMovingMode    = 0;
+       b->beams[pos].autoMoveLock      = false;
+       b->beams[pos].pressedCenterMode = false;
+       b->beams[pos].disabled          = false;
+       b->beams[pos].shock             = 0;
+       if (b->default_deform < b->beam_creak)
+               b->default_deform = b->beam_creak;
+       b->beams[pos].default_deform    = b->default_deform  * 
b->default_deform_scale;
+       b->beams[pos].minmaxposnegstress = b->default_deform * 
b->default_deform_scale;
+       b->beams[pos].maxposstress      = b->default_deform  * 
b->default_deform_scale;
+       b->beams[pos].maxnegstress      = - b->beams[pos].maxposstress;
+       b->beams[pos].plastic_coef      = b->default_plastic_coef;
+       b->beams[pos].default_plastic_coef = b->default_plastic_coef;
+       b->beams[pos].strength          = strength;
+       b->beams[pos].iStrength         = strength;
+       b->beams[pos].diameter          = b->default_beam_diameter;
+       b->beams[pos].minendmass        = 1;
+       b->beams[pos].diameter          = diameter;
+       b->beams[pos].scale             = 0;
+       if (shortbound != -1.0)
+       {
+               b->beams[pos].bounded       = SHOCK1;
+               b->beams[pos].shortbound    = shortbound;
+               b->beams[pos].longbound     = longbound;
+
+       } else
+       {
+               b->beams[pos].bounded       = NOSHOCK;
+       }
+
+       // no visuals here
+       b->beams[pos].mSceneNode        = 0;
+       b->beams[pos].mEntity           = 0;
+
+       b->free_beam++;
+       return pos;
+}
+
+void init_node(rig_t *rig, int pos, float x, float y, float z, int type, float 
m, int iswheel, float friction, int id, int wheelid, float nfriction, float 
nvolume, float nsurface, float nloadweight)
+{
+       nodessection *n = rig->nodes;
+       n->nodes[pos].AbsPosition    = Vector3(x, y, z);
+       n->nodes[pos].RelPosition    = Vector3(x, y, z) - n->origin;
+       n->nodes[pos].smoothpos      = n->nodes[pos].AbsPosition;
+       n->nodes[pos].iPosition      = Vector3(x, y, z);
+       if(pos != 0)
+               n->nodes[pos].iDistance  = (n->nodes[0].AbsPosition - 
Vector3(x, y, z)).squaredLength();
+       else
+               n->nodes[pos].iDistance  = 0;
+       n->nodes[pos].Velocity       = Vector3::ZERO;
+       n->nodes[pos].Forces         = Vector3::ZERO;
+       n->nodes[pos].locked         = m < 0.0;
+       n->nodes[pos].mass           = m;
+       n->nodes[pos].iswheel        = iswheel;
+       n->nodes[pos].wheelid        = wheelid;
+       n->nodes[pos].friction_coef  = nfriction;
+       n->nodes[pos].volume_coef    = nvolume;
+       n->nodes[pos].surface_coef   = nsurface;
+       if (nloadweight >= 0.0f)
+       {
+               n->nodes[pos].masstype   = NODE_LOADED;
+               n->nodes[pos].overrideMass = true;
+               n->nodes[pos].mass       = nloadweight;
+       }
+       n->nodes[pos].disable_particles = false;
+       n->nodes[pos].masstype       = type;
+       n->nodes[pos].contactless    = 0;
+       n->nodes[pos].contacted      = 0;
+       n->nodes[pos].lockednode     = 0;
+       n->nodes[pos].buoyanceForce  = Vector3::ZERO;
+       n->nodes[pos].buoyancy       = rig->globals->truckmass / 
15.0f;//DEFAULT_BUOYANCY;
+       n->nodes[pos].lastdrag       = Vector3(0,0,0);
+       // XXX: TOFIX
+       //n->nodes[pos].gravimass      = Vector3(0, 
RoRFrameListener::getGravity()*m, 0);
+       n->nodes[pos].gravimass      = Vector3(0, n->gravitation * m, 0);
+       n->nodes[pos].wetstate       = DRY;
+       n->nodes[pos].isHot          = false;
+       n->nodes[pos].overrideMass   = false;
+       n->nodes[pos].id             = id;
+       n->nodes[pos].colltesttimer  = 0;
+       n->nodes[pos].iIsSkin        = false;
+       n->nodes[pos].isSkin         = n->nodes[pos].iIsSkin;
+       n->nodes[pos].pos            = pos;
+       if (type == NODE_LOADED)
+               n->masscount++;
+}
\ No newline at end of file

Added: trunk/source/serializer/serializer.cpp
===================================================================
--- trunk/source/serializer/serializer.cpp                              (rev 0)
+++ trunk/source/serializer/serializer.cpp      2010-05-08 22:13:25 UTC (rev 
1381)
@@ -0,0 +1,137 @@
+
+#include "string.h"
+
+#include "serializer.h"
+#include "BeamData.h"
+#include "rormemory.h"
+#include "serializationmodules.h"
+
+#include "OgreResourceGroupManager.h"
+
+using namespace Ogre;
+
+
+RoRSerializer::RoRSerializer()
+{
+       // register all available modules :)
+       new GlobalsSerializer(this);
+       new NodeSerializer(this);
+       new BeamSerializer(this);
+
+       new FileInfoSerializer(this);
+       new AuthorSerializer(this);
+       new EngineSerializer(this);
+       new CamerasSerializer(this);
+       new ShocksSerializer(this);
+       new HydrosSerializer(this);
+}
+
+RoRSerializer::~RoRSerializer()
+{
+}
+
+int RoRSerializer::loadRig(Ogre::DataStreamPtr ds, rig_t *rig)
+{
+       //log(INFO, "loading Rig from %s ...", filename);
+       if(!rig) return 1;
+
+       // clear rig
+       memset(rig, 0, sizeof(rig_t));
+
+       // file things
+       char line[1024];
+       int linecounter = 0;
+       std::string activeSection;
+
+       // first: init rig
+       // TODO: IMPORTANT: FIX the rig_t initialization
+       rig->patchEngineTorque = false;
+       rig->forwardcommands = 0;
+       rig->importcommands = 0;
+       rig->wheel_contact_requested = false;
+       rig->rescuer = false;
+       rig->disable_default_sounds = false;
+
+       // read in truckname
+       ds->readLine(line, 1023);
+       strncpy(rig->realtruckname, line, 255);
+
+       // loop through all the files lines
+       SerializationContext ctx("foobar", 0);
+
+       while (!ds->eof())
+       {
+               size_t ll = ds->readLine(line, 1023);
+               linecounter++;
+               // ignore comments and empty lines
+               if (ll==0 || line[0]==';' || line[0]=='/')
+                       continue;
+
+               // update context
+               ctx.lineNo = linecounter;
+
+               // now process the modules and try to parse the line
+               // -1 = no match
+               int res = processModules(line, rig, &ctx, activeSection);
+               if(!activeSection.empty() && res == 0)
+               {
+                       LogManager::getSingleton().logMessage("line section 
parsing with no result: " + String(line));
+               }
+               if(res == -1)
+               {
+                       LogManager::getSingleton().logMessage("line with no 
match: " + String(line));
+               }
+
+       }
+       LogManager::getSingleton().logMessage("done loading");
+       return 0;
+}
+
+int RoRSerializer::saveRig(std::string filename, rig_t *rig)
+{
+       // XXX: TODO
+       return 0;
+}
+
+int RoRSerializer::registerModuleSerializer(RoRSerializationModule *module)
+{
+       modules[module->getName()] = module;
+       return 0;
+}
+
+int RoRSerializer::processModules(char *line, rig_t *rig, SerializationContext 
*ctx, std::string &activeSection)
+{
+       // parse for commands or other sections
+       std::map < std::string, RoRSerializationModule *>::iterator it;
+       for(it = modules.begin(); it != modules.end() ; it++)
+       {
+               // check if that command is matched
+               std::string *cmd = &it->second->commandTrigger;
+               if(cmd->size() && !strncmp(cmd->c_str(), line, cmd->size()))
+               {
+                       // match, using this module
+                       return it->second->deserialize(line, rig);
+               }
+
+               // check for a new section
+               std::string *sec = &it->second->sectionTrigger;
+               if(sec->size() && !strcmp(sec->c_str(), line))
+               {
+                       // match, using this module
+                       //set section as active
+                       activeSection = it->first;
+                       // parse this as well, could be that the section header 
contains information as well
+                       return it->second->deserialize(line, rig);
+               }
+       }
+
+       // if we are in a section, parse it in its module handler
+       if(!activeSection.empty())
+       {
+               // just try to use that section and ignore the others
+               return modules[activeSection]->deserialize(line, rig);
+       }
+
+       // no match
+       return -1;
+}
\ No newline at end of file

Added: trunk/source/serializer/serializer.h
===================================================================
--- trunk/source/serializer/serializer.h                                (rev 0)
+++ trunk/source/serializer/serializer.h        2010-05-08 22:13:25 UTC (rev 
1381)
@@ -0,0 +1,105 @@
+/*
+This source file is part of Rigs of Rods
+Copyright 2005,2006,2007,2008,2009 Pierre-Michel Ricordel
+Copyright 2007,2008,2009 Thomas Fischer
+
+For more information, see http://www.rigsofrods.com/
+
+Rigs of Rods is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 3, as
+published by the Free Software Foundation.
+
+Rigs of Rods 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 Rigs of Rods.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SERIALIZER_H__
+#define SERIALIZER_H__
+
+#include <string>
+#include <map>
+#include "RoRPrerequisites.h"
+
+#include "OgreDataStream.h"
+#include "OgreLogManager.h"
+
+class RoRSerializer;
+class RoRSerializationModule;
+
+// TODO: make this class more independend from Ogre
+
+class SerializationContext
+{
+public:
+       SerializationContext(std::string filename, int lineNo) : 
+               filename(filename), lineNo(lineNo)
+       {
+       }
+       
+       std::string filename;
+       int lineNo;
+};
+
+class RoRSerializer
+{
+       friend class RoRSerializationModule;
+public:
+       RoRSerializer();
+       ~RoRSerializer();
+
+       int loadRig(Ogre::DataStreamPtr ds, rig_t *rig);
+       int saveRig(std::string filename, rig_t *rig);
+
+       int registerModuleSerializer(RoRSerializationModule *module);
+protected:
+       int processModules(char *line, rig_t *rig, SerializationContext *ctx, 
std::string &activeSection);
+
+       std::map < std::string, RoRSerializationModule *> modules;
+};
+
+class RoRSerializationModule
+{
+       friend class RoRSerializer;
+public:
+       RoRSerializationModule(RoRSerializer *s) :
+               s(s),
+               name(),
+               commandTrigger(),
+               sectionTrigger(),
+               initiated(false)
+       {
+       }
+
+       ~RoRSerializationModule() {}
+
+       virtual int deserialize(char *line, rig_t *rig) = 0;
+       virtual int serialize(char *line, rig_t *rig) = 0;
+
+       std::string getName() { return name; };
+protected:
+       RoRSerializer *s;
+       std::string name;
+       std::string commandTrigger;
+       std::string sectionTrigger;
+       bool initiated;
+
+       // some utils
+       int checkRes(int minArgs, int result)
+       {
+               if (result < 1 || result == EOF)
+               {
+                       Ogre::LogManager::getSingleton().logMessage("Error 
parsing " + this->getName() + "");
+                       // TODO output more info about the problem
+               }
+               return result;
+       }
+       
+       virtual void initData(rig_t *rig) = 0;
+
+};
+
+#endif // SERIALIZER_H__

Added: trunk/source/serializer/tests/main.cpp
===================================================================
--- trunk/source/serializer/tests/main.cpp                              (rev 0)
+++ trunk/source/serializer/tests/main.cpp      2010-05-08 22:13:25 UTC (rev 
1381)
@@ -0,0 +1,35 @@
+
+// example program to test the serializer
+
+#include "serializer.h"
+#include "BeamData.h"
+#include "Ogre.h"
+
+using namespace std;
+using namespace Ogre;
+
+int main(int argc, char **argv)
+{
+       String filename = "b6b0UID-semi.truck";
+       
+       // start ogre
+       Ogre::Root* root = new Ogre::Root("", "", "ogre.log");
+       
+       // add resource dir
+       
ResourceGroupManager::getSingleton().addResourceLocation("streams/dev/dafsemi.zip",
 "Zip");
+       ResourceGroupManager::getSingleton().initialiseAllResourceGroups();     
+
+       //      load the file
+       DataStreamPtr ds = 
ResourceGroupManager::getSingleton().openResource(filename);
+       
+       // root struct
+       rig_t rig;
+       
+       // create the serializer
+       RoRSerializer *s = new RoRSerializer();
+       int result = s->loadRig(ds, &rig);
+       printf("result: %d\n", result);
+
+       delete root;
+}
+


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------

_______________________________________________
Rigsofrods-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rigsofrods-devel

Reply via email to