From: Charles McGarvey Date: Wed, 2 Sep 2009 06:01:09 +0000 (-0600) Subject: considerable refactoring X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=fdfba4553433b9b2804c2772c7645211b828c2ea;p=chaz%2Fyoink considerable refactoring --- diff --git a/src/Character.hh b/src/Character.hh index a92992c..b72e8c8 100644 --- a/src/Character.hh +++ b/src/Character.hh @@ -40,15 +40,17 @@ #include +struct Character; +typedef boost::shared_ptr CharacterP; + + /** * Parent class of animate objects with "personalities." This basically * includes the heroine herself and the bad guys. */ -class Character : public Mf::Entity +struct Character : public Mf::Entity { -public: - struct Derivative { Mf::Vector2 velocity; @@ -128,33 +130,38 @@ public: } }; - - Character(const std::string& name); - virtual ~Character(); - - void update(Mf::Scalar t, Mf::Scalar dt); - void handleEvent(const Mf::Event& event); - void draw(Mf::Scalar alpha) const; - - Mf::Tilemap& getTilemap(); - Mf::Animation& getAnimation(); - State previous; State current; stlplus::ntree::iterator treeNode; -private: - void updateContainers(); +private: static const Mf::Scalar z = 96.0; Mf::Tilemap tilemap_; Mf::Animation animation_; -}; -typedef boost::shared_ptr CharacterPtr; + void updateContainers(); + +public: + + inline static CharacterP alloc(const std::string& name) + { + return CharacterP(new Character(name)); + } + + Character(const std::string& name); + virtual ~Character(); + + void update(Mf::Scalar t, Mf::Scalar dt); + void handleEvent(const Mf::Event& event); + void draw(Mf::Scalar alpha) const; + + Mf::Tilemap& getTilemap(); + Mf::Animation& getAnimation(); +}; inline Character::State operator*(Mf::Scalar scalar, const Character::State& state) diff --git a/src/Moof/Animation.cc b/src/Moof/Animation.cc index 39dcb5a..7eaec19 100644 --- a/src/Moof/Animation.cc +++ b/src/Moof/Animation.cc @@ -46,8 +46,9 @@ namespace Mf { * instances. */ -struct Animation::Impl +class Animation::Impl { + friend class Animation; /** * Contains "global" animation data for the various animations which get @@ -55,8 +56,11 @@ struct Animation::Impl * which wants to use these loaded sequences. */ - struct GlobalData : public Mippleton + class Data : public Mippleton { + friend class Impl; + friend class Mippleton; + /** * A frame of an animation sequence. A frame is merely an index which * presumably represents a "slide" or tile which should be displayed, @@ -73,15 +77,15 @@ struct Animation::Impl * frame map which is probably loaded within an animation file. */ - Frame(SerializablePtr root) : + Frame(SerializableP root) : index(0), duration(1.0) { - std::map rootObj; + Serializable::Map rootObj; if (root->get(rootObj)) { - std::map::iterator it; + Serializable::Map::iterator it; for (it = rootObj.begin(); it != rootObj.end(); ++it) { @@ -123,26 +127,26 @@ struct Animation::Impl * constructor which loads each individual frame. */ - Sequence(SerializablePtr root) : + Sequence(SerializableP root) : delay(0.0), loop(true) { - std::map rootObj; + Serializable::Map rootObj; if (root->get(rootObj)) { - std::map::iterator it; + Serializable::Map::iterator it; for (it = rootObj.begin(); it != rootObj.end(); ++it) { std::string key = (*it).first; if (key == "frames") { - std::vector framesObj; + Serializable::Array framesObj; if ((*it).second->get(framesObj)) { - std::vector::iterator jt; + Serializable::Array::iterator jt; for (jt = framesObj.begin(); jt != framesObj.end(); ++jt) @@ -186,15 +190,15 @@ struct Animation::Impl Deserializer deserializer(filePath); - SerializablePtr root = deserializer.deserialize(); + SerializableP root = deserializer.deserialize(); if (root) { - std::map rootObj; + Serializable::Map rootObj; if (root->get(rootObj)) { - std::map::iterator it; + Serializable::Map::iterator it; for (it = rootObj.begin(); it != rootObj.end(); ++it) { @@ -210,8 +214,8 @@ struct Animation::Impl * registers itself as a mippleton and then loads the animation data. */ - explicit GlobalData(const std::string& name) : - Mippleton(name) + explicit Data(const std::string& name) : + Mippleton(name) { loadFromFile(); } @@ -225,7 +229,7 @@ struct Animation::Impl */ Impl(const std::string& name) : - data(GlobalData::getInstance(name)), + data(Data::getInstance(name)), currentSequence(0), frameCounter(0), frameIndex(0), @@ -241,7 +245,7 @@ struct Animation::Impl void startSequence(const std::string& name) { - std::map::iterator it; + std::map::iterator it; it = data->sequences.find(name); @@ -299,13 +303,13 @@ struct Animation::Impl } } - boost::shared_ptr data; ///< Internal data. + boost::shared_ptr data; ///< Internal data. - GlobalData::Sequence* currentSequence; ///< Active sequence. - unsigned frameCounter; ///< Current frame. - unsigned frameIndex; ///< Index of current frame. - Scalar timeAccum; ///< Time accumulation. - Scalar frameDuration; ///< Scaled frame duration. + Data::Sequence* currentSequence; ///< Active sequence. + unsigned frameCounter; ///< Current frame. + unsigned frameIndex; ///< Index of current frame. + Scalar timeAccum; ///< Time accumulation. + Scalar frameDuration; ///< Scaled frame duration. }; diff --git a/src/Moof/Animation.hh b/src/Moof/Animation.hh index cfda19b..38a055d 100644 --- a/src/Moof/Animation.hh +++ b/src/Moof/Animation.hh @@ -45,6 +45,9 @@ namespace Mf { +class Animation; +typedef boost::shared_ptr AnimationP; + /** * A class to manage frame-based animation. Animation sequences can be loaded * from file, then named sequences are started. The animation is updated @@ -55,7 +58,16 @@ namespace Mf { class Animation : public Resource { + class Impl; + boost::shared_ptr impl_; + public: + + static AnimationP alloc(const std::string& name) + { + return AnimationP(new Animation(name)); + } + Animation(const std::string& name); void startSequence(const std::string& name); @@ -64,10 +76,6 @@ public: unsigned getFrame() const; static std::string getPath(const std::string& name); - -private: - class Impl; - boost::shared_ptr impl_; }; diff --git a/src/Moof/Deserializer.cc b/src/Moof/Deserializer.cc index 8bf230f..c92ef47 100644 --- a/src/Moof/Deserializer.cc +++ b/src/Moof/Deserializer.cc @@ -32,29 +32,30 @@ #include #include "Deserializer.hh" +#include "Log.hh" #include "Serializable.hh" namespace Mf { -class Deserializer::DeserializerImpl +class Deserializer::Impl { public: - DeserializerImpl(const std::string& filePath, bool comments = false, + Impl(const std::string& filePath, bool comments = false, bool check = false) { std::ifstream* input = new std::ifstream(filePath.c_str()); init(*input, true, comments, check); } - DeserializerImpl(std::istream& input, bool comments = false, + Impl(std::istream& input, bool comments = false, bool check = false) { init(input, false, comments, check); } - ~DeserializerImpl() + ~Impl() { while (!parsed.empty()) { @@ -69,51 +70,50 @@ public: yajl_free(hand); } - void throwError() + void raise() { unsigned char* errorStr = yajl_get_error(hand, 0, 0, 0); - Deserializer::Exception exception((char*)errorStr); + logError("parser error: %s", errorStr); yajl_free_error(hand, errorStr); - throw exception; + + throw Exception(Exception::PARSING_FAILED); } static int parsedNull(void* ctx) { - ((DeserializerImpl*)ctx)->parsed.push(new SerializableNull); + ((Impl*)ctx)->parsed.push(new SerializableNull); return 1; } static int parsedBoolean(void* ctx, int value) { - ((DeserializerImpl*)ctx)->parsed.push(new SerializableBoolean(value)); + ((Impl*)ctx)->parsed.push(new SerializableBasic(value)); return 1; } static int parsedInteger(void* ctx, long value) { - ((DeserializerImpl*)ctx)->parsed.push(new SerializableInteger(value)); + ((Impl*)ctx)->parsed.push(new SerializableBasic(value)); return 1; } static int parsedFloat(void* ctx, double value) { - ((DeserializerImpl*)ctx)->parsed.push(new SerializableReal(value)); + ((Impl*)ctx)->parsed.push(new SerializableBasic(value)); return 1; } static int parsedString(void* ctx, const unsigned char* value, unsigned length) { - SerializableString* parsed = - new SerializableString(std::string((char*)value, length)); - ((DeserializerImpl*)ctx)->parsed.push(parsed); + ((Impl*)ctx)->parsed.push(new SerializableBasic(std::string((char*)value, length))); return 1; } static int parsedBeginMap(void* ctx) { - ((DeserializerImpl*)ctx)->parsed.push(new SerializableMap); + ((Impl*)ctx)->parsed.push(new SerializableBasic); return 1; } @@ -126,19 +126,21 @@ public: static int parsedEndMap(void* ctx) { - ((DeserializerImpl*)ctx)->parsed.push(0); + // null means the end of a structure + ((Impl*)ctx)->parsed.push(0); return 1; } static int parsedBeginArray(void* ctx) { - ((DeserializerImpl*)ctx)->parsed.push(new SerializableArray); + ((Impl*)ctx)->parsed.push(new SerializableBasic); return 1; } static int parsedEndArray(void* ctx) { - ((DeserializerImpl*)ctx)->parsed.push(0); + // null means the end of a structure + ((Impl*)ctx)->parsed.push(0); return 1; } @@ -166,7 +168,7 @@ public: if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) { - throwError(); + raise(); } } } @@ -186,17 +188,17 @@ private: // internal data structures but rather keeps a pointer to this static const yajl_callbacks callbacks = { - DeserializerImpl::parsedNull, - DeserializerImpl::parsedBoolean, - DeserializerImpl::parsedInteger, - DeserializerImpl::parsedFloat, + Impl::parsedNull, + Impl::parsedBoolean, + Impl::parsedInteger, + Impl::parsedFloat, 0, - DeserializerImpl::parsedString, - DeserializerImpl::parsedBeginMap, - DeserializerImpl::parsedMapKey, - DeserializerImpl::parsedEndMap, - DeserializerImpl::parsedBeginArray, - DeserializerImpl::parsedEndArray + Impl::parsedString, + Impl::parsedBeginMap, + Impl::parsedMapKey, + Impl::parsedEndMap, + Impl::parsedBeginArray, + Impl::parsedEndArray }; in = &input; @@ -211,21 +213,21 @@ private: Deserializer::Deserializer(const std::string& filePath, bool comments, bool check) : // pass through - impl_(new Deserializer::DeserializerImpl(filePath, comments, check)) {} + impl_(new Deserializer::Impl(filePath, comments, check)) {} Deserializer::Deserializer(std::istream& input, bool comments, bool check) : // pass through - impl_(new Deserializer::DeserializerImpl(input, comments, check)) {} + impl_(new Deserializer::Impl(input, comments, check)) {} -SerializablePtr Deserializer::deserialize() +SerializableP Deserializer::deserialize() { Serializable* ptr = pullNext(); if (ptr) { ptr->deserialize(*this); } - return SerializablePtr(ptr); + return SerializableP(ptr); } diff --git a/src/Moof/Deserializer.hh b/src/Moof/Deserializer.hh index 8a771e8..cf99c2d 100644 --- a/src/Moof/Deserializer.hh +++ b/src/Moof/Deserializer.hh @@ -40,15 +40,21 @@ #include +#include + namespace Mf { class Serializable; // forward declaration -typedef boost::shared_ptr SerializablePtr; +typedef boost::shared_ptr SerializableP; + class Deserializer { + class Impl; + boost::shared_ptr impl_; + public: /** @@ -77,7 +83,7 @@ public: * deserializer. */ - SerializablePtr deserialize(); + SerializableP deserialize(); /** * Used by serializable objects to parse themselves. These methods should @@ -110,15 +116,31 @@ public: * This exception is thrown upon deserialization errors. */ - struct Exception : std::runtime_error + struct Exception : public Mf::Exception { - explicit Exception(const std::string& what_arg) : - std::runtime_error(what_arg) {} + enum + { + PARSING_FAILED = 1024 + }; + + explicit Exception(unsigned error) : + Mf::Exception(error) {} + + void raise() + { + throw *this; + } + + const char* what() const throw() + { + switch (code) + { + case PARSING_FAILED: + return "parsing failed"; + } + return Mf::Exception::what(); + } }; - -private: - class DeserializerImpl; - boost::shared_ptr impl_; }; diff --git a/src/Moof/Engine.cc b/src/Moof/Engine.cc index c74ace8..df6b35a 100644 --- a/src/Moof/Engine.cc +++ b/src/Moof/Engine.cc @@ -90,7 +90,7 @@ public: printFps = false; settings.get("video.printfps", printFps); - video = VideoPtr(new Video(name, iconFile)); + video = Video::alloc(name, iconFile); video->makeActive(); } @@ -222,7 +222,7 @@ public: Engine* interface; - VideoPtr video; + VideoP video; bool running; int exitCode; diff --git a/src/Moof/Entity.hh b/src/Moof/Entity.hh index f593d0c..33efcc9 100644 --- a/src/Moof/Entity.hh +++ b/src/Moof/Entity.hh @@ -40,8 +40,12 @@ namespace Mf { +class Entity; +typedef boost::shared_ptr EntityP; + class Camera; + /** * Interface for game objects that can be drawn to the screen and have a * specified size. @@ -72,8 +76,6 @@ protected: Sphere sphere_; }; -typedef boost::shared_ptr EntityPtr; - } // namespace Mf diff --git a/src/Moof/Log.cc b/src/Moof/Log.cc index dcdb5ec..ddd12bb 100644 --- a/src/Moof/Log.cc +++ b/src/Moof/Log.cc @@ -38,7 +38,7 @@ namespace Mf { static LogLevel logLevel_ = WARNING; -static void printLog_(int logLevel, const char* fmt, va_list args) +inline void printLog_(int logLevel, const char* fmt, va_list args) { if (logLevel_ < logLevel) return; @@ -72,8 +72,7 @@ LogLevel setLogLevel(LogLevel level) } -void -logError(const char* fmt, ...) +void logError(const char* fmt, ...) { va_list args; va_start(args, fmt); @@ -83,8 +82,7 @@ logError(const char* fmt, ...) va_end(args); } -void -logWarning(const char* fmt, ...) +void logWarning(const char* fmt, ...) { va_list args; va_start(args, fmt); @@ -94,8 +92,7 @@ logWarning(const char* fmt, ...) va_end(args); } -void -logInfo(const char* fmt, ...) +void logInfo(const char* fmt, ...) { va_list args; va_start(args, fmt); @@ -105,8 +102,7 @@ logInfo(const char* fmt, ...) va_end(args); } -void -logDebug(const char* fmt, ...) +void logDebug(const char* fmt, ...) { va_list args; va_start(args, fmt); diff --git a/src/Moof/Log.hh b/src/Moof/Log.hh index d3e4009..3f6b6d7 100644 --- a/src/Moof/Log.hh +++ b/src/Moof/Log.hh @@ -37,22 +37,23 @@ */ #include // exit -#include // errno #include // strerror -namespace Mf { - - /** * Macro which tests an assertion and issues an logError() and exits if false. - * This differs from the standard assert() in that this is a runtime assertion - * test and will always be compiled in. * @param X test to perform */ -#define ASSERT(X) if (!(X)) logError("false assertion at %s:%d, " #X \ - " (errno: %d, %s)", __FILE__, __LINE__, errno, strerror(errno)), exit(1) +#if ! NDEBUG +#define ASSERT(X) if (!(X)) Mf::logError("false assertion at %s:%d, " #X, \ + __FILE__, __LINE__), exit(1) +#else +#define ASSERT(X) +#endif + + +namespace Mf { /** diff --git a/src/Moof/Octree.cc b/src/Moof/Octree.cc index 50b38ac..22b4eb1 100644 --- a/src/Moof/Octree.cc +++ b/src/Moof/Octree.cc @@ -27,6 +27,7 @@ *******************************************************************************/ #include "Camera.hh" +#include "Log.hh" #include "Octree.hh" @@ -45,17 +46,14 @@ void Octree::sort() stlplus::ntree::iterator Octree::insert(stlplus::ntree::iterator node, - EntityPtr entity) + EntityP entity) { + ASSERT(node.valid() && "invalid node passed"); + ASSERT(entity && "null entity passed"); + Plane::Halfspace halfspace; int octantNum = -1; - if (!node.valid()) - { - std::cerr << "cannot insert into invalid node" << std::endl; - return stlplus::ntree::iterator(); - } - Plane xy = node->getAabb().getPlaneXY(); halfspace = xy.intersectsSphere(entity->getSphere()); if (halfspace == Plane::INTERSECT) @@ -169,29 +167,19 @@ stlplus::ntree::iterator Octree::insert(stlplus::ntree:: } stlplus::ntree::iterator child = tree_.child(node, octantNum); + ASSERT(child.valid() && "expected valid child node"); - if (child.valid()) - { - return insert(child, entity); - } - else - { - std::cerr << "expected but found no child at index " << octantNum << std::endl; - return stlplus::ntree::iterator(); - } + return insert(child, entity); } } -stlplus::ntree::iterator Octree::reinsert(EntityPtr entity, +stlplus::ntree::iterator Octree::reinsert(EntityP entity, stlplus::ntree::iterator node) { - if (!node.valid()) - { - std::cerr << "cannot move entity from invalid node" << std::endl; - return stlplus::ntree::iterator(); - } + ASSERT(entity && "null entity passed"); + ASSERT(node.valid() && "invalid node passed"); - std::list::iterator it; + std::list::iterator it; it = std::find(node->objects.begin(), node->objects.end(), entity); if (it != node->objects.end()) @@ -205,13 +193,9 @@ stlplus::ntree::iterator Octree::reinsert(EntityPtr entity, void Octree::addChild(stlplus::ntree::iterator node, int index) { - Aabb octant; + ASSERT(node.valid() && "invalid node passed"); - if (!node.valid()) - { - std::cerr << "cannot add children to invalid node" << std::endl; - return; - } + Aabb octant; for (int i = tree_.children(node); i <= index; ++i) { @@ -223,45 +207,30 @@ void Octree::addChild(stlplus::ntree::iterator node, int index) void Octree::draw(stlplus::ntree::iterator node, Scalar alpha) { - if (!node.valid()) - { - std::cerr << "cannot draw null child node :-(" << std::endl; - return; - } + ASSERT(node.valid() && "invalid node passed"); node->draw(alpha); for (unsigned i = 0; i < tree_.children(node); ++i) { stlplus::ntree::iterator child = tree_.child(node, i); + ASSERT(child.valid() && "expected valid child node"); - if (child.valid()) - { - draw(child, alpha); - } - else - { - std::cerr << "node is not a leaf, but has an invalid child" << std::endl; - } - + draw(child, alpha); } } void Octree::drawIfVisible(stlplus::ntree::iterator node, Scalar alpha, const Camera& cam) { - //node.drawIfVisible(alpha, cam); - - if (!node.valid()) - { - std::cerr << "invalid child while drawing :-(" << std::endl; - return; - } + ASSERT(node.valid() && "invalid node passed"); + // try to cull by sphere Frustum::Collision collision = cam.getFrustum().containsSphere(node->getSphere()); if (collision == Frustum::OUTSIDE) return; + // try to cull by aabb collision = cam.getFrustum().containsAabb(node->getAabb()); if (collision == Frustum::OUTSIDE) return; @@ -282,16 +251,9 @@ void Octree::drawIfVisible(stlplus::ntree::iterator node, for (unsigned i = 0; i < tree_.children(node); ++i) { stlplus::ntree::iterator child = tree_.child(node, i); + ASSERT(child.valid() && "expected valid child node"); - if (child.valid()) - { - draw(child, alpha); - } - else - { - std::cerr << "node is not a leaf, but has an invalid child" << std::endl; - } - + draw(child, alpha); } } else // collision == Frustum::INTERSECT @@ -299,15 +261,9 @@ void Octree::drawIfVisible(stlplus::ntree::iterator node, for (unsigned i = 0; i < tree_.children(node); ++i) { stlplus::ntree::iterator child = tree_.child(node, i); + ASSERT(child.valid() && "expected valid child node"); - if (child.valid()) - { - drawIfVisible(child, alpha, cam); - } - else - { - std::cerr << "node is not a leaf, but has an invalid child" << std::endl; - } + drawIfVisible(child, alpha, cam); } } } diff --git a/src/Moof/Octree.hh b/src/Moof/Octree.hh index d896844..774eece 100644 --- a/src/Moof/Octree.hh +++ b/src/Moof/Octree.hh @@ -51,7 +51,7 @@ class Camera; struct OctreeNode : public Entity { - std::list objects; + std::list objects; OctreeNode() { @@ -69,28 +69,28 @@ struct OctreeNode : public Entity void draw(Scalar alpha) const { - std::list::const_iterator it; + std::list::const_iterator it; for (it = objects.begin(); it != objects.end(); ++it) { (*it)->draw(alpha); } - //if (!objects.empty()) - //aabb_.draw(); // temporary + if (!objects.empty()) + aabb_.draw(); // temporary } void drawIfVisible(Scalar alpha, const Camera& cam) const { - std::list::const_iterator it; + std::list::const_iterator it; for (it = objects.begin(); it != objects.end(); ++it) { (*it)->drawIfVisible(alpha, cam); } - //if (!objects.empty()) - //aabb_.draw(); + if (!objects.empty()) + aabb_.draw(); } @@ -105,7 +105,7 @@ struct OctreeNode : public Entity } - static bool compareZOrder(EntityPtr a, EntityPtr b) + static bool compareZOrder(EntityP a, EntityP b) { return a->getSphere().point[2] < b->getSphere().point[2]; } @@ -118,21 +118,40 @@ struct OctreeNode : public Entity }; +class Octree; +typedef boost::shared_ptr OctreeP; + class Octree { + stlplus::ntree::iterator + insert(stlplus::ntree::iterator node, EntityP entity); + + void addChild(stlplus::ntree::iterator node, int index); + + void draw(stlplus::ntree::iterator node, Scalar alpha); + void drawIfVisible(stlplus::ntree::iterator node, + Scalar alpha, const Camera& cam); + + stlplus::ntree tree_; + public: + inline static OctreeP alloc(const OctreeNode& rootNode) + { + return OctreeP(new Octree(rootNode)); + } + explicit Octree(const OctreeNode& rootNode) { tree_.insert(rootNode); } - stlplus::ntree::iterator insert(EntityPtr entity) + stlplus::ntree::iterator insert(EntityP entity) { return insert(tree_.root(), entity); } - stlplus::ntree::iterator reinsert(EntityPtr entity, + stlplus::ntree::iterator reinsert(EntityP entity, stlplus::ntree::iterator node); void drawIfVisible(Scalar alpha, const Camera& cam) @@ -141,21 +160,8 @@ public: } void sort(); - -private: - stlplus::ntree::iterator insert(stlplus::ntree::iterator node, EntityPtr entity); - - void addChild(stlplus::ntree::iterator node, int index); - - void draw(stlplus::ntree::iterator node, Scalar alpha); - void drawIfVisible(stlplus::ntree::iterator node, - Scalar alpha, const Camera& cam); - - stlplus::ntree tree_; }; -typedef boost::shared_ptr OctreePtr; - } // namespace Mf diff --git a/src/Moof/Scene.cc b/src/Moof/Scene.cc index 1f76570..ccfd4f9 100644 --- a/src/Moof/Scene.cc +++ b/src/Moof/Scene.cc @@ -133,13 +133,13 @@ class Scene::Impl : public Mippleton }; - static void loadBox(Aabb& theBox, SerializablePtr obj) + static void loadBox(Aabb& theBox, SerializableP obj) { - std::vector numbers; + Serializable::Array numbers; if (obj->get(numbers) && numbers.size() == 6) { - double num; + Serializable::Float num; if (numbers[0]->getNumber(num)) theBox.min[0] = Scalar(num); if (numbers[1]->getNumber(num)) theBox.min[1] = Scalar(num); @@ -158,10 +158,10 @@ public: } - void loadInstructions(SerializablePtr root) + void loadInstructions(SerializableP root) { - std::vector rootObj; - std::vector::iterator it; + Serializable::Array rootObj; + Serializable::Array::iterator it; if (!root->get(rootObj)) { @@ -184,7 +184,7 @@ public: } else if (instruction == "translate") { - std::vector values; + Serializable::Array values; ++it; if ((*it)->get(values)) @@ -193,7 +193,7 @@ public: for (size_t i = 0; i < values.size(); ++i) { - double value; + Serializable::Float value; if (values[i]->getNumber(value)) { @@ -208,14 +208,14 @@ public: } else if (instruction == "scale") { - std::vector values; + Serializable::Array values; ++it; if ((*it)->get(values)) { if (values.size() == 1) { - double value = 1.0; + Serializable::Float value = 1.0; values[0]->getNumber(value); @@ -230,7 +230,7 @@ public: for (size_t i = 0; i < values.size(); ++i) { - double value; + Serializable::Float value; if (values[i]->getNumber(value)) { @@ -246,7 +246,7 @@ public: } else if (instruction == "rotate") { - std::vector values; + Serializable::Array values; ++it; if ((*it)->get(values)) @@ -255,7 +255,7 @@ public: { std::string axis; size_t index = 0; - double value = 0.0; + Serializable::Float value = 0.0; if (values[0]->get(axis)) { @@ -291,11 +291,11 @@ public: } - void loadTilemap(SerializablePtr root, const Matrix4& transform, + void loadTilemap(SerializableP root, const Matrix4& transform, const std::string& texture) { - std::map rootObj; - std::map::iterator it; + Serializable::Map rootObj; + Serializable::Map::iterator it; if (!root->get(rootObj)) { @@ -317,13 +317,13 @@ public: return; } - std::vector tiles; + Serializable::Array tiles; if ((it = rootObj.find("tiles")) != rootObj.end() && (*it).second->get(tiles) && tiles.size() % width == 0) { - std::vector::iterator jt; + Serializable::Array::iterator jt; int w, h; height = tiles.size() / width; @@ -339,7 +339,7 @@ public: for (w = 0; w < width && jt != tiles.end(); ++w, ++jt) { - long index; + Serializable::Integer index; if ((*jt)->get(index)) { @@ -391,11 +391,11 @@ public: } } - void loadBillboard(SerializablePtr root, const Matrix4& transform, + void loadBillboard(SerializableP root, const Matrix4& transform, const std::string& texture) { - std::map rootObj; - std::map::iterator it; + Serializable::Map rootObj; + Serializable::Map::iterator it; Tilemap::Index index = 0; long width = 1; @@ -406,7 +406,7 @@ public: { if ((it = rootObj.find("tile")) != rootObj.end()) { - long value; + Serializable::Integer value; if ((*it).second->get(value)) { index = Tilemap::Index(value); @@ -473,10 +473,10 @@ public: std::string filePath = Scene::getPath(getName()); Deserializer deserializer(filePath, true); - SerializablePtr root = deserializer.deserialize(); + SerializableP root = deserializer.deserialize(); - std::map rootObj; - std::map::iterator it; + Serializable::Map rootObj; + Serializable::Map::iterator it; if (!root || !root->get(rootObj)) { @@ -499,7 +499,7 @@ public: } // create the tree to store the quads - octree = OctreePtr(new Octree(maximumBounds)); + octree = Octree::alloc(maximumBounds); if ((it = rootObj.find("instructions")) != rootObj.end()) { @@ -535,7 +535,7 @@ public: Aabb playfieldBounds; Aabb maximumBounds; - OctreePtr octree; + OctreeP octree; }; @@ -557,7 +557,7 @@ void Scene::refresh() } -OctreePtr Scene::getOctree() const +OctreeP Scene::getOctree() const { // pass through return impl_->octree; diff --git a/src/Moof/Scene.hh b/src/Moof/Scene.hh index 4c4f297..f0e829d 100644 --- a/src/Moof/Scene.hh +++ b/src/Moof/Scene.hh @@ -41,23 +41,32 @@ namespace Mf { +class Scene; +typedef boost::shared_ptr SceneP; + class Camera; + class Scene : public Resource { + class Impl; + boost::shared_ptr impl_; + public: + + inline static SceneP alloc(const std::string& name) + { + return SceneP(new Scene(name)); + } + Scene(const std::string& name); void draw(Scalar alpha, const Camera& cam) const; void refresh(); - OctreePtr getOctree() const; + OctreeP getOctree() const; static std::string getPath(const std::string& name); - -private: - class Impl; - boost::shared_ptr impl_; }; diff --git a/src/Moof/Serializable.cc b/src/Moof/Serializable.cc index 583fce3..b374575 100644 --- a/src/Moof/Serializable.cc +++ b/src/Moof/Serializable.cc @@ -37,37 +37,37 @@ Serializable::~Serializable() } -bool Serializable::get(long& value) +bool Serializable::get(Integer& value) { return false; } -bool Serializable::get(double& value) +bool Serializable::get(Float& value) { return false; } -bool Serializable::get(bool& value) +bool Serializable::get(Boolean& value) { return false; } -bool Serializable::get(std::string& value) +bool Serializable::get(String& value) { return false; } -bool Serializable::get(std::wstring& value) +bool Serializable::get(WideString& value) { return false; } -bool Serializable::get(std::vector& value) +bool Serializable::get(Array& value) { return false; } -bool Serializable::get(std::map& value) +bool Serializable::get(Map& value) { return false; } @@ -79,7 +79,7 @@ bool Serializable::isNull() } -bool Serializable::getNumber(long& value) +bool Serializable::getNumber(Integer& value) { if (get(value)) { @@ -87,17 +87,17 @@ bool Serializable::getNumber(long& value) } else { - double doubleValue; + Float doubleValue; if (get(doubleValue)) { - value = long(doubleValue); + value = Integer(doubleValue); return true; } } return false; } -bool Serializable::getNumber(double& value) +bool Serializable::getNumber(Float& value) { if (get(value)) { @@ -105,10 +105,10 @@ bool Serializable::getNumber(double& value) } else { - long longValue; + Integer longValue; if (get(longValue)) { - value = double(longValue); + value = Float(longValue); return true; } } diff --git a/src/Moof/Serializable.hh b/src/Moof/Serializable.hh index f00fb94..e91660d 100644 --- a/src/Moof/Serializable.hh +++ b/src/Moof/Serializable.hh @@ -46,9 +46,18 @@ namespace Mf { * Interface for a type which can be serialized and deserialized. */ -class Serializable +struct Serializable { -public: + // basic types which are serializable + typedef long Integer; + typedef double Float; + typedef bool Boolean; + typedef std::string String; + typedef std::wstring WideString; + typedef std::vector Array; + typedef std::map Map; + + virtual ~Serializable(); virtual void serialize(Serializer& out) const = 0; @@ -56,32 +65,35 @@ public: virtual void print() const = 0; - virtual bool get(long& value); - virtual bool get(double& value); - virtual bool get(bool& value); - virtual bool get(std::string& value); - virtual bool get(std::wstring& value); - virtual bool get(std::vector& value); - virtual bool get(std::map& value); + virtual bool get(Integer& value); + virtual bool get(Float& value); + virtual bool get(Boolean& value); + virtual bool get(String& value); + virtual bool get(WideString& value); + virtual bool get(Array& value); + virtual bool get(Map& value); /* * To get a number value which may have been parsed as either an integer or * double, use these getters instead. */ - bool getNumber(long&); - bool getNumber(double&); + bool getNumber(Integer& value); + bool getNumber(Float& value); virtual bool isNull(); }; template -class SerializableBase : public Serializable +class SerializableBasic : public Serializable { + T value_; + public: - SerializableBase() {} - SerializableBase(const T& value) : + + SerializableBasic() {} + SerializableBasic(const T& value) : value_(value) {} void serialize(Serializer& out) const; @@ -89,15 +101,13 @@ public: void print() const; bool get(T& value); -public: - T value_; }; -class SerializableNull : public Serializable +struct SerializableNull : public Serializable { -public: SerializableNull() {} + void serialize(Serializer& out) const; void deserialize(Deserializer& in); @@ -106,30 +116,19 @@ public: }; -typedef SerializableBase SerializableInteger; -typedef SerializableBase SerializableReal; -typedef SerializableBase SerializableBoolean; -typedef SerializableBase SerializableString; -typedef SerializableBase SerializableWideString; -typedef SerializableBase > SerializableArray; -typedef SerializableBase > - SerializableMap; - - - template -inline void SerializableBase::serialize(Serializer& out) const +inline void SerializableBasic::serialize(Serializer& out) const { out.push(value_); } template <> inline void -SerializableBase >::serialize(Serializer& out) const +SerializableBasic::serialize(Serializer& out) const { out.pushArrayHead(); - std::vector::const_iterator it; + std::vector::const_iterator it; for (it = value_.begin(); it < value_.end(); ++it) { (*it)->serialize(out); @@ -140,12 +139,11 @@ SerializableBase >::serialize(Serializer& out) cons template <> inline void -SerializableBase >::serialize(Serializer& out) const +SerializableBasic::serialize(Serializer& out) const { out.pushMapHead(); - std::map::const_iterator it; - for (it = value_.begin(); it != value_.end(); ++it) + for (Map::const_iterator it = value_.begin(); it != value_.end(); ++it) { out.push((*it).first); (*it).second->serialize(out); @@ -161,21 +159,22 @@ inline void SerializableNull::serialize(Serializer& out) const template -inline void SerializableBase::deserialize(Deserializer& in) +inline void SerializableBasic::deserialize(Deserializer& in) { in.pop(); } template <> -inline void SerializableBase >::deserialize(Deserializer& in) +inline void +SerializableBasic::deserialize(Deserializer& in) { - SerializablePtr obj; + SerializableP obj; in.pop(); while (obj = in.deserialize()) { - value_.push_back(SerializablePtr(obj)); + value_.push_back(obj); } in.pop(); @@ -183,9 +182,9 @@ inline void SerializableBase >::deserialize(Deseria template <> inline void -SerializableBase >::deserialize(Deserializer& in) +SerializableBasic::deserialize(Deserializer& in) { - SerializablePtr obj; + SerializableP obj; in.pop(); @@ -208,25 +207,25 @@ inline void SerializableNull::deserialize(Deserializer& in) template -inline void SerializableBase::print() const +inline void SerializableBasic::print() const { std::cout << std::boolalpha << typeid(T).name() << "(" << value_ << ")"; } template <> -inline void SerializableBase::print() const +inline void SerializableBasic::print() const { std::wcout << value_; } template <> -inline void SerializableBase >::print() const +inline void SerializableBasic::print() const { std::cout << "array"; } template <> -inline void SerializableBase >::print() const +inline void SerializableBasic::print() const { std::cout << "map"; } @@ -238,7 +237,7 @@ inline void SerializableNull::print() const template -inline bool SerializableBase::get(T& value) +inline bool SerializableBasic::get(T& value) { value = value_; return true; diff --git a/src/Moof/Serializer.cc b/src/Moof/Serializer.cc index a93eb5a..570ee5a 100644 --- a/src/Moof/Serializer.cc +++ b/src/Moof/Serializer.cc @@ -37,21 +37,20 @@ namespace Mf { -class Serializer::SerializerImpl +struct Serializer::Impl { -public: - SerializerImpl(const std::string& filePath, const std::string& indent = "") + Impl(const std::string& filePath, const std::string& indent = "") { std::ofstream* output = new std::ofstream(filePath.c_str()); init(*output, true, indent); } - SerializerImpl(std::ostream& output, const std::string& indent = "") + Impl(std::ostream& output, const std::string& indent = "") { init(output, false, indent); } - ~SerializerImpl() + ~Impl() { if (deleteWhenDone) { @@ -60,18 +59,18 @@ public: yajl_gen_free(gen); } - static void throwError(yajl_gen_status err) + static void raise(yajl_gen_status err) { switch (err) { case yajl_gen_generation_complete: - throw Serializer::Exception("the archive has already terminated"); + throw Serializer::Exception(Exception::ARCHIVE_TERMINATED); case yajl_gen_keys_must_be_strings: - throw Serializer::Exception("map keys must be strings"); + throw Serializer::Exception(Exception::KEYS_MUST_BE_STRINGS); case yajl_max_depth_exceeded: - throw Serializer::Exception("maximum archive depth exceeded"); + throw Serializer::Exception(Exception::RECURSION_TOO_DEEP); case yajl_gen_in_error_state: - throw Serializer::Exception("serializer already in error state"); + throw Serializer::Exception(Exception::ALREADY_FAILED); case yajl_gen_status_ok: ; // There is no error here. Move along... } @@ -83,6 +82,7 @@ public: bool deleteWhenDone; private: + void init(std::ostream& output, bool deleteOut, const std::string& indent) { yajl_gen_config config; @@ -108,11 +108,11 @@ private: Serializer::Serializer(const std::string& filePath, const std::string& indent) : // pass through - impl_(new Serializer::SerializerImpl(filePath, indent)) {} + impl_(new Serializer::Impl(filePath, indent)) {} Serializer::Serializer(std::ostream& output, const std::string& indent) : // pass through - impl_(new Serializer::SerializerImpl(output, indent)) {} + impl_(new Serializer::Impl(output, indent)) {} Serializer::~Serializer() { @@ -123,30 +123,26 @@ Serializer::~Serializer() void Serializer::push(long value) { yajl_gen_status stat = yajl_gen_integer(impl_->gen, value); - if (stat != yajl_gen_status_ok) - Serializer::SerializerImpl::throwError(stat); + if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat); } void Serializer::push(double value) { yajl_gen_status stat = yajl_gen_double(impl_->gen, value); - if (stat != yajl_gen_status_ok) - Serializer::SerializerImpl::throwError(stat); + if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat); } void Serializer::push(bool value) { yajl_gen_status stat = yajl_gen_bool(impl_->gen, value); - if (stat != yajl_gen_status_ok) - Serializer::SerializerImpl::throwError(stat); + if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat); } void Serializer::push(const std::string& value) { yajl_gen_status stat = yajl_gen_string(impl_->gen, (const unsigned char*)value.c_str(), value.length()); - if (stat != yajl_gen_status_ok) - Serializer::SerializerImpl::throwError(stat); + if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat); } void Serializer::push(const std::wstring& value) @@ -157,37 +153,32 @@ void Serializer::push(const std::wstring& value) void Serializer::pushNull() { yajl_gen_status stat = yajl_gen_null(impl_->gen); - if (stat != yajl_gen_status_ok) - Serializer::SerializerImpl::throwError(stat); + if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat); } void Serializer::pushMapHead() { yajl_gen_status stat = yajl_gen_map_open(impl_->gen); - if (stat != yajl_gen_status_ok) - Serializer::SerializerImpl::throwError(stat); + if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat); } void Serializer::pushMapTail() { yajl_gen_status stat = yajl_gen_map_close(impl_->gen); - if (stat != yajl_gen_status_ok) - Serializer::SerializerImpl::throwError(stat); + if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat); } void Serializer::pushArrayHead() { yajl_gen_status stat = yajl_gen_array_open(impl_->gen); - if (stat != yajl_gen_status_ok) - Serializer::SerializerImpl::throwError(stat); + if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat); } void Serializer::pushArrayTail() { yajl_gen_status stat = yajl_gen_array_close(impl_->gen); - if (stat != yajl_gen_status_ok) - Serializer::SerializerImpl::throwError(stat); + if (stat != yajl_gen_status_ok) Serializer::Impl::raise(stat); } diff --git a/src/Moof/Serializer.hh b/src/Moof/Serializer.hh index 7d54834..4329e6f 100644 --- a/src/Moof/Serializer.hh +++ b/src/Moof/Serializer.hh @@ -40,12 +40,17 @@ #include +#include + namespace Mf { class Serializer { + class Impl; + boost::shared_ptr impl_; + public: /** @@ -95,19 +100,45 @@ public: void flush(); + /** * This exception is thrown for serializer-related exceptional errors. */ - struct Exception : std::runtime_error + struct Exception : public Mf::Exception { - explicit Exception(const std::string& what_arg) : - std::runtime_error(what_arg) {} + enum + { + ARCHIVE_TERMINATED = 1024, + KEYS_MUST_BE_STRINGS = 1025, + RECURSION_TOO_DEEP = 1026, + ALREADY_FAILED = 1027, + }; + + explicit Exception(unsigned error) : + Mf::Exception(error) {} + + void raise() + { + throw *this; + } + + const char* what() const throw() + { + switch (code) + { + case ARCHIVE_TERMINATED: + return "archive is already terminated"; + case KEYS_MUST_BE_STRINGS: + return "map keys must be strings"; + case RECURSION_TOO_DEEP: + return "generator recursion too deep"; + case ALREADY_FAILED: + return "generator already errored out"; + } + return Mf::Exception::what(); + } }; - -private: - class SerializerImpl; - boost::shared_ptr impl_; }; } // namespace Mf diff --git a/src/Moof/Settings.cc b/src/Moof/Settings.cc index ad9c3b0..624179c 100644 --- a/src/Moof/Settings.cc +++ b/src/Moof/Settings.cc @@ -69,14 +69,14 @@ void Settings::parseArgs(int argc, char* argv[]) try { - SerializablePtr value(deserializer.deserialize()); + SerializableP value(deserializer.deserialize()); map_[key] = value; } catch (std::exception e) { // it doesn't deserialize to anything we know, so just store it // as a string - map_[key] = SerializablePtr(new SerializableString(stringValue)); + map_[key] = SerializableP(new SerializableBasic(stringValue)); } } } @@ -111,8 +111,8 @@ void Settings::loadFromFiles(const std::vector& filePaths, { Deserializer deserializer(*it, true); - SerializablePtr obj = deserializer.deserialize(); - std::map map; + SerializableP obj = deserializer.deserialize(); + Serializable::Map map; if (obj && obj->get(map)) { diff --git a/src/Moof/Settings.hh b/src/Moof/Settings.hh index faad547..653d456 100644 --- a/src/Moof/Settings.hh +++ b/src/Moof/Settings.hh @@ -64,18 +64,18 @@ public: bool getNumber(const std::string& key, T& value); private: - std::map map_; + Serializable::Map map_; }; template bool Settings::get(const std::string& key, T& value) { - std::map::const_iterator it = map_.find(key); + Serializable::Map::const_iterator it = map_.find(key); if (it != map_.end()) { - SerializablePtr obj = (*it).second; + SerializableP obj = (*it).second; return obj->get(value); } else @@ -87,11 +87,11 @@ bool Settings::get(const std::string& key, T& value) template bool Settings::getNumber(const std::string& key, T& value) { - std::map::const_iterator it = map_.find(key); + Serializable::Map::const_iterator it = map_.find(key); if (it != map_.end()) { - SerializablePtr obj = (*it).second; + SerializableP obj = (*it).second; return obj->getNumber(value); } else diff --git a/src/Moof/Sound.hh b/src/Moof/Sound.hh index bc669bc..3f64162 100644 --- a/src/Moof/Sound.hh +++ b/src/Moof/Sound.hh @@ -46,9 +46,24 @@ namespace Mf { +class Sound; +typedef boost::shared_ptr SoundP; + + class Sound : public Resource { +protected: + Sound() {} + class Impl; + boost::shared_ptr impl_; + public: + + static SoundP alloc(const std::string& name) + { + return SoundP(new Sound(name)); + } + Sound(const std::string& name); void play(); @@ -59,6 +74,7 @@ public: static std::string getPath(const std::string& name); + struct Exception : public Mf::Exception { enum @@ -84,11 +100,6 @@ public: return Mf::Exception::what(); } }; - -protected: - Sound() {} - class Impl; - boost::shared_ptr impl_; }; diff --git a/src/Moof/Texture.hh b/src/Moof/Texture.hh index d55f6f7..5710298 100644 --- a/src/Moof/Texture.hh +++ b/src/Moof/Texture.hh @@ -46,9 +46,22 @@ namespace Mf { +class Texture; +typedef boost::shared_ptr TextureP; + + class Texture : public Resource { + class Impl; + boost::shared_ptr impl_; + public: + + static TextureP alloc(const std::string& name) + { + return TextureP(new Texture(name)); + } + Texture(const std::string& name); void bind() const; @@ -66,6 +79,7 @@ public: static std::string getPath(const std::string& name); + struct Exception : public Mf::Exception { enum @@ -86,15 +100,11 @@ public: switch (code) { case BAD_IMAGE_FORMAT: - return "inappropriate image format"; + return "unknown image format"; } return Mf::Exception::what(); } }; - -private: - class Impl; - boost::shared_ptr impl_; }; diff --git a/src/Moof/Tilemap.cc b/src/Moof/Tilemap.cc index 85c117e..4fe5e97 100644 --- a/src/Moof/Tilemap.cc +++ b/src/Moof/Tilemap.cc @@ -91,15 +91,15 @@ public: { Deserializer deserializer(Tilemap::getPath(getName())); - SerializablePtr root = deserializer.deserialize(); + SerializableP root = deserializer.deserialize(); if (root) { - std::map rootObj; + Serializable::Map rootObj; if (root->get(rootObj)) { - std::map::iterator it; + Serializable::Map::iterator it; if ((it = rootObj.find("tiles_s")) != rootObj.end()) { diff --git a/src/Moof/Video.cc b/src/Moof/Video.cc index 0452c97..63970e4 100644 --- a/src/Moof/Video.cc +++ b/src/Moof/Video.cc @@ -311,7 +311,7 @@ Video::Attributes::Attributes() Settings& settings = Settings::getInstance(); - std::vector colors; + Serializable::Array colors; settings.get("video.colorbuffers", colors); if (colors.size() > 0) colors[0]->get(colorBuffer[0]); if (colors.size() > 1) colors[1]->get(colorBuffer[1]); @@ -323,7 +323,7 @@ Video::Attributes::Attributes() settings.get("video.depthbuffer", depthBuffer); settings.get("video.stencilbuffer", stencilBuffer); - std::vector accum; + Serializable::Array accum; settings.get("video.accumbuffers", accum); if (accum.size() > 0) accum[0]->get(accumBuffer[0]); if (accum.size() > 1) accum[1]->get(accumBuffer[1]); @@ -342,7 +342,7 @@ Video::Attributes::Attributes() } settings.get("video.icon", icon); - std::vector dimensions; + Serializable::Array dimensions; settings.get("video.mode", dimensions); if (dimensions.size() > 0) dimensions[0]->get(mode[0]); if (dimensions.size() > 1) dimensions[1]->get(mode[1]); diff --git a/src/Moof/Video.hh b/src/Moof/Video.hh index bb1fdd4..4be691d 100644 --- a/src/Moof/Video.hh +++ b/src/Moof/Video.hh @@ -39,9 +39,12 @@ namespace Mf { -class Video +class Video; +typedef boost::shared_ptr