From 8a607777ede560f8b275410c03d49e7fefb30a4b Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 19 Jul 2009 11:28:45 +0100 Subject: [PATCH] Load engines from XML file --- base.wings => engines/base.wings | Bin engines/red/red.xml | 5 ++++ include/IResource.hpp | 1 + include/IRollingStock.hpp | 2 +- include/ResourceCache.hpp | 26 +++++++++++++----- schemas/engine.xsd | 12 +++++++++ src/Building.cpp | 7 +++-- src/Engine.cpp | 44 ++++++++++++++++++++++++------- src/Train.cpp | 2 +- 9 files changed, 77 insertions(+), 22 deletions(-) rename base.wings => engines/base.wings (100%) create mode 100644 engines/red/red.xml create mode 100644 schemas/engine.xsd diff --git a/base.wings b/engines/base.wings similarity index 100% rename from base.wings rename to engines/base.wings diff --git a/engines/red/red.xml b/engines/red/red.xml new file mode 100644 index 0000000..71f6c08 --- /dev/null +++ b/engines/red/red.xml @@ -0,0 +1,5 @@ + + + Basic red engine + train.obj + diff --git a/include/IResource.hpp b/include/IResource.hpp index 05aa22f..a5d3e76 100644 --- a/include/IResource.hpp +++ b/include/IResource.hpp @@ -33,6 +33,7 @@ struct IResource { virtual string name() const = 0; virtual string xmlFileName() const = 0; // REMOVE + // (Should be replaced by Handle openXmlFile() // A handle for reading data out of files in resources class Handle { diff --git a/include/IRollingStock.hpp b/include/IRollingStock.hpp index e303174..50fd7d8 100644 --- a/include/IRollingStock.hpp +++ b/include/IRollingStock.hpp @@ -45,7 +45,7 @@ struct IRollingStock { typedef shared_ptr IRollingStockPtr; // Make various waggons and engines -IRollingStockPtr makeEngine(); +IRollingStockPtr loadEngine(const string& aResId); IRollingStockPtr makeWaggon(); #endif diff --git a/include/ResourceCache.hpp b/include/ResourceCache.hpp index 38c6946..a087af8 100644 --- a/include/ResourceCache.hpp +++ b/include/ResourceCache.hpp @@ -27,28 +27,40 @@ template class ResourceCache { public: - typedef function LoaderType; + typedef function LoaderType; ResourceCache(LoaderType aLoader, const string& aClass) : myLoader(aLoader), myClass(aClass) {} - - T load(const string& aResId) + + // Load one single copy of this object + // -> use this if the object has no state + shared_ptr load(const string& aResId) { typename CacheType::iterator it = myCache.find(aResId); if (it != myCache.end()) return (*it).second; else { - T loaded = myLoader(findResource(aResId, myClass)); - myCache[aResId] = loaded; - return loaded; + T* loaded = myLoader(findResource(aResId, myClass)); + shared_ptr ptr(loaded); + myCache[aResId] = ptr; + return ptr; } } + + // Make a copy each time a new object is loaded but only + // parse the XML once + // -> use this if the object has state + shared_ptr loadCopy(const string& aResId) + { + shared_ptr original = load(aResId); + return shared_ptr(new T(*original.get())); + } private: LoaderType myLoader; const string myClass; - typedef map CacheType; + typedef map > CacheType; CacheType myCache; }; diff --git a/schemas/engine.xsd b/schemas/engine.xsd new file mode 100644 index 0000000..a1f736b --- /dev/null +++ b/schemas/engine.xsd @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/Building.cpp b/src/Building.cpp index 4548e7d..6f0c61c 100644 --- a/src/Building.cpp +++ b/src/Building.cpp @@ -56,17 +56,16 @@ void Building::text(const string& localName, const string& aString) } namespace { - - IBuildingPtr loadBuildingXml(IResourcePtr aRes) + Building* loadBuildingXml(IResourcePtr aRes) { log() << "Loading building from " << aRes->xmlFileName(); - return IBuildingPtr(new Building(aRes)); + return new Building(aRes); } } IBuildingPtr loadBuilding(const string& aResId) { - static ResourceCache cache(loadBuildingXml, "buildings"); + static ResourceCache cache(loadBuildingXml, "buildings"); return cache.load(aResId); } diff --git a/src/Engine.cpp b/src/Engine.cpp index 9f78df5..77333ed 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -19,6 +19,8 @@ #include "IModel.hpp" #include "ILogger.hpp" #include "MovingAverage.hpp" +#include "IXMLParser.hpp" +#include "ResourceCache.hpp" #include @@ -55,9 +57,10 @@ // Concrete implementation of a steam engine class Engine : public IRollingStock, public IController, + public IXMLCallback, public enable_shared_from_this { public: - Engine(); + Engine(IResourcePtr aRes); // IRollingStock interface void render() const; @@ -74,6 +77,9 @@ public: double pressure() const { return myBoilerPressure; } double temp() const { return myFireTemp; } track::Choice consumeChoice(); + + // IXMLCallback interface + void text(const string& localName, const string& aString); private: double tractiveEffort() const; double resistance() const; @@ -90,6 +96,8 @@ private: // Boiler pressure lags behind temperature MovingAverage myBoilerDelay; + + IResourcePtr myResource; static const float MODEL_SCALE; static const double TRACTIVE_EFFORT_KNEE; @@ -102,16 +110,24 @@ const double Engine::TRACTIVE_EFFORT_KNEE(10.0); const double Engine::INIT_PRESSURE(0.2); const double Engine::INIT_TEMP(50.0); -Engine::Engine() +Engine::Engine(IResourcePtr aRes) : mySpeed(0.0), myMass(29.0), myBoilerPressure(INIT_PRESSURE), myFireTemp(INIT_TEMP), myStatTractiveEffort(34.7), - isBrakeOn(true), myThrottle(0) + isBrakeOn(true), myThrottle(0), + myResource(aRes) { - IResourcePtr res = findResource("pclass", "engines"); - - myModel = loadModel(res, "pclass.obj", MODEL_SCALE); + static IXMLParserPtr parser = makeXMLParser("schemas/engine.xsd"); + + parser->parse(myResource->xmlFileName(), *this); +} + +// Callback for loading elements from the XML file +void Engine::text(const string& localName, const string& aString) +{ + if (localName == "model") + myModel = loadModel(myResource, aString, MODEL_SCALE); } // Draw the engine model @@ -210,8 +226,18 @@ void Engine::actOn(Action anAction) } } -// Make a new engine -IRollingStockPtr makeEngine() +namespace { + Engine* loadEngineXml(IResourcePtr aRes) + { + log() << "Loading engine from " << aRes->xmlFileName(); + + return new Engine(aRes); + } +} + +// Load an engine from a resource file +IRollingStockPtr loadEngine(const string& aResId) { - return IRollingStockPtr(new Engine); + static ResourceCache cache(loadEngineXml, "engines"); + return cache.loadCopy(aResId); } diff --git a/src/Train.cpp b/src/Train.cpp index 631121f..941c197 100644 --- a/src/Train.cpp +++ b/src/Train.cpp @@ -94,7 +94,7 @@ const double Train::SEPARATION(0.1); Train::Train(IMapPtr aMap) : myMap(aMap), myVelocityVector(makeVector(0.0f, 0.0f, 0.0f)) { - myParts.push_front(Part(makeEngine(), true)); + myParts.push_front(Part(loadEngine("red"), true)); enterSegment(engine(), aMap->startLocation()); -- 2.39.2