Browse Source

Normalize line endings

seanpaultaylor 12 years ago
parent
commit
cf89aed02c
69 changed files with 13175 additions and 13175 deletions
  1. 621 621
      tools/encoder/src/GPBFile.cpp
  2. 171 171
      tools/encoder/src/GPBFile.h
  3. 42 42
      tools/encoder/src/Glyph.cpp
  4. 34 34
      tools/encoder/src/Glyph.h
  5. 39 39
      tools/encoder/src/MaterialParameter.cpp
  6. 35 35
      tools/encoder/src/MaterialParameter.h
  7. 407 407
      tools/encoder/src/Matrix.cpp
  8. 169 169
      tools/encoder/src/Matrix.h
  9. 233 233
      tools/encoder/src/Mesh.cpp
  10. 81 81
      tools/encoder/src/Mesh.h
  11. 114 114
      tools/encoder/src/MeshPart.cpp
  12. 97 97
      tools/encoder/src/MeshPart.h
  13. 450 450
      tools/encoder/src/MeshSkin.cpp
  14. 77 77
      tools/encoder/src/MeshSkin.h
  15. 39 39
      tools/encoder/src/MeshSubSet.cpp
  16. 31 31
      tools/encoder/src/MeshSubSet.h
  17. 155 155
      tools/encoder/src/Model.cpp
  18. 47 47
      tools/encoder/src/Model.h
  19. 329 329
      tools/encoder/src/Node.cpp
  20. 193 193
      tools/encoder/src/Node.h
  21. 80 80
      tools/encoder/src/Object.cpp
  22. 151 151
      tools/encoder/src/Object.h
  23. 400 400
      tools/encoder/src/Quaternion.cpp
  24. 364 364
      tools/encoder/src/Quaternion.h
  25. 19 19
      tools/encoder/src/Quaternion.inl
  26. 87 87
      tools/encoder/src/Reference.cpp
  27. 57 57
      tools/encoder/src/Reference.h
  28. 69 69
      tools/encoder/src/ReferenceTable.cpp
  29. 58 58
      tools/encoder/src/ReferenceTable.h
  30. 82 82
      tools/encoder/src/Sampler.cpp
  31. 50 50
      tools/encoder/src/Sampler.h
  32. 124 124
      tools/encoder/src/Scene.cpp
  33. 78 78
      tools/encoder/src/Scene.h
  34. 131 131
      tools/encoder/src/StringUtil.cpp
  35. 38 38
      tools/encoder/src/StringUtil.h
  36. 487 487
      tools/encoder/src/TTFFontEncoder.cpp
  37. 34 34
      tools/encoder/src/TTFFontEncoder.h
  38. 69 69
      tools/encoder/src/Transform.cpp
  39. 69 69
      tools/encoder/src/Transform.h
  40. 271 271
      tools/encoder/src/Vector2.cpp
  41. 413 413
      tools/encoder/src/Vector2.h
  42. 77 77
      tools/encoder/src/Vector2.inl
  43. 318 318
      tools/encoder/src/Vector3.cpp
  44. 443 443
      tools/encoder/src/Vector3.h
  45. 82 82
      tools/encoder/src/Vector3.inl
  46. 330 330
      tools/encoder/src/Vector4.cpp
  47. 438 438
      tools/encoder/src/Vector4.h
  48. 89 89
      tools/encoder/src/Vector4.inl
  49. 125 125
      tools/encoder/src/Vertex.cpp
  50. 121 121
      tools/encoder/src/Vertex.h
  51. 76 76
      tools/encoder/src/VertexElement.cpp
  52. 35 35
      tools/encoder/src/VertexElement.h
  53. 170 170
      tools/encoder/src/main.cpp
  54. 20 20
      tools/luagen/gameplay-luagen.sln
  55. 47 47
      tools/luagen/gameplay-luagen.vcxproj.filters
  56. 12 12
      tools/luagen/gameplay-luagen.vcxproj.user
  57. 1 1
      tools/luagen/generate-doxygen-xml.bat
  58. 90 90
      tools/luagen/src/Base.h
  59. 297 297
      tools/luagen/src/ClassBinding.cpp
  60. 51 51
      tools/luagen/src/ClassBinding.h
  61. 302 302
      tools/luagen/src/DebugNew.cpp
  62. 50 50
      tools/luagen/src/DebugNew.h
  63. 16 16
      tools/luagen/src/EnumBinding.h
  64. 1032 1032
      tools/luagen/src/FunctionBinding.cpp
  65. 167 167
      tools/luagen/src/FunctionBinding.h
  66. 1985 1985
      tools/luagen/src/Generator.cpp
  67. 207 207
      tools/luagen/src/Generator.h
  68. 16 16
      tools/luagen/src/TypedefBinding.h
  69. 83 83
      tools/luagen/src/main.cpp

+ 621 - 621
tools/encoder/src/GPBFile.cpp

@@ -1,621 +1,621 @@
-#include "Base.h"
-#include "GPBFile.h"
-#include "Transform.h"
-#include "StringUtil.h"
-#include "EncoderArguments.h"
-#include "Heightmap.h"
-
-#define EPSILON 1.2e-7f;
-
-namespace gameplay
-{
-
-static GPBFile* __instance = NULL;
-
-/**
- * Returns true if the given value is close to one.
- */
-static bool isAlmostOne(float value);
-
-/**
- * Returns true if the given value is close to zero.
- */
-static bool isAlmostZero(float value);
-
-/**
- * Gets the common node ancestor for the given list of nodes.
- * This function assumes that the nodes share a common ancestor.
- * 
- * @param nodes The list of nodes.
- * 
- * @return The common node ancestor or NULL if the list of was empty.
- */
-static Node* getCommonNodeAncestor(const std::vector<Node*>& nodes);
-
-/**
- * Gets the list of node ancestors for the given node.
- * 
- * @param node The node to get the ancestors for.
- * @param ancestors The output list of ancestors. 
- *                  The first element is the root node and the last element is the direct parent of the node.
- */
-static void getNodeAncestors(Node* node, std::list<Node*>& ancestors);
-
-
-GPBFile::GPBFile(void)
-    : _file(NULL), _animationsAdded(false)
-{
-    __instance = this;
-}
-
-GPBFile::~GPBFile(void)
-{
-}
-
-GPBFile* GPBFile::getInstance()
-{
-    return __instance;
-}
-
-bool GPBFile::saveBinary(const std::string& filepath)
-{
-    _file = fopen(filepath.c_str(), "w+b");
-    if (!_file)
-    {
-        return false;
-    }
-    size_t n = 0;
-
-    // identifier
-    char identifier[] = { '\xAB', 'G', 'P', 'B', '\xBB', '\r', '\n', '\x1A', '\n' };
-    n = fwrite(identifier, 1, sizeof(identifier), _file);
-    if (n != sizeof(identifier))
-    {
-        fclose(_file);
-        return false;
-    }
-
-    // version
-    n = fwrite(GPB_VERSION, 1, sizeof(GPB_VERSION), _file);
-    if (n != sizeof(GPB_VERSION))
-    {
-        fclose(_file);
-        return false;
-    }
-
-    // TODO: Check for errors on all file writing.
-
-    // write refs
-    _refTable.writeBinary(_file);
-
-    // meshes
-    write((unsigned int)_geometry.size(), _file);
-    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
-    {
-        (*i)->writeBinary(_file);
-    }
-
-    // Objects
-    write((unsigned int)_objects.size(), _file);
-    for (std::list<Object*>::const_iterator i = _objects.begin(); i != _objects.end(); ++i)
-    {
-        (*i)->writeBinary(_file);
-    }
-
-    _refTable.updateOffsets(_file);
-    
-    fclose(_file);
-    return true;
-}
-
-bool GPBFile::saveText(const std::string& filepath)
-{
-    _file = fopen(filepath.c_str(), "w");
-    if (!_file)
-    {
-        return false;
-    }
-
-    if (fprintf(_file, "<root>\n") <= 0)
-    {
-        fclose(_file);
-        return false;
-    }
-
-    // TODO: Check for errors on all file writing.
-
-    // write refs
-    _refTable.writeText(_file);
-
-    // meshes
-    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
-    {
-        (*i)->writeText(_file);
-    }
-
-    // Objects
-    for (std::list<Object*>::const_iterator i = _objects.begin(); i != _objects.end(); ++i)
-    {
-        (*i)->writeText(_file);
-    }
-
-    fprintf(_file, "</root>");
-
-    fclose(_file);
-    return true;
-}
-
-void GPBFile::add(Object* obj)
-{
-    _objects.push_back(obj);
-}
-
-void GPBFile::addScene(Scene* scene)
-{
-    addToRefTable(scene);
-    _objects.push_back(scene);
-}
-
-void GPBFile::addCamera(Camera* camera)
-{
-    addToRefTable(camera);
-    _cameras.push_back(camera);
-}
-
-void GPBFile::addLight(Light* light)
-{
-    addToRefTable(light);
-    _lights.push_back(light);
-}
-
-void GPBFile::addMesh(Mesh* mesh)
-{
-    addToRefTable(mesh);
-    _geometry.push_back(mesh);
-}
-
-void GPBFile::addNode(Node* node)
-{
-    addToRefTable(node);
-    _nodes.push_back(node);
-}
-
-void GPBFile::addScenelessNode(Node* node)
-{
-    addToRefTable(node);
-    _nodes.push_back(node);
-    // Nodes are normally written to file as part of a scene. 
-    // Nodes that don't belong to a scene need to be written on their own (outside a scene).
-    // That is why node is added to the list of objects here.
-    _objects.push_back(node);
-}
-
-void GPBFile::addAnimation(Animation* animation)
-{
-    _animations.add(animation);
-
-    if (!_animationsAdded)
-    {
-        // The animations container should only be added once and only if the file has at least one animation.
-        _animationsAdded = true;
-        addToRefTable(&_animations);
-        add(&_animations);
-    }
-}
-
-void GPBFile::addToRefTable(Object* obj)
-{
-    if (obj)
-    {
-        const std::string& id = obj->getId();
-        if (id.length() > 0)
-        {
-            if (_refTable.get(id) == NULL)
-            {
-                _refTable.add(id, obj);
-            }
-        }
-    }
-}
-
-Object* GPBFile::getFromRefTable(const std::string& id)
-{
-    return _refTable.get(id);
-}
-
-bool GPBFile::idExists(const std::string& id)
-{
-    return _refTable.get(id) != NULL;
-}
-
-Camera* GPBFile::getCamera(const char* id)
-{
-    if (!id)
-        return NULL;
-    // TODO: O(n) search is not ideal
-    for (std::list<Camera*>::const_iterator i = _cameras.begin(); i != _cameras.end(); ++i)
-    {
-        const std::string& _id = (*i)->getId();
-        if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
-        {
-            return *i;
-        }
-    }
-    return NULL;
-}
-
-Light* GPBFile::getLight(const char* id)
-{
-    if (!id)
-        return NULL;
-    // TODO: O(n) search is not ideal
-    for (std::list<Light*>::const_iterator i = _lights.begin(); i != _lights.end(); ++i)
-    {
-        const std::string& _id = (*i)->getId();
-        if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
-        {
-            return *i;
-        }
-    }
-    return NULL;
-}
-
-Mesh* GPBFile::getMesh(const char* id)
-{
-    if (!id)
-        return NULL;
-    // TODO: O(n) search is not ideal
-    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
-    {
-        const std::string& _id = (*i)->getId();
-        if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
-        {
-            return *i;
-        }
-    }
-    return NULL;
-}
-
-Node* GPBFile::getNode(const char* id)
-{
-    if (!id)
-        return NULL;
-    // TODO: O(n) search is not ideal
-    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
-    {
-        const std::string& _id = (*i)->getId();
-        if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
-        {
-            return *i;
-        }
-    }
-    return NULL;
-}
-
-Animations* GPBFile::getAnimations()
-{
-    return &_animations;
-}
-
-unsigned int GPBFile::getLightCount() const
-{
-    return (unsigned int)_lights.size();
-}
-
-void GPBFile::adjust()
-{
-    // calculate the ambient color for each scene
-    for (std::list<Object*>::iterator i = _objects.begin(); i != _objects.end(); ++i)
-    {
-        Object* obj = *i;
-        if (obj->getTypeId() == Object::SCENE_ID)
-        {
-            Scene* scene = dynamic_cast<Scene*>(obj);
-            scene->calcAmbientColor();
-        }
-    }
-
-    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
-    {
-        computeBounds(*i);
-    }
-
-    if (EncoderArguments::getInstance()->optimizeAnimationsEnabled())
-    {
-        LOG(1, "Optimizing animations.\n");
-        optimizeAnimations();
-    }
-
-    // TODO:
-    // remove ambient _lights
-    // for each node
-    //   if node has ambient light
-    //     if node has no camera, mesh or children but 1 ambient light
-    //       delete node and remove from ref table
-    //     delete light and remove from ref table
-    //
-    // merge animations if possible
-    //   Search for animations that have the same target and key times and see if they can be merged.
-    //   Blender will output a simple translation animation to 3 separate animations with the same key times but targeting X, Y and Z.
-    //   This can be merged into one animation. Same for scale animations.
-
-    // Generate heightmaps
-    const std::vector<EncoderArguments::HeightmapOption>& heightmaps = EncoderArguments::getInstance()->getHeightmapOptions();
-    for (unsigned int i = 0, count = heightmaps.size(); i < count; ++i)
-    {
-        Heightmap::generate(heightmaps[i].nodeIds, heightmaps[i].width, heightmaps[i].height, heightmaps[i].filename.c_str(), heightmaps[i].isHighPrecision);
-    }
-}
-
-void GPBFile::groupMeshSkinAnimations()
-{
-    for (std::list<Node*>::iterator it = _nodes.begin(); it != _nodes.end(); ++it)
-    {
-        if (Model* model = (*it)->getModel())
-        {
-            if (MeshSkin* skin = model->getSkin())
-            {
-                const std::vector<Node*>& joints = skin->getJoints();
-                Node* commonAncestor = getCommonNodeAncestor(joints);
-                if (commonAncestor)
-                {
-                    // group the animation channels that target this common ancestor and its child nodes
-                    Animation* animation = new Animation();
-                    animation->setId("animations");
-
-                    moveAnimationChannels(commonAncestor, animation);
-                    _animations.add(animation);
-                }
-            }
-        }
-    }
-}
-
-void GPBFile::renameAnimations(std::vector<std::string>& animationIds, const char* newId)
-{
-    const unsigned int animationCount = _animations.getAnimationCount();
-    for (unsigned int animationIndex = 0; animationIndex < animationCount; ++animationIndex)
-    {
-        Animation* animation = _animations.getAnimation(animationIndex);
-        assert(animation);
-        std::vector<std::string>::const_iterator it = find(animationIds.begin(), animationIds.end(), animation->getId());
-        if (it != animationIds.end())
-        {
-            animation->setId(newId);
-        }
-    }
-}
-
-void GPBFile::computeBounds(Node* node)
-{
-    assert(node);
-    if (Model* model = node->getModel())
-    {
-        if (Mesh* mesh = model->getMesh())
-        {
-            mesh->computeBounds();
-        }
-    }
-}
-
-void GPBFile::optimizeAnimations()
-{
-    const unsigned int animationCount = _animations.getAnimationCount();
-    for (unsigned int animationIndex = 0; animationIndex < animationCount; ++animationIndex)
-    {
-        Animation* animation = _animations.getAnimation(animationIndex);
-        assert(animation);
-
-        const int channelCount = animation->getAnimationChannelCount();
-
-        LOG(2, "Optimizing %d channel(s) in animation '%s'.\n", channelCount, animation->getId().c_str());
-
-        // loop backwards because we will be adding and removing channels
-        for (int channelIndex = channelCount -1; channelIndex >= 0 ; --channelIndex)
-        {
-            AnimationChannel* channel = animation->getAnimationChannel(channelIndex);
-            assert(channel);
-
-            // Optimize node animation channels
-            const Object* obj = _refTable.get(channel->getTargetId());
-            if (obj && obj->getTypeId() == Object::NODE_ID)
-            {
-                if (channel->getTargetAttribute() == Transform::ANIMATE_SCALE_ROTATE_TRANSLATE)
-                {
-                    decomposeTransformAnimationChannel(animation, channel, channelIndex);
-
-                    animation->remove(channel);
-                    SAFE_DELETE(channel);
-                }
-            }
-        }
-    }
-}
-
-void GPBFile::decomposeTransformAnimationChannel(Animation* animation, AnimationChannel* channel, int channelIndex)
-{
-    LOG(2, "  Optimizing animaton channel %s:%d.\n", animation->getId().c_str(), channelIndex+1);
-
-    const std::vector<float>& keyTimes = channel->getKeyTimes();
-    const std::vector<float>& keyValues = channel->getKeyValues();
-    const size_t keyTimesSize = keyTimes.size();
-    const size_t keyValuesSize = keyValues.size();
-
-    std::vector<float> scaleKeyValues;
-    std::vector<float> rotateKeyValues;
-    std::vector<float> translateKeyValues;
-
-    scaleKeyValues.reserve(keyTimesSize * 3);
-    rotateKeyValues.reserve(keyTimesSize * 4);
-    translateKeyValues.reserve(keyTimesSize * 3);
-
-    for (size_t kv = 0; kv < keyValuesSize; kv += 10)
-    {
-        scaleKeyValues.push_back(keyValues[kv]);
-        scaleKeyValues.push_back(keyValues[kv+1]);
-        scaleKeyValues.push_back(keyValues[kv+2]);
-
-        rotateKeyValues.push_back(keyValues[kv+3]);
-        rotateKeyValues.push_back(keyValues[kv+4]);
-        rotateKeyValues.push_back(keyValues[kv+5]);
-        rotateKeyValues.push_back(keyValues[kv+6]);
-
-        translateKeyValues.push_back(keyValues[kv+7]);
-        translateKeyValues.push_back(keyValues[kv+8]);
-        translateKeyValues.push_back(keyValues[kv+9]);
-    }
-
-    // replace transform animation channel with translate, rotate and scale animation channels
-
-    // Don't add the scale channel if all the key values are close to 1.0
-    size_t oneCount = (size_t)std::count_if(scaleKeyValues.begin(), scaleKeyValues.end(), isAlmostOne);
-    if (scaleKeyValues.size() == oneCount)
-    {
-        LOG(2, "    Discarding scale channel.\n");
-    }
-    else
-    {
-        LOG(3, "    Keeping scale channel.\n");
-        AnimationChannel* scaleChannel = new AnimationChannel();
-        scaleChannel->setTargetId(channel->getTargetId());
-        scaleChannel->setKeyTimes(channel->getKeyTimes());
-        scaleChannel->setTangentsIn(channel->getTangentsIn());
-        scaleChannel->setTangentsOut(channel->getTangentsOut());
-        scaleChannel->setInterpolations(channel->getInterpolationTypes());
-        scaleChannel->setTargetAttribute(Transform::ANIMATE_SCALE);
-        scaleChannel->setKeyValues(scaleKeyValues);
-        scaleChannel->removeDuplicates();
-        animation->add(scaleChannel);
-    }
-
-    // Don't add the rotation channel if all quaternions are close to identity
-    oneCount = 0;
-    for (unsigned int i = 0, count = rotateKeyValues.size(); i < count; i += 4)
-    {
-        float x = rotateKeyValues[i];
-        float y = rotateKeyValues[i+1];
-        float z = rotateKeyValues[i+2];
-        float w = rotateKeyValues[i+3];
-        if (ISZERO(x) && ISZERO(y) && ISZERO(z) && ISONE(w))
-            ++oneCount;
-        else
-        {
-            LOG(4, "Rotation not identity: %u\n", i);
-            Quaternion q(x, y, z, w);
-            Vector3 axis;
-            float angle = q.toAxisAngle(&axis);
-            angle = 0;
-        }
-    }
-    if ((rotateKeyValues.size()>>2) == oneCount)
-    {
-        LOG(2, "    Discarding rotation channel.\n");
-    }
-    else
-    {
-        LOG(3, "    Keeping rotation channel.\n");
-        AnimationChannel* rotateChannel = new AnimationChannel();
-        rotateChannel->setTargetId(channel->getTargetId());
-        rotateChannel->setKeyTimes(channel->getKeyTimes());
-        rotateChannel->setTangentsIn(channel->getTangentsIn());
-        rotateChannel->setTangentsOut(channel->getTangentsOut());
-        rotateChannel->setInterpolations(channel->getInterpolationTypes());
-        rotateChannel->setTargetAttribute(Transform::ANIMATE_ROTATE);
-        rotateChannel->setKeyValues(rotateKeyValues);
-        rotateChannel->removeDuplicates();
-        animation->add(rotateChannel);
-    }
-
-    // Don't add the translation channel if all values are close to zero
-    oneCount = (size_t)std::count_if(translateKeyValues.begin(), translateKeyValues.end(), isAlmostZero);
-    if (translateKeyValues.size() == oneCount)
-    {
-        LOG(2, "    Discarding translation channel.\n");
-    }
-    else
-    {
-        LOG(3, "    Keeping translation channel.\n");
-        AnimationChannel* translateChannel = new AnimationChannel();
-        translateChannel->setTargetId(channel->getTargetId());
-        translateChannel->setKeyTimes(channel->getKeyTimes());
-        translateChannel->setTangentsIn(channel->getTangentsIn());
-        translateChannel->setTangentsOut(channel->getTangentsOut());
-        translateChannel->setInterpolations(channel->getInterpolationTypes());
-        translateChannel->setTargetAttribute(Transform::ANIMATE_TRANSLATE);
-        translateChannel->setKeyValues(translateKeyValues);
-        translateChannel->removeDuplicates();
-        animation->add(translateChannel);
-    }
-}
-
-void GPBFile::moveAnimationChannels(Node* node, Animation* dstAnimation)
-{
-    // Loop through the animations and channels backwards because they will be removed when found.
-    int animationCount = _animations.getAnimationCount();
-    for (int i = animationCount - 1; i >= 0; --i)
-    {
-        Animation* animation = _animations.getAnimation(i);
-        int channelCount = animation->getAnimationChannelCount();
-        for (int j = channelCount - 1; j >= 0; --j)
-        {
-            AnimationChannel* channel = animation->getAnimationChannel(j);
-            if (equals(channel->getTargetId(), node->getId()))
-            {
-                animation->remove(channel);
-                dstAnimation->add(channel);
-            }
-        }
-        if (animation->getAnimationChannelCount() == 0)
-        {
-            _animations.removeAnimation(i);
-        }
-    }
-    for (Node* child = node->getFirstChild(); child != NULL; child = child->getNextSibling())
-    {
-        moveAnimationChannels(child, dstAnimation);
-    }
-}
-
-bool isAlmostOne(float value)
-{
-    return (value - 1.0f) < EPSILON;
-}
-
-bool isAlmostZero(float value)
-{
-    return std::fabs(value) < EPSILON;
-}
-
-Node* getCommonNodeAncestor(const std::vector<Node*>& nodes)
-{
-    if (nodes.empty())
-        return NULL;
-    if (nodes.size() == 1)
-        return nodes.front();
-
-    std::list<Node*> ancestors;
-    size_t minAncestorCount = INT_MAX;
-    for (std::vector<Node*>::const_iterator it = nodes.begin(); it != nodes.end(); ++it)
-    {
-        Node* node = *it;
-        getNodeAncestors(node, ancestors);
-        ancestors.push_back(node);
-        minAncestorCount = std::min(minAncestorCount, ancestors.size());
-    }
-    ancestors.resize(minAncestorCount);
-
-    return ancestors.back();
-}
-
-void getNodeAncestors(Node* node, std::list<Node*>& ancestors)
-{
-    ancestors.clear();
-    Node* parent = node->getParent();
-    while (parent != NULL)
-    {
-        ancestors.push_front(parent);
-        parent = parent->getParent();
-    }
-}
-
-}
+#include "Base.h"
+#include "GPBFile.h"
+#include "Transform.h"
+#include "StringUtil.h"
+#include "EncoderArguments.h"
+#include "Heightmap.h"
+
+#define EPSILON 1.2e-7f;
+
+namespace gameplay
+{
+
+static GPBFile* __instance = NULL;
+
+/**
+ * Returns true if the given value is close to one.
+ */
+static bool isAlmostOne(float value);
+
+/**
+ * Returns true if the given value is close to zero.
+ */
+static bool isAlmostZero(float value);
+
+/**
+ * Gets the common node ancestor for the given list of nodes.
+ * This function assumes that the nodes share a common ancestor.
+ * 
+ * @param nodes The list of nodes.
+ * 
+ * @return The common node ancestor or NULL if the list of was empty.
+ */
+static Node* getCommonNodeAncestor(const std::vector<Node*>& nodes);
+
+/**
+ * Gets the list of node ancestors for the given node.
+ * 
+ * @param node The node to get the ancestors for.
+ * @param ancestors The output list of ancestors. 
+ *                  The first element is the root node and the last element is the direct parent of the node.
+ */
+static void getNodeAncestors(Node* node, std::list<Node*>& ancestors);
+
+
+GPBFile::GPBFile(void)
+    : _file(NULL), _animationsAdded(false)
+{
+    __instance = this;
+}
+
+GPBFile::~GPBFile(void)
+{
+}
+
+GPBFile* GPBFile::getInstance()
+{
+    return __instance;
+}
+
+bool GPBFile::saveBinary(const std::string& filepath)
+{
+    _file = fopen(filepath.c_str(), "w+b");
+    if (!_file)
+    {
+        return false;
+    }
+    size_t n = 0;
+
+    // identifier
+    char identifier[] = { '\xAB', 'G', 'P', 'B', '\xBB', '\r', '\n', '\x1A', '\n' };
+    n = fwrite(identifier, 1, sizeof(identifier), _file);
+    if (n != sizeof(identifier))
+    {
+        fclose(_file);
+        return false;
+    }
+
+    // version
+    n = fwrite(GPB_VERSION, 1, sizeof(GPB_VERSION), _file);
+    if (n != sizeof(GPB_VERSION))
+    {
+        fclose(_file);
+        return false;
+    }
+
+    // TODO: Check for errors on all file writing.
+
+    // write refs
+    _refTable.writeBinary(_file);
+
+    // meshes
+    write((unsigned int)_geometry.size(), _file);
+    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
+    {
+        (*i)->writeBinary(_file);
+    }
+
+    // Objects
+    write((unsigned int)_objects.size(), _file);
+    for (std::list<Object*>::const_iterator i = _objects.begin(); i != _objects.end(); ++i)
+    {
+        (*i)->writeBinary(_file);
+    }
+
+    _refTable.updateOffsets(_file);
+    
+    fclose(_file);
+    return true;
+}
+
+bool GPBFile::saveText(const std::string& filepath)
+{
+    _file = fopen(filepath.c_str(), "w");
+    if (!_file)
+    {
+        return false;
+    }
+
+    if (fprintf(_file, "<root>\n") <= 0)
+    {
+        fclose(_file);
+        return false;
+    }
+
+    // TODO: Check for errors on all file writing.
+
+    // write refs
+    _refTable.writeText(_file);
+
+    // meshes
+    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
+    {
+        (*i)->writeText(_file);
+    }
+
+    // Objects
+    for (std::list<Object*>::const_iterator i = _objects.begin(); i != _objects.end(); ++i)
+    {
+        (*i)->writeText(_file);
+    }
+
+    fprintf(_file, "</root>");
+
+    fclose(_file);
+    return true;
+}
+
+void GPBFile::add(Object* obj)
+{
+    _objects.push_back(obj);
+}
+
+void GPBFile::addScene(Scene* scene)
+{
+    addToRefTable(scene);
+    _objects.push_back(scene);
+}
+
+void GPBFile::addCamera(Camera* camera)
+{
+    addToRefTable(camera);
+    _cameras.push_back(camera);
+}
+
+void GPBFile::addLight(Light* light)
+{
+    addToRefTable(light);
+    _lights.push_back(light);
+}
+
+void GPBFile::addMesh(Mesh* mesh)
+{
+    addToRefTable(mesh);
+    _geometry.push_back(mesh);
+}
+
+void GPBFile::addNode(Node* node)
+{
+    addToRefTable(node);
+    _nodes.push_back(node);
+}
+
+void GPBFile::addScenelessNode(Node* node)
+{
+    addToRefTable(node);
+    _nodes.push_back(node);
+    // Nodes are normally written to file as part of a scene. 
+    // Nodes that don't belong to a scene need to be written on their own (outside a scene).
+    // That is why node is added to the list of objects here.
+    _objects.push_back(node);
+}
+
+void GPBFile::addAnimation(Animation* animation)
+{
+    _animations.add(animation);
+
+    if (!_animationsAdded)
+    {
+        // The animations container should only be added once and only if the file has at least one animation.
+        _animationsAdded = true;
+        addToRefTable(&_animations);
+        add(&_animations);
+    }
+}
+
+void GPBFile::addToRefTable(Object* obj)
+{
+    if (obj)
+    {
+        const std::string& id = obj->getId();
+        if (id.length() > 0)
+        {
+            if (_refTable.get(id) == NULL)
+            {
+                _refTable.add(id, obj);
+            }
+        }
+    }
+}
+
+Object* GPBFile::getFromRefTable(const std::string& id)
+{
+    return _refTable.get(id);
+}
+
+bool GPBFile::idExists(const std::string& id)
+{
+    return _refTable.get(id) != NULL;
+}
+
+Camera* GPBFile::getCamera(const char* id)
+{
+    if (!id)
+        return NULL;
+    // TODO: O(n) search is not ideal
+    for (std::list<Camera*>::const_iterator i = _cameras.begin(); i != _cameras.end(); ++i)
+    {
+        const std::string& _id = (*i)->getId();
+        if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
+        {
+            return *i;
+        }
+    }
+    return NULL;
+}
+
+Light* GPBFile::getLight(const char* id)
+{
+    if (!id)
+        return NULL;
+    // TODO: O(n) search is not ideal
+    for (std::list<Light*>::const_iterator i = _lights.begin(); i != _lights.end(); ++i)
+    {
+        const std::string& _id = (*i)->getId();
+        if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
+        {
+            return *i;
+        }
+    }
+    return NULL;
+}
+
+Mesh* GPBFile::getMesh(const char* id)
+{
+    if (!id)
+        return NULL;
+    // TODO: O(n) search is not ideal
+    for (std::list<Mesh*>::const_iterator i = _geometry.begin(); i != _geometry.end(); ++i)
+    {
+        const std::string& _id = (*i)->getId();
+        if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
+        {
+            return *i;
+        }
+    }
+    return NULL;
+}
+
+Node* GPBFile::getNode(const char* id)
+{
+    if (!id)
+        return NULL;
+    // TODO: O(n) search is not ideal
+    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
+    {
+        const std::string& _id = (*i)->getId();
+        if (_id.length() > 0 && strncmp(id, _id.c_str(), 255) == 0)
+        {
+            return *i;
+        }
+    }
+    return NULL;
+}
+
+Animations* GPBFile::getAnimations()
+{
+    return &_animations;
+}
+
+unsigned int GPBFile::getLightCount() const
+{
+    return (unsigned int)_lights.size();
+}
+
+void GPBFile::adjust()
+{
+    // calculate the ambient color for each scene
+    for (std::list<Object*>::iterator i = _objects.begin(); i != _objects.end(); ++i)
+    {
+        Object* obj = *i;
+        if (obj->getTypeId() == Object::SCENE_ID)
+        {
+            Scene* scene = dynamic_cast<Scene*>(obj);
+            scene->calcAmbientColor();
+        }
+    }
+
+    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
+    {
+        computeBounds(*i);
+    }
+
+    if (EncoderArguments::getInstance()->optimizeAnimationsEnabled())
+    {
+        LOG(1, "Optimizing animations.\n");
+        optimizeAnimations();
+    }
+
+    // TODO:
+    // remove ambient _lights
+    // for each node
+    //   if node has ambient light
+    //     if node has no camera, mesh or children but 1 ambient light
+    //       delete node and remove from ref table
+    //     delete light and remove from ref table
+    //
+    // merge animations if possible
+    //   Search for animations that have the same target and key times and see if they can be merged.
+    //   Blender will output a simple translation animation to 3 separate animations with the same key times but targeting X, Y and Z.
+    //   This can be merged into one animation. Same for scale animations.
+
+    // Generate heightmaps
+    const std::vector<EncoderArguments::HeightmapOption>& heightmaps = EncoderArguments::getInstance()->getHeightmapOptions();
+    for (unsigned int i = 0, count = heightmaps.size(); i < count; ++i)
+    {
+        Heightmap::generate(heightmaps[i].nodeIds, heightmaps[i].width, heightmaps[i].height, heightmaps[i].filename.c_str(), heightmaps[i].isHighPrecision);
+    }
+}
+
+void GPBFile::groupMeshSkinAnimations()
+{
+    for (std::list<Node*>::iterator it = _nodes.begin(); it != _nodes.end(); ++it)
+    {
+        if (Model* model = (*it)->getModel())
+        {
+            if (MeshSkin* skin = model->getSkin())
+            {
+                const std::vector<Node*>& joints = skin->getJoints();
+                Node* commonAncestor = getCommonNodeAncestor(joints);
+                if (commonAncestor)
+                {
+                    // group the animation channels that target this common ancestor and its child nodes
+                    Animation* animation = new Animation();
+                    animation->setId("animations");
+
+                    moveAnimationChannels(commonAncestor, animation);
+                    _animations.add(animation);
+                }
+            }
+        }
+    }
+}
+
+void GPBFile::renameAnimations(std::vector<std::string>& animationIds, const char* newId)
+{
+    const unsigned int animationCount = _animations.getAnimationCount();
+    for (unsigned int animationIndex = 0; animationIndex < animationCount; ++animationIndex)
+    {
+        Animation* animation = _animations.getAnimation(animationIndex);
+        assert(animation);
+        std::vector<std::string>::const_iterator it = find(animationIds.begin(), animationIds.end(), animation->getId());
+        if (it != animationIds.end())
+        {
+            animation->setId(newId);
+        }
+    }
+}
+
+void GPBFile::computeBounds(Node* node)
+{
+    assert(node);
+    if (Model* model = node->getModel())
+    {
+        if (Mesh* mesh = model->getMesh())
+        {
+            mesh->computeBounds();
+        }
+    }
+}
+
+void GPBFile::optimizeAnimations()
+{
+    const unsigned int animationCount = _animations.getAnimationCount();
+    for (unsigned int animationIndex = 0; animationIndex < animationCount; ++animationIndex)
+    {
+        Animation* animation = _animations.getAnimation(animationIndex);
+        assert(animation);
+
+        const int channelCount = animation->getAnimationChannelCount();
+
+        LOG(2, "Optimizing %d channel(s) in animation '%s'.\n", channelCount, animation->getId().c_str());
+
+        // loop backwards because we will be adding and removing channels
+        for (int channelIndex = channelCount -1; channelIndex >= 0 ; --channelIndex)
+        {
+            AnimationChannel* channel = animation->getAnimationChannel(channelIndex);
+            assert(channel);
+
+            // Optimize node animation channels
+            const Object* obj = _refTable.get(channel->getTargetId());
+            if (obj && obj->getTypeId() == Object::NODE_ID)
+            {
+                if (channel->getTargetAttribute() == Transform::ANIMATE_SCALE_ROTATE_TRANSLATE)
+                {
+                    decomposeTransformAnimationChannel(animation, channel, channelIndex);
+
+                    animation->remove(channel);
+                    SAFE_DELETE(channel);
+                }
+            }
+        }
+    }
+}
+
+void GPBFile::decomposeTransformAnimationChannel(Animation* animation, AnimationChannel* channel, int channelIndex)
+{
+    LOG(2, "  Optimizing animaton channel %s:%d.\n", animation->getId().c_str(), channelIndex+1);
+
+    const std::vector<float>& keyTimes = channel->getKeyTimes();
+    const std::vector<float>& keyValues = channel->getKeyValues();
+    const size_t keyTimesSize = keyTimes.size();
+    const size_t keyValuesSize = keyValues.size();
+
+    std::vector<float> scaleKeyValues;
+    std::vector<float> rotateKeyValues;
+    std::vector<float> translateKeyValues;
+
+    scaleKeyValues.reserve(keyTimesSize * 3);
+    rotateKeyValues.reserve(keyTimesSize * 4);
+    translateKeyValues.reserve(keyTimesSize * 3);
+
+    for (size_t kv = 0; kv < keyValuesSize; kv += 10)
+    {
+        scaleKeyValues.push_back(keyValues[kv]);
+        scaleKeyValues.push_back(keyValues[kv+1]);
+        scaleKeyValues.push_back(keyValues[kv+2]);
+
+        rotateKeyValues.push_back(keyValues[kv+3]);
+        rotateKeyValues.push_back(keyValues[kv+4]);
+        rotateKeyValues.push_back(keyValues[kv+5]);
+        rotateKeyValues.push_back(keyValues[kv+6]);
+
+        translateKeyValues.push_back(keyValues[kv+7]);
+        translateKeyValues.push_back(keyValues[kv+8]);
+        translateKeyValues.push_back(keyValues[kv+9]);
+    }
+
+    // replace transform animation channel with translate, rotate and scale animation channels
+
+    // Don't add the scale channel if all the key values are close to 1.0
+    size_t oneCount = (size_t)std::count_if(scaleKeyValues.begin(), scaleKeyValues.end(), isAlmostOne);
+    if (scaleKeyValues.size() == oneCount)
+    {
+        LOG(2, "    Discarding scale channel.\n");
+    }
+    else
+    {
+        LOG(3, "    Keeping scale channel.\n");
+        AnimationChannel* scaleChannel = new AnimationChannel();
+        scaleChannel->setTargetId(channel->getTargetId());
+        scaleChannel->setKeyTimes(channel->getKeyTimes());
+        scaleChannel->setTangentsIn(channel->getTangentsIn());
+        scaleChannel->setTangentsOut(channel->getTangentsOut());
+        scaleChannel->setInterpolations(channel->getInterpolationTypes());
+        scaleChannel->setTargetAttribute(Transform::ANIMATE_SCALE);
+        scaleChannel->setKeyValues(scaleKeyValues);
+        scaleChannel->removeDuplicates();
+        animation->add(scaleChannel);
+    }
+
+    // Don't add the rotation channel if all quaternions are close to identity
+    oneCount = 0;
+    for (unsigned int i = 0, count = rotateKeyValues.size(); i < count; i += 4)
+    {
+        float x = rotateKeyValues[i];
+        float y = rotateKeyValues[i+1];
+        float z = rotateKeyValues[i+2];
+        float w = rotateKeyValues[i+3];
+        if (ISZERO(x) && ISZERO(y) && ISZERO(z) && ISONE(w))
+            ++oneCount;
+        else
+        {
+            LOG(4, "Rotation not identity: %u\n", i);
+            Quaternion q(x, y, z, w);
+            Vector3 axis;
+            float angle = q.toAxisAngle(&axis);
+            angle = 0;
+        }
+    }
+    if ((rotateKeyValues.size()>>2) == oneCount)
+    {
+        LOG(2, "    Discarding rotation channel.\n");
+    }
+    else
+    {
+        LOG(3, "    Keeping rotation channel.\n");
+        AnimationChannel* rotateChannel = new AnimationChannel();
+        rotateChannel->setTargetId(channel->getTargetId());
+        rotateChannel->setKeyTimes(channel->getKeyTimes());
+        rotateChannel->setTangentsIn(channel->getTangentsIn());
+        rotateChannel->setTangentsOut(channel->getTangentsOut());
+        rotateChannel->setInterpolations(channel->getInterpolationTypes());
+        rotateChannel->setTargetAttribute(Transform::ANIMATE_ROTATE);
+        rotateChannel->setKeyValues(rotateKeyValues);
+        rotateChannel->removeDuplicates();
+        animation->add(rotateChannel);
+    }
+
+    // Don't add the translation channel if all values are close to zero
+    oneCount = (size_t)std::count_if(translateKeyValues.begin(), translateKeyValues.end(), isAlmostZero);
+    if (translateKeyValues.size() == oneCount)
+    {
+        LOG(2, "    Discarding translation channel.\n");
+    }
+    else
+    {
+        LOG(3, "    Keeping translation channel.\n");
+        AnimationChannel* translateChannel = new AnimationChannel();
+        translateChannel->setTargetId(channel->getTargetId());
+        translateChannel->setKeyTimes(channel->getKeyTimes());
+        translateChannel->setTangentsIn(channel->getTangentsIn());
+        translateChannel->setTangentsOut(channel->getTangentsOut());
+        translateChannel->setInterpolations(channel->getInterpolationTypes());
+        translateChannel->setTargetAttribute(Transform::ANIMATE_TRANSLATE);
+        translateChannel->setKeyValues(translateKeyValues);
+        translateChannel->removeDuplicates();
+        animation->add(translateChannel);
+    }
+}
+
+void GPBFile::moveAnimationChannels(Node* node, Animation* dstAnimation)
+{
+    // Loop through the animations and channels backwards because they will be removed when found.
+    int animationCount = _animations.getAnimationCount();
+    for (int i = animationCount - 1; i >= 0; --i)
+    {
+        Animation* animation = _animations.getAnimation(i);
+        int channelCount = animation->getAnimationChannelCount();
+        for (int j = channelCount - 1; j >= 0; --j)
+        {
+            AnimationChannel* channel = animation->getAnimationChannel(j);
+            if (equals(channel->getTargetId(), node->getId()))
+            {
+                animation->remove(channel);
+                dstAnimation->add(channel);
+            }
+        }
+        if (animation->getAnimationChannelCount() == 0)
+        {
+            _animations.removeAnimation(i);
+        }
+    }
+    for (Node* child = node->getFirstChild(); child != NULL; child = child->getNextSibling())
+    {
+        moveAnimationChannels(child, dstAnimation);
+    }
+}
+
+bool isAlmostOne(float value)
+{
+    return (value - 1.0f) < EPSILON;
+}
+
+bool isAlmostZero(float value)
+{
+    return std::fabs(value) < EPSILON;
+}
+
+Node* getCommonNodeAncestor(const std::vector<Node*>& nodes)
+{
+    if (nodes.empty())
+        return NULL;
+    if (nodes.size() == 1)
+        return nodes.front();
+
+    std::list<Node*> ancestors;
+    size_t minAncestorCount = INT_MAX;
+    for (std::vector<Node*>::const_iterator it = nodes.begin(); it != nodes.end(); ++it)
+    {
+        Node* node = *it;
+        getNodeAncestors(node, ancestors);
+        ancestors.push_back(node);
+        minAncestorCount = std::min(minAncestorCount, ancestors.size());
+    }
+    ancestors.resize(minAncestorCount);
+
+    return ancestors.back();
+}
+
+void getNodeAncestors(Node* node, std::list<Node*>& ancestors)
+{
+    ancestors.clear();
+    Node* parent = node->getParent();
+    while (parent != NULL)
+    {
+        ancestors.push_front(parent);
+        parent = parent->getParent();
+    }
+}
+
+}

+ 171 - 171
tools/encoder/src/GPBFile.h

@@ -1,171 +1,171 @@
-#ifndef GPBFILE_H_
-#define GPBFILE_H_
-
-#include "FileIO.h"
-#include "Object.h"
-#include "Scene.h"
-#include "Node.h"
-#include "Camera.h"
-#include "Light.h"
-#include "Mesh.h"
-#include "Reference.h"
-#include "ReferenceTable.h"
-#include "Animations.h"
-#include "Animation.h"
-#include "AnimationChannel.h"
-
-namespace gameplay
-{
-
-/**
- * Increment the version number when making a change that break binary compatibility.
- * [0] is major, [1] is minor.
- */
-const unsigned char GPB_VERSION[2] = {1, 4};
-
-/**
- * The GamePlay Binary file class handles writing the GamePlay Binary file.
- */
-class GPBFile
-{
-public:
-
-    /**
-     * Constructor.
-     */
-    GPBFile(void);
-
-    /**
-     * Destructor.
-     */
-    ~GPBFile(void);
-
-    /**
-     * Returns the GPBFile instance.
-     */
-    static GPBFile* getInstance();
-
-    /**
-     * Saves the GPBFile as a binary file at filepath.
-     *
-     * @param filepath The file name and path to save to.
-     * 
-     * @return True if successful, false if error.
-     */
-    bool saveBinary(const std::string& filepath);
-
-    /**
-     * Saves the GPBFile as a text file at filepath. Useful for debugging.
-     *
-     * @param filepath The file name and path to save to.
-     * 
-     * @return True if successful, false if error.
-     */
-    bool saveText(const std::string& filepath);
-    
-    void add(Object* obj);
-    void addScene(Scene* scene);
-    void addCamera(Camera* camera);
-    void addLight(Light* light);
-    void addMesh(Mesh* mesh);
-    void addNode(Node* node);
-    /**
-     * Adds a node that does not belong to a scene.
-     */
-    void addScenelessNode(Node* node);
-    void addAnimation(Animation* animation);
-
-    /**
-     * Adds the given object to the ref table.
-     */
-    void addToRefTable(Object* obj);
-
-    /**
-     * Returns the object with the given id. Returns NULL if not found.
-     */
-    Object* getFromRefTable(const std::string& id);
-
-    /**
-    * Returns true if the id was found in the ref table.
-    */
-    bool idExists(const std::string& id);
-
-    Camera* getCamera(const char* id);
-    Light* getLight(const char* id);
-    Mesh* getMesh(const char* id);
-    Node* getNode(const char* id);
-
-    Animations* getAnimations();
-
-    /**
-     * Returns the number of lights.
-     */
-    unsigned int getLightCount() const;
-
-    /**
-     * Adjusts the game play binary file before it is written.
-     */
-    void adjust();
-
-    /**
-     * Groups the animations of all mesh skins to be under one animation per mesh skin.
-     */
-    void groupMeshSkinAnimations();
-
-    /**
-     * Renames the animations in the list of animation ids to the new animation id.
-     * 
-     * @param animationIds The list of animations to rename.
-     * @param newId The new animation id.
-     */
-    void renameAnimations(std::vector<std::string>& animationIds, const char* newId);
-
-private:
-
-    /**
-     * Computes the bounds of all meshes in the node hierarchy.
-     */
-    void computeBounds(Node* node);
-
-    /**
-     * Optimizes animation data by removing unneccessary channels and keyframes.
-     */
-    void optimizeAnimations();
-
-    /**
-     * Decomposes an ANIMATE_SCALE_ROTATE_TRANSLATE channel into 3 new channels. (Scale, Rotate and Translate)
-     * 
-     * @param animation The animation that the channel belongs to.
-     * @param channel The animation channel to decompose.
-     * @param channelIndex Index of the channel.
-     */
-    void decomposeTransformAnimationChannel(Animation* animation, AnimationChannel* channel, int channelIndex);
-
-    /**
-     * Moves the animation channels that target the given node and its children to be under the given animation.
-     * 
-     * @param node The node to recursively search from.
-     * @param animation The animation to move the channels to.
-     */
-    void moveAnimationChannels(Node* node, Animation* animation);
-
-private:
-
-    FILE* _file;
-    std::list<Object*> _objects;
-    std::list<Camera*> _cameras;
-    std::list<Light*> _lights;
-    std::list<Mesh*> _geometry;
-    /**
-     * The flat list of all nodes.
-     */
-    std::list<Node*> _nodes;
-    Animations _animations;
-    bool _animationsAdded;
-
-    ReferenceTable _refTable;
-};
-
-}
-
-#endif
+#ifndef GPBFILE_H_
+#define GPBFILE_H_
+
+#include "FileIO.h"
+#include "Object.h"
+#include "Scene.h"
+#include "Node.h"
+#include "Camera.h"
+#include "Light.h"
+#include "Mesh.h"
+#include "Reference.h"
+#include "ReferenceTable.h"
+#include "Animations.h"
+#include "Animation.h"
+#include "AnimationChannel.h"
+
+namespace gameplay
+{
+
+/**
+ * Increment the version number when making a change that break binary compatibility.
+ * [0] is major, [1] is minor.
+ */
+const unsigned char GPB_VERSION[2] = {1, 4};
+
+/**
+ * The GamePlay Binary file class handles writing the GamePlay Binary file.
+ */
+class GPBFile
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    GPBFile(void);
+
+    /**
+     * Destructor.
+     */
+    ~GPBFile(void);
+
+    /**
+     * Returns the GPBFile instance.
+     */
+    static GPBFile* getInstance();
+
+    /**
+     * Saves the GPBFile as a binary file at filepath.
+     *
+     * @param filepath The file name and path to save to.
+     * 
+     * @return True if successful, false if error.
+     */
+    bool saveBinary(const std::string& filepath);
+
+    /**
+     * Saves the GPBFile as a text file at filepath. Useful for debugging.
+     *
+     * @param filepath The file name and path to save to.
+     * 
+     * @return True if successful, false if error.
+     */
+    bool saveText(const std::string& filepath);
+    
+    void add(Object* obj);
+    void addScene(Scene* scene);
+    void addCamera(Camera* camera);
+    void addLight(Light* light);
+    void addMesh(Mesh* mesh);
+    void addNode(Node* node);
+    /**
+     * Adds a node that does not belong to a scene.
+     */
+    void addScenelessNode(Node* node);
+    void addAnimation(Animation* animation);
+
+    /**
+     * Adds the given object to the ref table.
+     */
+    void addToRefTable(Object* obj);
+
+    /**
+     * Returns the object with the given id. Returns NULL if not found.
+     */
+    Object* getFromRefTable(const std::string& id);
+
+    /**
+    * Returns true if the id was found in the ref table.
+    */
+    bool idExists(const std::string& id);
+
+    Camera* getCamera(const char* id);
+    Light* getLight(const char* id);
+    Mesh* getMesh(const char* id);
+    Node* getNode(const char* id);
+
+    Animations* getAnimations();
+
+    /**
+     * Returns the number of lights.
+     */
+    unsigned int getLightCount() const;
+
+    /**
+     * Adjusts the game play binary file before it is written.
+     */
+    void adjust();
+
+    /**
+     * Groups the animations of all mesh skins to be under one animation per mesh skin.
+     */
+    void groupMeshSkinAnimations();
+
+    /**
+     * Renames the animations in the list of animation ids to the new animation id.
+     * 
+     * @param animationIds The list of animations to rename.
+     * @param newId The new animation id.
+     */
+    void renameAnimations(std::vector<std::string>& animationIds, const char* newId);
+
+private:
+
+    /**
+     * Computes the bounds of all meshes in the node hierarchy.
+     */
+    void computeBounds(Node* node);
+
+    /**
+     * Optimizes animation data by removing unneccessary channels and keyframes.
+     */
+    void optimizeAnimations();
+
+    /**
+     * Decomposes an ANIMATE_SCALE_ROTATE_TRANSLATE channel into 3 new channels. (Scale, Rotate and Translate)
+     * 
+     * @param animation The animation that the channel belongs to.
+     * @param channel The animation channel to decompose.
+     * @param channelIndex Index of the channel.
+     */
+    void decomposeTransformAnimationChannel(Animation* animation, AnimationChannel* channel, int channelIndex);
+
+    /**
+     * Moves the animation channels that target the given node and its children to be under the given animation.
+     * 
+     * @param node The node to recursively search from.
+     * @param animation The animation to move the channels to.
+     */
+    void moveAnimationChannels(Node* node, Animation* animation);
+
+private:
+
+    FILE* _file;
+    std::list<Object*> _objects;
+    std::list<Camera*> _cameras;
+    std::list<Light*> _lights;
+    std::list<Mesh*> _geometry;
+    /**
+     * The flat list of all nodes.
+     */
+    std::list<Node*> _nodes;
+    Animations _animations;
+    bool _animationsAdded;
+
+    ReferenceTable _refTable;
+};
+
+}
+
+#endif

+ 42 - 42
tools/encoder/src/Glyph.cpp

@@ -1,42 +1,42 @@
-#include "Base.h"
-#include "Glyph.h"
-
-namespace gameplay
-{
-
-Glyph::Glyph(void) :
-    index(0),
-    width(0)
-{
-    fillArray(uvCoords, 0.0f, 4);
-}
-
-    Glyph::~Glyph(void)
-{
-}
-
-const char* Glyph::getElementName(void) const
-{
-    return "Glyph";
-}
-
-void Glyph::writeBinary(FILE* file)
-{
-    Object::writeBinary(file);
-
-    write(index, file);
-    write(width, file);
-    write(uvCoords, 4, file);
-
-}
-
-void Glyph::writeText(FILE* file)
-{
-    fprintElementStart(file);
-    fprintfElement(file, "index", index);
-    fprintfElement(file, "width", width);
-    fprintfElement(file, "uvCoords", uvCoords, 4);
-    fprintElementEnd(file);
-}
-
-}
+#include "Base.h"
+#include "Glyph.h"
+
+namespace gameplay
+{
+
+Glyph::Glyph(void) :
+    index(0),
+    width(0)
+{
+    fillArray(uvCoords, 0.0f, 4);
+}
+
+    Glyph::~Glyph(void)
+{
+}
+
+const char* Glyph::getElementName(void) const
+{
+    return "Glyph";
+}
+
+void Glyph::writeBinary(FILE* file)
+{
+    Object::writeBinary(file);
+
+    write(index, file);
+    write(width, file);
+    write(uvCoords, 4, file);
+
+}
+
+void Glyph::writeText(FILE* file)
+{
+    fprintElementStart(file);
+    fprintfElement(file, "index", index);
+    fprintfElement(file, "width", width);
+    fprintfElement(file, "uvCoords", uvCoords, 4);
+    fprintElementEnd(file);
+}
+
+}

+ 34 - 34
tools/encoder/src/Glyph.h

@@ -1,34 +1,34 @@
-#ifndef GLYPH_H_
-#define GLYPH_H_
-
-#include "Object.h"
-
-namespace gameplay
-{
-
-class Glyph : public Object
-{
-public:
-
-    /**
-     * Constructor.
-     */
-    Glyph(void);
-
-    /**
-     * Destructor.
-     */
-    virtual ~Glyph(void);
-
-    virtual const char* getElementName(void) const;
-    virtual void writeBinary(FILE* file);
-    virtual void writeText(FILE* file);
-
-    unsigned int index;
-    unsigned int width;
-    float uvCoords[4];
-};
-
-}
-
-#endif
+#ifndef GLYPH_H_
+#define GLYPH_H_
+
+#include "Object.h"
+
+namespace gameplay
+{
+
+class Glyph : public Object
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    Glyph(void);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Glyph(void);
+
+    virtual const char* getElementName(void) const;
+    virtual void writeBinary(FILE* file);
+    virtual void writeText(FILE* file);
+
+    unsigned int index;
+    unsigned int width;
+    float uvCoords[4];
+};
+
+}
+
+#endif

+ 39 - 39
tools/encoder/src/MaterialParameter.cpp

@@ -1,39 +1,39 @@
-#include "Base.h"
-#include "MaterialParameter.h"
-
-namespace gameplay
-{
-
-MaterialParameter::MaterialParameter(void) :
-    _type(0)
-{
-}
-
-MaterialParameter::~MaterialParameter(void)
-{
-}
-
-unsigned int MaterialParameter::getTypeId(void) const
-{
-    return MATERIAL_ID;
-}
-const char* MaterialParameter::getElementName(void) const
-{
-    return "MaterialParameter";
-}
-
-void MaterialParameter::writeBinary(FILE* file)
-{
-    Object::writeBinary(file);
-    write(_value, file);
-    write(_type, file);
-}
-void MaterialParameter::writeText(FILE* file)
-{
-    fprintElementStart(file);
-    fprintfElement(file, "%f ", "value", _value);
-    fprintfElement(file, "type", _type);
-    fprintElementEnd(file);
-}
-
-}
+#include "Base.h"
+#include "MaterialParameter.h"
+
+namespace gameplay
+{
+
+MaterialParameter::MaterialParameter(void) :
+    _type(0)
+{
+}
+
+MaterialParameter::~MaterialParameter(void)
+{
+}
+
+unsigned int MaterialParameter::getTypeId(void) const
+{
+    return MATERIAL_ID;
+}
+const char* MaterialParameter::getElementName(void) const
+{
+    return "MaterialParameter";
+}
+
+void MaterialParameter::writeBinary(FILE* file)
+{
+    Object::writeBinary(file);
+    write(_value, file);
+    write(_type, file);
+}
+void MaterialParameter::writeText(FILE* file)
+{
+    fprintElementStart(file);
+    fprintfElement(file, "%f ", "value", _value);
+    fprintfElement(file, "type", _type);
+    fprintElementEnd(file);
+}
+
+}

+ 35 - 35
tools/encoder/src/MaterialParameter.h

@@ -1,35 +1,35 @@
-#ifndef MATERIALPARAMETER_H_
-#define MATERIALPARAMETER_H_
-
-#include "Object.h"
-
-namespace gameplay
-{
-
-class MaterialParameter : public Object
-{
-public:
-
-    /**
-     * Constructor.
-     */
-    MaterialParameter(void);
-
-    /**
-     * Destructor.
-     */
-    virtual ~MaterialParameter(void);
-
-    virtual unsigned int getTypeId(void) const;
-    virtual const char* getElementName(void) const;
-    virtual void writeBinary(FILE* file);
-    virtual void writeText(FILE* file);
-
-private:
-    std::vector<float> _value;
-    unsigned int _type;
-};
-
-}
-
-#endif
+#ifndef MATERIALPARAMETER_H_
+#define MATERIALPARAMETER_H_
+
+#include "Object.h"
+
+namespace gameplay
+{
+
+class MaterialParameter : public Object
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    MaterialParameter(void);
+
+    /**
+     * Destructor.
+     */
+    virtual ~MaterialParameter(void);
+
+    virtual unsigned int getTypeId(void) const;
+    virtual const char* getElementName(void) const;
+    virtual void writeBinary(FILE* file);
+    virtual void writeText(FILE* file);
+
+private:
+    std::vector<float> _value;
+    unsigned int _type;
+};
+
+}
+
+#endif

+ 407 - 407
tools/encoder/src/Matrix.cpp

@@ -1,407 +1,407 @@
-#include "Base.h"
-#include "Matrix.h"
-
-namespace gameplay
-{
-
-Matrix::Matrix(void)
-{
-    setIdentity(m);
-}
-
-Matrix::Matrix(float m0, float m1, float m2, float m3,
-               float m4, float m5, float m6, float m7,
-               float m8, float m9, float m10, float m11,
-               float m12, float m13, float m14, float m15)
-{
-    m[0] = m0;
-    m[1] = m1;
-    m[2] = m2;
-    m[3] = m3;
-    m[4] = m4;
-    m[5] = m5;
-    m[6] = m6;
-    m[7] = m7;
-    m[8] = m8;
-    m[9] = m9;
-    m[10] = m10;
-    m[11] = m11;
-    m[12] = m12;
-    m[13] = m13;
-    m[14] = m14;
-    m[15] = m15;
-}
-
-Matrix::~Matrix(void)
-{
-}
-
-void Matrix::setIdentity(float* matrix)
-{
-    memcpy(matrix, MATRIX4F_IDENTITY, MATRIX4F_SIZE);
-}
-
-void Matrix::createRotation(const Quaternion& q, float* dst)
-{
-    assert(dst);
-
-    float x2 = q.x + q.x;
-    float y2 = q.y + q.y;
-    float z2 = q.z + q.z;
-
-    float xx2 = q.x * x2;
-    float yy2 = q.y * y2;
-    float zz2 = q.z * z2;
-    float xy2 = q.x * y2;
-    float xz2 = q.x * z2;
-    float yz2 = q.y * z2;
-    float wx2 = q.w * x2;
-    float wy2 = q.w * y2;
-    float wz2 = q.w * z2;
-
-    dst[0] = 1.0f - yy2 - zz2;
-    dst[1] = xy2 + wz2;
-    dst[2] = xz2 - wy2;
-    dst[3] = 0.0f;
-
-    dst[4] = xy2 - wz2;
-    dst[5] = 1.0f - xx2 - zz2;
-    dst[6] = yz2 + wx2;
-    dst[7] = 0.0f;
-
-    dst[8] = xz2 + wy2;
-    dst[9] = yz2 - wx2;
-    dst[10] = 1.0f - xx2 - yy2;
-    dst[11] = 0.0f;
-
-    dst[12] = 0.0f;
-    dst[13] = 0.0f;
-    dst[14] = 0.0f;
-    dst[15] = 1.0f;
-}
-
-void Matrix::createRotation(float x, float y, float z, float angle, float* dst)
-{
-    // Make sure the input axis is normalized
-    float n = x*x + y*y + z*z;
-    if (n != 1.0f)
-    {
-        // Not normalized
-        n = sqrt(n);
-        if (n > 0.000001f) // prevent divide too close to zero
-        {
-            n = 1.0f / n;
-            x *= n;
-            y *= n;
-            z *= n;
-        }
-    }
-
-    float c = cos(angle);
-    float s = sin(angle);
-
-    float t = 1.0f - c;
-    float tx = t * x;
-    float ty = t * y;
-    float tz = t * z;
-    float txy = tx * y;
-    float txz = tx * z;
-    float tyz = ty * z;
-    float sx = s * x;
-    float sy = s * y;
-    float sz = s * z;
-    
-    dst[0] = c + tx*x;
-    dst[1] = txy + sz;
-    dst[2] = txz - sy;
-    dst[3] = 0.0f;
-
-    dst[4] = txy - sz;
-    dst[5] = c + ty*y;
-    dst[6] = tyz + sx;
-    dst[7] = 0.0f;
-
-    dst[8] = txz + sy;
-    dst[9] = tyz - sx;
-    dst[10] = c + tz*z;
-    dst[11] = 0.0f;
-
-    dst[12] = 0.0f;
-    dst[13] = 0.0f;
-    dst[14] = 0.0f;
-    dst[15] = 1.0f;
-}
-
-void Matrix::createRotationX(float angle, float* dst)
-{
-    setIdentity(dst);
-
-    float c = cos(angle);
-    float s = sin(angle);
-
-    dst[5]  = c;
-    dst[6]  = s;
-    dst[9]  = -s;
-    dst[10] = c;
-}
-
-void Matrix::createRotationY(float angle, float* dst)
-{
-    setIdentity(dst);
-
-    float c = cos(angle);
-    float s = sin(angle);
-
-    dst[0]  = c;
-    dst[2]  = -s;
-    dst[8]  = s;
-    dst[10] = c;
-}
-
-void Matrix::createRotationZ(float angle, float* dst)
-{
-    setIdentity(dst);
-
-    float c = cos(angle);
-    float s = sin(angle);
-
-    dst[0] = c;
-    dst[1] = s;
-    dst[4] = -s;
-    dst[5] = c;
-}
-
-void Matrix::createTranslation(float x, float y, float z, float* dst)
-{
-    setIdentity(dst);
-    dst[12] = x;
-    dst[13] = y;
-    dst[14] = z;
-}
-
-void Matrix::createScale(float x, float y, float z, float* dst)
-{
-    setIdentity(dst);
-    dst[0]  = x;
-    dst[5]  = y;
-    dst[10] = z;
-}
-
-float* Matrix::getArray()
-{
-    return m;
-}
-
-void Matrix::translate(float x, float y, float z)
-{
-    float t[16];
-    createTranslation(x, y, z, t);
-    multiply(m, t, m);
-}
-
-void Matrix::scale(float x, float y, float z)
-{
-    float s[16];
-    createScale(x, y, z, s);
-    multiply(m, s, m);
-}
-
-void Matrix::rotate(const Quaternion& q)
-{
-    float r[16];
-    createRotation(q, r);
-    multiply(m, r, m);
-}
-
-void Matrix::rotate(float x, float y, float z, float angle)
-{
-    float r[16];
-    createRotation(x, y, z, angle, r);
-    multiply(m, r, m);
-}
-
-void Matrix::rotateX(float angle)
-{
-    float r[16];
-    createRotationX(angle, r);
-    multiply(m, r, m);
-}
-
-void Matrix::rotateY(float angle)
-{
-    float r[16];
-    createRotationY(angle, r);
-    multiply(m, r, m);
-}
-
-void Matrix::rotateZ(float angle)
-{
-    float r[16];
-    createRotationZ(angle, r);
-    multiply(m, r, m);
-}
-
-void Matrix::multiply(const float* m1, const float* m2, float* dst)
-{
-    // Support the case where m1 or m2 is the same array as dst.
-    float product[16];
-    product[0]  = m1[0] * m2[0]  + m1[4] * m2[1] + m1[8]   * m2[2]  + m1[12] * m2[3];
-    product[1]  = m1[1] * m2[0]  + m1[5] * m2[1] + m1[9]   * m2[2]  + m1[13] * m2[3];
-    product[2]  = m1[2] * m2[0]  + m1[6] * m2[1] + m1[10]  * m2[2]  + m1[14] * m2[3];
-    product[3]  = m1[3] * m2[0]  + m1[7] * m2[1] + m1[11]  * m2[2]  + m1[15] * m2[3];
-
-    product[4]  = m1[0] * m2[4]  + m1[4] * m2[5] + m1[8]   * m2[6]  + m1[12] * m2[7];
-    product[5]  = m1[1] * m2[4]  + m1[5] * m2[5] + m1[9]   * m2[6]  + m1[13] * m2[7];
-    product[6]  = m1[2] * m2[4]  + m1[6] * m2[5] + m1[10]  * m2[6]  + m1[14] * m2[7];
-    product[7]  = m1[3] * m2[4]  + m1[7] * m2[5] + m1[11]  * m2[6]  + m1[15] * m2[7];
-
-    product[8]  = m1[0] * m2[8]  + m1[4] * m2[9] + m1[8]   * m2[10] + m1[12] * m2[11];
-    product[9]  = m1[1] * m2[8]  + m1[5] * m2[9] + m1[9]   * m2[10] + m1[13] * m2[11];
-    product[10] = m1[2] * m2[8]  + m1[6] * m2[9] + m1[10]  * m2[10] + m1[14] * m2[11];
-    product[11] = m1[3] * m2[8]  + m1[7] * m2[9] + m1[11]  * m2[10] + m1[15] * m2[11];
-
-    product[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8]  * m2[14] + m1[12] * m2[15];
-    product[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9]  * m2[14] + m1[13] * m2[15];
-    product[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
-    product[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
-    memcpy(dst, product, MATRIX4F_SIZE);
-}
-
-bool Matrix::decompose(Vector3* scale, Quaternion* rotation, Vector3* translation) const
-{
-    if (translation)
-    {
-        // Extract the translation
-        translation->x = m[12];
-        translation->y = m[13];
-        translation->z = m[14];
-    }
-
-    // nothing left to do
-    if (scale == NULL && rotation == NULL)
-    {
-        return true;
-    }
-
-    // Extract the scale.
-    // This is simply the length of each axis (row/column) in the matrix.
-    Vector3 xaxis(m[0], m[1], m[2]);
-    float scaleX = xaxis.length();
-
-    Vector3 yaxis(m[4], m[5], m[6]);
-    float scaleY = yaxis.length();
-
-    Vector3 zaxis(m[8], m[9], m[10]);
-    float scaleZ = zaxis.length();
-
-    // Determine if we have a negative scale (true if determinant is less than zero).
-    // In this case, we simply negate a single axis of the scale.
-    float det = determinant();
-    if (det < 0)
-    {
-        scaleZ = -scaleZ;
-    }
-
-    if (scale)
-    {
-        scale->x = scaleX;
-        scale->y = scaleY;
-        scale->z = scaleZ;
-    }
-
-    // nothing left to do
-    if (rotation == NULL)
-        return true;
-
-    // scale too close to zero, can't decompose rotation
-    if (scaleX < MATH_TOLERANCE || scaleY < MATH_TOLERANCE || fabs(scaleZ) < MATH_TOLERANCE)
-        return false;
-
-    float rn;
-
-    // Factor the scale out of the matrix axes
-    rn = 1.0f / scaleX;
-    xaxis.x *= rn;
-    xaxis.y *= rn;
-    xaxis.z *= rn;
-
-    rn = 1.0f / scaleY;
-    yaxis.x *= rn;
-    yaxis.y *= rn;
-    yaxis.z *= rn;
-
-    rn = 1.0f / scaleZ;
-    zaxis.x *= rn;
-    zaxis.y *= rn;
-    zaxis.z *= rn;
-
-    // Now calculate the rotation from the resulting matrix (axes)
-    float trace = xaxis.x + yaxis.y + zaxis.z + 1.0f;
-
-    if (trace > MATH_TOLERANCE)
-    {
-        float s = 0.5f / sqrt(trace);
-        rotation->w = 0.25f / s;
-        rotation->x = ( yaxis.z - zaxis.y ) * s;
-        rotation->y = ( zaxis.x - xaxis.z ) * s;
-        rotation->z = ( xaxis.y - yaxis.x ) * s;
-    }
-    else
-    {
-        if (xaxis.x > yaxis.y && xaxis.x > zaxis.z)
-        {
-            float s = 2.0f * sqrt(1.0f + xaxis.x - yaxis.y - zaxis.z);
-            rotation->w = (yaxis.z - zaxis.y ) / s;
-            rotation->x = 0.25f * s;
-            rotation->y = (yaxis.x + xaxis.y ) / s;
-            rotation->z = (zaxis.x + xaxis.z ) / s;
-        }
-        else if (yaxis.y > zaxis.z)
-        {
-            float s = 2.0f * sqrt(1.0f + yaxis.y - xaxis.x - zaxis.z);
-            rotation->w = (zaxis.x - xaxis.z ) / s;
-            rotation->x = (yaxis.x + xaxis.y ) / s;
-            rotation->y = 0.25f * s;
-            rotation->z = (zaxis.y + yaxis.z ) / s;
-        }
-        else
-        {
-            float s = 2.0f * sqrt(1.0f + zaxis.z - xaxis.x - yaxis.y );
-            rotation->w = (xaxis.y - yaxis.x ) / s;
-            rotation->x = (zaxis.x + xaxis.z ) / s;
-            rotation->y = (zaxis.y + yaxis.z ) / s;
-            rotation->z = 0.25f * s;
-        }
-    }
-
-    return true;
-}
-
-float Matrix::determinant() const
-{
-    float a0 = m[0] * m[5] - m[1] * m[4];
-    float a1 = m[0] * m[6] - m[2] * m[4];
-    float a2 = m[0] * m[7] - m[3] * m[4];
-    float a3 = m[1] * m[6] - m[2] * m[5];
-    float a4 = m[1] * m[7] - m[3] * m[5];
-    float a5 = m[2] * m[7] - m[3] * m[6];
-    float b0 = m[8] * m[13] - m[9] * m[12];
-    float b1 = m[8] * m[14] - m[10] * m[12];
-    float b2 = m[8] * m[15] - m[11] * m[12];
-    float b3 = m[9] * m[14] - m[10] * m[13];
-    float b4 = m[9] * m[15] - m[11] * m[13];
-    float b5 = m[10] * m[15] - m[11] * m[14];
-
-    // Calculate the determinant
-    return (a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0);
-}
-
-void Matrix::transformPoint(const Vector3& p, Vector3* dst) const
-{
-    dst->set(
-        p.x * m[0] + p.y * m[4] + p.z * m[8] +  m[12],
-        p.x * m[1] + p.y * m[5] + p.z * m[9] +  m[13],
-        p.x * m[2] + p.y * m[6] + p.z * m[10] + m[14] );
-}
-
-}
+#include "Base.h"
+#include "Matrix.h"
+
+namespace gameplay
+{
+
+Matrix::Matrix(void)
+{
+    setIdentity(m);
+}
+
+Matrix::Matrix(float m0, float m1, float m2, float m3,
+               float m4, float m5, float m6, float m7,
+               float m8, float m9, float m10, float m11,
+               float m12, float m13, float m14, float m15)
+{
+    m[0] = m0;
+    m[1] = m1;
+    m[2] = m2;
+    m[3] = m3;
+    m[4] = m4;
+    m[5] = m5;
+    m[6] = m6;
+    m[7] = m7;
+    m[8] = m8;
+    m[9] = m9;
+    m[10] = m10;
+    m[11] = m11;
+    m[12] = m12;
+    m[13] = m13;
+    m[14] = m14;
+    m[15] = m15;
+}
+
+Matrix::~Matrix(void)
+{
+}
+
+void Matrix::setIdentity(float* matrix)
+{
+    memcpy(matrix, MATRIX4F_IDENTITY, MATRIX4F_SIZE);
+}
+
+void Matrix::createRotation(const Quaternion& q, float* dst)
+{
+    assert(dst);
+
+    float x2 = q.x + q.x;
+    float y2 = q.y + q.y;
+    float z2 = q.z + q.z;
+
+    float xx2 = q.x * x2;
+    float yy2 = q.y * y2;
+    float zz2 = q.z * z2;
+    float xy2 = q.x * y2;
+    float xz2 = q.x * z2;
+    float yz2 = q.y * z2;
+    float wx2 = q.w * x2;
+    float wy2 = q.w * y2;
+    float wz2 = q.w * z2;
+
+    dst[0] = 1.0f - yy2 - zz2;
+    dst[1] = xy2 + wz2;
+    dst[2] = xz2 - wy2;
+    dst[3] = 0.0f;
+
+    dst[4] = xy2 - wz2;
+    dst[5] = 1.0f - xx2 - zz2;
+    dst[6] = yz2 + wx2;
+    dst[7] = 0.0f;
+
+    dst[8] = xz2 + wy2;
+    dst[9] = yz2 - wx2;
+    dst[10] = 1.0f - xx2 - yy2;
+    dst[11] = 0.0f;
+
+    dst[12] = 0.0f;
+    dst[13] = 0.0f;
+    dst[14] = 0.0f;
+    dst[15] = 1.0f;
+}
+
+void Matrix::createRotation(float x, float y, float z, float angle, float* dst)
+{
+    // Make sure the input axis is normalized
+    float n = x*x + y*y + z*z;
+    if (n != 1.0f)
+    {
+        // Not normalized
+        n = sqrt(n);
+        if (n > 0.000001f) // prevent divide too close to zero
+        {
+            n = 1.0f / n;
+            x *= n;
+            y *= n;
+            z *= n;
+        }
+    }
+
+    float c = cos(angle);
+    float s = sin(angle);
+
+    float t = 1.0f - c;
+    float tx = t * x;
+    float ty = t * y;
+    float tz = t * z;
+    float txy = tx * y;
+    float txz = tx * z;
+    float tyz = ty * z;
+    float sx = s * x;
+    float sy = s * y;
+    float sz = s * z;
+    
+    dst[0] = c + tx*x;
+    dst[1] = txy + sz;
+    dst[2] = txz - sy;
+    dst[3] = 0.0f;
+
+    dst[4] = txy - sz;
+    dst[5] = c + ty*y;
+    dst[6] = tyz + sx;
+    dst[7] = 0.0f;
+
+    dst[8] = txz + sy;
+    dst[9] = tyz - sx;
+    dst[10] = c + tz*z;
+    dst[11] = 0.0f;
+
+    dst[12] = 0.0f;
+    dst[13] = 0.0f;
+    dst[14] = 0.0f;
+    dst[15] = 1.0f;
+}
+
+void Matrix::createRotationX(float angle, float* dst)
+{
+    setIdentity(dst);
+
+    float c = cos(angle);
+    float s = sin(angle);
+
+    dst[5]  = c;
+    dst[6]  = s;
+    dst[9]  = -s;
+    dst[10] = c;
+}
+
+void Matrix::createRotationY(float angle, float* dst)
+{
+    setIdentity(dst);
+
+    float c = cos(angle);
+    float s = sin(angle);
+
+    dst[0]  = c;
+    dst[2]  = -s;
+    dst[8]  = s;
+    dst[10] = c;
+}
+
+void Matrix::createRotationZ(float angle, float* dst)
+{
+    setIdentity(dst);
+
+    float c = cos(angle);
+    float s = sin(angle);
+
+    dst[0] = c;
+    dst[1] = s;
+    dst[4] = -s;
+    dst[5] = c;
+}
+
+void Matrix::createTranslation(float x, float y, float z, float* dst)
+{
+    setIdentity(dst);
+    dst[12] = x;
+    dst[13] = y;
+    dst[14] = z;
+}
+
+void Matrix::createScale(float x, float y, float z, float* dst)
+{
+    setIdentity(dst);
+    dst[0]  = x;
+    dst[5]  = y;
+    dst[10] = z;
+}
+
+float* Matrix::getArray()
+{
+    return m;
+}
+
+void Matrix::translate(float x, float y, float z)
+{
+    float t[16];
+    createTranslation(x, y, z, t);
+    multiply(m, t, m);
+}
+
+void Matrix::scale(float x, float y, float z)
+{
+    float s[16];
+    createScale(x, y, z, s);
+    multiply(m, s, m);
+}
+
+void Matrix::rotate(const Quaternion& q)
+{
+    float r[16];
+    createRotation(q, r);
+    multiply(m, r, m);
+}
+
+void Matrix::rotate(float x, float y, float z, float angle)
+{
+    float r[16];
+    createRotation(x, y, z, angle, r);
+    multiply(m, r, m);
+}
+
+void Matrix::rotateX(float angle)
+{
+    float r[16];
+    createRotationX(angle, r);
+    multiply(m, r, m);
+}
+
+void Matrix::rotateY(float angle)
+{
+    float r[16];
+    createRotationY(angle, r);
+    multiply(m, r, m);
+}
+
+void Matrix::rotateZ(float angle)
+{
+    float r[16];
+    createRotationZ(angle, r);
+    multiply(m, r, m);
+}
+
+void Matrix::multiply(const float* m1, const float* m2, float* dst)
+{
+    // Support the case where m1 or m2 is the same array as dst.
+    float product[16];
+    product[0]  = m1[0] * m2[0]  + m1[4] * m2[1] + m1[8]   * m2[2]  + m1[12] * m2[3];
+    product[1]  = m1[1] * m2[0]  + m1[5] * m2[1] + m1[9]   * m2[2]  + m1[13] * m2[3];
+    product[2]  = m1[2] * m2[0]  + m1[6] * m2[1] + m1[10]  * m2[2]  + m1[14] * m2[3];
+    product[3]  = m1[3] * m2[0]  + m1[7] * m2[1] + m1[11]  * m2[2]  + m1[15] * m2[3];
+
+    product[4]  = m1[0] * m2[4]  + m1[4] * m2[5] + m1[8]   * m2[6]  + m1[12] * m2[7];
+    product[5]  = m1[1] * m2[4]  + m1[5] * m2[5] + m1[9]   * m2[6]  + m1[13] * m2[7];
+    product[6]  = m1[2] * m2[4]  + m1[6] * m2[5] + m1[10]  * m2[6]  + m1[14] * m2[7];
+    product[7]  = m1[3] * m2[4]  + m1[7] * m2[5] + m1[11]  * m2[6]  + m1[15] * m2[7];
+
+    product[8]  = m1[0] * m2[8]  + m1[4] * m2[9] + m1[8]   * m2[10] + m1[12] * m2[11];
+    product[9]  = m1[1] * m2[8]  + m1[5] * m2[9] + m1[9]   * m2[10] + m1[13] * m2[11];
+    product[10] = m1[2] * m2[8]  + m1[6] * m2[9] + m1[10]  * m2[10] + m1[14] * m2[11];
+    product[11] = m1[3] * m2[8]  + m1[7] * m2[9] + m1[11]  * m2[10] + m1[15] * m2[11];
+
+    product[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8]  * m2[14] + m1[12] * m2[15];
+    product[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9]  * m2[14] + m1[13] * m2[15];
+    product[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
+    product[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
+    memcpy(dst, product, MATRIX4F_SIZE);
+}
+
+bool Matrix::decompose(Vector3* scale, Quaternion* rotation, Vector3* translation) const
+{
+    if (translation)
+    {
+        // Extract the translation
+        translation->x = m[12];
+        translation->y = m[13];
+        translation->z = m[14];
+    }
+
+    // nothing left to do
+    if (scale == NULL && rotation == NULL)
+    {
+        return true;
+    }
+
+    // Extract the scale.
+    // This is simply the length of each axis (row/column) in the matrix.
+    Vector3 xaxis(m[0], m[1], m[2]);
+    float scaleX = xaxis.length();
+
+    Vector3 yaxis(m[4], m[5], m[6]);
+    float scaleY = yaxis.length();
+
+    Vector3 zaxis(m[8], m[9], m[10]);
+    float scaleZ = zaxis.length();
+
+    // Determine if we have a negative scale (true if determinant is less than zero).
+    // In this case, we simply negate a single axis of the scale.
+    float det = determinant();
+    if (det < 0)
+    {
+        scaleZ = -scaleZ;
+    }
+
+    if (scale)
+    {
+        scale->x = scaleX;
+        scale->y = scaleY;
+        scale->z = scaleZ;
+    }
+
+    // nothing left to do
+    if (rotation == NULL)
+        return true;
+
+    // scale too close to zero, can't decompose rotation
+    if (scaleX < MATH_TOLERANCE || scaleY < MATH_TOLERANCE || fabs(scaleZ) < MATH_TOLERANCE)
+        return false;
+
+    float rn;
+
+    // Factor the scale out of the matrix axes
+    rn = 1.0f / scaleX;
+    xaxis.x *= rn;
+    xaxis.y *= rn;
+    xaxis.z *= rn;
+
+    rn = 1.0f / scaleY;
+    yaxis.x *= rn;
+    yaxis.y *= rn;
+    yaxis.z *= rn;
+
+    rn = 1.0f / scaleZ;
+    zaxis.x *= rn;
+    zaxis.y *= rn;
+    zaxis.z *= rn;
+
+    // Now calculate the rotation from the resulting matrix (axes)
+    float trace = xaxis.x + yaxis.y + zaxis.z + 1.0f;
+
+    if (trace > MATH_TOLERANCE)
+    {
+        float s = 0.5f / sqrt(trace);
+        rotation->w = 0.25f / s;
+        rotation->x = ( yaxis.z - zaxis.y ) * s;
+        rotation->y = ( zaxis.x - xaxis.z ) * s;
+        rotation->z = ( xaxis.y - yaxis.x ) * s;
+    }
+    else
+    {
+        if (xaxis.x > yaxis.y && xaxis.x > zaxis.z)
+        {
+            float s = 2.0f * sqrt(1.0f + xaxis.x - yaxis.y - zaxis.z);
+            rotation->w = (yaxis.z - zaxis.y ) / s;
+            rotation->x = 0.25f * s;
+            rotation->y = (yaxis.x + xaxis.y ) / s;
+            rotation->z = (zaxis.x + xaxis.z ) / s;
+        }
+        else if (yaxis.y > zaxis.z)
+        {
+            float s = 2.0f * sqrt(1.0f + yaxis.y - xaxis.x - zaxis.z);
+            rotation->w = (zaxis.x - xaxis.z ) / s;
+            rotation->x = (yaxis.x + xaxis.y ) / s;
+            rotation->y = 0.25f * s;
+            rotation->z = (zaxis.y + yaxis.z ) / s;
+        }
+        else
+        {
+            float s = 2.0f * sqrt(1.0f + zaxis.z - xaxis.x - yaxis.y );
+            rotation->w = (xaxis.y - yaxis.x ) / s;
+            rotation->x = (zaxis.x + xaxis.z ) / s;
+            rotation->y = (zaxis.y + yaxis.z ) / s;
+            rotation->z = 0.25f * s;
+        }
+    }
+
+    return true;
+}
+
+float Matrix::determinant() const
+{
+    float a0 = m[0] * m[5] - m[1] * m[4];
+    float a1 = m[0] * m[6] - m[2] * m[4];
+    float a2 = m[0] * m[7] - m[3] * m[4];
+    float a3 = m[1] * m[6] - m[2] * m[5];
+    float a4 = m[1] * m[7] - m[3] * m[5];
+    float a5 = m[2] * m[7] - m[3] * m[6];
+    float b0 = m[8] * m[13] - m[9] * m[12];
+    float b1 = m[8] * m[14] - m[10] * m[12];
+    float b2 = m[8] * m[15] - m[11] * m[12];
+    float b3 = m[9] * m[14] - m[10] * m[13];
+    float b4 = m[9] * m[15] - m[11] * m[13];
+    float b5 = m[10] * m[15] - m[11] * m[14];
+
+    // Calculate the determinant
+    return (a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0);
+}
+
+void Matrix::transformPoint(const Vector3& p, Vector3* dst) const
+{
+    dst->set(
+        p.x * m[0] + p.y * m[4] + p.z * m[8] +  m[12],
+        p.x * m[1] + p.y * m[5] + p.z * m[9] +  m[13],
+        p.x * m[2] + p.y * m[6] + p.z * m[10] + m[14] );
+}
+
+}

+ 169 - 169
tools/encoder/src/Matrix.h

@@ -1,169 +1,169 @@
-#ifndef MATRIX_H_
-#define MATRIX_H_
-
-#include "Vector4.h"
-#include "Vector3.h"
-#include "Vector2.h"
-#include "Quaternion.h"
-#include "FileIO.h"
-
-#define MATRIX4F_SIZE   (sizeof(float) * 16)
-#define PI 3.14159265f
-#define TORADIANS(degrees) (degrees * (PI / 180.0f))
-#define TODEGREES(radians) (radians * (180.0f / PI))
-
-namespace gameplay
-{
-
-/**
- * The identify matrix.
- */
-static const float MATRIX4F_IDENTITY[16] =
-{
-    1.0f, 0.0f, 0.0f, 0.0f,
-    0.0f, 1.0f, 0.0f, 0.0f,
-    0.0f, 0.0f, 1.0f, 0.0f,
-    0.0f, 0.0f, 0.0f, 1.0f
-};
-
-class Matrix
-{
-public:
-
-    /**
-     * Matrix colums.
-     */
-    float m[16];
-
-    /**
-     * Constructor.
-     */
-    Matrix(void);
-
-    /**
-     * Constructor.
-     */
-    Matrix(float m0, float m1, float m2, float m3,
-           float m4, float m5, float m6, float m7,
-           float m8, float m9, float m10, float m11,
-           float m12, float m13, float m14, float m15);
-
-    /**
-     * Destructor.
-     */
-    ~Matrix(void);
-
-    /**
-     * Computes the determinant of this matrix.
-     *
-     * @return The determinant.
-     */
-    float determinant() const;
-
-    /**
-     * Decomposes the scale, rotation and translation components of this matrix.
-     *
-     * @param scale The scale.
-     * @param rotation The rotation.
-     * @param translation The translation.
-     */
-    bool decompose(Vector3* scale, Quaternion* rotation, Vector3* translation) const;
-
-    /**
-     * Sets the given matrix to be the identity matrix.
-     */
-    static void setIdentity(float* matrix);
-
-    /**
-     * Multiplies two matrices and stores the results in dst.
-     * m1 and m2 may be the same as dst.
-     */
-    static void multiply(const float* m1, const float* m2, float* dst);
-
-    /**
-     * Creates a scale matrix for the givent x,y,z scale factors.
-     */
-    static void createScale(float x, float y, float z, float* dst);
-
-    /**
-     * Creates a rotation matrix from the given quaternion.
-     */
-    static void createRotation(const Quaternion& q, float* dst);
-
-    /**
-     * Creates a rotation matrix from the given axis and angle in degrees.
-     */
-    static void createRotation(float x, float y, float z, float angle, float* dst);
-    
-    /**
-     * Creates a rotation matrix for the given angle in the x axis and angle in degrees
-     */
-    void createRotationX(float angle, float* dst);
-    
-    /**
-     * Creates a rotation matrix for the given angle in the y axis and angle in degrees
-     */
-    void createRotationY(float angle, float* dst);
-        
-    /**
-     * Creates a rotation matrix for the given angle in the z axis and angle in degrees
-     */
-    void createRotationZ(float angle, float* dst);
-    
-    /**
-     * Creates a translation matrix for the given x, y ,x values.
-     */
-    static void createTranslation(float x, float y, float z, float* dst);
-
-    /**
-     * Returns the pointer to the float array.
-     */
-    float* getArray();
-
-    /**
-     * Translates the matrix by the x, y, z values.
-     */
-    void translate(float x, float y, float z);
-
-    /**
-     * Scales the matrix by the x, y, z factors.
-     */
-    void scale(float x, float y, float z);
-
-    /**
-     * Rotates the matrix by the given Quaternion.
-     */
-    void rotate(const Quaternion& q);
-
-    /**
-     * Rotates the matrix by the axies specified and angle.
-     */
-    void rotate(float x, float y, float z, float angle);
-
-    /**
-     * Rotates the matrix on the y-axis by the specified angle in degrees.
-     */
-    void rotateX(float angle);
-    
-    /**
-     * Rotates the matrix on the y-axis by the specified angle in degrees.
-     */
-    void rotateY(float angle);
-
-    /**
-     * Rotates the matrix on the z-axis by the specified angle in degrees.
-     */
-    void rotateZ(float angle);
-
-    /**
-     * Transforms the specified point by this matrix.
-     *
-     * Note that the input vector is treated as a point and NOT a vector.
-     */
-    void transformPoint(const Vector3& p, Vector3* dst) const;
-
-};
-
-}
-
-#endif
+#ifndef MATRIX_H_
+#define MATRIX_H_
+
+#include "Vector4.h"
+#include "Vector3.h"
+#include "Vector2.h"
+#include "Quaternion.h"
+#include "FileIO.h"
+
+#define MATRIX4F_SIZE   (sizeof(float) * 16)
+#define PI 3.14159265f
+#define TORADIANS(degrees) (degrees * (PI / 180.0f))
+#define TODEGREES(radians) (radians * (180.0f / PI))
+
+namespace gameplay
+{
+
+/**
+ * The identify matrix.
+ */
+static const float MATRIX4F_IDENTITY[16] =
+{
+    1.0f, 0.0f, 0.0f, 0.0f,
+    0.0f, 1.0f, 0.0f, 0.0f,
+    0.0f, 0.0f, 1.0f, 0.0f,
+    0.0f, 0.0f, 0.0f, 1.0f
+};
+
+class Matrix
+{
+public:
+
+    /**
+     * Matrix colums.
+     */
+    float m[16];
+
+    /**
+     * Constructor.
+     */
+    Matrix(void);
+
+    /**
+     * Constructor.
+     */
+    Matrix(float m0, float m1, float m2, float m3,
+           float m4, float m5, float m6, float m7,
+           float m8, float m9, float m10, float m11,
+           float m12, float m13, float m14, float m15);
+
+    /**
+     * Destructor.
+     */
+    ~Matrix(void);
+
+    /**
+     * Computes the determinant of this matrix.
+     *
+     * @return The determinant.
+     */
+    float determinant() const;
+
+    /**
+     * Decomposes the scale, rotation and translation components of this matrix.
+     *
+     * @param scale The scale.
+     * @param rotation The rotation.
+     * @param translation The translation.
+     */
+    bool decompose(Vector3* scale, Quaternion* rotation, Vector3* translation) const;
+
+    /**
+     * Sets the given matrix to be the identity matrix.
+     */
+    static void setIdentity(float* matrix);
+
+    /**
+     * Multiplies two matrices and stores the results in dst.
+     * m1 and m2 may be the same as dst.
+     */
+    static void multiply(const float* m1, const float* m2, float* dst);
+
+    /**
+     * Creates a scale matrix for the givent x,y,z scale factors.
+     */
+    static void createScale(float x, float y, float z, float* dst);
+
+    /**
+     * Creates a rotation matrix from the given quaternion.
+     */
+    static void createRotation(const Quaternion& q, float* dst);
+
+    /**
+     * Creates a rotation matrix from the given axis and angle in degrees.
+     */
+    static void createRotation(float x, float y, float z, float angle, float* dst);
+    
+    /**
+     * Creates a rotation matrix for the given angle in the x axis and angle in degrees
+     */
+    void createRotationX(float angle, float* dst);
+    
+    /**
+     * Creates a rotation matrix for the given angle in the y axis and angle in degrees
+     */
+    void createRotationY(float angle, float* dst);
+        
+    /**
+     * Creates a rotation matrix for the given angle in the z axis and angle in degrees
+     */
+    void createRotationZ(float angle, float* dst);
+    
+    /**
+     * Creates a translation matrix for the given x, y ,x values.
+     */
+    static void createTranslation(float x, float y, float z, float* dst);
+
+    /**
+     * Returns the pointer to the float array.
+     */
+    float* getArray();
+
+    /**
+     * Translates the matrix by the x, y, z values.
+     */
+    void translate(float x, float y, float z);
+
+    /**
+     * Scales the matrix by the x, y, z factors.
+     */
+    void scale(float x, float y, float z);
+
+    /**
+     * Rotates the matrix by the given Quaternion.
+     */
+    void rotate(const Quaternion& q);
+
+    /**
+     * Rotates the matrix by the axies specified and angle.
+     */
+    void rotate(float x, float y, float z, float angle);
+
+    /**
+     * Rotates the matrix on the y-axis by the specified angle in degrees.
+     */
+    void rotateX(float angle);
+    
+    /**
+     * Rotates the matrix on the y-axis by the specified angle in degrees.
+     */
+    void rotateY(float angle);
+
+    /**
+     * Rotates the matrix on the z-axis by the specified angle in degrees.
+     */
+    void rotateZ(float angle);
+
+    /**
+     * Transforms the specified point by this matrix.
+     *
+     * Note that the input vector is treated as a point and NOT a vector.
+     */
+    void transformPoint(const Vector3& p, Vector3* dst) const;
+
+};
+
+}
+
+#endif

+ 233 - 233
tools/encoder/src/Mesh.cpp

@@ -1,233 +1,233 @@
-#include "Base.h"
-#include "Mesh.h"
-#include "Model.h"
-
-namespace gameplay
-{
-
-Mesh::Mesh(void) : model(NULL)
-{
-}
-
-Mesh::~Mesh(void)
-{
-}
-
-unsigned int Mesh::getTypeId(void) const
-{
-    return MESH_ID;
-}
-
-const char* Mesh::getElementName(void) const
-{
-    return "Mesh";
-}
-
-void Mesh::writeBinary(FILE* file)
-{
-    Object::writeBinary(file);
-    // vertex formats
-    write((unsigned int)_vertexFormat.size(), file);
-    for (std::vector<VertexElement>::iterator i = _vertexFormat.begin(); i != _vertexFormat.end(); ++i)
-    {
-        i->writeBinary(file);
-    }
-    // vertices
-    writeBinaryVertices(file);
-    // parts
-    writeBinaryObjects(parts, file);
-}
-
-void Mesh::writeBinaryVertices(FILE* file)
-{
-    if (vertices.size() > 0)
-    {
-        // Assumes that all vertices are the same size.
-        // Write the number of bytes for the vertex data
-        const Vertex& vertex = vertices.front();
-        write((unsigned int)(vertices.size() * vertex.byteSize()), file); // (vertex count) * (vertex size)
-
-        // for each vertex
-        for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)
-        {
-            // Write this vertex
-            i->writeBinary(file);
-        }
-    }
-    else
-    {
-        // No vertex data
-        writeZero(file);
-    }
-
-    // Write bounds
-    write(&bounds.min.x, 3, file);
-    write(&bounds.max.x, 3, file);
-    write(&bounds.center.x, 3, file);
-    write(bounds.radius, file);
-}
-
-void Mesh::writeText(FILE* file)
-{
-    fprintElementStart(file);
-
-    // for each VertexFormat
-    if (vertices.size() > 0 )
-    {
-        for (std::vector<VertexElement>::iterator i = _vertexFormat.begin(); i != _vertexFormat.end(); ++i)
-        {
-            i->writeText(file);
-        }
-    }
-
-    // for each Vertex
-    fprintf(file, "<vertices count=\"%lu\">\n", vertices.size());
-    for (std::vector<Vertex>::iterator i = vertices.begin(); i != vertices.end(); ++i)
-    {
-        i->writeText(file);
-    }
-    fprintf(file, "</vertices>\n");
-
-    // write bounds
-    fprintf(file, "<bounds>\n");
-    fprintf(file, "<min>\n");
-    writeVectorText(bounds.min, file);
-    fprintf(file, "</min>\n");
-    fprintf(file, "<max>\n");
-    writeVectorText(bounds.max, file);
-    fprintf(file, "</max>\n");
-    fprintf(file, "<center>\n");
-    writeVectorText(bounds.center, file);
-    fprintf(file, "</center>\n");
-    fprintf(file, "<radius>%f</radius>\n", bounds.radius);
-    fprintf(file, "</bounds>\n");
-
-    // for each MeshPart
-    for (std::vector<MeshPart*>::iterator i = parts.begin(); i != parts.end(); ++i)
-    {
-        (*i)->writeText(file);
-    }
-
-    fprintElementEnd(file);
-}
-
-void Mesh::addMeshPart(MeshPart* part)
-{
-    parts.push_back(part);
-}
-
-void Mesh::addMeshPart(Vertex* vertex)
-{
-    vertices.push_back(*vertex);
-}
-
-void Mesh::addVetexAttribute(unsigned int usage, unsigned int count)
-{
-    _vertexFormat.push_back(VertexElement(usage, count));
-}
-
-size_t Mesh::getVertexCount() const
-{
-    return vertices.size();
-}
-
-const Vertex& Mesh::getVertex(unsigned int index) const
-{
-    return vertices[index];
-}
-
-size_t Mesh::getVertexElementCount() const
-{
-    return _vertexFormat.size();
-}
-
-const VertexElement& Mesh::getVertexElement(unsigned int index) const
-{
-    return _vertexFormat[index];
-}
-
-bool Mesh::contains(const Vertex& vertex) const
-{
-    return vertexLookupTable.count(vertex) > 0;
-}
-
-unsigned int Mesh::addVertex(const Vertex& vertex)
-{
-    unsigned int index = getVertexCount();
-    vertices.push_back(vertex);
-    vertexLookupTable[vertex] = index;
-    return index;
-}
-
-unsigned int Mesh::getVertexIndex(const Vertex& vertex)
-{
-    std::map<Vertex,unsigned int>::iterator it;
-    it = vertexLookupTable.find(vertex);
-    return it->second;
-}
-
-bool Mesh::hasNormals() const
-{
-    return !vertices.empty() && vertices[0].hasNormal;
-}
-
-bool Mesh::hasVertexColors() const
-{
-    return !vertices.empty() && vertices[0].hasDiffuse;
-}
-
-void Mesh::computeBounds()
-{
-    // If we have a Model with a MeshSkin associated with it,
-    // compute the bounds from the skin - otherwise compute
-    // it from the local mesh data.
-    if (model && model->getSkin())
-    {
-        model->getSkin()->computeBounds();
-        return;
-    }
-
-    LOG(2, "Computing bounds for mesh: %s\n", getId().c_str());
-
-    bounds.min.x = bounds.min.y = bounds.min.z = FLT_MAX;
-    bounds.max.x = bounds.max.y = bounds.max.z = -FLT_MAX;
-    bounds.center.x = bounds.center.y = bounds.center.z = 0.0f;
-    bounds.radius = 0.0f;
-
-    for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)
-    {
-        // Update min/max for this vertex
-        if (i->position.x < bounds.min.x)
-            bounds.min.x = i->position.x;
-        if (i->position.y < bounds.min.y)
-            bounds.min.y = i->position.y;
-        if (i->position.z < bounds.min.z)
-            bounds.min.z = i->position.z;
-        if (i->position.x > bounds.max.x)
-            bounds.max.x = i->position.x;
-        if (i->position.y > bounds.max.y)
-            bounds.max.y = i->position.y;
-        if (i->position.z > bounds.max.z)
-            bounds.max.z = i->position.z;
-    }
-
-    // Compute center point
-    Vector3::add(bounds.min, bounds.max, &bounds.center);
-    bounds.center.scale(0.5f);
-
-    // Compute radius by looping through all points again and finding the max
-    // distance between the center point and each vertex position
-    for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)
-    {
-        float d = bounds.center.distanceSquared(i->position);
-        if (d > bounds.radius)
-        {
-            bounds.radius = d;
-        }
-    }
-
-    // Convert squared distance to distance for radius
-    bounds.radius = sqrt(bounds.radius);
-}
-
-}
+#include "Base.h"
+#include "Mesh.h"
+#include "Model.h"
+
+namespace gameplay
+{
+
+Mesh::Mesh(void) : model(NULL)
+{
+}
+
+Mesh::~Mesh(void)
+{
+}
+
+unsigned int Mesh::getTypeId(void) const
+{
+    return MESH_ID;
+}
+
+const char* Mesh::getElementName(void) const
+{
+    return "Mesh";
+}
+
+void Mesh::writeBinary(FILE* file)
+{
+    Object::writeBinary(file);
+    // vertex formats
+    write((unsigned int)_vertexFormat.size(), file);
+    for (std::vector<VertexElement>::iterator i = _vertexFormat.begin(); i != _vertexFormat.end(); ++i)
+    {
+        i->writeBinary(file);
+    }
+    // vertices
+    writeBinaryVertices(file);
+    // parts
+    writeBinaryObjects(parts, file);
+}
+
+void Mesh::writeBinaryVertices(FILE* file)
+{
+    if (vertices.size() > 0)
+    {
+        // Assumes that all vertices are the same size.
+        // Write the number of bytes for the vertex data
+        const Vertex& vertex = vertices.front();
+        write((unsigned int)(vertices.size() * vertex.byteSize()), file); // (vertex count) * (vertex size)
+
+        // for each vertex
+        for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)
+        {
+            // Write this vertex
+            i->writeBinary(file);
+        }
+    }
+    else
+    {
+        // No vertex data
+        writeZero(file);
+    }
+
+    // Write bounds
+    write(&bounds.min.x, 3, file);
+    write(&bounds.max.x, 3, file);
+    write(&bounds.center.x, 3, file);
+    write(bounds.radius, file);
+}
+
+void Mesh::writeText(FILE* file)
+{
+    fprintElementStart(file);
+
+    // for each VertexFormat
+    if (vertices.size() > 0 )
+    {
+        for (std::vector<VertexElement>::iterator i = _vertexFormat.begin(); i != _vertexFormat.end(); ++i)
+        {
+            i->writeText(file);
+        }
+    }
+
+    // for each Vertex
+    fprintf(file, "<vertices count=\"%lu\">\n", vertices.size());
+    for (std::vector<Vertex>::iterator i = vertices.begin(); i != vertices.end(); ++i)
+    {
+        i->writeText(file);
+    }
+    fprintf(file, "</vertices>\n");
+
+    // write bounds
+    fprintf(file, "<bounds>\n");
+    fprintf(file, "<min>\n");
+    writeVectorText(bounds.min, file);
+    fprintf(file, "</min>\n");
+    fprintf(file, "<max>\n");
+    writeVectorText(bounds.max, file);
+    fprintf(file, "</max>\n");
+    fprintf(file, "<center>\n");
+    writeVectorText(bounds.center, file);
+    fprintf(file, "</center>\n");
+    fprintf(file, "<radius>%f</radius>\n", bounds.radius);
+    fprintf(file, "</bounds>\n");
+
+    // for each MeshPart
+    for (std::vector<MeshPart*>::iterator i = parts.begin(); i != parts.end(); ++i)
+    {
+        (*i)->writeText(file);
+    }
+
+    fprintElementEnd(file);
+}
+
+void Mesh::addMeshPart(MeshPart* part)
+{
+    parts.push_back(part);
+}
+
+void Mesh::addMeshPart(Vertex* vertex)
+{
+    vertices.push_back(*vertex);
+}
+
+void Mesh::addVetexAttribute(unsigned int usage, unsigned int count)
+{
+    _vertexFormat.push_back(VertexElement(usage, count));
+}
+
+size_t Mesh::getVertexCount() const
+{
+    return vertices.size();
+}
+
+const Vertex& Mesh::getVertex(unsigned int index) const
+{
+    return vertices[index];
+}
+
+size_t Mesh::getVertexElementCount() const
+{
+    return _vertexFormat.size();
+}
+
+const VertexElement& Mesh::getVertexElement(unsigned int index) const
+{
+    return _vertexFormat[index];
+}
+
+bool Mesh::contains(const Vertex& vertex) const
+{
+    return vertexLookupTable.count(vertex) > 0;
+}
+
+unsigned int Mesh::addVertex(const Vertex& vertex)
+{
+    unsigned int index = getVertexCount();
+    vertices.push_back(vertex);
+    vertexLookupTable[vertex] = index;
+    return index;
+}
+
+unsigned int Mesh::getVertexIndex(const Vertex& vertex)
+{
+    std::map<Vertex,unsigned int>::iterator it;
+    it = vertexLookupTable.find(vertex);
+    return it->second;
+}
+
+bool Mesh::hasNormals() const
+{
+    return !vertices.empty() && vertices[0].hasNormal;
+}
+
+bool Mesh::hasVertexColors() const
+{
+    return !vertices.empty() && vertices[0].hasDiffuse;
+}
+
+void Mesh::computeBounds()
+{
+    // If we have a Model with a MeshSkin associated with it,
+    // compute the bounds from the skin - otherwise compute
+    // it from the local mesh data.
+    if (model && model->getSkin())
+    {
+        model->getSkin()->computeBounds();
+        return;
+    }
+
+    LOG(2, "Computing bounds for mesh: %s\n", getId().c_str());
+
+    bounds.min.x = bounds.min.y = bounds.min.z = FLT_MAX;
+    bounds.max.x = bounds.max.y = bounds.max.z = -FLT_MAX;
+    bounds.center.x = bounds.center.y = bounds.center.z = 0.0f;
+    bounds.radius = 0.0f;
+
+    for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)
+    {
+        // Update min/max for this vertex
+        if (i->position.x < bounds.min.x)
+            bounds.min.x = i->position.x;
+        if (i->position.y < bounds.min.y)
+            bounds.min.y = i->position.y;
+        if (i->position.z < bounds.min.z)
+            bounds.min.z = i->position.z;
+        if (i->position.x > bounds.max.x)
+            bounds.max.x = i->position.x;
+        if (i->position.y > bounds.max.y)
+            bounds.max.y = i->position.y;
+        if (i->position.z > bounds.max.z)
+            bounds.max.z = i->position.z;
+    }
+
+    // Compute center point
+    Vector3::add(bounds.min, bounds.max, &bounds.center);
+    bounds.center.scale(0.5f);
+
+    // Compute radius by looping through all points again and finding the max
+    // distance between the center point and each vertex position
+    for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)
+    {
+        float d = bounds.center.distanceSquared(i->position);
+        if (d > bounds.radius)
+        {
+            bounds.radius = d;
+        }
+    }
+
+    // Convert squared distance to distance for radius
+    bounds.radius = sqrt(bounds.radius);
+}
+
+}

+ 81 - 81
tools/encoder/src/Mesh.h

@@ -1,81 +1,81 @@
-#ifndef MESH_H_
-#define MESH_H_
-
-#include "Base.h"
-#include "Object.h"
-#include "MeshPart.h"
-#include "VertexElement.h"
-#include "BoundingVolume.h"
-
-namespace gameplay
-{
-
-class Model;
-
-class Mesh : public Object
-{
-    friend class Model;
-
-public:
-
-    /**
-     * Constructor.
-     */
-    Mesh(void);
-
-    /**
-     * Destructor.
-     */
-    virtual ~Mesh(void);
-
-    virtual unsigned int getTypeId(void) const;
-    virtual const char* getElementName(void) const;
-
-    virtual void writeBinary(FILE* file);
-    void writeBinaryVertices(FILE* file);
-
-    virtual void writeText(FILE* file);
-    void writeText(FILE* file, const Vertex& vertex);
-    void writeText(FILE* file, const Vector3& v);
-
-    void addMeshPart(MeshPart* part);
-    void addMeshPart(Vertex* vertex);
-    void addVetexAttribute(unsigned int usage, unsigned int count);
-
-    size_t getVertexCount() const;
-    const Vertex& getVertex(unsigned int index) const;
-
-    size_t getVertexElementCount() const;
-    const VertexElement& getVertexElement(unsigned int index) const;
-
-    /**
-     * Returns true if this MeshPart contains the given Vertex.
-     */
-    bool contains(const Vertex& vertex) const;
-
-    /**
-     * Adds a vertex to this MeshPart and returns the index.
-     */
-    unsigned int addVertex(const Vertex& vertex);
-
-    unsigned int getVertexIndex(const Vertex& vertex);
-
-    bool hasNormals() const;
-    bool hasVertexColors() const;
-
-    void computeBounds();
-
-    Model* model;
-    std::vector<Vertex> vertices;
-    std::vector<MeshPart*> parts;
-    BoundingVolume bounds;
-    std::map<Vertex, unsigned int> vertexLookupTable;
-
-private:
-    std::vector<VertexElement> _vertexFormat;
-
-};
-
-}
-
-#endif
+#ifndef MESH_H_
+#define MESH_H_
+
+#include "Base.h"
+#include "Object.h"
+#include "MeshPart.h"
+#include "VertexElement.h"
+#include "BoundingVolume.h"
+
+namespace gameplay
+{
+
+class Model;
+
+class Mesh : public Object
+{
+    friend class Model;
+
+public:
+
+    /**
+     * Constructor.
+     */
+    Mesh(void);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Mesh(void);
+
+    virtual unsigned int getTypeId(void) const;
+    virtual const char* getElementName(void) const;
+
+    virtual void writeBinary(FILE* file);
+    void writeBinaryVertices(FILE* file);
+
+    virtual void writeText(FILE* file);
+    void writeText(FILE* file, const Vertex& vertex);
+    void writeText(FILE* file, const Vector3& v);
+
+    void addMeshPart(MeshPart* part);
+    void addMeshPart(Vertex* vertex);
+    void addVetexAttribute(unsigned int usage, unsigned int count);
+
+    size_t getVertexCount() const;
+    const Vertex& getVertex(unsigned int index) const;
+
+    size_t getVertexElementCount() const;
+    const VertexElement& getVertexElement(unsigned int index) const;
+
+    /**
+     * Returns true if this MeshPart contains the given Vertex.
+     */
+    bool contains(const Vertex& vertex) const;
+
+    /**
+     * Adds a vertex to this MeshPart and returns the index.
+     */
+    unsigned int addVertex(const Vertex& vertex);
+
+    unsigned int getVertexIndex(const Vertex& vertex);
+
+    bool hasNormals() const;
+    bool hasVertexColors() const;
+
+    void computeBounds();
+
+    Model* model;
+    std::vector<Vertex> vertices;
+    std::vector<MeshPart*> parts;
+    BoundingVolume bounds;
+    std::map<Vertex, unsigned int> vertexLookupTable;
+
+private:
+    std::vector<VertexElement> _vertexFormat;
+
+};
+
+}
+
+#endif

+ 114 - 114
tools/encoder/src/MeshPart.cpp

@@ -1,114 +1,114 @@
-#include "Base.h"
-#include "MeshPart.h"
-
-namespace gameplay
-{
-
-MeshPart::MeshPart(void) :
-    _primitiveType(TRIANGLES),
-    _indexFormat(INDEX16)
-{
-}
-
-MeshPart::~MeshPart(void)
-{
-}
-
-unsigned int MeshPart::getTypeId(void) const
-{
-    return MESHPART_ID;
-}
-
-const char* MeshPart::getElementName(void) const
-{
-    return "MeshPart";
-}
-
-void MeshPart::writeBinary(FILE* file)
-{
-    Object::writeBinary(file);
-
-    write(_primitiveType, file);
-    write((unsigned int)_indexFormat, file);
-
-    // write the number of bytes
-    write(indicesByteSize(), file);
-    // for each index
-    for (std::vector<unsigned int>::const_iterator i = _indices.begin(); i != _indices.end(); ++i)
-    {
-        writeBinaryIndex(*i, file);
-    }
-}
-
-void MeshPart::writeText(FILE* file)
-{
-    fprintElementStart(file);
-    fprintfElement(file, "primitiveType", _primitiveType);
-    fprintfElement(file, "indexFormat", (unsigned int)_indexFormat);
-    fprintfElement(file, "%d ", "indices", _indices);
-    fprintElementEnd(file);
-}
-
-void MeshPart::addIndex(unsigned int index)
-{
-    updateIndexFormat(index);
-    _indices.push_back(index);
-}
-
-size_t MeshPart::getIndicesCount() const
-{
-    return _indices.size();
-}
-
-unsigned int MeshPart::indicesByteSize() const
-{
-    return _indices.size() * indexFormatSize();
-}
-
-unsigned int MeshPart::indexFormatSize() const
-{
-    switch (_indexFormat)
-    {
-    case INDEX32:
-        return 4;
-    default: // INDEX16
-        return 2;
-    }
-}
-
-MeshPart::IndexFormat MeshPart::getIndexFormat() const
-{
-    return _indexFormat;
-}
-
-unsigned int MeshPart::getIndex(unsigned int i) const
-{
-    return _indices[i];
-}
-
-void MeshPart::writeBinaryIndex(unsigned int index, FILE* file)
-{
-    switch (_indexFormat)
-    {
-    case INDEX32:
-        write(index, file);
-        break;
-    default: // INDEX16
-        write((unsigned short)index, file);
-        break;
-    }
-}
-
-void MeshPart::updateIndexFormat(unsigned int newIndex)
-{
-    if (newIndex >= 65536)
-    {
-        _indexFormat = INDEX32;
-    }
-    else if (newIndex >= 256 && _indexFormat != INDEX32)
-    {
-        _indexFormat = INDEX16;
-    }
-}
-
-}
+#include "Base.h"
+#include "MeshPart.h"
+
+namespace gameplay
+{
+
+MeshPart::MeshPart(void) :
+    _primitiveType(TRIANGLES),
+    _indexFormat(INDEX16)
+{
+}
+
+MeshPart::~MeshPart(void)
+{
+}
+
+unsigned int MeshPart::getTypeId(void) const
+{
+    return MESHPART_ID;
+}
+
+const char* MeshPart::getElementName(void) const
+{
+    return "MeshPart";
+}
+
+void MeshPart::writeBinary(FILE* file)
+{
+    Object::writeBinary(file);
+
+    write(_primitiveType, file);
+    write((unsigned int)_indexFormat, file);
+
+    // write the number of bytes
+    write(indicesByteSize(), file);
+    // for each index
+    for (std::vector<unsigned int>::const_iterator i = _indices.begin(); i != _indices.end(); ++i)
+    {
+        writeBinaryIndex(*i, file);
+    }
+}
+
+void MeshPart::writeText(FILE* file)
+{
+    fprintElementStart(file);
+    fprintfElement(file, "primitiveType", _primitiveType);
+    fprintfElement(file, "indexFormat", (unsigned int)_indexFormat);
+    fprintfElement(file, "%d ", "indices", _indices);
+    fprintElementEnd(file);
+}
+
+void MeshPart::addIndex(unsigned int index)
+{
+    updateIndexFormat(index);
+    _indices.push_back(index);
+}
+
+size_t MeshPart::getIndicesCount() const
+{
+    return _indices.size();
+}
+
+unsigned int MeshPart::indicesByteSize() const
+{
+    return _indices.size() * indexFormatSize();
+}
+
+unsigned int MeshPart::indexFormatSize() const
+{
+    switch (_indexFormat)
+    {
+    case INDEX32:
+        return 4;
+    default: // INDEX16
+        return 2;
+    }
+}
+
+MeshPart::IndexFormat MeshPart::getIndexFormat() const
+{
+    return _indexFormat;
+}
+
+unsigned int MeshPart::getIndex(unsigned int i) const
+{
+    return _indices[i];
+}
+
+void MeshPart::writeBinaryIndex(unsigned int index, FILE* file)
+{
+    switch (_indexFormat)
+    {
+    case INDEX32:
+        write(index, file);
+        break;
+    default: // INDEX16
+        write((unsigned short)index, file);
+        break;
+    }
+}
+
+void MeshPart::updateIndexFormat(unsigned int newIndex)
+{
+    if (newIndex >= 65536)
+    {
+        _indexFormat = INDEX32;
+    }
+    else if (newIndex >= 256 && _indexFormat != INDEX32)
+    {
+        _indexFormat = INDEX16;
+    }
+}
+
+}

+ 97 - 97
tools/encoder/src/MeshPart.h

@@ -1,97 +1,97 @@
-#ifndef MESHPART_H_
-#define MESHPART_H_
-
-#include "Base.h"
-#include "Object.h"
-#include "Vertex.h"
-
-namespace gameplay
-{
-
-class MeshPart : public Object
-{
-public:
-
-    enum PrimitiveType
-    {
-        TRIANGLES = 4,      // GL_TRIANGLES
-        TRIANGLE_STRIP = 5, // GL_TRIANGLE_STRIP
-        LINES = 1,          // GL_LINES
-        LINE_STRIP = 3,     // GL_LINE_STRIP
-        POINTS = 0          // GL_POINTS
-    };
-
-    enum IndexFormat
-    {
-        INDEX16 = 0x1403, // GL_UNSIGNED_SHORT
-        INDEX32 = 0x1405  // GL_UNSIGNED_INT
-    };
-
-    /**
-     * Constructor.
-     */
-    MeshPart(void);
-
-    /**
-     * Destructor.
-     */
-    virtual ~MeshPart(void);
-
-    virtual unsigned int getTypeId(void) const;
-    virtual const char* getElementName(void) const;
-    virtual void writeBinary(FILE* file);
-    virtual void writeText(FILE* file);
-
-    /**
-     * Adds an index to the list of indices.
-     */
-    void addIndex(unsigned int index);
-
-    /**
-     * Returns the number of indices.
-     */
-    size_t getIndicesCount() const;
-
-    /**
-     * Returns the index format.
-     */
-    IndexFormat getIndexFormat() const;
-
-    /**
-     * Gets the value of the index at the specificied location.
-     */
-    unsigned int getIndex(unsigned int i) const;
-
-private:
-
-    /**
-     * Returns the size of the indices array in bytes.
-     */
-    unsigned int indicesByteSize() const;
-
-    /**
-     * Returns the size of an index.
-     */
-    unsigned int indexFormatSize() const;
-
-    /**
-     * Updates the index format if newIndex is larger than 256 or 65536.
-     */
-    void updateIndexFormat(unsigned int newIndex);
-
-    /**
-     * Writes the index to the binary file stream.
-     * The number of bytes written depends on indexFormat.
-     */
-    void writeBinaryIndex(unsigned int index, FILE* file);
-
-private:
-
-    unsigned int _primitiveType;
-    IndexFormat _indexFormat;
-    std::vector<unsigned int> _indices;
-};
-
-}
-
-#endif
+#ifndef MESHPART_H_
+#define MESHPART_H_
+
+#include "Base.h"
+#include "Object.h"
+#include "Vertex.h"
+
+namespace gameplay
+{
+
+class MeshPart : public Object
+{
+public:
+
+    enum PrimitiveType
+    {
+        TRIANGLES = 4,      // GL_TRIANGLES
+        TRIANGLE_STRIP = 5, // GL_TRIANGLE_STRIP
+        LINES = 1,          // GL_LINES
+        LINE_STRIP = 3,     // GL_LINE_STRIP
+        POINTS = 0          // GL_POINTS
+    };
+
+    enum IndexFormat
+    {
+        INDEX16 = 0x1403, // GL_UNSIGNED_SHORT
+        INDEX32 = 0x1405  // GL_UNSIGNED_INT
+    };
+
+    /**
+     * Constructor.
+     */
+    MeshPart(void);
+
+    /**
+     * Destructor.
+     */
+    virtual ~MeshPart(void);
+
+    virtual unsigned int getTypeId(void) const;
+    virtual const char* getElementName(void) const;
+    virtual void writeBinary(FILE* file);
+    virtual void writeText(FILE* file);
+
+    /**
+     * Adds an index to the list of indices.
+     */
+    void addIndex(unsigned int index);
+
+    /**
+     * Returns the number of indices.
+     */
+    size_t getIndicesCount() const;
+
+    /**
+     * Returns the index format.
+     */
+    IndexFormat getIndexFormat() const;
+
+    /**
+     * Gets the value of the index at the specificied location.
+     */
+    unsigned int getIndex(unsigned int i) const;
+
+private:
+
+    /**
+     * Returns the size of the indices array in bytes.
+     */
+    unsigned int indicesByteSize() const;
+
+    /**
+     * Returns the size of an index.
+     */
+    unsigned int indexFormatSize() const;
+
+    /**
+     * Updates the index format if newIndex is larger than 256 or 65536.
+     */
+    void updateIndexFormat(unsigned int newIndex);
+
+    /**
+     * Writes the index to the binary file stream.
+     * The number of bytes written depends on indexFormat.
+     */
+    void writeBinaryIndex(unsigned int index, FILE* file);
+
+private:
+
+    unsigned int _primitiveType;
+    IndexFormat _indexFormat;
+    std::vector<unsigned int> _indices;
+};
+
+}
+
+#endif

+ 450 - 450
tools/encoder/src/MeshSkin.cpp

@@ -1,450 +1,450 @@
-#include "Base.h"
-#include "MeshSkin.h"
-#include "Node.h"
-#include "StringUtil.h"
-#include "Mesh.h"
-#include "GPBFile.h"
-#include "Animations.h"
-#include "Transform.h"
-#include "Curve.h"
-#include "Matrix.h"
-
-namespace gameplay
-{
-
-MeshSkin::MeshSkin(void) :
-    _vertexInfluenceCount(0)
-{
-    Matrix::setIdentity(_bindShape);
-}
-
-MeshSkin::~MeshSkin(void)
-{
-}
-
-unsigned int MeshSkin::getTypeId(void) const
-{
-    return MESHPART_ID;
-}
-
-const char* MeshSkin::getElementName(void) const
-{
-    return "MeshSkin";
-}
-
-void MeshSkin::writeBinary(FILE* file)
-{
-    Object::writeBinary(file);
-    write(_bindShape, 16, file);
-    write((unsigned int)_joints.size(), file);
-    for (std::vector<Node*>::const_iterator i = _joints.begin(); i != _joints.end(); ++i)
-    {
-        (*i)->writeBinaryXref(file);
-    }
-    write((unsigned int)_bindPoses.size() * 16, file);
-    for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); ++i)
-    {
-        write(i->m, 16, file);
-    }
-
-    /*
-    // Write joint bounding spheres
-    write((unsigned int)_jointBounds.size(), file);
-    for (unsigned int i = 0; i < _jointBounds.size(); ++i)
-    {
-        BoundingVolume& v = _jointBounds[i];
-        write(v.center.x, file);
-        write(v.center.y, file);
-        write(v.center.z, file);
-        write(v.radius, file);
-    }
-    */
-}
-
-void MeshSkin::writeText(FILE* file)
-{
-    fprintElementStart(file);
-    fprintf(file, "<bindShape>");
-    fprintfMatrix4f(file, _bindShape);
-    fprintf(file, "</bindShape>");
-    fprintf(file, "<joints>");
-    for (std::vector<std::string>::const_iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
-    {
-        fprintf(file, "%s ", i->c_str());
-    }
-    fprintf(file, "</joints>\n");
-    fprintf(file, "<bindPoses count=\"%lu\">", _bindPoses.size() * 16);
-    for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); ++i)
-    {
-        for (unsigned int j = 0; j < 16; ++j)
-        {
-            fprintf(file, "%f ", i->m[j]);
-        }
-    }
-    fprintf(file, "</bindPoses>\n");
-
-    fprintElementEnd(file);
-}
-
-unsigned int MeshSkin::getJointCount() const
-{
-    return _joints.size();
-}
-
-void MeshSkin::setBindShape(const float data[])
-{
-    for (int i = 0; i < 16; ++i)
-    {
-        _bindShape[i] = data[i];
-    }
-}
-
-void MeshSkin::setVertexInfluenceCount(unsigned int count)
-{
-    _vertexInfluenceCount = count;
-}
-
-void MeshSkin::setJointNames(const std::vector<std::string>& list)
-{
-    _jointNames = list;
-}
-
-const std::vector<std::string>& MeshSkin::getJointNames()
-{
-    return _jointNames;
-}
-
-const std::vector<Node*>& MeshSkin::getJoints() const
-{
-    return _joints;
-}
-
-void MeshSkin::setJoints(const std::vector<Node*>& list)
-{
-    _joints = list;
-}
-
-void MeshSkin::setBindPoses(std::vector<Matrix>& list)
-{
-    for (std::vector<Matrix>::iterator i = list.begin(); i != list.end(); ++i)
-    {
-        _bindPoses.push_back(*i);
-    }
-}
-
-bool MeshSkin::hasJoint(const char* id)
-{
-    for (std::vector<std::string>::iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
-    {
-        if (equals(*i, id))
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-void MeshSkin::computeBounds()
-{
-    // Find the offset of the blend indices and blend weights within the mesh vertices
-    int blendIndexOffset = -1;
-    int blendWeightOffset = -1;
-    for (unsigned int i = 0, count = _mesh->getVertexElementCount(); i < count; ++i)
-    {
-        const VertexElement& e = _mesh->getVertexElement(i);
-        switch (e.usage)
-        {
-        case BLENDINDICES:
-            blendIndexOffset = i;
-            break;
-        case BLENDWEIGHTS:
-            blendWeightOffset = i;
-            break;
-        }
-    }
-    if (blendIndexOffset == -1 || blendWeightOffset == -1)
-    {
-        // Need blend indices and blend weights to calculate skinned bounding volume
-        return;
-    }
-
-    LOG(2, "Computing bounds for skin of mesh: %s\n", _mesh->getId().c_str());
-
-    // Get the root joint
-    Node* rootJoint = _joints[0];
-    Node* parent = rootJoint->getParent();
-    while (parent)
-    {
-        // Is this parent in the list of joints that form the skeleton?
-        // If not, then it's simply a parent node to the root joint
-        if (find(_joints.begin(), _joints.end(), parent) != _joints.end())
-        {
-            rootJoint = parent;
-        }
-        parent = parent->getParent();
-    }
-
-    // If the root joint has a parent node, temporarily detach it so that its transform is
-    // not included in the bounding volume calculation below
-    Node* rootJointParent = rootJoint->getParent();
-    if (rootJointParent)
-    {
-        rootJointParent->removeChild(rootJoint);
-    }
-
-    unsigned int jointCount = _joints.size();
-    unsigned int vertexCount = _mesh->getVertexCount();
-
-    LOG(3, "  %u joints found.\n", jointCount);
-
-    std::vector<AnimationChannel*> channels;
-    std::vector<Node*> channelTargets;
-    std::vector<Curve*> curves;
-    std::vector<Vector3> vertices;
-    _jointBounds.resize(jointCount);
-
-    // Construct a list of all animation channels that target the joints affecting this mesh skin
-    LOG(3, "  Collecting animations...\n");
-    LOG(3, "  0%%\r");
-    for (unsigned int i = 0; i < jointCount; ++i)
-    {
-        Node* joint = _joints[i];
-
-        // Find all animations that target this joint
-        Animations* animations = GPBFile::getInstance()->getAnimations();
-        for (unsigned int j = 0, animationCount = animations->getAnimationCount(); j < animationCount; ++j)
-        {
-            Animation* animation = animations->getAnimation(j);
-            for (unsigned int k = 0, channelCount = animation->getAnimationChannelCount(); k < channelCount; ++k)
-            {
-                AnimationChannel* channel = animation->getAnimationChannel(k);
-                if (channel->getTargetId() == joint->getId())
-                {
-                    if (find(channels.begin(), channels.end(), channel) == channels.end())
-                    {
-                        channels.push_back(channel);
-                        channelTargets.push_back(joint);
-                    }
-                }
-            }
-        }
-
-        // Calculate the local bounding volume for this joint
-        vertices.clear();
-        BoundingVolume jointBounds;
-        jointBounds.min.set(FLT_MAX, FLT_MAX, FLT_MAX);
-        jointBounds.max.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
-        for (unsigned int j = 0; j < vertexCount; ++j)
-        {
-            const Vertex& v = _mesh->getVertex(j);
-
-            if ((v.blendIndices.x == i && !ISZERO(v.blendWeights.x)) ||
-                (v.blendIndices.y == i && !ISZERO(v.blendWeights.y)) ||
-                (v.blendIndices.z == i && !ISZERO(v.blendWeights.z)) ||
-                (v.blendIndices.w == i && !ISZERO(v.blendWeights.w)))
-            {
-                vertices.push_back(v.position);
-                // Update box min/max
-                if (v.position.x < jointBounds.min.x)
-                    jointBounds.min.x = v.position.x;
-                if (v.position.y < jointBounds.min.y)
-                    jointBounds.min.y = v.position.y;
-                if (v.position.z < jointBounds.min.z)
-                    jointBounds.min.z = v.position.z;
-                if (v.position.x > jointBounds.max.x)
-                    jointBounds.max.x = v.position.x;
-                if (v.position.y > jointBounds.max.y)
-                    jointBounds.max.y = v.position.y;
-                if (v.position.z > jointBounds.max.z)
-                    jointBounds.max.z = v.position.z;
-            }
-        }
-        if (vertices.size() > 0)
-        {
-            // Compute center point
-            Vector3::add(jointBounds.min, jointBounds.max, &jointBounds.center);
-            jointBounds.center.scale(0.5f);
-            // Compute radius
-            for (unsigned int j = 0, jointVertexCount = vertices.size(); j < jointVertexCount; ++j)
-            {
-                float d = jointBounds.center.distanceSquared(vertices[j]);
-                if (d > jointBounds.radius)
-                    jointBounds.radius = d;
-            }
-            jointBounds.radius = sqrt(jointBounds.radius);
-        }
-        _jointBounds[i] = jointBounds;
-
-        LOG(3, "  %d%%\r", (int)((float)(i+1) / (float)jointCount * 100.0f));
-    }
-    LOG(3, "\n");
-
-    unsigned int channelCount = channels.size();
-
-    // Create a Curve for each animation channel
-    float maxDuration = 0.0f;
-    LOG(3, "  Building animation curves...\n");
-    LOG(3, "  0%%\r");
-    for (unsigned int i = 0; i < channelCount; ++i)
-    {
-        AnimationChannel* channel = channels[i];
-
-        const std::vector<float>& keyTimes = channel->getKeyTimes();
-        unsigned int keyCount = keyTimes.size();
-        if (keyCount == 0)
-            continue;
-
-        // Create a curve for this animation channel
-        Curve* curve = NULL;
-        switch (channel->getTargetAttribute())
-        {
-        case Transform::ANIMATE_SCALE_ROTATE_TRANSLATE:
-            curve = new Curve(keyCount, 10);
-            curve->setQuaternionOffset(3);
-            break;
-        }
-        if (curve == NULL)
-        {
-            // Unsupported/not implemented curve type 
-            continue;
-        }
-
-        // Copy key values into a temporary array
-        unsigned int keyValuesCount = channel->getKeyValues().size();
-        float* keyValues = new float[keyValuesCount];
-        for (unsigned int j = 0; j < keyValuesCount; ++j)
-            keyValues[j] = channel->getKeyValues()[j];
-
-        // Determine animation duration
-        float startTime = keyTimes[0];
-        float duration = keyTimes[keyCount-1] - startTime;
-        if (duration > maxDuration)
-            maxDuration = duration;
-
-        if (duration > 0.0f)
-        {
-            // Set curve points
-            float* keyValuesPtr = keyValues;
-            for (unsigned int j = 0; j < keyCount; ++j)
-            {
-                // Store time normalized, between 0-1
-                float t = (keyTimes[j] - startTime) / duration;
-
-                // Set the curve point
-                // TODO: Handle other interpolation types
-                curve->setPoint(j, t, keyValuesPtr, gameplay::Curve::LINEAR);
-
-                // Move to the next point on the curve
-                keyValuesPtr += curve->getComponentCount();
-            }
-            curves.push_back(curve);
-        }
-
-        delete[] keyValues;
-        keyValues = NULL;
-
-        LOG(3, "  %d%%\r", (int)((float)(i+1) / (float)channelCount * 100.0f));
-    }
-    LOG(3, "\n");
-
-    // Compute a total combined bounding volume for the MeshSkin that contains all possible
-    // vertex positions for all animations targeting the skin. This rough approximation allows
-    // us to store a volume that can be used for rough intersection tests (such as for visibility
-    // determination) efficiently at runtime.
-
-    // Backup existing node transforms so we can restore them when we are finished
-    Matrix* oldTransforms = new Matrix[jointCount];
-    for (unsigned int i = 0; i < jointCount; ++i)
-    {
-        memcpy(oldTransforms[i].m, _joints[i]->getTransformMatrix().m, 16 * sizeof(float));
-    }
-
-    float time = 0.0f;
-    float srt[10];
-    Matrix temp;
-    Matrix* jointTransforms = new Matrix[jointCount];
-    _mesh->bounds.min.set(FLT_MAX, FLT_MAX, FLT_MAX);
-    _mesh->bounds.max.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
-    _mesh->bounds.center.set(0, 0, 0);
-    _mesh->bounds.radius = 0;
-    Vector3 skinnedPos;
-    Vector3 tempPos;
-    LOG(3, "  Evaluating joints...\n");
-    LOG(3, "  0%%\r");
-    BoundingVolume finalBounds;
-    while (time <= maxDuration)
-    {
-        // Evaluate joint transforms at this time interval
-        for (unsigned int i = 0, curveCount = curves.size(); i < curveCount; ++i)
-        {
-            Node* joint = channelTargets[i];
-            Curve* curve = curves[i];
-
-            // Evalulate the curve at this time to get the new value
-            float tn = time / maxDuration;
-            if (tn > 1.0f)
-                tn = 1.0f;
-            curve->evaluate(tn, srt);
-
-            // Update the joint's local transform
-            Matrix::createTranslation(srt[7], srt[8], srt[9], temp.m);
-            temp.rotate(*((Quaternion*)&srt[3]));
-            temp.scale(srt[0], srt[1], srt[2]);
-            joint->setTransformMatrix(temp.m);
-        }
-
-        // Store the final matrix pallette of resovled world space joint matrices
-        std::vector<Matrix>::const_iterator bindPoseItr = _bindPoses.begin();
-        for (unsigned int i = 0; i < jointCount; ++i, bindPoseItr++)
-        {
-            BoundingVolume bounds = _jointBounds[i];
-            if (ISZERO(bounds.radius))
-                continue;
-
-            Matrix& m = jointTransforms[i];
-            Matrix::multiply(_joints[i]->getWorldMatrix().m, bindPoseItr->m, m.m);
-            Matrix::multiply(m.m, _bindShape, m.m);
-
-            // Get a world-space bounding volume for this joint
-            bounds.transform(m);
-            if (ISZERO(finalBounds.radius))
-                finalBounds = bounds;
-            else
-                finalBounds.merge(bounds);
-        }
-
-        // Increment time by 1/30th of second (~ 33 ms)
-        if (time < maxDuration && (time + 33.0f) > maxDuration)
-            time = maxDuration;
-        else
-            time += 33.0f;
-
-        LOG(3, "  %d%%\r", (int)(time / maxDuration * 100.0f));
-    }
-    LOG(3, "\n");
-
-    // Update the bounding sphere for the mesh
-    _mesh->bounds = finalBounds;
-
-    // Restore original joint transforms
-    for (unsigned int i = 0; i < jointCount; ++i)
-    {
-        _joints[i]->setTransformMatrix(oldTransforms[i].m);
-    }
-
-    // Cleanup
-    for (unsigned int i = 0, curveCount = curves.size(); i < curveCount; ++i)
-    {
-        delete curves[i];
-    }
-    delete[] oldTransforms;
-    delete[] jointTransforms;
-
-    // Restore removed joints
-    if (rootJointParent)
-    {
-        rootJointParent->addChild(rootJoint);
-    }
-}
-
-}
+#include "Base.h"
+#include "MeshSkin.h"
+#include "Node.h"
+#include "StringUtil.h"
+#include "Mesh.h"
+#include "GPBFile.h"
+#include "Animations.h"
+#include "Transform.h"
+#include "Curve.h"
+#include "Matrix.h"
+
+namespace gameplay
+{
+
+MeshSkin::MeshSkin(void) :
+    _vertexInfluenceCount(0)
+{
+    Matrix::setIdentity(_bindShape);
+}
+
+MeshSkin::~MeshSkin(void)
+{
+}
+
+unsigned int MeshSkin::getTypeId(void) const
+{
+    return MESHPART_ID;
+}
+
+const char* MeshSkin::getElementName(void) const
+{
+    return "MeshSkin";
+}
+
+void MeshSkin::writeBinary(FILE* file)
+{
+    Object::writeBinary(file);
+    write(_bindShape, 16, file);
+    write((unsigned int)_joints.size(), file);
+    for (std::vector<Node*>::const_iterator i = _joints.begin(); i != _joints.end(); ++i)
+    {
+        (*i)->writeBinaryXref(file);
+    }
+    write((unsigned int)_bindPoses.size() * 16, file);
+    for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); ++i)
+    {
+        write(i->m, 16, file);
+    }
+
+    /*
+    // Write joint bounding spheres
+    write((unsigned int)_jointBounds.size(), file);
+    for (unsigned int i = 0; i < _jointBounds.size(); ++i)
+    {
+        BoundingVolume& v = _jointBounds[i];
+        write(v.center.x, file);
+        write(v.center.y, file);
+        write(v.center.z, file);
+        write(v.radius, file);
+    }
+    */
+}
+
+void MeshSkin::writeText(FILE* file)
+{
+    fprintElementStart(file);
+    fprintf(file, "<bindShape>");
+    fprintfMatrix4f(file, _bindShape);
+    fprintf(file, "</bindShape>");
+    fprintf(file, "<joints>");
+    for (std::vector<std::string>::const_iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
+    {
+        fprintf(file, "%s ", i->c_str());
+    }
+    fprintf(file, "</joints>\n");
+    fprintf(file, "<bindPoses count=\"%lu\">", _bindPoses.size() * 16);
+    for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); ++i)
+    {
+        for (unsigned int j = 0; j < 16; ++j)
+        {
+            fprintf(file, "%f ", i->m[j]);
+        }
+    }
+    fprintf(file, "</bindPoses>\n");
+
+    fprintElementEnd(file);
+}
+
+unsigned int MeshSkin::getJointCount() const
+{
+    return _joints.size();
+}
+
+void MeshSkin::setBindShape(const float data[])
+{
+    for (int i = 0; i < 16; ++i)
+    {
+        _bindShape[i] = data[i];
+    }
+}
+
+void MeshSkin::setVertexInfluenceCount(unsigned int count)
+{
+    _vertexInfluenceCount = count;
+}
+
+void MeshSkin::setJointNames(const std::vector<std::string>& list)
+{
+    _jointNames = list;
+}
+
+const std::vector<std::string>& MeshSkin::getJointNames()
+{
+    return _jointNames;
+}
+
+const std::vector<Node*>& MeshSkin::getJoints() const
+{
+    return _joints;
+}
+
+void MeshSkin::setJoints(const std::vector<Node*>& list)
+{
+    _joints = list;
+}
+
+void MeshSkin::setBindPoses(std::vector<Matrix>& list)
+{
+    for (std::vector<Matrix>::iterator i = list.begin(); i != list.end(); ++i)
+    {
+        _bindPoses.push_back(*i);
+    }
+}
+
+bool MeshSkin::hasJoint(const char* id)
+{
+    for (std::vector<std::string>::iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
+    {
+        if (equals(*i, id))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+void MeshSkin::computeBounds()
+{
+    // Find the offset of the blend indices and blend weights within the mesh vertices
+    int blendIndexOffset = -1;
+    int blendWeightOffset = -1;
+    for (unsigned int i = 0, count = _mesh->getVertexElementCount(); i < count; ++i)
+    {
+        const VertexElement& e = _mesh->getVertexElement(i);
+        switch (e.usage)
+        {
+        case BLENDINDICES:
+            blendIndexOffset = i;
+            break;
+        case BLENDWEIGHTS:
+            blendWeightOffset = i;
+            break;
+        }
+    }
+    if (blendIndexOffset == -1 || blendWeightOffset == -1)
+    {
+        // Need blend indices and blend weights to calculate skinned bounding volume
+        return;
+    }
+
+    LOG(2, "Computing bounds for skin of mesh: %s\n", _mesh->getId().c_str());
+
+    // Get the root joint
+    Node* rootJoint = _joints[0];
+    Node* parent = rootJoint->getParent();
+    while (parent)
+    {
+        // Is this parent in the list of joints that form the skeleton?
+        // If not, then it's simply a parent node to the root joint
+        if (find(_joints.begin(), _joints.end(), parent) != _joints.end())
+        {
+            rootJoint = parent;
+        }
+        parent = parent->getParent();
+    }
+
+    // If the root joint has a parent node, temporarily detach it so that its transform is
+    // not included in the bounding volume calculation below
+    Node* rootJointParent = rootJoint->getParent();
+    if (rootJointParent)
+    {
+        rootJointParent->removeChild(rootJoint);
+    }
+
+    unsigned int jointCount = _joints.size();
+    unsigned int vertexCount = _mesh->getVertexCount();
+
+    LOG(3, "  %u joints found.\n", jointCount);
+
+    std::vector<AnimationChannel*> channels;
+    std::vector<Node*> channelTargets;
+    std::vector<Curve*> curves;
+    std::vector<Vector3> vertices;
+    _jointBounds.resize(jointCount);
+
+    // Construct a list of all animation channels that target the joints affecting this mesh skin
+    LOG(3, "  Collecting animations...\n");
+    LOG(3, "  0%%\r");
+    for (unsigned int i = 0; i < jointCount; ++i)
+    {
+        Node* joint = _joints[i];
+
+        // Find all animations that target this joint
+        Animations* animations = GPBFile::getInstance()->getAnimations();
+        for (unsigned int j = 0, animationCount = animations->getAnimationCount(); j < animationCount; ++j)
+        {
+            Animation* animation = animations->getAnimation(j);
+            for (unsigned int k = 0, channelCount = animation->getAnimationChannelCount(); k < channelCount; ++k)
+            {
+                AnimationChannel* channel = animation->getAnimationChannel(k);
+                if (channel->getTargetId() == joint->getId())
+                {
+                    if (find(channels.begin(), channels.end(), channel) == channels.end())
+                    {
+                        channels.push_back(channel);
+                        channelTargets.push_back(joint);
+                    }
+                }
+            }
+        }
+
+        // Calculate the local bounding volume for this joint
+        vertices.clear();
+        BoundingVolume jointBounds;
+        jointBounds.min.set(FLT_MAX, FLT_MAX, FLT_MAX);
+        jointBounds.max.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+        for (unsigned int j = 0; j < vertexCount; ++j)
+        {
+            const Vertex& v = _mesh->getVertex(j);
+
+            if ((v.blendIndices.x == i && !ISZERO(v.blendWeights.x)) ||
+                (v.blendIndices.y == i && !ISZERO(v.blendWeights.y)) ||
+                (v.blendIndices.z == i && !ISZERO(v.blendWeights.z)) ||
+                (v.blendIndices.w == i && !ISZERO(v.blendWeights.w)))
+            {
+                vertices.push_back(v.position);
+                // Update box min/max
+                if (v.position.x < jointBounds.min.x)
+                    jointBounds.min.x = v.position.x;
+                if (v.position.y < jointBounds.min.y)
+                    jointBounds.min.y = v.position.y;
+                if (v.position.z < jointBounds.min.z)
+                    jointBounds.min.z = v.position.z;
+                if (v.position.x > jointBounds.max.x)
+                    jointBounds.max.x = v.position.x;
+                if (v.position.y > jointBounds.max.y)
+                    jointBounds.max.y = v.position.y;
+                if (v.position.z > jointBounds.max.z)
+                    jointBounds.max.z = v.position.z;
+            }
+        }
+        if (vertices.size() > 0)
+        {
+            // Compute center point
+            Vector3::add(jointBounds.min, jointBounds.max, &jointBounds.center);
+            jointBounds.center.scale(0.5f);
+            // Compute radius
+            for (unsigned int j = 0, jointVertexCount = vertices.size(); j < jointVertexCount; ++j)
+            {
+                float d = jointBounds.center.distanceSquared(vertices[j]);
+                if (d > jointBounds.radius)
+                    jointBounds.radius = d;
+            }
+            jointBounds.radius = sqrt(jointBounds.radius);
+        }
+        _jointBounds[i] = jointBounds;
+
+        LOG(3, "  %d%%\r", (int)((float)(i+1) / (float)jointCount * 100.0f));
+    }
+    LOG(3, "\n");
+
+    unsigned int channelCount = channels.size();
+
+    // Create a Curve for each animation channel
+    float maxDuration = 0.0f;
+    LOG(3, "  Building animation curves...\n");
+    LOG(3, "  0%%\r");
+    for (unsigned int i = 0; i < channelCount; ++i)
+    {
+        AnimationChannel* channel = channels[i];
+
+        const std::vector<float>& keyTimes = channel->getKeyTimes();
+        unsigned int keyCount = keyTimes.size();
+        if (keyCount == 0)
+            continue;
+
+        // Create a curve for this animation channel
+        Curve* curve = NULL;
+        switch (channel->getTargetAttribute())
+        {
+        case Transform::ANIMATE_SCALE_ROTATE_TRANSLATE:
+            curve = new Curve(keyCount, 10);
+            curve->setQuaternionOffset(3);
+            break;
+        }
+        if (curve == NULL)
+        {
+            // Unsupported/not implemented curve type 
+            continue;
+        }
+
+        // Copy key values into a temporary array
+        unsigned int keyValuesCount = channel->getKeyValues().size();
+        float* keyValues = new float[keyValuesCount];
+        for (unsigned int j = 0; j < keyValuesCount; ++j)
+            keyValues[j] = channel->getKeyValues()[j];
+
+        // Determine animation duration
+        float startTime = keyTimes[0];
+        float duration = keyTimes[keyCount-1] - startTime;
+        if (duration > maxDuration)
+            maxDuration = duration;
+
+        if (duration > 0.0f)
+        {
+            // Set curve points
+            float* keyValuesPtr = keyValues;
+            for (unsigned int j = 0; j < keyCount; ++j)
+            {
+                // Store time normalized, between 0-1
+                float t = (keyTimes[j] - startTime) / duration;
+
+                // Set the curve point
+                // TODO: Handle other interpolation types
+                curve->setPoint(j, t, keyValuesPtr, gameplay::Curve::LINEAR);
+
+                // Move to the next point on the curve
+                keyValuesPtr += curve->getComponentCount();
+            }
+            curves.push_back(curve);
+        }
+
+        delete[] keyValues;
+        keyValues = NULL;
+
+        LOG(3, "  %d%%\r", (int)((float)(i+1) / (float)channelCount * 100.0f));
+    }
+    LOG(3, "\n");
+
+    // Compute a total combined bounding volume for the MeshSkin that contains all possible
+    // vertex positions for all animations targeting the skin. This rough approximation allows
+    // us to store a volume that can be used for rough intersection tests (such as for visibility
+    // determination) efficiently at runtime.
+
+    // Backup existing node transforms so we can restore them when we are finished
+    Matrix* oldTransforms = new Matrix[jointCount];
+    for (unsigned int i = 0; i < jointCount; ++i)
+    {
+        memcpy(oldTransforms[i].m, _joints[i]->getTransformMatrix().m, 16 * sizeof(float));
+    }
+
+    float time = 0.0f;
+    float srt[10];
+    Matrix temp;
+    Matrix* jointTransforms = new Matrix[jointCount];
+    _mesh->bounds.min.set(FLT_MAX, FLT_MAX, FLT_MAX);
+    _mesh->bounds.max.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+    _mesh->bounds.center.set(0, 0, 0);
+    _mesh->bounds.radius = 0;
+    Vector3 skinnedPos;
+    Vector3 tempPos;
+    LOG(3, "  Evaluating joints...\n");
+    LOG(3, "  0%%\r");
+    BoundingVolume finalBounds;
+    while (time <= maxDuration)
+    {
+        // Evaluate joint transforms at this time interval
+        for (unsigned int i = 0, curveCount = curves.size(); i < curveCount; ++i)
+        {
+            Node* joint = channelTargets[i];
+            Curve* curve = curves[i];
+
+            // Evalulate the curve at this time to get the new value
+            float tn = time / maxDuration;
+            if (tn > 1.0f)
+                tn = 1.0f;
+            curve->evaluate(tn, srt);
+
+            // Update the joint's local transform
+            Matrix::createTranslation(srt[7], srt[8], srt[9], temp.m);
+            temp.rotate(*((Quaternion*)&srt[3]));
+            temp.scale(srt[0], srt[1], srt[2]);
+            joint->setTransformMatrix(temp.m);
+        }
+
+        // Store the final matrix pallette of resovled world space joint matrices
+        std::vector<Matrix>::const_iterator bindPoseItr = _bindPoses.begin();
+        for (unsigned int i = 0; i < jointCount; ++i, bindPoseItr++)
+        {
+            BoundingVolume bounds = _jointBounds[i];
+            if (ISZERO(bounds.radius))
+                continue;
+
+            Matrix& m = jointTransforms[i];
+            Matrix::multiply(_joints[i]->getWorldMatrix().m, bindPoseItr->m, m.m);
+            Matrix::multiply(m.m, _bindShape, m.m);
+
+            // Get a world-space bounding volume for this joint
+            bounds.transform(m);
+            if (ISZERO(finalBounds.radius))
+                finalBounds = bounds;
+            else
+                finalBounds.merge(bounds);
+        }
+
+        // Increment time by 1/30th of second (~ 33 ms)
+        if (time < maxDuration && (time + 33.0f) > maxDuration)
+            time = maxDuration;
+        else
+            time += 33.0f;
+
+        LOG(3, "  %d%%\r", (int)(time / maxDuration * 100.0f));
+    }
+    LOG(3, "\n");
+
+    // Update the bounding sphere for the mesh
+    _mesh->bounds = finalBounds;
+
+    // Restore original joint transforms
+    for (unsigned int i = 0; i < jointCount; ++i)
+    {
+        _joints[i]->setTransformMatrix(oldTransforms[i].m);
+    }
+
+    // Cleanup
+    for (unsigned int i = 0, curveCount = curves.size(); i < curveCount; ++i)
+    {
+        delete curves[i];
+    }
+    delete[] oldTransforms;
+    delete[] jointTransforms;
+
+    // Restore removed joints
+    if (rootJointParent)
+    {
+        rootJointParent->addChild(rootJoint);
+    }
+}
+
+}

+ 77 - 77
tools/encoder/src/MeshSkin.h

@@ -1,77 +1,77 @@
-#ifndef MESHSKIN_H_
-#define MESHSKIN_H_
-
-#include "Base.h"
-#include "Object.h"
-#include "Matrix.h"
-#include "Animation.h"
-#include "BoundingVolume.h"
-
-namespace gameplay
-{
-
-class Node;
-class Mesh;
-
-class MeshSkin : public Object
-{
-    friend class Model;
-
-public:
-
-    /**
-     * Constructor.
-     */
-    MeshSkin(void);
-
-    /**
-     * Destructor.
-     */
-    virtual ~MeshSkin(void);
-
-    virtual unsigned int getTypeId(void) const;
-    virtual const char* getElementName(void) const;
-    virtual void writeBinary(FILE* file);
-    virtual void writeText(FILE* file);
-
-    unsigned int getJointCount() const;
-
-    void setBindShape(const float data[]);
-
-    void setVertexInfluenceCount(unsigned int count);
-
-    const std::vector<std::string>& getJointNames();
-
-    void setJointNames(const std::vector<std::string>& list);
-
-    const std::vector<Node*>& getJoints() const;
-
-    void setJoints(const std::vector<Node*>& list);
-
-    void setBindPoses(std::vector<Matrix>& list);
-
-    /**
-     * Returns true if the MeshSkin contains a joint with the given ID.
-     * 
-     * @param id The ID of the joint to search for.
-     * 
-     * @return True if the joint belongs to this skin, false otherwise.
-     */
-    bool hasJoint(const char* id);
-
-    void computeBounds();
-
-private:
-
-    Mesh* _mesh;
-    float _bindShape[16];
-    std::vector<Node*> _joints;
-    std::vector<Matrix> _bindPoses;
-    std::vector<std::string> _jointNames;
-    unsigned int _vertexInfluenceCount;
-    std::vector<BoundingVolume> _jointBounds;
-};
-
-}
-
-#endif
+#ifndef MESHSKIN_H_
+#define MESHSKIN_H_
+
+#include "Base.h"
+#include "Object.h"
+#include "Matrix.h"
+#include "Animation.h"
+#include "BoundingVolume.h"
+
+namespace gameplay
+{
+
+class Node;
+class Mesh;
+
+class MeshSkin : public Object
+{
+    friend class Model;
+
+public:
+
+    /**
+     * Constructor.
+     */
+    MeshSkin(void);
+
+    /**
+     * Destructor.
+     */
+    virtual ~MeshSkin(void);
+
+    virtual unsigned int getTypeId(void) const;
+    virtual const char* getElementName(void) const;
+    virtual void writeBinary(FILE* file);
+    virtual void writeText(FILE* file);
+
+    unsigned int getJointCount() const;
+
+    void setBindShape(const float data[]);
+
+    void setVertexInfluenceCount(unsigned int count);
+
+    const std::vector<std::string>& getJointNames();
+
+    void setJointNames(const std::vector<std::string>& list);
+
+    const std::vector<Node*>& getJoints() const;
+
+    void setJoints(const std::vector<Node*>& list);
+
+    void setBindPoses(std::vector<Matrix>& list);
+
+    /**
+     * Returns true if the MeshSkin contains a joint with the given ID.
+     * 
+     * @param id The ID of the joint to search for.
+     * 
+     * @return True if the joint belongs to this skin, false otherwise.
+     */
+    bool hasJoint(const char* id);
+
+    void computeBounds();
+
+private:
+
+    Mesh* _mesh;
+    float _bindShape[16];
+    std::vector<Node*> _joints;
+    std::vector<Matrix> _bindPoses;
+    std::vector<std::string> _jointNames;
+    unsigned int _vertexInfluenceCount;
+    std::vector<BoundingVolume> _jointBounds;
+};
+
+}
+
+#endif

+ 39 - 39
tools/encoder/src/MeshSubSet.cpp

@@ -1,40 +1,40 @@
-#include "MeshSubSet.h"
-
-namespace gameplay
-{
-
-MeshSubSet::MeshSubSet(void)
-{
-    
-}
-
-
-MeshSubSet::~MeshSubSet(void)
-{
-}
-
-unsigned int MeshSubSet::getTypeId(void)
-{
-    return MESHPART_ID;
-}
-    
-const char* MeshSubSet::getElementName(void)
-{
-    return "MeshSubSet";
-}
-
-void MeshSubSet::writeBinary(FILE* file)
-{
-    write(getTypeId(), file);
-
-}
-void MeshSubSet::writeText(FILE* file)
-{
-    fprintElementStart(file);
-
-    fprintfElement(file, "%d ", "indices", indices);
-
-    fprintElementEnd(file);
-}
-
+#include "MeshSubSet.h"
+
+namespace gameplay
+{
+
+MeshSubSet::MeshSubSet(void)
+{
+    
+}
+
+
+MeshSubSet::~MeshSubSet(void)
+{
+}
+
+unsigned int MeshSubSet::getTypeId(void)
+{
+    return MESHPART_ID;
+}
+    
+const char* MeshSubSet::getElementName(void)
+{
+    return "MeshSubSet";
+}
+
+void MeshSubSet::writeBinary(FILE* file)
+{
+    write(getTypeId(), file);
+
+}
+void MeshSubSet::writeText(FILE* file)
+{
+    fprintElementStart(file);
+
+    fprintfElement(file, "%d ", "indices", indices);
+
+    fprintElementEnd(file);
+}
+
 }

+ 31 - 31
tools/encoder/src/MeshSubSet.h

@@ -1,31 +1,31 @@
-#ifndef MESHSUBSET_H_
-#define MESHSUBSET_H_
-
-#include "Base.h"
-#include "Object.h"
-#include "Vertex.h"
-
-namespace gameplay 
-{
-
-class MeshSubSet : public Object
-{
-public:
-    MeshSubSet(void);
-    virtual ~MeshSubSet(void);
-
-    virtual unsigned int getTypeId(void);
-    virtual const char* getElementName(void);
-    virtual void writeBinary(FILE* file);
-    virtual void writeText(FILE* file);
-
-    std::vector<Vertex*> vertices;
-    std::vector<int> indices;
-    //Set<Vertex*, int> vertexLookupTable;
-    std::map<Vertex, int> vertexLookupTable;
-};
-
-}
-
-#endif
-
+#ifndef MESHSUBSET_H_
+#define MESHSUBSET_H_
+
+#include "Base.h"
+#include "Object.h"
+#include "Vertex.h"
+
+namespace gameplay 
+{
+
+class MeshSubSet : public Object
+{
+public:
+    MeshSubSet(void);
+    virtual ~MeshSubSet(void);
+
+    virtual unsigned int getTypeId(void);
+    virtual const char* getElementName(void);
+    virtual void writeBinary(FILE* file);
+    virtual void writeText(FILE* file);
+
+    std::vector<Vertex*> vertices;
+    std::vector<int> indices;
+    //Set<Vertex*, int> vertexLookupTable;
+    std::map<Vertex, int> vertexLookupTable;
+};
+
+}
+
+#endif
+

+ 155 - 155
tools/encoder/src/Model.cpp

@@ -1,155 +1,155 @@
-#include "Base.h"
-#include "Model.h"
-
-namespace gameplay
-{
-
-Model::Model(void) :
-    _mesh(NULL),
-    _meshSkin(NULL),
-    _material(NULL)
-{
-}
-
-Model::~Model(void)
-{
-}
-
-unsigned int Model::getTypeId(void) const
-{
-    return MODEL_ID;
-}
-const char* Model::getElementName(void) const
-{
-    return "Model";
-}
-void Model::writeBinary(FILE* file)
-{
-    Object::writeBinary(file);
-
-    // xref:Mesh
-    if (_mesh != NULL)
-    {
-        _mesh->writeBinaryXref(file);
-    }
-    else
-    {
-        writeZero(file);
-    }
-    // _meshSkin
-    // Write one unsigned char to indicate if this model has a skin
-    if (_meshSkin != NULL)
-    {
-        write((bool)true, file); // has a skin
-        _meshSkin->writeBinary(file);
-    }
-    else
-    {
-        write((bool)false, file); // doesn't have a skin
-    }
-    // Write the list of materials or zero if there are no materials
-    if (_material && _materials.empty())
-    {
-        write((unsigned int)1, file);
-        write(_material->getId(), file);
-    }
-    else
-    {
-        write((unsigned int)_materials.size(), file);
-        if (_materials.size() > 0)
-        {
-            // Write the material names for each mesh part
-            for (unsigned int i = 0; i < _materials.size(); ++i)
-            {
-                if (Material* mat = _materials[i])
-                {
-                    write(mat->getId(), file);
-                }
-                else
-                {
-                    writeZero(file);
-                }
-            }
-        }
-    }
-}
-
-void Model::writeText(FILE* file)
-{
-    // Compute mesh bounds before writing
-
-    fprintElementStart(file);
-    if (_mesh != NULL)
-    {
-        fprintfElement(file, "ref", _mesh->getId());
-    }
-    if (_meshSkin != NULL)
-    {
-        _meshSkin->writeText(file);
-    }
-    if (_material)
-    {
-        fprintfElement(file, "material", _material->getId().c_str());
-    }
-    for (unsigned int i = 0; i < _materials.size(); ++i)
-    {
-        if (Material* mat = _materials[i])
-        {
-            fprintfElement(file, "material", mat->getId().c_str());
-        }
-    }
-    fprintElementEnd(file);
-}
-
-MeshSkin* Model::getSkin()
-{
-    return _meshSkin;
-}
-
-Mesh* Model::getMesh()
-{
-    return _mesh;
-}
-
-void Model::setMesh(Mesh* mesh)
-{
-    _mesh = mesh;
-
-    if (mesh)
-    {
-        mesh->model = this;
-    }
-
-    if (_mesh && _meshSkin)
-    {
-        _meshSkin->_mesh = _mesh;
-    }
-}
-
-void Model::setSkin(MeshSkin* skin)
-{
-    _meshSkin = skin;
-
-    if (_meshSkin)
-    {
-        _meshSkin->_mesh = _mesh;
-    }
-}
-
-void Model::setMaterial(Material* material, int partIndex)
-{
-    if (partIndex < 0)
-    {
-        _material = material;
-    }
-    else
-    {
-        if ((int)_materials.size() < partIndex + 1)
-        {
-            _materials.resize(partIndex + 1, (Material*)NULL);
-        }
-        _materials[partIndex] = material;
-    }
-}
-
-}
+#include "Base.h"
+#include "Model.h"
+
+namespace gameplay
+{
+
+Model::Model(void) :
+    _mesh(NULL),
+    _meshSkin(NULL),
+    _material(NULL)
+{
+}
+
+Model::~Model(void)
+{
+}
+
+unsigned int Model::getTypeId(void) const
+{
+    return MODEL_ID;
+}
+const char* Model::getElementName(void) const
+{
+    return "Model";
+}
+void Model::writeBinary(FILE* file)
+{
+    Object::writeBinary(file);
+
+    // xref:Mesh
+    if (_mesh != NULL)
+    {
+        _mesh->writeBinaryXref(file);
+    }
+    else
+    {
+        writeZero(file);
+    }
+    // _meshSkin
+    // Write one unsigned char to indicate if this model has a skin
+    if (_meshSkin != NULL)
+    {
+        write((bool)true, file); // has a skin
+        _meshSkin->writeBinary(file);
+    }
+    else
+    {
+        write((bool)false, file); // doesn't have a skin
+    }
+    // Write the list of materials or zero if there are no materials
+    if (_material && _materials.empty())
+    {
+        write((unsigned int)1, file);
+        write(_material->getId(), file);
+    }
+    else
+    {
+        write((unsigned int)_materials.size(), file);
+        if (_materials.size() > 0)
+        {
+            // Write the material names for each mesh part
+            for (unsigned int i = 0; i < _materials.size(); ++i)
+            {
+                if (Material* mat = _materials[i])
+                {
+                    write(mat->getId(), file);
+                }
+                else
+                {
+                    writeZero(file);
+                }
+            }
+        }
+    }
+}
+
+void Model::writeText(FILE* file)
+{
+    // Compute mesh bounds before writing
+
+    fprintElementStart(file);
+    if (_mesh != NULL)
+    {
+        fprintfElement(file, "ref", _mesh->getId());
+    }
+    if (_meshSkin != NULL)
+    {
+        _meshSkin->writeText(file);
+    }
+    if (_material)
+    {
+        fprintfElement(file, "material", _material->getId().c_str());
+    }
+    for (unsigned int i = 0; i < _materials.size(); ++i)
+    {
+        if (Material* mat = _materials[i])
+        {
+            fprintfElement(file, "material", mat->getId().c_str());
+        }
+    }
+    fprintElementEnd(file);
+}
+
+MeshSkin* Model::getSkin()
+{
+    return _meshSkin;
+}
+
+Mesh* Model::getMesh()
+{
+    return _mesh;
+}
+
+void Model::setMesh(Mesh* mesh)
+{
+    _mesh = mesh;
+
+    if (mesh)
+    {
+        mesh->model = this;
+    }
+
+    if (_mesh && _meshSkin)
+    {
+        _meshSkin->_mesh = _mesh;
+    }
+}
+
+void Model::setSkin(MeshSkin* skin)
+{
+    _meshSkin = skin;
+
+    if (_meshSkin)
+    {
+        _meshSkin->_mesh = _mesh;
+    }
+}
+
+void Model::setMaterial(Material* material, int partIndex)
+{
+    if (partIndex < 0)
+    {
+        _material = material;
+    }
+    else
+    {
+        if ((int)_materials.size() < partIndex + 1)
+        {
+            _materials.resize(partIndex + 1, (Material*)NULL);
+        }
+        _materials[partIndex] = material;
+    }
+}
+
+}

+ 47 - 47
tools/encoder/src/Model.h

@@ -1,47 +1,47 @@
-#ifndef MODEL_H_
-#define MODEL_H_
-
-#include "Object.h"
-#include "Mesh.h"
-#include "MeshSkin.h"
-#include "Material.h"
-
-namespace gameplay
-{
-
-class Model : public Object
-{
-public:
-
-    /**
-     * Constructor.
-     */
-    Model(void);
-
-    /**
-     * Destructor.
-     */
-    virtual ~Model(void);
-
-    virtual unsigned int getTypeId(void) const;
-    virtual const char* getElementName(void) const;
-    virtual void writeBinary(FILE* file);
-    virtual void writeText(FILE* file);
-
-    Mesh* getMesh();
-    void setMesh(Mesh* mesh);
-    MeshSkin* getSkin();
-    void setSkin(MeshSkin* skin);
-    void setMaterial(Material* material, int partIndex = -1);
-
-private:
-
-    Mesh* _mesh;
-    MeshSkin* _meshSkin;
-    std::vector<Material*> _materials;
-    Material* _material;
-};
-
-}
-
-#endif
+#ifndef MODEL_H_
+#define MODEL_H_
+
+#include "Object.h"
+#include "Mesh.h"
+#include "MeshSkin.h"
+#include "Material.h"
+
+namespace gameplay
+{
+
+class Model : public Object
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    Model(void);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Model(void);
+
+    virtual unsigned int getTypeId(void) const;
+    virtual const char* getElementName(void) const;
+    virtual void writeBinary(FILE* file);
+    virtual void writeText(FILE* file);
+
+    Mesh* getMesh();
+    void setMesh(Mesh* mesh);
+    MeshSkin* getSkin();
+    void setSkin(MeshSkin* skin);
+    void setMaterial(Material* material, int partIndex = -1);
+
+private:
+
+    Mesh* _mesh;
+    MeshSkin* _meshSkin;
+    std::vector<Material*> _materials;
+    Material* _material;
+};
+
+}
+
+#endif

+ 329 - 329
tools/encoder/src/Node.cpp

@@ -1,329 +1,329 @@
-#include "Base.h"
-#include "Node.h"
-#include "Matrix.h"
-#include "EncoderArguments.h"
-
-#define NODE 1
-#define JOINT 2
-
-namespace gameplay
-{
-
-Node::Node(void) :
-    _childCount(0),
-    _nextSibling(NULL), _previousSibling(NULL),
-    _firstChild(NULL), _lastChild(NULL), _parent(NULL),
-    _camera(NULL), _light(NULL), _model(NULL), _joint(false)
-{
-}
-
-Node::~Node(void)
-{
-}
-
-unsigned int Node::getTypeId(void) const
-{
-    return NODE_ID;
-}
-
-const char* Node::getElementName(void) const
-{
-    return "Node";
-}
-
-void Node::writeBinary(FILE* file)
-{
-    Object::writeBinary(file);
-
-    // node type
-    unsigned int type = _joint ? JOINT : NODE;
-    write(type, file);
-
-    write(_transform.m, 16, file);
-
-    // write parent's id
-    write((_parent) ? _parent->getId() : std::string(), file);
-
-    // children
-    write(getChildCount(), file); // write number of children
-    for (Node* node = getFirstChild(); node != NULL; node = node->getNextSibling())
-    {
-        node->writeBinary(file);
-    }
-
-    // camera
-    if (_camera != NULL)
-    {
-        _camera->writeBinary(file);
-    }
-    else
-    {
-        write((unsigned char)0, file);
-    }
-    // light
-    if (_light != NULL && !_light->isAmbient())
-    {
-        _light->writeBinary(file);
-    }
-    else
-    {
-        write((unsigned char)0, file);
-    }
-    // mesh
-    if (_model != NULL)
-    {
-        _model->writeBinary(file);
-    }
-    else
-    {
-        writeZero(file);
-    }
-}
-
-void Node::writeText(FILE* file)
-{
-    if (isJoint())
-    {
-        fprintf(file, "<%s id=\"%s\" type=\"%s\">\n", getElementName(), getId().c_str(), "JOINT");
-    }
-    else
-    {
-        fprintElementStart(file);
-    }
-    fprintf(file, "<transform>");
-    fprintfMatrix4f(file, _transform.m);
-    fprintf(file, "</transform>\n");
-
-    // children
-    for (Node* node = getFirstChild(); node != NULL; node = node->getNextSibling())
-    {
-        node->writeText(file);
-    }
-    // camera
-    if (_camera != NULL)
-    {
-        _camera->writeText(file);
-    }
-    // light
-    if (_light != NULL && !_light->isAmbient())
-    {
-        _light->writeText(file);
-    }
-    // mesh
-    if (_model != NULL)
-    {
-        _model->writeText(file);
-    }
-    fprintElementEnd(file);
-}
-
-void Node::addChild(Node* child)
-{
-    // If this child is already parented, remove it from its parent
-    if (child->_parent)
-    {
-        child->_parent->removeChild(child);
-    }
-
-    if (_firstChild == NULL)
-    {
-        // No children yet
-        _firstChild = child;
-        child->_previousSibling = NULL;
-    }
-    else
-    {
-        // We already have children, so append to them
-        child->_previousSibling = _lastChild;
-        _lastChild->_nextSibling = child;
-    }
-
-    child->_parent = this;
-    child->_nextSibling = NULL;
-    this->_lastChild = child;
-
-    ++_childCount;
-}
-
-
-void Node::removeChild(Node* child)
-{
-    // The child must have already been our child to remove it
-    if (child->_parent != this)
-    {
-        return;
-    }
-
-    // Remove the child by un-linking it from our child list
-    if (child->_nextSibling)
-    {
-        child->_nextSibling->_previousSibling = child->_previousSibling;
-    }
-    if (child->_previousSibling)
-    {
-        child->_previousSibling->_nextSibling = child->_nextSibling;
-    }
-
-    // Was this child our first or last child?
-    if (child == _firstChild)
-    {
-        _firstChild = child->_nextSibling;
-    }
-    if (child == _lastChild)
-    {
-        _lastChild = child->_previousSibling;
-    }
-
-    // Remove parent and sibling info from the child, now that it is no longer parented
-    child->_parent = NULL;
-    child->_nextSibling = NULL;
-    child->_previousSibling = NULL;
-
-    --_childCount;
-}
-
-void Node::removeChildren()
-{
-    Node* child;
-    while ((child = _firstChild) != NULL)
-    {
-        removeChild(child);
-    }
-}
-
-bool Node::hasChildren() const
-{
-    return (_firstChild != NULL);
-}
-
-unsigned int Node::getChildCount() const
-{
-    return _childCount;
-}
-
-Node* Node::getNextSibling() const
-{
-    return _nextSibling;
-}
-
-Node* Node::getPreviousSibling() const
-{
-    return _previousSibling;
-}
-
-Node* Node::getFirstChild() const
-{
-    return _firstChild;
-}
-
-Node* Node::getLastChild() const
-{
-    return _lastChild;
-}
-
-Node* Node::getParent() const
-{
-    return _parent;
-}
-
-void Node::setCamera(Camera* camera)
-{
-    _camera = camera;
-}
-
-void Node::setLight(Light* light)
-{
-    _light = light;
-}
-
-void Node::setModel(Model* model)
-{
-    _model = model;
-}
-
-const Matrix& Node::getTransformMatrix() const
-{
-    return _transform;
-}
-
-void Node::setTransformMatrix(float matrix[])
-{
-    memcpy(_transform.m, matrix, 16 * sizeof(float));
-}
-
-const Matrix& Node::getWorldMatrix() const
-{
-    if (_parent)
-    {
-        Matrix::multiply(_parent->getWorldMatrix().m, _transform.m, _worldTransform.m);
-    }
-    else
-    {
-        memcpy(_worldTransform.m, _transform.m, 16 * sizeof(float));
-    }
-
-    return _worldTransform;
-}
-
-void Node::resetTransformMatrix()
-{
-    Matrix::setIdentity(_transform.m);
-}
-
-void Node::setIsJoint(bool value)
-{
-    _joint = value;
-}
-
-bool Node::isJoint() const
-{
-    return _joint;
-}
-
-Camera* Node::getCamera() const
-{
-    return _camera;
-}
-
-Light* Node::getLight() const
-{
-    return _light;
-}
-
-Model* Node::getModel() const
-{
-    if (_model)
-    {
-        return _model;
-    }
-    return NULL;
-}
-
-Node* Node::getFirstCameraNode() const
-{
-    if (hasCamera())
-    {
-        return const_cast<Node*>(this);
-    }
-    for (Node* node = getFirstChild(); node != NULL; node = node->getNextSibling())
-    {
-        Node* n = node->getFirstCameraNode();
-        if (n)
-        {
-            return n;
-        }
-    }
-    return NULL;
-}
-
-bool Node::hasCamera() const
-{
-    return _camera != NULL;
-}
-
-bool Node::hasLight() const
-{
-    return _light != NULL;
-}
-
-}
+#include "Base.h"
+#include "Node.h"
+#include "Matrix.h"
+#include "EncoderArguments.h"
+
+#define NODE 1
+#define JOINT 2
+
+namespace gameplay
+{
+
+Node::Node(void) :
+    _childCount(0),
+    _nextSibling(NULL), _previousSibling(NULL),
+    _firstChild(NULL), _lastChild(NULL), _parent(NULL),
+    _camera(NULL), _light(NULL), _model(NULL), _joint(false)
+{
+}
+
+Node::~Node(void)
+{
+}
+
+unsigned int Node::getTypeId(void) const
+{
+    return NODE_ID;
+}
+
+const char* Node::getElementName(void) const
+{
+    return "Node";
+}
+
+void Node::writeBinary(FILE* file)
+{
+    Object::writeBinary(file);
+
+    // node type
+    unsigned int type = _joint ? JOINT : NODE;
+    write(type, file);
+
+    write(_transform.m, 16, file);
+
+    // write parent's id
+    write((_parent) ? _parent->getId() : std::string(), file);
+
+    // children
+    write(getChildCount(), file); // write number of children
+    for (Node* node = getFirstChild(); node != NULL; node = node->getNextSibling())
+    {
+        node->writeBinary(file);
+    }
+
+    // camera
+    if (_camera != NULL)
+    {
+        _camera->writeBinary(file);
+    }
+    else
+    {
+        write((unsigned char)0, file);
+    }
+    // light
+    if (_light != NULL && !_light->isAmbient())
+    {
+        _light->writeBinary(file);
+    }
+    else
+    {
+        write((unsigned char)0, file);
+    }
+    // mesh
+    if (_model != NULL)
+    {
+        _model->writeBinary(file);
+    }
+    else
+    {
+        writeZero(file);
+    }
+}
+
+void Node::writeText(FILE* file)
+{
+    if (isJoint())
+    {
+        fprintf(file, "<%s id=\"%s\" type=\"%s\">\n", getElementName(), getId().c_str(), "JOINT");
+    }
+    else
+    {
+        fprintElementStart(file);
+    }
+    fprintf(file, "<transform>");
+    fprintfMatrix4f(file, _transform.m);
+    fprintf(file, "</transform>\n");
+
+    // children
+    for (Node* node = getFirstChild(); node != NULL; node = node->getNextSibling())
+    {
+        node->writeText(file);
+    }
+    // camera
+    if (_camera != NULL)
+    {
+        _camera->writeText(file);
+    }
+    // light
+    if (_light != NULL && !_light->isAmbient())
+    {
+        _light->writeText(file);
+    }
+    // mesh
+    if (_model != NULL)
+    {
+        _model->writeText(file);
+    }
+    fprintElementEnd(file);
+}
+
+void Node::addChild(Node* child)
+{
+    // If this child is already parented, remove it from its parent
+    if (child->_parent)
+    {
+        child->_parent->removeChild(child);
+    }
+
+    if (_firstChild == NULL)
+    {
+        // No children yet
+        _firstChild = child;
+        child->_previousSibling = NULL;
+    }
+    else
+    {
+        // We already have children, so append to them
+        child->_previousSibling = _lastChild;
+        _lastChild->_nextSibling = child;
+    }
+
+    child->_parent = this;
+    child->_nextSibling = NULL;
+    this->_lastChild = child;
+
+    ++_childCount;
+}
+
+
+void Node::removeChild(Node* child)
+{
+    // The child must have already been our child to remove it
+    if (child->_parent != this)
+    {
+        return;
+    }
+
+    // Remove the child by un-linking it from our child list
+    if (child->_nextSibling)
+    {
+        child->_nextSibling->_previousSibling = child->_previousSibling;
+    }
+    if (child->_previousSibling)
+    {
+        child->_previousSibling->_nextSibling = child->_nextSibling;
+    }
+
+    // Was this child our first or last child?
+    if (child == _firstChild)
+    {
+        _firstChild = child->_nextSibling;
+    }
+    if (child == _lastChild)
+    {
+        _lastChild = child->_previousSibling;
+    }
+
+    // Remove parent and sibling info from the child, now that it is no longer parented
+    child->_parent = NULL;
+    child->_nextSibling = NULL;
+    child->_previousSibling = NULL;
+
+    --_childCount;
+}
+
+void Node::removeChildren()
+{
+    Node* child;
+    while ((child = _firstChild) != NULL)
+    {
+        removeChild(child);
+    }
+}
+
+bool Node::hasChildren() const
+{
+    return (_firstChild != NULL);
+}
+
+unsigned int Node::getChildCount() const
+{
+    return _childCount;
+}
+
+Node* Node::getNextSibling() const
+{
+    return _nextSibling;
+}
+
+Node* Node::getPreviousSibling() const
+{
+    return _previousSibling;
+}
+
+Node* Node::getFirstChild() const
+{
+    return _firstChild;
+}
+
+Node* Node::getLastChild() const
+{
+    return _lastChild;
+}
+
+Node* Node::getParent() const
+{
+    return _parent;
+}
+
+void Node::setCamera(Camera* camera)
+{
+    _camera = camera;
+}
+
+void Node::setLight(Light* light)
+{
+    _light = light;
+}
+
+void Node::setModel(Model* model)
+{
+    _model = model;
+}
+
+const Matrix& Node::getTransformMatrix() const
+{
+    return _transform;
+}
+
+void Node::setTransformMatrix(float matrix[])
+{
+    memcpy(_transform.m, matrix, 16 * sizeof(float));
+}
+
+const Matrix& Node::getWorldMatrix() const
+{
+    if (_parent)
+    {
+        Matrix::multiply(_parent->getWorldMatrix().m, _transform.m, _worldTransform.m);
+    }
+    else
+    {
+        memcpy(_worldTransform.m, _transform.m, 16 * sizeof(float));
+    }
+
+    return _worldTransform;
+}
+
+void Node::resetTransformMatrix()
+{
+    Matrix::setIdentity(_transform.m);
+}
+
+void Node::setIsJoint(bool value)
+{
+    _joint = value;
+}
+
+bool Node::isJoint() const
+{
+    return _joint;
+}
+
+Camera* Node::getCamera() const
+{
+    return _camera;
+}
+
+Light* Node::getLight() const
+{
+    return _light;
+}
+
+Model* Node::getModel() const
+{
+    if (_model)
+    {
+        return _model;
+    }
+    return NULL;
+}
+
+Node* Node::getFirstCameraNode() const
+{
+    if (hasCamera())
+    {
+        return const_cast<Node*>(this);
+    }
+    for (Node* node = getFirstChild(); node != NULL; node = node->getNextSibling())
+    {
+        Node* n = node->getFirstCameraNode();
+        if (n)
+        {
+            return n;
+        }
+    }
+    return NULL;
+}
+
+bool Node::hasCamera() const
+{
+    return _camera != NULL;
+}
+
+bool Node::hasLight() const
+{
+    return _light != NULL;
+}
+
+}

+ 193 - 193
tools/encoder/src/Node.h

@@ -1,193 +1,193 @@
-#ifndef NODE_H_
-#define NODE_H_
-
-#include "Object.h"
-#include "Camera.h"
-#include "Light.h"
-#include "Model.h"
-
-namespace gameplay
-{
-
-class Node : public Object
-{
-public:
-
-    /**
-     * Constructor.
-     */
-    Node(void);
-
-    /**
-     * Destructor.
-     */
-    virtual ~Node(void);
-
-    virtual unsigned int getTypeId(void) const;
-    virtual const char* getElementName(void) const;
-    virtual void writeBinary(FILE* file);
-    virtual void writeText(FILE* file);
-
-    /**
-     * Adds a child node.
-     *
-     * If the ownChild is true. The child is deleted when this
-     * node is deleted.
-     *
-     * @param child The child to add.
-     */
-    void addChild(Node* child);
-
-    /**
-     * Removes a child node.
-     *
-     * If no longer referenced it destroys the node.
-     * To avoid destroy on changing hierarchy, ensure you add first before removing.
-     *
-     * @param child The child to remove.
-     */
-    void removeChild(Node* child);
-
-    /**
-     * Removes all the child node.
-     */
-    void removeChildren();
-
-    /**
-     * Determines if this node has child nodes.
-     *
-     * @return true if it has 1 or more children; false if otherwise.
-     */
-    bool hasChildren() const;
-
-    /**
-     * Get the number of children for this node.
-     *
-     * @return The number of child nodes for this node.
-     */
-    unsigned int getChildCount() const;
-
-    /**
-     * Gets the next sibling node.
-     *
-     * @return The next sibling node.
-     */
-    Node* getNextSibling() const;
-
-    /**
-     * Gets the previous sibling node.
-     *
-     * @return The previous sibling node.
-     */
-    Node* getPreviousSibling() const;
-
-    /**
-     * Gets the first child node.
-     *
-     * @return The first child node.
-     */
-    Node* getFirstChild() const;
-
-    /**
-     * Gets the last child node.
-     *
-     * @return The last child node.
-     */
-    Node* getLastChild() const;
-
-    /**
-     * Gets the parent node.
-     *
-     * @return The parent node.
-     */
-    Node* getParent() const;
-
-    /**
-     * Returns the Camera for this node.
-     * 
-     * @return The camera for this node or NULL if no camera is set.
-     */
-    Camera* getCamera() const;
-
-    /**
-     * Returns the Light for this node.
-     * 
-     * @return The light for this node or NULL if no light is set.
-     */
-    Light* getLight() const;
-
-    /**
-     * Returns the Model of this node.
-     * 
-     * @return The model for this node or NULL if no model is set.
-     */
-    Model* getModel() const;
-
-    /**
-     * Returns the transform matrix for the node.
-     */
-    const Matrix& getTransformMatrix() const;
-
-    /**
-     * Sets the transform for this node.
-     */
-    void setTransformMatrix(float matrix[]);
-
-    /**
-     * Returns the resolved world matrix for the node.
-     */
-    const Matrix& getWorldMatrix() const;
-
-    /*
-     * Resets the node's transform matrix to the identity matrix.
-     */
-    void resetTransformMatrix();
-
-    void setCamera(Camera* camera);
-    void setLight(Light* light);
-    void setModel(Model* model);
-
-    /**
-     * Sets if this node is a joint node.
-     */
-    void setIsJoint(bool value);
-
-    /**
-     * Returns true if this is a joint node.
-     */
-    bool isJoint() const;
-
-    Node* getFirstCameraNode() const;
-
-    /**
-     * Returns true if this node has a camera.
-     */
-    bool hasCamera() const;
-
-    /**
-     * Returns true if this node has a light.
-     */
-    bool hasLight() const;
-    
-private:
-
-    Matrix _transform;
-    mutable Matrix _worldTransform;
-
-    int _childCount;
-    Node* _nextSibling;
-    Node* _previousSibling;
-    Node* _firstChild;
-    Node* _lastChild;
-    Node* _parent;
-
-    Camera* _camera;
-    Light* _light;
-    Model* _model;
-
-    bool _joint;
-};
-
-}
-
-#endif
+#ifndef NODE_H_
+#define NODE_H_
+
+#include "Object.h"
+#include "Camera.h"
+#include "Light.h"
+#include "Model.h"
+
+namespace gameplay
+{
+
+class Node : public Object
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    Node(void);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Node(void);
+
+    virtual unsigned int getTypeId(void) const;
+    virtual const char* getElementName(void) const;
+    virtual void writeBinary(FILE* file);
+    virtual void writeText(FILE* file);
+
+    /**
+     * Adds a child node.
+     *
+     * If the ownChild is true. The child is deleted when this
+     * node is deleted.
+     *
+     * @param child The child to add.
+     */
+    void addChild(Node* child);
+
+    /**
+     * Removes a child node.
+     *
+     * If no longer referenced it destroys the node.
+     * To avoid destroy on changing hierarchy, ensure you add first before removing.
+     *
+     * @param child The child to remove.
+     */
+    void removeChild(Node* child);
+
+    /**
+     * Removes all the child node.
+     */
+    void removeChildren();
+
+    /**
+     * Determines if this node has child nodes.
+     *
+     * @return true if it has 1 or more children; false if otherwise.
+     */
+    bool hasChildren() const;
+
+    /**
+     * Get the number of children for this node.
+     *
+     * @return The number of child nodes for this node.
+     */
+    unsigned int getChildCount() const;
+
+    /**
+     * Gets the next sibling node.
+     *
+     * @return The next sibling node.
+     */
+    Node* getNextSibling() const;
+
+    /**
+     * Gets the previous sibling node.
+     *
+     * @return The previous sibling node.
+     */
+    Node* getPreviousSibling() const;
+
+    /**
+     * Gets the first child node.
+     *
+     * @return The first child node.
+     */
+    Node* getFirstChild() const;
+
+    /**
+     * Gets the last child node.
+     *
+     * @return The last child node.
+     */
+    Node* getLastChild() const;
+
+    /**
+     * Gets the parent node.
+     *
+     * @return The parent node.
+     */
+    Node* getParent() const;
+
+    /**
+     * Returns the Camera for this node.
+     * 
+     * @return The camera for this node or NULL if no camera is set.
+     */
+    Camera* getCamera() const;
+
+    /**
+     * Returns the Light for this node.
+     * 
+     * @return The light for this node or NULL if no light is set.
+     */
+    Light* getLight() const;
+
+    /**
+     * Returns the Model of this node.
+     * 
+     * @return The model for this node or NULL if no model is set.
+     */
+    Model* getModel() const;
+
+    /**
+     * Returns the transform matrix for the node.
+     */
+    const Matrix& getTransformMatrix() const;
+
+    /**
+     * Sets the transform for this node.
+     */
+    void setTransformMatrix(float matrix[]);
+
+    /**
+     * Returns the resolved world matrix for the node.
+     */
+    const Matrix& getWorldMatrix() const;
+
+    /*
+     * Resets the node's transform matrix to the identity matrix.
+     */
+    void resetTransformMatrix();
+
+    void setCamera(Camera* camera);
+    void setLight(Light* light);
+    void setModel(Model* model);
+
+    /**
+     * Sets if this node is a joint node.
+     */
+    void setIsJoint(bool value);
+
+    /**
+     * Returns true if this is a joint node.
+     */
+    bool isJoint() const;
+
+    Node* getFirstCameraNode() const;
+
+    /**
+     * Returns true if this node has a camera.
+     */
+    bool hasCamera() const;
+
+    /**
+     * Returns true if this node has a light.
+     */
+    bool hasLight() const;
+    
+private:
+
+    Matrix _transform;
+    mutable Matrix _worldTransform;
+
+    int _childCount;
+    Node* _nextSibling;
+    Node* _previousSibling;
+    Node* _firstChild;
+    Node* _lastChild;
+    Node* _parent;
+
+    Camera* _camera;
+    Light* _light;
+    Model* _model;
+
+    bool _joint;
+};
+
+}
+
+#endif

+ 80 - 80
tools/encoder/src/Object.cpp

@@ -1,80 +1,80 @@
-#include "Base.h"
-#include "Object.h"
-
-namespace gameplay
-{
-
-Object::Object(void) : _fposition(0)
-{
-}
-
-Object::~Object(void)
-{
-}
-
-unsigned int Object::getTypeId(void) const
-{
-    return 0;
-}
-
-void Object::writeBinary(FILE* file)
-{
-    saveFilePosition(file);
-}
-
-const std::string& Object::getId() const
-{
-    return _id;
-}
-
-void Object::setId(const char* idStr)
-{
-    if (idStr)
-    {
-        _id = idStr;
-    }
-}
-
-void Object::setId(const std::string& newId)
-{
-    if (newId.length() > 0)
-    {
-        _id = newId;
-    }
-}
-
-void Object::fprintElementStart(FILE* file)
-{
-    if (_id.length() > 0)
-    {
-        fprintf(file, "<%s id=\"%s\">\n", getElementName(), _id.c_str());
-    }
-    else
-    {
-        fprintf(file, "<%s>\n", getElementName());
-    }
-}
-
-void Object::fprintElementEnd(FILE* file)
-{
-    fprintf(file, "</%s>\n", getElementName());
-}
-
-unsigned int Object::getFilePosition()
-{
-    return (unsigned int)_fposition;
-}
-
-void Object::saveFilePosition(FILE* file)
-{
-    _fposition = ftell(file);
-}
-
-void Object::writeBinaryXref(FILE* file)
-{
-    std::string xref("#");
-    xref.append(getId());
-    write(xref, file);
-}
-
-}
+#include "Base.h"
+#include "Object.h"
+
+namespace gameplay
+{
+
+Object::Object(void) : _fposition(0)
+{
+}
+
+Object::~Object(void)
+{
+}
+
+unsigned int Object::getTypeId(void) const
+{
+    return 0;
+}
+
+void Object::writeBinary(FILE* file)
+{
+    saveFilePosition(file);
+}
+
+const std::string& Object::getId() const
+{
+    return _id;
+}
+
+void Object::setId(const char* idStr)
+{
+    if (idStr)
+    {
+        _id = idStr;
+    }
+}
+
+void Object::setId(const std::string& newId)
+{
+    if (newId.length() > 0)
+    {
+        _id = newId;
+    }
+}
+
+void Object::fprintElementStart(FILE* file)
+{
+    if (_id.length() > 0)
+    {
+        fprintf(file, "<%s id=\"%s\">\n", getElementName(), _id.c_str());
+    }
+    else
+    {
+        fprintf(file, "<%s>\n", getElementName());
+    }
+}
+
+void Object::fprintElementEnd(FILE* file)
+{
+    fprintf(file, "</%s>\n", getElementName());
+}
+
+unsigned int Object::getFilePosition()
+{
+    return (unsigned int)_fposition;
+}
+
+void Object::saveFilePosition(FILE* file)
+{
+    _fposition = ftell(file);
+}
+
+void Object::writeBinaryXref(FILE* file)
+{
+    std::string xref("#");
+    xref.append(getId());
+    write(xref, file);
+}
+
+}

+ 151 - 151
tools/encoder/src/Object.h

@@ -1,151 +1,151 @@
-#ifndef OBJ_H_
-#define OBJ_H_
-
-#include "FileIO.h"
-#include "Base.h"
-
-namespace gameplay
-{
-
-/**
- * Object is the abstract base class of all the objects that can be written in the GamePlay Binary file.
- */
-class Object
-{
-public:
-
-    // TypeID's
-    enum TypeID
-    {
-        SCENE_ID = 1,
-        NODE_ID = 2,
-        ANIMATIONS_ID = 3,
-        ANIMATION_ID = 4,
-        ANIMATIONCHANNEL_ID = 5,
-        NODEINSTANCE_ID = 8,
-        MODEL_ID = 11,
-        MATERIAL_ID = 16,
-        EFFECT_ID = 17,
-        CAMERA_ID = 32,
-        LIGHT_ID = 33,
-        MESH_ID = 34,
-        MESHPART_ID = 35,
-        MESHSKIN_ID = 36,
-        FONT_ID = 128,
-    };
-
-    /**
-     * Constructor.
-     */
-    Object(void);
-
-    /**
-     * Destructor.
-     */
-    virtual ~Object(void);
-
-    /**
-     * Returns the Object TypeID.
-     */
-    virtual unsigned int getTypeId(void) const;
-
-    /**
-     * Returns the string element name of the object.
-     * Used for printing the gameplayfile as text.
-     */
-    virtual const char* getElementName(void) const = 0;
-
-    /**
-     * Writes this object to the file stream as binary.
-     */
-    virtual void writeBinary(FILE* file);
-
-    /**
-     * Writes this object to the file stream as text.
-     */
-    virtual void writeText(FILE* file) = 0;
-
-    /**
-     * Returns this object's id string.
-     */
-    const std::string& getId() const;
-
-    /**
-     * Sets this object's id string.
-     */
-    void setId(const char* id);
-
-    /**
-     * Sets this object's id string.
-     */
-    void setId(const std::string& id);
-
-    /**
-     * Prints an XML start element with the name of this object to the text file stream.
-     * Also prints the id as an attribute if the id length is greater than zero.
-     */
-    void fprintElementStart(FILE* file);
-
-    /**
-     * Prints an XML end element with the name of this object to the text file stream.
-     */
-    void fprintElementEnd(FILE* file);
-
-    /**
-     * Writes the xref of this object to the binary file stream.
-     */
-    void writeBinaryXref(FILE* file);
-
-    /**
-     * Returns the file position that this object was written to.
-     * An offset of zero means this object has not been written yet.
-     */
-    unsigned int getFilePosition();
-
-    /**
-     * Writes out a list of objects to a binary file stream.
-     */
-    template <class T>
-    static void writeBinaryObjects(std::list<T> list, FILE* file)
-    {
-        // First write the size of the list
-        write((unsigned int)list.size(), file);
-        // Then write each element
-        typename std::list<T>::const_iterator i;
-        for (i = list.begin(); i != list.end(); ++i)
-        {
-            (*i)->writeBinary(file);
-        }
-    }
-
-    /**
-     * Writes out a vector of objects to a binary file stream.
-     */
-    template <class T>
-    static void writeBinaryObjects(std::vector<T> vector, FILE* file)
-    {
-        // First write the size of the vector
-        write((unsigned int)vector.size(), file);
-        // Then write each element
-        typename std::vector<T>::const_iterator i;
-        for (i = vector.begin(); i != vector.end(); ++i)
-        {
-            (*i)->writeBinary(file);
-        }
-    }
-
-private:
-
-    /**
-     * Saves where this object was written to in the binary file.
-     */
-    void saveFilePosition(FILE* file);
-
-private:
-    std::string _id;
-    long _fposition;
-};
-
-}
-
-#endif
+#ifndef OBJ_H_
+#define OBJ_H_
+
+#include "FileIO.h"
+#include "Base.h"
+
+namespace gameplay
+{
+
+/**
+ * Object is the abstract base class of all the objects that can be written in the GamePlay Binary file.
+ */
+class Object
+{
+public:
+
+    // TypeID's
+    enum TypeID
+    {
+        SCENE_ID = 1,
+        NODE_ID = 2,
+        ANIMATIONS_ID = 3,
+        ANIMATION_ID = 4,
+        ANIMATIONCHANNEL_ID = 5,
+        NODEINSTANCE_ID = 8,
+        MODEL_ID = 11,
+        MATERIAL_ID = 16,
+        EFFECT_ID = 17,
+        CAMERA_ID = 32,
+        LIGHT_ID = 33,
+        MESH_ID = 34,
+        MESHPART_ID = 35,
+        MESHSKIN_ID = 36,
+        FONT_ID = 128,
+    };
+
+    /**
+     * Constructor.
+     */
+    Object(void);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Object(void);
+
+    /**
+     * Returns the Object TypeID.
+     */
+    virtual unsigned int getTypeId(void) const;
+
+    /**
+     * Returns the string element name of the object.
+     * Used for printing the gameplayfile as text.
+     */
+    virtual const char* getElementName(void) const = 0;
+
+    /**
+     * Writes this object to the file stream as binary.
+     */
+    virtual void writeBinary(FILE* file);
+
+    /**
+     * Writes this object to the file stream as text.
+     */
+    virtual void writeText(FILE* file) = 0;
+
+    /**
+     * Returns this object's id string.
+     */
+    const std::string& getId() const;
+
+    /**
+     * Sets this object's id string.
+     */
+    void setId(const char* id);
+
+    /**
+     * Sets this object's id string.
+     */
+    void setId(const std::string& id);
+
+    /**
+     * Prints an XML start element with the name of this object to the text file stream.
+     * Also prints the id as an attribute if the id length is greater than zero.
+     */
+    void fprintElementStart(FILE* file);
+
+    /**
+     * Prints an XML end element with the name of this object to the text file stream.
+     */
+    void fprintElementEnd(FILE* file);
+
+    /**
+     * Writes the xref of this object to the binary file stream.
+     */
+    void writeBinaryXref(FILE* file);
+
+    /**
+     * Returns the file position that this object was written to.
+     * An offset of zero means this object has not been written yet.
+     */
+    unsigned int getFilePosition();
+
+    /**
+     * Writes out a list of objects to a binary file stream.
+     */
+    template <class T>
+    static void writeBinaryObjects(std::list<T> list, FILE* file)
+    {
+        // First write the size of the list
+        write((unsigned int)list.size(), file);
+        // Then write each element
+        typename std::list<T>::const_iterator i;
+        for (i = list.begin(); i != list.end(); ++i)
+        {
+            (*i)->writeBinary(file);
+        }
+    }
+
+    /**
+     * Writes out a vector of objects to a binary file stream.
+     */
+    template <class T>
+    static void writeBinaryObjects(std::vector<T> vector, FILE* file)
+    {
+        // First write the size of the vector
+        write((unsigned int)vector.size(), file);
+        // Then write each element
+        typename std::vector<T>::const_iterator i;
+        for (i = vector.begin(); i != vector.end(); ++i)
+        {
+            (*i)->writeBinary(file);
+        }
+    }
+
+private:
+
+    /**
+     * Saves where this object was written to in the binary file.
+     */
+    void saveFilePosition(FILE* file);
+
+private:
+    std::string _id;
+    long _fposition;
+};
+
+}
+
+#endif

+ 400 - 400
tools/encoder/src/Quaternion.cpp

@@ -1,400 +1,400 @@
-#include "Base.h"
-#include "Quaternion.h"
-
-namespace gameplay
-{
-
-Quaternion::Quaternion()
-    : x(0.0f), y(0.0f), z(0.0f), w(1.0f)
-{
-}
-
-Quaternion::Quaternion(float x, float y, float z, float w)
-{
-    set(x, y, z, w);
-}
-
-Quaternion::Quaternion(float* array)
-{
-    set(array);
-}
-
-Quaternion::Quaternion(const Vector3& axis, float angle)
-{
-    set(axis, angle);
-}
-
-Quaternion::Quaternion(const Quaternion& copy)
-{
-    set(copy);
-}
-
-Quaternion::~Quaternion()
-{
-}
-
-const Quaternion& Quaternion::identity()
-{
-    static Quaternion value(0.0f, 0.0f, 0.0f, 1.0f);
-    return value;
-}
-
-const Quaternion& Quaternion::zero()
-{
-    static Quaternion value(0.0f, 0.0f, 0.0f, 0.0f);
-    return value;
-}
-
-bool Quaternion::isIdentity() const
-{
-    return x == 0.0f && y == 0.0f && z == 0.0f && w == 1.0f;
-}
-
-bool Quaternion::isZero() const
-{
-    return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f;
-}
-
-void Quaternion::createFromAxisAngle(const Vector3& axis, float angle, Quaternion* dst)
-{
-    assert(dst);
-
-    float halfAngle = angle * 0.5f;
-    float sinHalfAngle = sin(halfAngle);
-
-    Vector3 normal(axis);
-    normal.normalize();
-    dst->x = normal.x * sinHalfAngle;
-    dst->y = normal.y * sinHalfAngle;
-    dst->z = normal.z * sinHalfAngle;
-    dst->w = cos(halfAngle);
-}
-
-void Quaternion::conjugate()
-{
-    conjugate(this);
-}
-
-void Quaternion::conjugate(Quaternion* dst) const
-{
-    dst->x = -x;
-    dst->y = -y;
-    dst->z = -z;
-    dst->w =  w;
-}
-
-bool Quaternion::inverse()
-{
-    return inverse(this);
-}
-
-bool Quaternion::inverse(Quaternion* dst) const
-{
-    float n = x * x + y * y + z * z + w * w;
-    if (n == 1.0f)
-    {
-        dst->x = -x;
-        dst->y = -y;
-        dst->z = -z;
-        dst->w = w;
-
-        return true;
-    }
-
-    // too close to zero
-    if (n < 0.000001f)
-        return false;
-
-    n = 1.0f / n;
-    dst->x = -x * n;
-    dst->y = -y * n;
-    dst->z = -z * n;
-    dst->w = w * n;
-
-    return true;
-}
-
-void Quaternion::multiply(const Quaternion& q)
-{
-    multiply(*this, q, this);
-}
-
-void Quaternion::multiply(const Quaternion& q1, const Quaternion& q2, Quaternion* dst)
-{
-    float x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
-    float y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x;
-    float z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w;
-    float w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
-
-    dst->x = x;
-    dst->y = y;
-    dst->z = z;
-    dst->w = w;
-}
-
-void Quaternion::normalize()
-{
-    normalize(this);
-}
-
-void Quaternion::normalize(Quaternion* dst) const
-{
-    assert(dst);
-
-    if (this != dst)
-    {
-        dst->x = x;
-        dst->y = y;
-        dst->z = z;
-        dst->w = w;
-    }
-
-    float n = x * x + y * y + z * z + w * w;
-
-    // Already normalized.
-    if (n == 1.0f)
-        return;
-
-    n = sqrt(n);
-    // Too close to zero.
-    if (n < 0.000001f)
-        return;
-
-    n = 1.0f / n;
-    dst->x *= n;
-    dst->y *= n;
-    dst->z *= n;
-    dst->w *= n;
-}
-
-void Quaternion::set(float x, float y, float z, float w)
-{
-    this->x = x;
-    this->y = y;
-    this->z = z;
-    this->w = w;
-}
-
-void Quaternion::set(float* array)
-{
-    assert(array);
-
-    x = array[0];
-    y = array[1];
-    z = array[2];
-    w = array[3];
-}
-
-void Quaternion::set(const Vector3& axis, float angle)
-{
-    Quaternion::createFromAxisAngle(axis, angle, this);
-}
-
-void Quaternion::set(const Quaternion& q)
-{
-    this->x = q.x;
-    this->y = q.y;
-    this->z = q.z;
-    this->w = q.w;
-}
-
-void Quaternion::setIdentity()
-{
-    x = 0.0f;
-    y = 0.0f;
-    z = 0.0f;
-    w = 1.0f;
-}
-
-float Quaternion::toAxisAngle(Vector3* axis) const
-{
-    assert(axis);
-
-    Quaternion q(x, y, z, w);
-    q.normalize();
-    axis->x = q.x;
-    axis->y = q.y;
-    axis->z = q.z;
-    axis->normalize();
-
-    return (2.0f * acos(q.w));
-}
-
-void Quaternion::lerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
-{
-    assert(dst);
-    assert(!(t < 0.0f || t > 1.0f));
-
-    if (t == 0.0f)
-    {
-        memcpy(dst, &q1, sizeof(float) * 4);
-        return;
-    }
-    else if (t == 1.0f)
-    {
-        memcpy(dst, &q2, sizeof(float) * 4);
-        return;
-    }
-
-    float t1 = 1.0f - t;
-
-    dst->x = t1 * q1.x + t * q2.x;
-    dst->y = t1 * q1.y + t * q2.y;
-    dst->z = t1 * q1.z + t * q2.z;
-    dst->w = t1 * q1.w + t * q2.w;
-}
-
-void Quaternion::slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
-{
-    slerp(q1.x, q1.y, q1.z, q1.w, q2.x, q2.y, q2.z, q2.w, t, &dst->x, &dst->y, &dst->z, &dst->w);
-}
-
-void Quaternion::squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst)
-{
-    assert(dst);
-    assert(!(t < 0.0f || t > 1.0f));
-
-    Quaternion dstQ(0.0f, 0.0f, 0.0f, 1.0f);
-    Quaternion dstS(0.0f, 0.0f, 0.0f, 1.0f);
-
-    slerpForSquad(q1, q2, t, &dstQ);
-    slerpForSquad(s1, s2, t, &dstS);
-    slerpForSquad(dstQ, dstS, 2.0f * t * (1.0f - t), dst);
-}
-
-void Quaternion::slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float* dstx, float* dsty, float* dstz, float* dstw)
-{
-    // Fast slerp implementation by kwhatmough:
-    // It contains no division operations, no trig, no inverse trig
-    // and no sqrt. Not only does this code tolerate small constraint
-    // errors in the input quaternions, it actually corrects for them.
-    assert(dstx && dsty && dstz && dstw);
-    assert(!(t < 0.0f || t > 1.0f));
-
-    if (t == 0.0f)
-    {
-        *dstx = q1x;
-        *dsty = q1y;
-        *dstz = q1z;
-        *dstw = q1w;
-        return;
-    }
-    else if (t == 1.0f)
-    {
-        *dstx = q2x;
-        *dsty = q2y;
-        *dstz = q2z;
-        *dstw = q2w;
-        return;
-    }
-
-    if (q1x == q2x && q1y == q2y && q1z == q2z && q1w == q2w)
-    {
-        *dstx = q1x;
-        *dsty = q1y;
-        *dstz = q1z;
-        *dstw = q1w;
-        return;
-    }
-
-    float halfY, alpha, beta;
-    float u, f1, f2a, f2b;
-    float ratio1, ratio2;
-    float halfSecHalfTheta, versHalfTheta;
-    float sqNotU, sqU;
-
-    float cosTheta = q1w * q2w + q1x * q2x + q1y * q2y + q1z * q2z;
-
-    // As usual in all slerp implementations, we fold theta.
-    alpha = cosTheta >= 0 ? 1.0f : -1.0f;
-    halfY = 1.0f + alpha * cosTheta;
-
-    // Here we bisect the interval, so we need to fold t as well.
-    f2b = t - 0.5f;
-    u = f2b >= 0 ? f2b : -f2b;
-    f2a = u - f2b;
-    f2b += u;
-    u += u;
-    f1 = 1.0f - u;
-
-    // One iteration of Newton to get 1-cos(theta / 2) to good accuracy.
-    halfSecHalfTheta = 1.09f - (0.476537f - 0.0903321f * halfY) * halfY;
-    halfSecHalfTheta *= 1.5f - halfY * halfSecHalfTheta * halfSecHalfTheta;
-    versHalfTheta = 1.0f - halfY * halfSecHalfTheta;
-
-    // Evaluate series expansions of the coefficients.
-    sqNotU = f1 * f1;
-    ratio2 = 0.0000440917108f * versHalfTheta;
-    ratio1 = -0.00158730159f + (sqNotU - 16.0f) * ratio2;
-    ratio1 = 0.0333333333f + ratio1 * (sqNotU - 9.0f) * versHalfTheta;
-    ratio1 = -0.333333333f + ratio1 * (sqNotU - 4.0f) * versHalfTheta;
-    ratio1 = 1.0f + ratio1 * (sqNotU - 1.0f) * versHalfTheta;
-
-    sqU = u * u;
-    ratio2 = -0.00158730159f + (sqU - 16.0f) * ratio2;
-    ratio2 = 0.0333333333f + ratio2 * (sqU - 9.0f) * versHalfTheta;
-    ratio2 = -0.333333333f + ratio2 * (sqU - 4.0f) * versHalfTheta;
-    ratio2 = 1.0f + ratio2 * (sqU - 1.0f) * versHalfTheta;
-
-    // Perform the bisection and resolve the folding done earlier.
-    f1 *= ratio1 * halfSecHalfTheta;
-    f2a *= ratio2;
-    f2b *= ratio2;
-    alpha *= f1 + f2a;
-    beta = f1 + f2b;
-
-    // Apply final coefficients to a and b as usual.
-    float w = alpha * q1w + beta * q2w;
-    float x = alpha * q1x + beta * q2x;
-    float y = alpha * q1y + beta * q2y;
-    float z = alpha * q1z + beta * q2z;
-
-    // This final adjustment to the quaternion's length corrects for
-    // any small constraint error in the inputs q1 and q2 But as you
-    // can see, it comes at the cost of 9 additional multiplication
-    // operations. If this error-correcting feature is not required,
-    // the following code may be removed.
-    f1 = 1.5f - 0.5f * (w * w + x * x + y * y + z * z);
-    *dstw = w * f1;
-    *dstx = x * f1;
-    *dsty = y * f1;
-    *dstz = z * f1;
-}
-
-void Quaternion::slerpForSquad(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
-{
-    // cos(omega) = q1 * q2;
-    // slerp(q1, q2, t) = (q1*sin((1-t)*omega) + q2*sin(t*omega))/sin(omega);
-    // q1 = +- q2, slerp(q1,q2,t) = q1.
-    // This is a straight-foward implementation of the formula of slerp. It does not do any sign switching.
-    float c = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
-
-    if (fabs(c) >= 1.0f)
-    {
-        dst->x = q1.x;
-        dst->y = q1.y;
-        dst->z = q1.z;
-        dst->w = q1.w;
-        return;
-    }
-
-    float omega = acos(c);
-    float s = sqrt(1.0f - c * c);
-    if (fabs(s) <= 0.00001f)
-    {
-        dst->x = q1.x;
-        dst->y = q1.y;
-        dst->z = q1.z;
-        dst->w = q1.w;
-        return;
-    }
-
-    float r1 = sin((1 - t) * omega) / s;
-    float r2 = sin(t * omega) / s;
-    dst->x = (q1.x * r1 + q2.x * r2);
-    dst->y = (q1.y * r1 + q2.y * r2);
-    dst->z = (q1.z * r1 + q2.z * r2);
-    dst->w = (q1.w * r1 + q2.w * r2);
-}
-
-}
+#include "Base.h"
+#include "Quaternion.h"
+
+namespace gameplay
+{
+
+Quaternion::Quaternion()
+    : x(0.0f), y(0.0f), z(0.0f), w(1.0f)
+{
+}
+
+Quaternion::Quaternion(float x, float y, float z, float w)
+{
+    set(x, y, z, w);
+}
+
+Quaternion::Quaternion(float* array)
+{
+    set(array);
+}
+
+Quaternion::Quaternion(const Vector3& axis, float angle)
+{
+    set(axis, angle);
+}
+
+Quaternion::Quaternion(const Quaternion& copy)
+{
+    set(copy);
+}
+
+Quaternion::~Quaternion()
+{
+}
+
+const Quaternion& Quaternion::identity()
+{
+    static Quaternion value(0.0f, 0.0f, 0.0f, 1.0f);
+    return value;
+}
+
+const Quaternion& Quaternion::zero()
+{
+    static Quaternion value(0.0f, 0.0f, 0.0f, 0.0f);
+    return value;
+}
+
+bool Quaternion::isIdentity() const
+{
+    return x == 0.0f && y == 0.0f && z == 0.0f && w == 1.0f;
+}
+
+bool Quaternion::isZero() const
+{
+    return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f;
+}
+
+void Quaternion::createFromAxisAngle(const Vector3& axis, float angle, Quaternion* dst)
+{
+    assert(dst);
+
+    float halfAngle = angle * 0.5f;
+    float sinHalfAngle = sin(halfAngle);
+
+    Vector3 normal(axis);
+    normal.normalize();
+    dst->x = normal.x * sinHalfAngle;
+    dst->y = normal.y * sinHalfAngle;
+    dst->z = normal.z * sinHalfAngle;
+    dst->w = cos(halfAngle);
+}
+
+void Quaternion::conjugate()
+{
+    conjugate(this);
+}
+
+void Quaternion::conjugate(Quaternion* dst) const
+{
+    dst->x = -x;
+    dst->y = -y;
+    dst->z = -z;
+    dst->w =  w;
+}
+
+bool Quaternion::inverse()
+{
+    return inverse(this);
+}
+
+bool Quaternion::inverse(Quaternion* dst) const
+{
+    float n = x * x + y * y + z * z + w * w;
+    if (n == 1.0f)
+    {
+        dst->x = -x;
+        dst->y = -y;
+        dst->z = -z;
+        dst->w = w;
+
+        return true;
+    }
+
+    // too close to zero
+    if (n < 0.000001f)
+        return false;
+
+    n = 1.0f / n;
+    dst->x = -x * n;
+    dst->y = -y * n;
+    dst->z = -z * n;
+    dst->w = w * n;
+
+    return true;
+}
+
+void Quaternion::multiply(const Quaternion& q)
+{
+    multiply(*this, q, this);
+}
+
+void Quaternion::multiply(const Quaternion& q1, const Quaternion& q2, Quaternion* dst)
+{
+    float x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
+    float y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x;
+    float z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w;
+    float w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
+
+    dst->x = x;
+    dst->y = y;
+    dst->z = z;
+    dst->w = w;
+}
+
+void Quaternion::normalize()
+{
+    normalize(this);
+}
+
+void Quaternion::normalize(Quaternion* dst) const
+{
+    assert(dst);
+
+    if (this != dst)
+    {
+        dst->x = x;
+        dst->y = y;
+        dst->z = z;
+        dst->w = w;
+    }
+
+    float n = x * x + y * y + z * z + w * w;
+
+    // Already normalized.
+    if (n == 1.0f)
+        return;
+
+    n = sqrt(n);
+    // Too close to zero.
+    if (n < 0.000001f)
+        return;
+
+    n = 1.0f / n;
+    dst->x *= n;
+    dst->y *= n;
+    dst->z *= n;
+    dst->w *= n;
+}
+
+void Quaternion::set(float x, float y, float z, float w)
+{
+    this->x = x;
+    this->y = y;
+    this->z = z;
+    this->w = w;
+}
+
+void Quaternion::set(float* array)
+{
+    assert(array);
+
+    x = array[0];
+    y = array[1];
+    z = array[2];
+    w = array[3];
+}
+
+void Quaternion::set(const Vector3& axis, float angle)
+{
+    Quaternion::createFromAxisAngle(axis, angle, this);
+}
+
+void Quaternion::set(const Quaternion& q)
+{
+    this->x = q.x;
+    this->y = q.y;
+    this->z = q.z;
+    this->w = q.w;
+}
+
+void Quaternion::setIdentity()
+{
+    x = 0.0f;
+    y = 0.0f;
+    z = 0.0f;
+    w = 1.0f;
+}
+
+float Quaternion::toAxisAngle(Vector3* axis) const
+{
+    assert(axis);
+
+    Quaternion q(x, y, z, w);
+    q.normalize();
+    axis->x = q.x;
+    axis->y = q.y;
+    axis->z = q.z;
+    axis->normalize();
+
+    return (2.0f * acos(q.w));
+}
+
+void Quaternion::lerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
+{
+    assert(dst);
+    assert(!(t < 0.0f || t > 1.0f));
+
+    if (t == 0.0f)
+    {
+        memcpy(dst, &q1, sizeof(float) * 4);
+        return;
+    }
+    else if (t == 1.0f)
+    {
+        memcpy(dst, &q2, sizeof(float) * 4);
+        return;
+    }
+
+    float t1 = 1.0f - t;
+
+    dst->x = t1 * q1.x + t * q2.x;
+    dst->y = t1 * q1.y + t * q2.y;
+    dst->z = t1 * q1.z + t * q2.z;
+    dst->w = t1 * q1.w + t * q2.w;
+}
+
+void Quaternion::slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
+{
+    slerp(q1.x, q1.y, q1.z, q1.w, q2.x, q2.y, q2.z, q2.w, t, &dst->x, &dst->y, &dst->z, &dst->w);
+}
+
+void Quaternion::squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst)
+{
+    assert(dst);
+    assert(!(t < 0.0f || t > 1.0f));
+
+    Quaternion dstQ(0.0f, 0.0f, 0.0f, 1.0f);
+    Quaternion dstS(0.0f, 0.0f, 0.0f, 1.0f);
+
+    slerpForSquad(q1, q2, t, &dstQ);
+    slerpForSquad(s1, s2, t, &dstS);
+    slerpForSquad(dstQ, dstS, 2.0f * t * (1.0f - t), dst);
+}
+
+void Quaternion::slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float* dstx, float* dsty, float* dstz, float* dstw)
+{
+    // Fast slerp implementation by kwhatmough:
+    // It contains no division operations, no trig, no inverse trig
+    // and no sqrt. Not only does this code tolerate small constraint
+    // errors in the input quaternions, it actually corrects for them.
+    assert(dstx && dsty && dstz && dstw);
+    assert(!(t < 0.0f || t > 1.0f));
+
+    if (t == 0.0f)
+    {
+        *dstx = q1x;
+        *dsty = q1y;
+        *dstz = q1z;
+        *dstw = q1w;
+        return;
+    }
+    else if (t == 1.0f)
+    {
+        *dstx = q2x;
+        *dsty = q2y;
+        *dstz = q2z;
+        *dstw = q2w;
+        return;
+    }
+
+    if (q1x == q2x && q1y == q2y && q1z == q2z && q1w == q2w)
+    {
+        *dstx = q1x;
+        *dsty = q1y;
+        *dstz = q1z;
+        *dstw = q1w;
+        return;
+    }
+
+    float halfY, alpha, beta;
+    float u, f1, f2a, f2b;
+    float ratio1, ratio2;
+    float halfSecHalfTheta, versHalfTheta;
+    float sqNotU, sqU;
+
+    float cosTheta = q1w * q2w + q1x * q2x + q1y * q2y + q1z * q2z;
+
+    // As usual in all slerp implementations, we fold theta.
+    alpha = cosTheta >= 0 ? 1.0f : -1.0f;
+    halfY = 1.0f + alpha * cosTheta;
+
+    // Here we bisect the interval, so we need to fold t as well.
+    f2b = t - 0.5f;
+    u = f2b >= 0 ? f2b : -f2b;
+    f2a = u - f2b;
+    f2b += u;
+    u += u;
+    f1 = 1.0f - u;
+
+    // One iteration of Newton to get 1-cos(theta / 2) to good accuracy.
+    halfSecHalfTheta = 1.09f - (0.476537f - 0.0903321f * halfY) * halfY;
+    halfSecHalfTheta *= 1.5f - halfY * halfSecHalfTheta * halfSecHalfTheta;
+    versHalfTheta = 1.0f - halfY * halfSecHalfTheta;
+
+    // Evaluate series expansions of the coefficients.
+    sqNotU = f1 * f1;
+    ratio2 = 0.0000440917108f * versHalfTheta;
+    ratio1 = -0.00158730159f + (sqNotU - 16.0f) * ratio2;
+    ratio1 = 0.0333333333f + ratio1 * (sqNotU - 9.0f) * versHalfTheta;
+    ratio1 = -0.333333333f + ratio1 * (sqNotU - 4.0f) * versHalfTheta;
+    ratio1 = 1.0f + ratio1 * (sqNotU - 1.0f) * versHalfTheta;
+
+    sqU = u * u;
+    ratio2 = -0.00158730159f + (sqU - 16.0f) * ratio2;
+    ratio2 = 0.0333333333f + ratio2 * (sqU - 9.0f) * versHalfTheta;
+    ratio2 = -0.333333333f + ratio2 * (sqU - 4.0f) * versHalfTheta;
+    ratio2 = 1.0f + ratio2 * (sqU - 1.0f) * versHalfTheta;
+
+    // Perform the bisection and resolve the folding done earlier.
+    f1 *= ratio1 * halfSecHalfTheta;
+    f2a *= ratio2;
+    f2b *= ratio2;
+    alpha *= f1 + f2a;
+    beta = f1 + f2b;
+
+    // Apply final coefficients to a and b as usual.
+    float w = alpha * q1w + beta * q2w;
+    float x = alpha * q1x + beta * q2x;
+    float y = alpha * q1y + beta * q2y;
+    float z = alpha * q1z + beta * q2z;
+
+    // This final adjustment to the quaternion's length corrects for
+    // any small constraint error in the inputs q1 and q2 But as you
+    // can see, it comes at the cost of 9 additional multiplication
+    // operations. If this error-correcting feature is not required,
+    // the following code may be removed.
+    f1 = 1.5f - 0.5f * (w * w + x * x + y * y + z * z);
+    *dstw = w * f1;
+    *dstx = x * f1;
+    *dsty = y * f1;
+    *dstz = z * f1;
+}
+
+void Quaternion::slerpForSquad(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
+{
+    // cos(omega) = q1 * q2;
+    // slerp(q1, q2, t) = (q1*sin((1-t)*omega) + q2*sin(t*omega))/sin(omega);
+    // q1 = +- q2, slerp(q1,q2,t) = q1.
+    // This is a straight-foward implementation of the formula of slerp. It does not do any sign switching.
+    float c = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
+
+    if (fabs(c) >= 1.0f)
+    {
+        dst->x = q1.x;
+        dst->y = q1.y;
+        dst->z = q1.z;
+        dst->w = q1.w;
+        return;
+    }
+
+    float omega = acos(c);
+    float s = sqrt(1.0f - c * c);
+    if (fabs(s) <= 0.00001f)
+    {
+        dst->x = q1.x;
+        dst->y = q1.y;
+        dst->z = q1.z;
+        dst->w = q1.w;
+        return;
+    }
+
+    float r1 = sin((1 - t) * omega) / s;
+    float r2 = sin(t * omega) / s;
+    dst->x = (q1.x * r1 + q2.x * r2);
+    dst->y = (q1.y * r1 + q2.y * r2);
+    dst->z = (q1.z * r1 + q2.z * r2);
+    dst->w = (q1.w * r1 + q2.w * r2);
+}
+
+}

+ 364 - 364
tools/encoder/src/Quaternion.h

@@ -1,364 +1,364 @@
-#ifndef QUATERNION_H_
-#define QUATERNION_H_
-
-#include "Vector3.h"
-#include "Matrix.h"
-
-namespace gameplay
-{
-
-class Matrix;
-
-/**
- * Defines a 4-element quaternion that represents the orientation of an object in space.
- *
- * Quaternions are typically used as a replacement for euler angles and rotation matrices as a way to achieve smooth interpolation and avoid gimbal lock.
- *
- * Note that this quaternion class does not automatically keep the quaternion normalized. Therefore, care must be taken to normalize the quaternion when necessary, by calling the normalize method.
- * The package provides three methods for doing quaternion interpolation: lerp, slerp, and squad.
- *
- * lerp (linear interpolation): the interpolation curve gives a straight line in quaternion space. It is simple and fast to compute. The only problem is that it does not provide constant angular velocity. Note that a constant velocity is not necessarily a requirement for a curve;
- * slerp (spherical linear interpolation): the interpolation curve forms a great arc on the quaternion unit sphere. Slerp provides constant angular velocity;
- * squad (spherical spline interpolation): interpolating between a series of rotations using slerp leads to the following problems:
- * - the curve is not smooth at the control points;
- * - the angular velocity is not constant;
- * - the angular velocity is not continuous at the control points.
- *
- * Since squad is continuously differentiable, it remedies the first and third problems mentioned above.
- * The slerp method provided here is intended for interpolation of principal rotations. It treats +q and -q as the same principal rotation and is at liberty to use the negative of either input. The resulting path is always the shorter arc.
- *
- * The lerp method provided here interpolates strictly in quaternion space. Note that the resulting path may pass through the origin if interpolating between a quaternion and its exact negative.
- *
- * As an example, consider the following quaternions:
- *
- * q1 = (0.6, 0.8, 0.0, 0.0),
- * q2 = (0.0, 0.6, 0.8, 0.0),
- * q3 = (0.6, 0.0, 0.8, 0.0), and
- * q4 = (-0.8, 0.0, -0.6, 0.0).
- * For the point p = (1.0, 1.0, 1.0), the following figures show the trajectories of p using lerp, slerp, and squad.
- */
-class Quaternion
-{
-    friend class Curve;
-
-public:
-
-    /**
-     * The x-value of the quaternion's vector component.
-     */
-    float x;
-    /**
-     * The y-value of the quaternion's vector component.
-     */
-    float y;
-    /**
-     * The z-value of the quaternion's vector component.
-     */
-    float z;
-    /**
-     * The scalar component of the quaternion.
-     */
-    float w;
-
-    /**
-     * Constructs a quaternion initialized to (0, 0, 0, 1).
-     */
-    Quaternion();
-
-    /**
-     * Constructs a quaternion initialized to (0, 0, 0, 1).
-     *
-     * @param x The x component of the quaternion.
-     * @param y The y component of the quaternion.
-     * @param z The z component of the quaternion.
-     * @param w The w component of the quaternion.
-     */
-    Quaternion(float x, float y, float z, float w);
-
-    /**
-     * Constructs a new quaternion from the values in the specified array.
-     *
-     * @param array The values for the new quaternion.
-     */
-    Quaternion(float* array);
-
-    /**
-     * Constructs a quaternion equal to the rotation from the specified axis and angle.
-     *
-     * @param axis A vector describing the axis of rotation.
-     * @param angle The angle of rotation (in radians).
-     */
-    Quaternion(const Vector3& axis, float angle);
-
-    /**
-     * Constructs a new quaternion that is a copy of the specified one.
-     *
-     * @param copy The quaternion to copy.
-     */
-    Quaternion(const Quaternion& copy);
-
-    /**
-     * Destructor.
-     */
-    ~Quaternion();
-
-    /**
-     * Returns the identity quaternion.
-     *
-     * @return The identity quaternion.
-     */
-    static const Quaternion& identity();
-
-    /**
-     * Returns the quaternion with all zeros.
-     *
-     * @return The quaternion.
-     */
-    static const Quaternion& zero();
-
-    /**
-     * Determines if this quaternion is equal to the identity quaternion.
-     *
-     * @return true if it is the identity quaternion, false otherwise.
-     */
-    bool isIdentity() const;
-
-    /**
-     * Determines if this quaternion is all zeros.
-     *
-     * @return true if this quaternion is all zeros, false otherwise.
-     */
-    bool isZero() const;
-
-    /**
-     * Creates this quaternion equal to the rotation from the specified axis and angle
-     * and stores the result in dst.
-     *
-     * @param axis A vector describing the axis of rotation.
-     * @param angle The angle of rotation (in radians).
-     * @param dst A quaternion to store the conjugate in.
-     */
-    static void createFromAxisAngle(const Vector3& axis, float angle, Quaternion* dst);
-
-    /**
-     * Sets this quaternion to the conjugate of itself.
-     */
-    void conjugate();
-
-    /**
-     * Gets the conjugate of this quaternion in dst.
-     *
-     * @param dst A quaternion to store the conjugate in.
-     */
-    void conjugate(Quaternion* dst) const;
-
-    /**
-     * Sets this quaternion to the inverse of itself.
-     *
-     * Note that the inverse of a quaternion is equal to its conjugate
-     * when the quaternion is unit-length. For this reason, it is more
-     * efficient to use the conjugate method directly when you know your
-     * quaternion is already unit-length.
-     *
-     * @return true if the inverse can be computed, false otherwise.
-     */
-    bool inverse();
-
-    /**
-     * Gets the inverse of this quaternion in dst.
-     *
-     * Note that the inverse of a quaternion is equal to its conjugate
-     * when the quaternion is unit-length. For this reason, it is more
-     * efficient to use the conjugate method directly when you know your
-     * quaternion is already unit-length.
-     *
-     * @param dst A quaternion to store the inverse in.
-     * 
-     * @return true if the inverse can be computed, false otherwise.
-     */
-    bool inverse(Quaternion* dst) const;
-
-    /**
-     * Multiplies this quaternion by the specified one and stores the result in this quaternion.
-     *
-     * @param q The quaternion to multiply.
-     */
-    void multiply(const Quaternion& q);
-
-    /**
-     * Multiplies the specified quaternions and stores the result in dst.
-     *
-     * @param q1 The first quaternion.
-     * @param q2 The second quaternion.
-     * @param dst A quaternion to store the result in.
-     */
-    static void multiply(const Quaternion& q1, const Quaternion& q2, Quaternion* dst);
-
-    /**
-     * Normalizes this quaternion to have unit length.
-     *
-     * If the quaternion already has unit length or if the length
-     * of the quaternion is zero, this method does nothing.
-     */
-    void normalize();
-
-    /**
-     * Normalizes this quaternion and stores the result in dst.
-     *
-     * If the quaternion already has unit length or if the length
-     * of the quaternion is zero, this method simply copies
-     * this vector into dst.
-     *
-     * @param dst A quaternion to store the result in.
-     */
-    void normalize(Quaternion* dst) const;
-
-    /**
-     * Sets the elements of the quaternion to the specified values.
-     *
-     * @param x The new x-value.
-     * @param y The new y-value.
-     * @param z The new z-value.
-     * @param w The new w-value.
-     */
-    void set(float x, float y, float z, float w);
-
-    /**
-     * Sets the elements of the quaternion from the values in the specified array.
-     *
-     * @param array An array containing the elements of the quaternion in the order x, y, z, w.
-     */
-    void set(float* array);
-
-    /**
-     * Sets the quaternion equal to the rotation from the specified axis and angle.
-     * 
-     * @param axis The axis of rotation.
-     * @param angle The angle of rotation (in radians).
-     */
-    void set(const Vector3& axis, float angle);
-
-    /**
-     * Sets the elements of this quaternion to a copy of the specified quaternion.
-     *
-     * @param q The quaternion to copy.
-     */
-    void set(const Quaternion& q);
-
-    /**
-     * Sets this quaternion to be equal to the identity quaternion.
-     */
-    void setIdentity();
-
-    /**
-     * Converts this Quaternion4f to axis-angle notation. The axis is normalized.
-     *
-     * @param e The Vector3f which stores the axis.
-     * 
-     * @return The angle (in radians).
-     */
-    float toAxisAngle(Vector3* e) const;
-
-    /**
-     * Interpolates between two quaternions using linear interpolation.
-     *
-     * The interpolation curve for linear interpolation between
-     * quaternions gives a straight line in quaternion space.
-     *
-     * @param q1 The first quaternion.
-     * @param q2 The second quaternion.
-     * @param t The interpolation coefficient.
-     * @param dst A quaternion to store the result in.
-     */
-    static void lerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
-    
-    /**
-     * Interpolates between two quaternions using spherical linear interpolation.
-     *
-     * Spherical linear interpolation provides smooth transitions between different
-     * orientations and is often useful for animating models or cameras in 3D.
-     *
-     * Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
-     * This method does not automatically normalize the input quaternions, so it is up to the
-     * caller to ensure they call normalize beforehand, if necessary.
-     *
-     * @param q1 The first quaternion.
-     * @param q2 The second quaternion.
-     * @param t The interpolation coefficient.
-     * @param dst A quaternion to store the result in.
-     */
-    static void slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
-    
-    /**
-     * Interpolates over a series of quaternions using spherical spline interpolation.
-     *
-     * Spherical spline interpolation provides smooth transitions between different
-     * orientations and is often useful for animating models or cameras in 3D.
-     *
-     * Note: For accurate interpolation, the input quaternions must be unit.
-     * This method does not automatically normalize the input quaternions,
-     * so it is up to the caller to ensure they call normalize beforehand, if necessary.
-     *
-     * @param q1 The first quaternion.
-     * @param q2 The second quaternion.
-     * @param s1 The first control point.
-     * @param s2 The second control point.
-     * @param t The interpolation coefficient.
-     * @param dst A quaternion to store the result in.
-     */
-    static void squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst);
-
-    /**
-     * Calculates the quaternion product of this quaternion with the given quaternion.
-     * 
-     * Note: this does not modify this quaternion.
-     * 
-     * @param q The quaternion to multiply.
-     * @return The quaternion product.
-     */
-    inline Quaternion operator*(const Quaternion& q) const;
-
-    /**
-     * Multiplies this quaternion with the given quaternion.
-     * 
-     * @param q The quaternion to multiply.
-     * @return This quaternion, after the multiplication occurs.
-     */
-    inline Quaternion& operator*=(const Quaternion& q);
-
-private:
-
-    /**
-     * Interpolates between two quaternions using spherical linear interpolation.
-     *
-     * Spherical linear interpolation provides smooth transitions between different
-     * orientations and is often useful for animating models or cameras in 3D.
-     *
-     * Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
-     * This method does not automatically normalize the input quaternions, so it is up to the
-     * caller to ensure they call normalize beforehand, if necessary.
-     *
-     * @param q1x The x component of the first quaternion.
-     * @param q1y The y component of the first quaternion.
-     * @param q1z The z component of the first quaternion.
-     * @param q1w The w component of the first quaternion.
-     * @param q2x The x component of the second quaternion.
-     * @param q2y The y component of the second quaternion.
-     * @param q2z The z component of the second quaternion.
-     * @param q2w The w component of the second quaternion.
-     * @param t The interpolation coefficient.
-     * @param dstx A pointer to store the x component of the slerp in.
-     * @param dsty A pointer to store the y component of the slerp in.
-     * @param dstz A pointer to store the z component of the slerp in.
-     * @param dstw A pointer to store the w component of the slerp in.
-     */
-    static void slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float* dstx, float* dsty, float* dstz, float* dstw);
-
-    static void slerpForSquad(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
-};
-
-}
-
-#include "Quaternion.inl"
-
-#endif
+#ifndef QUATERNION_H_
+#define QUATERNION_H_
+
+#include "Vector3.h"
+#include "Matrix.h"
+
+namespace gameplay
+{
+
+class Matrix;
+
+/**
+ * Defines a 4-element quaternion that represents the orientation of an object in space.
+ *
+ * Quaternions are typically used as a replacement for euler angles and rotation matrices as a way to achieve smooth interpolation and avoid gimbal lock.
+ *
+ * Note that this quaternion class does not automatically keep the quaternion normalized. Therefore, care must be taken to normalize the quaternion when necessary, by calling the normalize method.
+ * The package provides three methods for doing quaternion interpolation: lerp, slerp, and squad.
+ *
+ * lerp (linear interpolation): the interpolation curve gives a straight line in quaternion space. It is simple and fast to compute. The only problem is that it does not provide constant angular velocity. Note that a constant velocity is not necessarily a requirement for a curve;
+ * slerp (spherical linear interpolation): the interpolation curve forms a great arc on the quaternion unit sphere. Slerp provides constant angular velocity;
+ * squad (spherical spline interpolation): interpolating between a series of rotations using slerp leads to the following problems:
+ * - the curve is not smooth at the control points;
+ * - the angular velocity is not constant;
+ * - the angular velocity is not continuous at the control points.
+ *
+ * Since squad is continuously differentiable, it remedies the first and third problems mentioned above.
+ * The slerp method provided here is intended for interpolation of principal rotations. It treats +q and -q as the same principal rotation and is at liberty to use the negative of either input. The resulting path is always the shorter arc.
+ *
+ * The lerp method provided here interpolates strictly in quaternion space. Note that the resulting path may pass through the origin if interpolating between a quaternion and its exact negative.
+ *
+ * As an example, consider the following quaternions:
+ *
+ * q1 = (0.6, 0.8, 0.0, 0.0),
+ * q2 = (0.0, 0.6, 0.8, 0.0),
+ * q3 = (0.6, 0.0, 0.8, 0.0), and
+ * q4 = (-0.8, 0.0, -0.6, 0.0).
+ * For the point p = (1.0, 1.0, 1.0), the following figures show the trajectories of p using lerp, slerp, and squad.
+ */
+class Quaternion
+{
+    friend class Curve;
+
+public:
+
+    /**
+     * The x-value of the quaternion's vector component.
+     */
+    float x;
+    /**
+     * The y-value of the quaternion's vector component.
+     */
+    float y;
+    /**
+     * The z-value of the quaternion's vector component.
+     */
+    float z;
+    /**
+     * The scalar component of the quaternion.
+     */
+    float w;
+
+    /**
+     * Constructs a quaternion initialized to (0, 0, 0, 1).
+     */
+    Quaternion();
+
+    /**
+     * Constructs a quaternion initialized to (0, 0, 0, 1).
+     *
+     * @param x The x component of the quaternion.
+     * @param y The y component of the quaternion.
+     * @param z The z component of the quaternion.
+     * @param w The w component of the quaternion.
+     */
+    Quaternion(float x, float y, float z, float w);
+
+    /**
+     * Constructs a new quaternion from the values in the specified array.
+     *
+     * @param array The values for the new quaternion.
+     */
+    Quaternion(float* array);
+
+    /**
+     * Constructs a quaternion equal to the rotation from the specified axis and angle.
+     *
+     * @param axis A vector describing the axis of rotation.
+     * @param angle The angle of rotation (in radians).
+     */
+    Quaternion(const Vector3& axis, float angle);
+
+    /**
+     * Constructs a new quaternion that is a copy of the specified one.
+     *
+     * @param copy The quaternion to copy.
+     */
+    Quaternion(const Quaternion& copy);
+
+    /**
+     * Destructor.
+     */
+    ~Quaternion();
+
+    /**
+     * Returns the identity quaternion.
+     *
+     * @return The identity quaternion.
+     */
+    static const Quaternion& identity();
+
+    /**
+     * Returns the quaternion with all zeros.
+     *
+     * @return The quaternion.
+     */
+    static const Quaternion& zero();
+
+    /**
+     * Determines if this quaternion is equal to the identity quaternion.
+     *
+     * @return true if it is the identity quaternion, false otherwise.
+     */
+    bool isIdentity() const;
+
+    /**
+     * Determines if this quaternion is all zeros.
+     *
+     * @return true if this quaternion is all zeros, false otherwise.
+     */
+    bool isZero() const;
+
+    /**
+     * Creates this quaternion equal to the rotation from the specified axis and angle
+     * and stores the result in dst.
+     *
+     * @param axis A vector describing the axis of rotation.
+     * @param angle The angle of rotation (in radians).
+     * @param dst A quaternion to store the conjugate in.
+     */
+    static void createFromAxisAngle(const Vector3& axis, float angle, Quaternion* dst);
+
+    /**
+     * Sets this quaternion to the conjugate of itself.
+     */
+    void conjugate();
+
+    /**
+     * Gets the conjugate of this quaternion in dst.
+     *
+     * @param dst A quaternion to store the conjugate in.
+     */
+    void conjugate(Quaternion* dst) const;
+
+    /**
+     * Sets this quaternion to the inverse of itself.
+     *
+     * Note that the inverse of a quaternion is equal to its conjugate
+     * when the quaternion is unit-length. For this reason, it is more
+     * efficient to use the conjugate method directly when you know your
+     * quaternion is already unit-length.
+     *
+     * @return true if the inverse can be computed, false otherwise.
+     */
+    bool inverse();
+
+    /**
+     * Gets the inverse of this quaternion in dst.
+     *
+     * Note that the inverse of a quaternion is equal to its conjugate
+     * when the quaternion is unit-length. For this reason, it is more
+     * efficient to use the conjugate method directly when you know your
+     * quaternion is already unit-length.
+     *
+     * @param dst A quaternion to store the inverse in.
+     * 
+     * @return true if the inverse can be computed, false otherwise.
+     */
+    bool inverse(Quaternion* dst) const;
+
+    /**
+     * Multiplies this quaternion by the specified one and stores the result in this quaternion.
+     *
+     * @param q The quaternion to multiply.
+     */
+    void multiply(const Quaternion& q);
+
+    /**
+     * Multiplies the specified quaternions and stores the result in dst.
+     *
+     * @param q1 The first quaternion.
+     * @param q2 The second quaternion.
+     * @param dst A quaternion to store the result in.
+     */
+    static void multiply(const Quaternion& q1, const Quaternion& q2, Quaternion* dst);
+
+    /**
+     * Normalizes this quaternion to have unit length.
+     *
+     * If the quaternion already has unit length or if the length
+     * of the quaternion is zero, this method does nothing.
+     */
+    void normalize();
+
+    /**
+     * Normalizes this quaternion and stores the result in dst.
+     *
+     * If the quaternion already has unit length or if the length
+     * of the quaternion is zero, this method simply copies
+     * this vector into dst.
+     *
+     * @param dst A quaternion to store the result in.
+     */
+    void normalize(Quaternion* dst) const;
+
+    /**
+     * Sets the elements of the quaternion to the specified values.
+     *
+     * @param x The new x-value.
+     * @param y The new y-value.
+     * @param z The new z-value.
+     * @param w The new w-value.
+     */
+    void set(float x, float y, float z, float w);
+
+    /**
+     * Sets the elements of the quaternion from the values in the specified array.
+     *
+     * @param array An array containing the elements of the quaternion in the order x, y, z, w.
+     */
+    void set(float* array);
+
+    /**
+     * Sets the quaternion equal to the rotation from the specified axis and angle.
+     * 
+     * @param axis The axis of rotation.
+     * @param angle The angle of rotation (in radians).
+     */
+    void set(const Vector3& axis, float angle);
+
+    /**
+     * Sets the elements of this quaternion to a copy of the specified quaternion.
+     *
+     * @param q The quaternion to copy.
+     */
+    void set(const Quaternion& q);
+
+    /**
+     * Sets this quaternion to be equal to the identity quaternion.
+     */
+    void setIdentity();
+
+    /**
+     * Converts this Quaternion4f to axis-angle notation. The axis is normalized.
+     *
+     * @param e The Vector3f which stores the axis.
+     * 
+     * @return The angle (in radians).
+     */
+    float toAxisAngle(Vector3* e) const;
+
+    /**
+     * Interpolates between two quaternions using linear interpolation.
+     *
+     * The interpolation curve for linear interpolation between
+     * quaternions gives a straight line in quaternion space.
+     *
+     * @param q1 The first quaternion.
+     * @param q2 The second quaternion.
+     * @param t The interpolation coefficient.
+     * @param dst A quaternion to store the result in.
+     */
+    static void lerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
+    
+    /**
+     * Interpolates between two quaternions using spherical linear interpolation.
+     *
+     * Spherical linear interpolation provides smooth transitions between different
+     * orientations and is often useful for animating models or cameras in 3D.
+     *
+     * Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
+     * This method does not automatically normalize the input quaternions, so it is up to the
+     * caller to ensure they call normalize beforehand, if necessary.
+     *
+     * @param q1 The first quaternion.
+     * @param q2 The second quaternion.
+     * @param t The interpolation coefficient.
+     * @param dst A quaternion to store the result in.
+     */
+    static void slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
+    
+    /**
+     * Interpolates over a series of quaternions using spherical spline interpolation.
+     *
+     * Spherical spline interpolation provides smooth transitions between different
+     * orientations and is often useful for animating models or cameras in 3D.
+     *
+     * Note: For accurate interpolation, the input quaternions must be unit.
+     * This method does not automatically normalize the input quaternions,
+     * so it is up to the caller to ensure they call normalize beforehand, if necessary.
+     *
+     * @param q1 The first quaternion.
+     * @param q2 The second quaternion.
+     * @param s1 The first control point.
+     * @param s2 The second control point.
+     * @param t The interpolation coefficient.
+     * @param dst A quaternion to store the result in.
+     */
+    static void squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst);
+
+    /**
+     * Calculates the quaternion product of this quaternion with the given quaternion.
+     * 
+     * Note: this does not modify this quaternion.
+     * 
+     * @param q The quaternion to multiply.
+     * @return The quaternion product.
+     */
+    inline Quaternion operator*(const Quaternion& q) const;
+
+    /**
+     * Multiplies this quaternion with the given quaternion.
+     * 
+     * @param q The quaternion to multiply.
+     * @return This quaternion, after the multiplication occurs.
+     */
+    inline Quaternion& operator*=(const Quaternion& q);
+
+private:
+
+    /**
+     * Interpolates between two quaternions using spherical linear interpolation.
+     *
+     * Spherical linear interpolation provides smooth transitions between different
+     * orientations and is often useful for animating models or cameras in 3D.
+     *
+     * Note: For accurate interpolation, the input quaternions must be at (or close to) unit length.
+     * This method does not automatically normalize the input quaternions, so it is up to the
+     * caller to ensure they call normalize beforehand, if necessary.
+     *
+     * @param q1x The x component of the first quaternion.
+     * @param q1y The y component of the first quaternion.
+     * @param q1z The z component of the first quaternion.
+     * @param q1w The w component of the first quaternion.
+     * @param q2x The x component of the second quaternion.
+     * @param q2y The y component of the second quaternion.
+     * @param q2z The z component of the second quaternion.
+     * @param q2w The w component of the second quaternion.
+     * @param t The interpolation coefficient.
+     * @param dstx A pointer to store the x component of the slerp in.
+     * @param dsty A pointer to store the y component of the slerp in.
+     * @param dstz A pointer to store the z component of the slerp in.
+     * @param dstw A pointer to store the w component of the slerp in.
+     */
+    static void slerp(float q1x, float q1y, float q1z, float q1w, float q2x, float q2y, float q2z, float q2w, float t, float* dstx, float* dsty, float* dstz, float* dstw);
+
+    static void slerpForSquad(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst);
+};
+
+}
+
+#include "Quaternion.inl"
+
+#endif

+ 19 - 19
tools/encoder/src/Quaternion.inl

@@ -1,19 +1,19 @@
-#include "Quaternion.h"
-
-namespace gameplay
-{
-
-inline Quaternion Quaternion::operator*(const Quaternion& q) const
-{
-    Quaternion result(*this);
-    result.multiply(q);
-    return result;
-}
-
-inline Quaternion& Quaternion::operator*=(const Quaternion& q)
-{
-    multiply(q);
-    return *this;
-}
-
-}
+#include "Quaternion.h"
+
+namespace gameplay
+{
+
+inline Quaternion Quaternion::operator*(const Quaternion& q) const
+{
+    Quaternion result(*this);
+    result.multiply(q);
+    return result;
+}
+
+inline Quaternion& Quaternion::operator*=(const Quaternion& q)
+{
+    multiply(q);
+    return *this;
+}
+
+}

+ 87 - 87
tools/encoder/src/Reference.cpp

@@ -1,87 +1,87 @@
-#include "Base.h"
-#include "Reference.h"
-
-namespace gameplay
-{
-
-Reference::Reference(void) :
-    _type(0),
-    _offset(0),
-    _ref(NULL)
-{
-}
-
-Reference::Reference(std::string _xref, Object* _ref) :
-    _xref(_xref),
-    _type(_ref->getTypeId()),
-    _offset(0),
-    _ref(_ref)
-{
-}
-
-Reference::~Reference(void)
-{
-}
-
-const char* Reference::getElementName(void) const
-{
-    return "Reference";
-}
-
-void Reference::writeBinary(FILE* file)
-{
-    Object::writeBinary(file);
-    write(_xref, file);
-    write(_type, file);
-    write(_offset, file);
-}
-void Reference::writeText(FILE* file)
-{
-    fprintElementStart(file);
-    fprintfElement(file, "xref", _xref);
-    fprintfElement(file, "type", _type);
-    fprintfElement(file, "offset", _offset);
-    fprintElementEnd(file);
-}
-
-bool Reference::updateOffset(FILE* file)
-{
-    long newOffset = _ref->getFilePosition();
-    return updateOffset(file, newOffset);
-}
-
-bool Reference::updateOffset(FILE* file, long newOffset)
-{
-    if (getFilePosition() > 0)
-    {
-        // save the current offset
-        long savedOffset = ftell(file);
-
-        // update the offset data for this
-        _offset = newOffset;
-        // seek this Reference object in the file
-        fseek(file, getFilePosition(), SEEK_SET);
-
-        // skip over the object type
-        //fseek(file, sizeof(unsigned int), SEEK_CUR);
-        // skip over the id string
-        skipString(file);
-        // skip over the type
-        //skipUint(file);
-
-        // write over the old offset
-        write(_offset, file);
-
-        // restore the offset
-        fseek(file, savedOffset, SEEK_SET);
-        return true;
-    }
-    return false;
-}
-
-Object* Reference::getObj()
-{
-    return _ref;
-}
-
-}
+#include "Base.h"
+#include "Reference.h"
+
+namespace gameplay
+{
+
+Reference::Reference(void) :
+    _type(0),
+    _offset(0),
+    _ref(NULL)
+{
+}
+
+Reference::Reference(std::string _xref, Object* _ref) :
+    _xref(_xref),
+    _type(_ref->getTypeId()),
+    _offset(0),
+    _ref(_ref)
+{
+}
+
+Reference::~Reference(void)
+{
+}
+
+const char* Reference::getElementName(void) const
+{
+    return "Reference";
+}
+
+void Reference::writeBinary(FILE* file)
+{
+    Object::writeBinary(file);
+    write(_xref, file);
+    write(_type, file);
+    write(_offset, file);
+}
+void Reference::writeText(FILE* file)
+{
+    fprintElementStart(file);
+    fprintfElement(file, "xref", _xref);
+    fprintfElement(file, "type", _type);
+    fprintfElement(file, "offset", _offset);
+    fprintElementEnd(file);
+}
+
+bool Reference::updateOffset(FILE* file)
+{
+    long newOffset = _ref->getFilePosition();
+    return updateOffset(file, newOffset);
+}
+
+bool Reference::updateOffset(FILE* file, long newOffset)
+{
+    if (getFilePosition() > 0)
+    {
+        // save the current offset
+        long savedOffset = ftell(file);
+
+        // update the offset data for this
+        _offset = newOffset;
+        // seek this Reference object in the file
+        fseek(file, getFilePosition(), SEEK_SET);
+
+        // skip over the object type
+        //fseek(file, sizeof(unsigned int), SEEK_CUR);
+        // skip over the id string
+        skipString(file);
+        // skip over the type
+        //skipUint(file);
+
+        // write over the old offset
+        write(_offset, file);
+
+        // restore the offset
+        fseek(file, savedOffset, SEEK_SET);
+        return true;
+    }
+    return false;
+}
+
+Object* Reference::getObj()
+{
+    return _ref;
+}
+
+}

+ 57 - 57
tools/encoder/src/Reference.h

@@ -1,57 +1,57 @@
-#ifndef REFERENCE_H_
-#define REFERENCE_H_
-
-#include "Object.h"
-
-namespace gameplay
-{
-
-class Reference : public Object
-{
-public:
-
-    /**
-     * Constructor.
-     */
-    Reference(void);
-    Reference(std::string _xref, Object* _ref);
-
-    /**
-     * Destructor.
-     */
-    virtual ~Reference(void);
-
-    virtual const char* getElementName(void) const;
-    virtual void writeBinary(FILE* file);
-    virtual void writeText(FILE* file);
-
-    /**
-     * Updates the offset of this Reference object if it has already need written to file.
-     * @param file The file stream.
-     * 
-     * @return True if the offset was updates, false otherwise.
-     */
-    bool updateOffset(FILE* file);
-
-    /**
-     * Updates the offset of this Reference object if it has already need written to file.
-     * @param file The file stream.
-     * @param newOffset The new file offset.
-     * 
-     * @return True if the offset in the binary file was updated. False if this ref hasn't been written to file yet.
-     */
-    bool updateOffset(FILE* file, long newOffset);
-
-    Object* getObj();
-
-private:
-    std::string _xref;
-    unsigned int _type;
-    unsigned int _offset;
-
-    Object* _ref;
-};
-
-}
-
-#endif
+#ifndef REFERENCE_H_
+#define REFERENCE_H_
+
+#include "Object.h"
+
+namespace gameplay
+{
+
+class Reference : public Object
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    Reference(void);
+    Reference(std::string _xref, Object* _ref);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Reference(void);
+
+    virtual const char* getElementName(void) const;
+    virtual void writeBinary(FILE* file);
+    virtual void writeText(FILE* file);
+
+    /**
+     * Updates the offset of this Reference object if it has already need written to file.
+     * @param file The file stream.
+     * 
+     * @return True if the offset was updates, false otherwise.
+     */
+    bool updateOffset(FILE* file);
+
+    /**
+     * Updates the offset of this Reference object if it has already need written to file.
+     * @param file The file stream.
+     * @param newOffset The new file offset.
+     * 
+     * @return True if the offset in the binary file was updated. False if this ref hasn't been written to file yet.
+     */
+    bool updateOffset(FILE* file, long newOffset);
+
+    Object* getObj();
+
+private:
+    std::string _xref;
+    unsigned int _type;
+    unsigned int _offset;
+
+    Object* _ref;
+};
+
+}
+
+#endif

+ 69 - 69
tools/encoder/src/ReferenceTable.cpp

@@ -1,69 +1,69 @@
-#include "Base.h"
-#include "ReferenceTable.h"
-
-namespace gameplay
-{
-
-ReferenceTable::ReferenceTable(void)
-{
-}
-
-ReferenceTable::~ReferenceTable(void)
-{
-}
-
-void ReferenceTable::add(std::string xref, Object* obj)
-{
-    _table[xref] = Reference(xref, obj);
-}
-
-Object* ReferenceTable::get(const std::string& xref)
-{
-    std::map<std::string, Reference>::iterator it = _table.find(xref);
-    if (it != _table.end())
-    {
-        Reference ref = it->second;
-        return ref.getObj();
-    }
-    return NULL;
-}
-
-void ReferenceTable::writeBinary(FILE* file)
-{
-    write((unsigned int)_table.size(), file);
-    for ( std::map<std::string, Reference>::iterator i=_table.begin() ; i != _table.end(); ++i)
-    {
-        i->second.writeBinary(file);
-    }
-}
-
-void ReferenceTable::writeText(FILE* file)
-{
-    fprintf(file, "<RefTable>\n");
-    for ( std::map<std::string, Reference>::iterator i=_table.begin() ; i != _table.end(); ++i)
-    {
-        i->second.writeText(file);
-    }
-    fprintf(file, "</RefTable>\n");
-}
-
-void ReferenceTable::updateOffsets(FILE* file)
-{
-    for (std::map<std::string, Reference>::iterator i = _table.begin(); i != _table.end(); ++i)
-    {
-        Reference& ref = i->second;
-        ref.updateOffset(file);
-    }
-}
-
-std::map<std::string, Reference>::iterator ReferenceTable::begin()
-{
-    return _table.begin();
-}
-
-std::map<std::string, Reference>::iterator ReferenceTable::end()
-{
-    return _table.end();
-}
-
-}
+#include "Base.h"
+#include "ReferenceTable.h"
+
+namespace gameplay
+{
+
+ReferenceTable::ReferenceTable(void)
+{
+}
+
+ReferenceTable::~ReferenceTable(void)
+{
+}
+
+void ReferenceTable::add(std::string xref, Object* obj)
+{
+    _table[xref] = Reference(xref, obj);
+}
+
+Object* ReferenceTable::get(const std::string& xref)
+{
+    std::map<std::string, Reference>::iterator it = _table.find(xref);
+    if (it != _table.end())
+    {
+        Reference ref = it->second;
+        return ref.getObj();
+    }
+    return NULL;
+}
+
+void ReferenceTable::writeBinary(FILE* file)
+{
+    write((unsigned int)_table.size(), file);
+    for ( std::map<std::string, Reference>::iterator i=_table.begin() ; i != _table.end(); ++i)
+    {
+        i->second.writeBinary(file);
+    }
+}
+
+void ReferenceTable::writeText(FILE* file)
+{
+    fprintf(file, "<RefTable>\n");
+    for ( std::map<std::string, Reference>::iterator i=_table.begin() ; i != _table.end(); ++i)
+    {
+        i->second.writeText(file);
+    }
+    fprintf(file, "</RefTable>\n");
+}
+
+void ReferenceTable::updateOffsets(FILE* file)
+{
+    for (std::map<std::string, Reference>::iterator i = _table.begin(); i != _table.end(); ++i)
+    {
+        Reference& ref = i->second;
+        ref.updateOffset(file);
+    }
+}
+
+std::map<std::string, Reference>::iterator ReferenceTable::begin()
+{
+    return _table.begin();
+}
+
+std::map<std::string, Reference>::iterator ReferenceTable::end()
+{
+    return _table.end();
+}
+
+}

+ 58 - 58
tools/encoder/src/ReferenceTable.h

@@ -1,58 +1,58 @@
-#ifndef REFTABLE_H_
-#define REFTABLE_H_
-
-#include "FileIO.h"
-#include "Reference.h"
-#include "Object.h"
-
-namespace gameplay
-{
-
-/**
- * Collection of unique Reference objects stored in a hashtable.
- */
-class ReferenceTable
-{
-public:
-
-    /**
-     * Constructor.
-     */
-    ReferenceTable(void);
-
-    /**
-     * Destructor.
-     */
-    virtual ~ReferenceTable(void);
-
-    /**
-     * Adds an object to the reference table.
-     * 
-     * @param xref The xref for the object.
-     * @param obj The object to be added.
-     */
-    void add(std::string xref, Object* obj);
-
-    Object* get(const std::string& xref);
-
-    void writeBinary(FILE* file);
-    void writeText(FILE* file);
-
-    /**
-     * Updates the file positon offsets of the Reference objects in the GamePlay binary file.
-     * This needs to be called after all of the objects have been written.
-     * 
-     * @param file The file pointer.
-     */
-    void updateOffsets(FILE* file);
-
-    std::map<std::string, Reference>::iterator begin();
-    std::map<std::string, Reference>::iterator end();
-
-private:
-    std::map<std::string, Reference> _table;
-};
-
-}
-
-#endif
+#ifndef REFTABLE_H_
+#define REFTABLE_H_
+
+#include "FileIO.h"
+#include "Reference.h"
+#include "Object.h"
+
+namespace gameplay
+{
+
+/**
+ * Collection of unique Reference objects stored in a hashtable.
+ */
+class ReferenceTable
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    ReferenceTable(void);
+
+    /**
+     * Destructor.
+     */
+    virtual ~ReferenceTable(void);
+
+    /**
+     * Adds an object to the reference table.
+     * 
+     * @param xref The xref for the object.
+     * @param obj The object to be added.
+     */
+    void add(std::string xref, Object* obj);
+
+    Object* get(const std::string& xref);
+
+    void writeBinary(FILE* file);
+    void writeText(FILE* file);
+
+    /**
+     * Updates the file positon offsets of the Reference objects in the GamePlay binary file.
+     * This needs to be called after all of the objects have been written.
+     * 
+     * @param file The file pointer.
+     */
+    void updateOffsets(FILE* file);
+
+    std::map<std::string, Reference>::iterator begin();
+    std::map<std::string, Reference>::iterator end();
+
+private:
+    std::map<std::string, Reference> _table;
+};
+
+}
+
+#endif

+ 82 - 82
tools/encoder/src/Sampler.cpp

@@ -1,82 +1,82 @@
-#include "Base.h"
-#include "Sampler.h"
-#include "FileIO.h"
-
-namespace gameplay
-{
-
-using std::string;
-using std::map;
-
-Sampler::Sampler(const char* id) :
-    _id(id)
-{
-}
-
-Sampler::~Sampler(void)
-{
-}
-
-const string& Sampler::getId() const
-{
-    return _id;
-}
-
-const char* Sampler::getString(const string& name)
-{
-    map<string, string>::const_iterator it = props.find(name);
-    if (it != props.end())
-    {
-        return it->second.c_str();
-    }
-    return NULL;
-}
-
-void Sampler::set(const string& name, const string& value)
-{
-    props[name] = value;
-}
-
-void Sampler::writeMaterial(FILE* file, unsigned int indent, Sampler* parent)
-{
-    writeIndent(indent, file);
-    fprintf(file, "sampler %s\n", _id.c_str());
-    writeIndent(indent, file);
-    fprintf(file, "{\n");
-    ++indent;
-
-    const char* relativePath = getString("relativePath");
-    if (relativePath)
-        set("path", relativePath);
-
-    writeProperty(file, "path", indent, parent);
-    writeProperty(file, "mipmap", indent, parent);
-    writeProperty(file, "wrapS", indent, parent);
-    writeProperty(file, "wrapT", indent, parent);
-    writeProperty(file, MIN_FILTER, indent, parent);
-    writeProperty(file, MAG_FILTER, indent, parent);
-    --indent;
-    writeIndent(indent, file);
-    fprintf(file, "}\n");
-}
-
-void Sampler::writeProperty(FILE* file, const string& name, unsigned int indent, Sampler* parent)
-{
-    const char* value = getString(name);
-    if (value != NULL)
-    {
-        const char* parentValue = NULL;
-        // Don't print the property if it is the same as the parent's property
-        if (parent != NULL)
-        {
-            parentValue = parent->getString(name);
-        }
-        if (parentValue == NULL || strcmp(value, parentValue) != 0)
-        {
-            writeIndent(indent, file);
-            fprintf(file, "%s = %s\n", name.c_str(), value);
-        }
-    }
-}
-
-}
+#include "Base.h"
+#include "Sampler.h"
+#include "FileIO.h"
+
+namespace gameplay
+{
+
+using std::string;
+using std::map;
+
+Sampler::Sampler(const char* id) :
+    _id(id)
+{
+}
+
+Sampler::~Sampler(void)
+{
+}
+
+const string& Sampler::getId() const
+{
+    return _id;
+}
+
+const char* Sampler::getString(const string& name)
+{
+    map<string, string>::const_iterator it = props.find(name);
+    if (it != props.end())
+    {
+        return it->second.c_str();
+    }
+    return NULL;
+}
+
+void Sampler::set(const string& name, const string& value)
+{
+    props[name] = value;
+}
+
+void Sampler::writeMaterial(FILE* file, unsigned int indent, Sampler* parent)
+{
+    writeIndent(indent, file);
+    fprintf(file, "sampler %s\n", _id.c_str());
+    writeIndent(indent, file);
+    fprintf(file, "{\n");
+    ++indent;
+
+    const char* relativePath = getString("relativePath");
+    if (relativePath)
+        set("path", relativePath);
+
+    writeProperty(file, "path", indent, parent);
+    writeProperty(file, "mipmap", indent, parent);
+    writeProperty(file, "wrapS", indent, parent);
+    writeProperty(file, "wrapT", indent, parent);
+    writeProperty(file, MIN_FILTER, indent, parent);
+    writeProperty(file, MAG_FILTER, indent, parent);
+    --indent;
+    writeIndent(indent, file);
+    fprintf(file, "}\n");
+}
+
+void Sampler::writeProperty(FILE* file, const string& name, unsigned int indent, Sampler* parent)
+{
+    const char* value = getString(name);
+    if (value != NULL)
+    {
+        const char* parentValue = NULL;
+        // Don't print the property if it is the same as the parent's property
+        if (parent != NULL)
+        {
+            parentValue = parent->getString(name);
+        }
+        if (parentValue == NULL || strcmp(value, parentValue) != 0)
+        {
+            writeIndent(indent, file);
+            fprintf(file, "%s = %s\n", name.c_str(), value);
+        }
+    }
+}
+
+}

+ 50 - 50
tools/encoder/src/Sampler.h

@@ -1,50 +1,50 @@
-#ifndef Sampler_H_
-#define Sampler_H_
-
-#include "Base.h"
-#include "Constants.h"
-
-namespace gameplay
-{
-
-class Sampler
-{
-public:
-
-    /**
-     * Constructor.
-     */
-    Sampler(const char* id);
-
-    /**
-     * Destructor.
-     */
-    virtual ~Sampler(void);
-
-    const std::string& getId() const;
-
-    const char* getString(const std::string& name);
-    void set(const std::string& name, const std::string& value);
-
-    /**
-     * Writes this sampler to a material file.
-     * 
-     * @param file The file pointer.
-     * @param indent The number of indentation levels.
-     * @param parent The parent sampler from this material's parent.
-     */
-    void writeMaterial(FILE* file, unsigned int indent, Sampler* parent = NULL);
-
-private:
-
-    void writeProperty(FILE* file, const std::string& name, unsigned int indent, Sampler* parent = NULL);
-
-private:
-
-    std::string _id;
-    std::map<std::string, std::string> props;
-};
-
-}
-
-#endif
+#ifndef Sampler_H_
+#define Sampler_H_
+
+#include "Base.h"
+#include "Constants.h"
+
+namespace gameplay
+{
+
+class Sampler
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    Sampler(const char* id);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Sampler(void);
+
+    const std::string& getId() const;
+
+    const char* getString(const std::string& name);
+    void set(const std::string& name, const std::string& value);
+
+    /**
+     * Writes this sampler to a material file.
+     * 
+     * @param file The file pointer.
+     * @param indent The number of indentation levels.
+     * @param parent The parent sampler from this material's parent.
+     */
+    void writeMaterial(FILE* file, unsigned int indent, Sampler* parent = NULL);
+
+private:
+
+    void writeProperty(FILE* file, const std::string& name, unsigned int indent, Sampler* parent = NULL);
+
+private:
+
+    std::string _id;
+    std::map<std::string, std::string> props;
+};
+
+}
+
+#endif

+ 124 - 124
tools/encoder/src/Scene.cpp

@@ -1,124 +1,124 @@
-#include "Base.h"
-#include "Scene.h"
-
-namespace gameplay
-{
-
-Scene::Scene(void) : _cameraNode(NULL)
-{
-    _ambientColor[0] = 0.0f;
-    _ambientColor[1] = 0.0f;
-    _ambientColor[2] = 0.0f;
-    setId("scene");
-}
-
-Scene::~Scene(void)
-{
-}
-
-unsigned int Scene::getTypeId(void) const
-{
-    return SCENE_ID;
-}
-
-const char* Scene::getElementName(void) const
-{
-    return "Scene";
-}
-
-void Scene::writeBinary(FILE* file)
-{
-    Object::writeBinary(file);
-    writeBinaryObjects(_nodes, file);
-    if (_cameraNode)
-    {
-        _cameraNode->writeBinaryXref(file);
-    }
-    else
-    {
-        writeZero(file);
-    }
-    write(_ambientColor, Light::COLOR_SIZE, file);
-}
-
-void Scene::writeText(FILE* file)
-{
-    fprintElementStart(file);
-    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
-    {
-        (*i)->writeText(file);
-    }
-    if (_cameraNode)
-    {
-        fprintfElement(file, "activeCamera", _cameraNode->getId());
-    }
-    fprintfElement(file, "ambientColor", _ambientColor, Light::COLOR_SIZE);
-    fprintElementEnd(file);
-}
-
-void Scene::add(Node* node)
-{
-    _nodes.push_back(node);
-}
-
-void Scene::setActiveCameraNode(Node* node)
-{
-    _cameraNode = node;
-}
-
-Node* Scene::getFirstCameraNode() const
-{
-    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
-    {
-        Node* n = (*i)->getFirstCameraNode();
-        if (n)
-        {
-            return n;
-        }
-    }
-    return NULL;
-}
-
-void Scene::calcAmbientColor()
-{
-    float values[3] = {0.0f, 0.0f, 0.0f};
-    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
-    {
-        calcAmbientColor(*i, values);
-    }
-    
-    _ambientColor[0] = std::min(values[0], 1.0f);
-    _ambientColor[1] = std::min(values[1], 1.0f);
-    _ambientColor[2] = std::min(values[2], 1.0f);
-}
-
-void Scene::setAmbientColor(float red, float green, float blue)
-{
-    _ambientColor[0] = red;
-    _ambientColor[1] = green;
-    _ambientColor[2] = blue;
-}
-
-void Scene::calcAmbientColor(const Node* node, float* values) const
-{
-    if (!node)
-    {
-        return;
-    }
-    if (node->hasLight())
-    {
-        Light* light = node->getLight();
-        if (light->isAmbient())
-        {
-            values[0] += light->getRed();
-            values[1] += light->getGreen();
-            values[2] += light->getBlue();
-        }
-    }
-    for (Node* child = node->getFirstChild(); child != NULL; child = child->getNextSibling())
-    {
-        calcAmbientColor(child, values);
-    }
-}
-
-}
+#include "Base.h"
+#include "Scene.h"
+
+namespace gameplay
+{
+
+Scene::Scene(void) : _cameraNode(NULL)
+{
+    _ambientColor[0] = 0.0f;
+    _ambientColor[1] = 0.0f;
+    _ambientColor[2] = 0.0f;
+    setId("scene");
+}
+
+Scene::~Scene(void)
+{
+}
+
+unsigned int Scene::getTypeId(void) const
+{
+    return SCENE_ID;
+}
+
+const char* Scene::getElementName(void) const
+{
+    return "Scene";
+}
+
+void Scene::writeBinary(FILE* file)
+{
+    Object::writeBinary(file);
+    writeBinaryObjects(_nodes, file);
+    if (_cameraNode)
+    {
+        _cameraNode->writeBinaryXref(file);
+    }
+    else
+    {
+        writeZero(file);
+    }
+    write(_ambientColor, Light::COLOR_SIZE, file);
+}
+
+void Scene::writeText(FILE* file)
+{
+    fprintElementStart(file);
+    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
+    {
+        (*i)->writeText(file);
+    }
+    if (_cameraNode)
+    {
+        fprintfElement(file, "activeCamera", _cameraNode->getId());
+    }
+    fprintfElement(file, "ambientColor", _ambientColor, Light::COLOR_SIZE);
+    fprintElementEnd(file);
+}
+
+void Scene::add(Node* node)
+{
+    _nodes.push_back(node);
+}
+
+void Scene::setActiveCameraNode(Node* node)
+{
+    _cameraNode = node;
+}
+
+Node* Scene::getFirstCameraNode() const
+{
+    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
+    {
+        Node* n = (*i)->getFirstCameraNode();
+        if (n)
+        {
+            return n;
+        }
+    }
+    return NULL;
+}
+
+void Scene::calcAmbientColor()
+{
+    float values[3] = {0.0f, 0.0f, 0.0f};
+    for (std::list<Node*>::const_iterator i = _nodes.begin(); i != _nodes.end(); ++i)
+    {
+        calcAmbientColor(*i, values);
+    }
+    
+    _ambientColor[0] = std::min(values[0], 1.0f);
+    _ambientColor[1] = std::min(values[1], 1.0f);
+    _ambientColor[2] = std::min(values[2], 1.0f);
+}
+
+void Scene::setAmbientColor(float red, float green, float blue)
+{
+    _ambientColor[0] = red;
+    _ambientColor[1] = green;
+    _ambientColor[2] = blue;
+}
+
+void Scene::calcAmbientColor(const Node* node, float* values) const
+{
+    if (!node)
+    {
+        return;
+    }
+    if (node->hasLight())
+    {
+        Light* light = node->getLight();
+        if (light->isAmbient())
+        {
+            values[0] += light->getRed();
+            values[1] += light->getGreen();
+            values[2] += light->getBlue();
+        }
+    }
+    for (Node* child = node->getFirstChild(); child != NULL; child = child->getNextSibling())
+    {
+        calcAmbientColor(child, values);
+    }
+}
+
+}

+ 78 - 78
tools/encoder/src/Scene.h

@@ -1,78 +1,78 @@
-#ifndef SCENE_H_
-#define SCENE_H_
-
-#include "Object.h"
-#include "Node.h"
-#include "FileIO.h"
-
-namespace gameplay
-{
-
-class Scene : public Object
-{
-public:
-
-    /**
-     * Constructor.
-     */
-    Scene(void);
-
-    /**
-     * Destructor.
-     */
-    virtual ~Scene(void);
-
-    virtual unsigned int getTypeId(void) const;
-    virtual const char* getElementName(void) const;
-    virtual void writeBinary(FILE* file);
-    virtual void writeText(FILE* file);
-
-    /**
-     * Adds the given node as a child of this scene.
-     * 
-     * @param node The node to add.
-     */
-    void add(Node* node);
-
-    /**
-     * Sets the activate camera node. This node should contain a camera.
-     */
-    void setActiveCameraNode(Node* node);
-
-    /**
-     * Returns the first node the this scene that contains a camera.
-     */
-    Node* getFirstCameraNode() const;
-
-    /**
-     * Calculates the ambient color of this scene by combining all of the ambient lights
-     * that are in this scene.
-     */
-    void calcAmbientColor();
-
-    /**
-     * Sets the scene's ambient color.
-     */
-    void setAmbientColor(float red, float green, float blue);
-
-private:
-
-    /**
-     * Recursively calculates the ambient color of the scene starting at the given node.
-     * The ambient light color is added to the given float array.
-     * 
-     * @param node The node in this scene to traverse from.
-     * @param values Pointer to 3 floats that contains the calculated ambient color.
-     */
-    void calcAmbientColor(const Node* node, float* values) const;
-
-private:
-    std::list<Node*> _nodes;
-    Node* _cameraNode;
-    float _ambientColor[Light::COLOR_SIZE];
-    Node* _lightNode;
-};
-
-}
-
-#endif
+#ifndef SCENE_H_
+#define SCENE_H_
+
+#include "Object.h"
+#include "Node.h"
+#include "FileIO.h"
+
+namespace gameplay
+{
+
+class Scene : public Object
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    Scene(void);
+
+    /**
+     * Destructor.
+     */
+    virtual ~Scene(void);
+
+    virtual unsigned int getTypeId(void) const;
+    virtual const char* getElementName(void) const;
+    virtual void writeBinary(FILE* file);
+    virtual void writeText(FILE* file);
+
+    /**
+     * Adds the given node as a child of this scene.
+     * 
+     * @param node The node to add.
+     */
+    void add(Node* node);
+
+    /**
+     * Sets the activate camera node. This node should contain a camera.
+     */
+    void setActiveCameraNode(Node* node);
+
+    /**
+     * Returns the first node the this scene that contains a camera.
+     */
+    Node* getFirstCameraNode() const;
+
+    /**
+     * Calculates the ambient color of this scene by combining all of the ambient lights
+     * that are in this scene.
+     */
+    void calcAmbientColor();
+
+    /**
+     * Sets the scene's ambient color.
+     */
+    void setAmbientColor(float red, float green, float blue);
+
+private:
+
+    /**
+     * Recursively calculates the ambient color of the scene starting at the given node.
+     * The ambient light color is added to the given float array.
+     * 
+     * @param node The node in this scene to traverse from.
+     * @param values Pointer to 3 floats that contains the calculated ambient color.
+     */
+    void calcAmbientColor(const Node* node, float* values) const;
+
+private:
+    std::list<Node*> _nodes;
+    Node* _cameraNode;
+    float _ambientColor[Light::COLOR_SIZE];
+    Node* _lightNode;
+};
+
+}
+
+#endif

+ 131 - 131
tools/encoder/src/StringUtil.cpp

@@ -1,131 +1,131 @@
-#include "Base.h"
-#include "StringUtil.h"
-
-namespace gameplay
-{
-
-inline char lowercase(char c)
-{
-    if (c >= 'A' && c <='Z')
-    {
-        c |= 0x20;
-    }
-    return c;
-}
-
-bool startsWith(const char* str, const char* prefix, bool ignoreCase)
-{
-    size_t length = strlen(str);
-    size_t prefixLength = strlen(prefix);
-
-    if (prefixLength > length)
-    {
-        return false;
-    }
-
-    const char* p = str;
-    while (*p != '\0' && *prefix != '\0')
-    {
-        if (ignoreCase)
-        {
-            if (lowercase(*p) != lowercase(*prefix))
-            {
-                return false;
-            }
-        }
-        else if (*p != *prefix)
-        {
-            return false;
-        }
-        
-        ++p;
-        ++prefix;
-    }
-    return true;
-}
-
-bool endsWith(const char* str, const char* suffix, bool ignoreCase)
-{
-    size_t length = strlen(str);
-    size_t suffixLength = strlen(suffix);
-
-    if (suffixLength > length)
-    {
-        return false;
-    }
-
-    size_t offset = length - suffixLength;
-
-    const char* p = str + offset;
-    while (*p != '\0' && *suffix != '\0')
-    {
-        if (ignoreCase)
-        {
-            if (lowercase(*p) != lowercase(*suffix))
-            {
-                return false;
-            }
-        }
-        else if (*p != *suffix)
-        {
-            return false;
-        }
-        
-        ++p;
-        ++suffix;
-    }
-    return true;
-}
-
-bool endsWith(const std::string& str, const char* suffix, bool ignoreCase)
-{
-    return endsWith(str.c_str(), suffix, ignoreCase);
-}
-
-bool equals(const std::string& a, const char* b)
-{
-    return (a.compare(b) == 0);
-}
-
-bool equals(const std::string& a, const std::string& b)
-{
-    return (a.compare(b) == 0);
-}
-
-bool equalsIgnoreCase(const std::string& a, const char* b)
-{
-    size_t bLength = strlen(b);
-    if (a.size() != bLength)
-    {
-        return false;
-    }
-    for (size_t i = 0; i < bLength; ++i)
-    {
-        if (lowercase(a[i]) != lowercase(b[i]))
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-std::string getFilenameFromFilePath(const std::string& filepath)
-{
-    if (filepath.find_last_of("/") != std::string::npos)
-    {
-        return filepath.substr(filepath.find_last_of("/") + 1);
-    }
-    return "";
-}
-
-
-std::string getFilenameNoExt(const std::string& filename)
-{
-    if (filename.find_last_of(".") != std::string::npos)
-    {
-        return filename.substr(0, filename.find_last_of("."));
-    }
-    return filename;
-}
-
-}
+#include "Base.h"
+#include "StringUtil.h"
+
+namespace gameplay
+{
+
+inline char lowercase(char c)
+{
+    if (c >= 'A' && c <='Z')
+    {
+        c |= 0x20;
+    }
+    return c;
+}
+
+bool startsWith(const char* str, const char* prefix, bool ignoreCase)
+{
+    size_t length = strlen(str);
+    size_t prefixLength = strlen(prefix);
+
+    if (prefixLength > length)
+    {
+        return false;
+    }
+
+    const char* p = str;
+    while (*p != '\0' && *prefix != '\0')
+    {
+        if (ignoreCase)
+        {
+            if (lowercase(*p) != lowercase(*prefix))
+            {
+                return false;
+            }
+        }
+        else if (*p != *prefix)
+        {
+            return false;
+        }
+        
+        ++p;
+        ++prefix;
+    }
+    return true;
+}
+
+bool endsWith(const char* str, const char* suffix, bool ignoreCase)
+{
+    size_t length = strlen(str);
+    size_t suffixLength = strlen(suffix);
+
+    if (suffixLength > length)
+    {
+        return false;
+    }
+
+    size_t offset = length - suffixLength;
+
+    const char* p = str + offset;
+    while (*p != '\0' && *suffix != '\0')
+    {
+        if (ignoreCase)
+        {
+            if (lowercase(*p) != lowercase(*suffix))
+            {
+                return false;
+            }
+        }
+        else if (*p != *suffix)
+        {
+            return false;
+        }
+        
+        ++p;
+        ++suffix;
+    }
+    return true;
+}
+
+bool endsWith(const std::string& str, const char* suffix, bool ignoreCase)
+{
+    return endsWith(str.c_str(), suffix, ignoreCase);
+}
+
+bool equals(const std::string& a, const char* b)
+{
+    return (a.compare(b) == 0);
+}
+
+bool equals(const std::string& a, const std::string& b)
+{
+    return (a.compare(b) == 0);
+}
+
+bool equalsIgnoreCase(const std::string& a, const char* b)
+{
+    size_t bLength = strlen(b);
+    if (a.size() != bLength)
+    {
+        return false;
+    }
+    for (size_t i = 0; i < bLength; ++i)
+    {
+        if (lowercase(a[i]) != lowercase(b[i]))
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+std::string getFilenameFromFilePath(const std::string& filepath)
+{
+    if (filepath.find_last_of("/") != std::string::npos)
+    {
+        return filepath.substr(filepath.find_last_of("/") + 1);
+    }
+    return "";
+}
+
+
+std::string getFilenameNoExt(const std::string& filename)
+{
+    if (filename.find_last_of(".") != std::string::npos)
+    {
+        return filename.substr(0, filename.find_last_of("."));
+    }
+    return filename;
+}
+
+}

+ 38 - 38
tools/encoder/src/StringUtil.h

@@ -1,38 +1,38 @@
-#ifndef STRINGUTIL_H_
-#define STRINGUTIL_H_
-
-namespace gameplay
-{
-
-/**
- * Returns true if the given string starts with the prefix.
- */
-bool startsWith(const char* str, const char* prefix, bool ignoreCase = true);
-
-/**
- * Returns true if the given string ends with the suffix.
- */
-bool endsWith(const char* str, const char* suffix, bool ignoreCase = true);
-bool endsWith(const std::string& str, const char* suffix, bool ignoreCase = true);
-
-/**
- * Return true if the strings are equal. Case sensitive.
- */
-bool equals(const std::string& a, const char* b);
-bool equals(const std::string& a, const std::string& b);
-
-/**
- * Returns true if the strings are equal. Case insensitive.
- */
-bool equalsIgnoreCase(const std::string& a, const char* b);
-
-/**
- * Returns the filename from the given real path.
- */
-std::string getFilenameFromFilePath(const std::string& filepath);
-
-std::string getFilenameNoExt(const std::string& filename);
-
-}
-
-#endif
+#ifndef STRINGUTIL_H_
+#define STRINGUTIL_H_
+
+namespace gameplay
+{
+
+/**
+ * Returns true if the given string starts with the prefix.
+ */
+bool startsWith(const char* str, const char* prefix, bool ignoreCase = true);
+
+/**
+ * Returns true if the given string ends with the suffix.
+ */
+bool endsWith(const char* str, const char* suffix, bool ignoreCase = true);
+bool endsWith(const std::string& str, const char* suffix, bool ignoreCase = true);
+
+/**
+ * Return true if the strings are equal. Case sensitive.
+ */
+bool equals(const std::string& a, const char* b);
+bool equals(const std::string& a, const std::string& b);
+
+/**
+ * Returns true if the strings are equal. Case insensitive.
+ */
+bool equalsIgnoreCase(const std::string& a, const char* b);
+
+/**
+ * Returns the filename from the given real path.
+ */
+std::string getFilenameFromFilePath(const std::string& filepath);
+
+std::string getFilenameNoExt(const std::string& filename);
+
+}
+
+#endif

+ 487 - 487
tools/encoder/src/TTFFontEncoder.cpp

@@ -1,487 +1,487 @@
-#include "Base.h"
-#include "TTFFontEncoder.h"
-#include "GPBFile.h"
-#include "StringUtil.h"
-
-namespace gameplay
-{
-
-static void drawBitmap(unsigned char* dstBitmap, int x, int y, int dstWidth, unsigned char* srcBitmap, int srcWidth, int srcHeight)
-{
-    // offset dst bitmap by x,y.
-    dstBitmap +=  (x + (y * dstWidth));
-
-    for (int i = 0; i < srcHeight; ++i)
-    {
-        memcpy(dstBitmap, (const void*)srcBitmap, srcWidth);
-        srcBitmap += srcWidth;
-        dstBitmap += dstWidth;
-    }
-}
-
-static void writeUint(FILE* fp, unsigned int i)
-{
-    fwrite(&i, sizeof(unsigned int), 1, fp);
-}
-
-static void writeString(FILE* fp, const char* str)
-{
-    unsigned int len = strlen(str);
-    fwrite(&len, sizeof(unsigned int), 1, fp);
-    if (len > 0)
-    {
-        fwrite(str, 1, len, fp);
-    }
-}
-
-unsigned char* createDistanceFields(unsigned char* img, unsigned int width, unsigned int height)
-{
-    short* xDistance = (short*)malloc(width * height * sizeof(short));
-    short* yDistance = (short*)malloc(width * height * sizeof(short));
-    double* gx = (double*)calloc(width * height, sizeof(double));
-    double* gy = (double*)calloc(width * height, sizeof(double));
-    double* data = (double*)calloc(width * height, sizeof(double));
-    double* outside = (double*)calloc(width * height, sizeof(double));
-    double* inside = (double*)calloc(width * height, sizeof(double));
-    unsigned int i;
-
-    // Convert img into double (data)
-    double imgMin = 255;
-    double imgMax = -255;
-    for (i = 0; i < width * height; ++i)
-    {
-        double v = img[i];
-        data[i] = v;
-        if (v > imgMax) 
-            imgMax = v;
-        if (v < imgMin) 
-            imgMin = v;
-    }
-    // Rescale image levels between 0 and 1
-    for (i = 0; i < width * height; ++i)
-    {
-        data[i] = (img[i] - imgMin) / imgMax;
-    }
-    // Compute outside = edtaa3(bitmap); % Transform background (0's)
-    computegradient(data, width, height, gx, gy);
-    edtaa3(data, gx, gy, height, width, xDistance, yDistance, outside);
-    for (i = 0; i < width * height; ++i)
-    {
-        if (outside[i] < 0 )
-            outside[i] = 0.0;
-    }
-    // Compute inside = edtaa3(1-bitmap); % Transform foreground (1's)
-    memset(gx, 0, sizeof(double) * width * height);
-    memset(gy, 0, sizeof(double) * width * height);
-    for (i = 0; i < width * height; ++i)
-    {
-        data[i] = 1 - data[i];
-    }
-    computegradient(data, width, height, gx, gy);
-    edtaa3(data, gx, gy, height, width, xDistance, yDistance, inside);
-    for (i = 0; i < width * height; ++i)
-    {
-        if( inside[i] < 0 )
-            inside[i] = 0.0;
-    }
-    // distmap = outside - inside; % Bipolar distance field
-    unsigned char* out = (unsigned char*)malloc(sizeof(unsigned char) * width * height);
-    for (i = 0; i < width * height; ++i)
-    {
-        outside[i] -= inside[i];
-        outside[i] = 128 + outside[i] * 16;
-        if (outside[i] < 0) 
-            outside[i] = 0;
-        if (outside[i] > 255) 
-            outside[i] = 255;
-        out[i] = 255 - (unsigned char) outside[i];
-    }
-    free(xDistance);
-    free(yDistance);
-    free(gx);
-    free(gy);
-    free(data);
-    free(outside);
-    free(inside);
-
-    return out;
-}
-
-int writeFont(const char* inFilePath, const char* outFilePath, std::vector<unsigned int>& fontSizes, const char* id, bool fontpreview = false, Font::FontFormat fontFormat = Font::BITMAP)
-{
-    // Initialize freetype library.
-    FT_Library library;
-    FT_Error error = FT_Init_FreeType(&library);
-    if (error)
-    {
-        LOG(1, "FT_Init_FreeType error: %d \n", error);
-        return -1;
-    }
-
-    // Initialize font face.
-    FT_Face face;
-    error = FT_New_Face(library, inFilePath, 0, &face);
-    if (error)
-    {
-        LOG(1, "FT_New_Face error: %d \n", error);
-        return -1;
-    }
-
-    // Stores a single genreated font size to be written into the GPB
-    struct FontData
-    {
-        // Array of glyphs for a font
-        TTFGlyph glyphArray[END_INDEX - START_INDEX];
-
-        // Stores final height of a row required to render all glyphs
-        int fontSize;
-
-        // Actual size of the underlying glyphs (may be different from fontSize)
-        int glyphSize;
-
-        // Font texture
-        unsigned char* imageBuffer;
-        unsigned int imageWidth;
-        unsigned int imageHeight;
-
-        FontData() : fontSize(0), glyphSize(0), imageBuffer(NULL), imageWidth(0), imageHeight(0)
-        {
-        }
-
-        ~FontData()
-        {
-            if (imageBuffer)
-                free(imageBuffer);
-        }
-    };
-    std::vector<FontData*> fonts;
-
-    for (size_t fontIndex = 0, count = fontSizes.size(); fontIndex < count; ++fontIndex)
-    {
-        unsigned int fontSize = fontSizes[fontIndex];
-
-        FontData* font = new FontData();
-        font->fontSize = fontSize;
-
-        TTFGlyph* glyphArray = font->glyphArray;
-
-        int rowSize = 0;
-        int glyphSize = 0;
-        int actualfontHeight = 0;
-
-        FT_GlyphSlot slot = NULL;
-        FT_Int32 loadFlags = FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT;
-
-        // We want to generate fonts that fit exactly the requested pixels size.
-        // Since free type (due to modern fonts) does not directly correlate requested
-        // size to glyph size, we'll brute-force attempt to set the largest font size
-        // possible that will fit within the requested pixel size.
-        for (unsigned int requestedSize = fontSize; requestedSize > 0; --requestedSize)
-        {
-            // Set the pixel size.
-            error = FT_Set_Char_Size( face, 0, requestedSize * 64, 0, 0 );
-            if (error)
-            {
-                LOG(1, "FT_Set_Pixel_Sizes error: %d \n", error);
-                return -1;
-            }
-
-            // Save glyph information (slot contains the actual glyph bitmap).
-            slot = face->glyph;
-
-            rowSize = 0;
-            glyphSize = 0;
-            actualfontHeight = 0;
-
-            // Find the width of the image.
-            for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ++ascii)
-            {
-                // Load glyph image into the slot (erase previous one)
-                error = FT_Load_Char(face, ascii, loadFlags);
-                if (error)
-                {
-                    LOG(1, "FT_Load_Char error : %d \n", error);
-                }
-
-                int bitmapRows = slot->bitmap.rows;
-                actualfontHeight = (actualfontHeight < bitmapRows) ? bitmapRows : actualfontHeight;
-
-                if (slot->bitmap.rows > slot->bitmap_top)
-                {
-                    bitmapRows += (slot->bitmap.rows - slot->bitmap_top);
-                }
-                rowSize = (rowSize < bitmapRows) ? bitmapRows : rowSize;
-            }
-
-            // Have we found a pixel size that fits?
-            if (rowSize <= (int)fontSize)
-            {
-                glyphSize = rowSize;
-                rowSize = fontSize;
-                break;
-            }
-        }
-
-        if (slot == NULL || glyphSize == 0)
-        {
-            LOG(1, "Cannot generate a font of the requested size: %d\n", fontSize);
-            return -1;
-        }
-
-        // Include padding in the rowSize.
-        rowSize += GLYPH_PADDING;
-
-        // Initialize with padding.
-        int penX = 0;
-        int penY = 0;
-        int row = 0;
-
-        double powerOf2 = 2;
-        unsigned int imageWidth = 0;
-        unsigned int imageHeight = 0;
-        bool textureSizeFound = false;
-
-        int advance;
-        int i;
-
-        while (textureSizeFound == false)
-        {
-            imageWidth =  (unsigned int)pow(2.0, powerOf2);
-            imageHeight = (unsigned int)pow(2.0, powerOf2);
-            penX = 0;
-            penY = 0;
-            row = 0;
-
-            // Find out the squared texture size that would fit all the require font glyphs.
-            i = 0;
-            for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ++ascii)
-            {
-                // Load glyph image into the slot (erase the previous one).
-                error = FT_Load_Char(face, ascii, loadFlags);
-                if (error)
-                {
-                    LOG(1, "FT_Load_Char error : %d \n", error);
-                }
-                // Glyph image.
-                int glyphWidth = slot->bitmap.pitch;
-                int glyphHeight = slot->bitmap.rows;
-
-                advance = glyphWidth + GLYPH_PADDING; 
-
-                // If we reach the end of the image wrap aroud to the next row.
-                if ((penX + advance) > (int)imageWidth)
-                {
-                    penX = 0;
-                    row += 1;
-                    penY = row * rowSize;
-                    if (penY + rowSize > (int)imageHeight)
-                    {
-                        powerOf2++;
-                        break;
-                    }
-                }
-
-                // penY should include the glyph offsets.
-                penY += (actualfontHeight - glyphHeight) + (glyphHeight - slot->bitmap_top);
-
-                // Set the pen position for the next glyph
-                penX += advance; // Move X to next glyph position
-                // Move Y back to the top of the row.
-                penY = row * rowSize;
-
-                if (ascii == (END_INDEX - 1))
-                {
-                    textureSizeFound = true;
-                }
-                i++;
-            }
-        }
-
-        // Try further to find a tighter texture size.
-        powerOf2 = 1;
-        for (;;)
-        {
-            if ((penY + rowSize) >= pow(2.0, powerOf2))
-            {
-                powerOf2++;
-            }
-            else
-            {
-                imageHeight = (int)pow(2.0, powerOf2);
-                break;
-            }
-        }
-
-        // Allocate temporary image buffer to draw the glyphs into.
-        unsigned char* imageBuffer = (unsigned char*)malloc(imageWidth * imageHeight);
-        memset(imageBuffer, 0, imageWidth * imageHeight);
-        penX = 0;
-        penY = 0;
-        row = 0;
-        i = 0;
-        for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ++ascii)
-        {
-            // Load glyph image into the slot (erase the previous one).
-            error = FT_Load_Char(face, ascii, loadFlags);
-            if (error)
-            {
-                LOG(1, "FT_Load_Char error : %d \n", error);
-            }
-
-            // Glyph image.
-            unsigned char* glyphBuffer =  slot->bitmap.buffer;
-            int glyphWidth = slot->bitmap.pitch;
-            int glyphHeight = slot->bitmap.rows;
-
-            advance = glyphWidth + GLYPH_PADDING;
-
-            // If we reach the end of the image wrap aroud to the next row.
-            if ((penX + advance) > (int)imageWidth)
-            {
-                penX = 0;
-                row += 1;
-                penY = row * rowSize;
-                if (penY + rowSize > (int)imageHeight)
-                {
-                    free(imageBuffer);
-                    LOG(1, "Image size exceeded!");
-                    return -1;
-                }
-            }
-
-            // penY should include the glyph offsets.
-            penY += (actualfontHeight - glyphHeight) + (glyphHeight - slot->bitmap_top);
-
-            // Draw the glyph to the bitmap with a one pixel padding.
-            drawBitmap(imageBuffer, penX, penY, imageWidth, glyphBuffer, glyphWidth, glyphHeight);
-
-            // Move Y back to the top of the row.
-            penY = row * rowSize;
-
-            glyphArray[i].index = ascii;
-            glyphArray[i].width = advance - GLYPH_PADDING;
-
-            // Generate UV coords.
-            glyphArray[i].uvCoords[0] = (float)penX / (float)imageWidth;
-            glyphArray[i].uvCoords[1] = (float)penY / (float)imageHeight;
-            glyphArray[i].uvCoords[2] = (float)(penX + advance - GLYPH_PADDING) / (float)imageWidth;
-            glyphArray[i].uvCoords[3] = (float)(penY + rowSize - GLYPH_PADDING) / (float)imageHeight;
-
-            // Set the pen position for the next glyph
-            penX += advance;
-            i++;
-        }
-
-        font->glyphSize = glyphSize;
-        font->imageBuffer = imageBuffer;
-        font->imageWidth = imageWidth;
-        font->imageHeight = imageHeight;
-        fonts.push_back(font);
-    }
-
-    // File header and version.
-    FILE *gpbFp = fopen(outFilePath, "wb");    
-    char fileHeader[9]     = {'\xAB', 'G', 'P', 'B', '\xBB', '\r', '\n', '\x1A', '\n'};
-    fwrite(fileHeader, sizeof(char), 9, gpbFp);
-    fwrite(gameplay::GPB_VERSION, sizeof(char), 2, gpbFp);
-
-    // Write Ref table (for a single font)
-    writeUint(gpbFp, 1);                // Ref[] count
-    writeString(gpbFp, id);             // Ref id
-    writeUint(gpbFp, 128);              // Ref type
-    writeUint(gpbFp, ftell(gpbFp) + 4); // Ref offset (current pos + 4 bytes)
-
-    // Family name.
-    writeString(gpbFp, face->family_name);
-
-    // Style.
-    // TODO: Switch based on TTF style name and write appropriate font style unsigned int for now just hardcoding to 0 = PLAIN.
-    writeUint(gpbFp, 0);
-
-    // Number of included font sizes (GPB version 1.3+)
-    writeUint(gpbFp, (unsigned int)fonts.size());
-
-    for (size_t i = 0, count = fonts.size(); i < count; ++i)
-    {
-        FontData* font = fonts[i];
-
-        // Font size (pixels).
-        writeUint(gpbFp, font->fontSize);
-
-        // Character set. TODO: Empty for now
-        writeString(gpbFp, "");
-
-        // Glyphs.
-        unsigned int glyphSetSize = END_INDEX - START_INDEX;
-        writeUint(gpbFp, glyphSetSize);
-        fwrite(&font->glyphArray, sizeof(TTFGlyph), glyphSetSize, gpbFp);
-
-        // Image dimensions
-        unsigned int imageSize = font->imageWidth * font->imageHeight;
-        writeUint(gpbFp, font->imageWidth);
-        writeUint(gpbFp, font->imageHeight);
-        writeUint(gpbFp, imageSize);
-
-        FILE* previewFp = NULL;
-        std::string pgmFilePath;
-        if (fontpreview)
-        {
-            // Save out a pgm monochome image file for preview
-            std::ostringstream pgmFilePathStream;
-            pgmFilePathStream << getFilenameNoExt(outFilePath) << "-" << font->fontSize << ".pgm";
-            pgmFilePath = pgmFilePathStream.str();
-            previewFp = fopen(pgmFilePath.c_str(), "wb");
-            fprintf(previewFp, "P5 %u %u 255\n", font->imageWidth, font->imageHeight);
-        }
-
-        if (fontFormat == Font::DISTANCE_FIELD)
-        {
-            // Flip height and width since the distance field map generator is column-wise.
-            unsigned char* distanceFieldBuffer = createDistanceFields(font->imageBuffer, font->imageHeight, font->imageWidth);
-
-            fwrite(distanceFieldBuffer, sizeof(unsigned char), imageSize, gpbFp);
-            writeUint(gpbFp, Font::DISTANCE_FIELD);
-
-            if (previewFp)
-            {
-                fwrite((const char*)distanceFieldBuffer, sizeof(unsigned char), imageSize, previewFp);
-                fclose(previewFp);
-            }
-
-            free(distanceFieldBuffer);
-        }
-        else
-        {
-            fwrite(font->imageBuffer, sizeof(unsigned char), imageSize, gpbFp);
-            writeUint(gpbFp, Font::BITMAP);
-
-            if (previewFp)
-            {
-                fwrite((const char*)font->imageBuffer, sizeof(unsigned char), font->imageWidth * font->imageHeight, previewFp);
-                fclose(previewFp);
-            }
-        }
-
-        if (previewFp)
-        {
-            fclose(previewFp);
-            LOG(1, "%s.pgm preview image created successfully. \n", getBaseName(pgmFilePath).c_str());
-        }
-    }
-
-    // Close file.
-    fclose(gpbFp);
-
-    LOG(1, "%s.gpb created successfully. \n", getBaseName(outFilePath).c_str());
-
-    for (size_t i = 0, count = fonts.size(); i < count; ++i)
-    {
-        delete fonts[i];
-    }
-
-    FT_Done_Face(face);
-    FT_Done_FreeType(library);
-    return 0;
-}
-
-}
+#include "Base.h"
+#include "TTFFontEncoder.h"
+#include "GPBFile.h"
+#include "StringUtil.h"
+
+namespace gameplay
+{
+
+static void drawBitmap(unsigned char* dstBitmap, int x, int y, int dstWidth, unsigned char* srcBitmap, int srcWidth, int srcHeight)
+{
+    // offset dst bitmap by x,y.
+    dstBitmap +=  (x + (y * dstWidth));
+
+    for (int i = 0; i < srcHeight; ++i)
+    {
+        memcpy(dstBitmap, (const void*)srcBitmap, srcWidth);
+        srcBitmap += srcWidth;
+        dstBitmap += dstWidth;
+    }
+}
+
+static void writeUint(FILE* fp, unsigned int i)
+{
+    fwrite(&i, sizeof(unsigned int), 1, fp);
+}
+
+static void writeString(FILE* fp, const char* str)
+{
+    unsigned int len = strlen(str);
+    fwrite(&len, sizeof(unsigned int), 1, fp);
+    if (len > 0)
+    {
+        fwrite(str, 1, len, fp);
+    }
+}
+
+unsigned char* createDistanceFields(unsigned char* img, unsigned int width, unsigned int height)
+{
+    short* xDistance = (short*)malloc(width * height * sizeof(short));
+    short* yDistance = (short*)malloc(width * height * sizeof(short));
+    double* gx = (double*)calloc(width * height, sizeof(double));
+    double* gy = (double*)calloc(width * height, sizeof(double));
+    double* data = (double*)calloc(width * height, sizeof(double));
+    double* outside = (double*)calloc(width * height, sizeof(double));
+    double* inside = (double*)calloc(width * height, sizeof(double));
+    unsigned int i;
+
+    // Convert img into double (data)
+    double imgMin = 255;
+    double imgMax = -255;
+    for (i = 0; i < width * height; ++i)
+    {
+        double v = img[i];
+        data[i] = v;
+        if (v > imgMax) 
+            imgMax = v;
+        if (v < imgMin) 
+            imgMin = v;
+    }
+    // Rescale image levels between 0 and 1
+    for (i = 0; i < width * height; ++i)
+    {
+        data[i] = (img[i] - imgMin) / imgMax;
+    }
+    // Compute outside = edtaa3(bitmap); % Transform background (0's)
+    computegradient(data, width, height, gx, gy);
+    edtaa3(data, gx, gy, height, width, xDistance, yDistance, outside);
+    for (i = 0; i < width * height; ++i)
+    {
+        if (outside[i] < 0 )
+            outside[i] = 0.0;
+    }
+    // Compute inside = edtaa3(1-bitmap); % Transform foreground (1's)
+    memset(gx, 0, sizeof(double) * width * height);
+    memset(gy, 0, sizeof(double) * width * height);
+    for (i = 0; i < width * height; ++i)
+    {
+        data[i] = 1 - data[i];
+    }
+    computegradient(data, width, height, gx, gy);
+    edtaa3(data, gx, gy, height, width, xDistance, yDistance, inside);
+    for (i = 0; i < width * height; ++i)
+    {
+        if( inside[i] < 0 )
+            inside[i] = 0.0;
+    }
+    // distmap = outside - inside; % Bipolar distance field
+    unsigned char* out = (unsigned char*)malloc(sizeof(unsigned char) * width * height);
+    for (i = 0; i < width * height; ++i)
+    {
+        outside[i] -= inside[i];
+        outside[i] = 128 + outside[i] * 16;
+        if (outside[i] < 0) 
+            outside[i] = 0;
+        if (outside[i] > 255) 
+            outside[i] = 255;
+        out[i] = 255 - (unsigned char) outside[i];
+    }
+    free(xDistance);
+    free(yDistance);
+    free(gx);
+    free(gy);
+    free(data);
+    free(outside);
+    free(inside);
+
+    return out;
+}
+
+int writeFont(const char* inFilePath, const char* outFilePath, std::vector<unsigned int>& fontSizes, const char* id, bool fontpreview = false, Font::FontFormat fontFormat = Font::BITMAP)
+{
+    // Initialize freetype library.
+    FT_Library library;
+    FT_Error error = FT_Init_FreeType(&library);
+    if (error)
+    {
+        LOG(1, "FT_Init_FreeType error: %d \n", error);
+        return -1;
+    }
+
+    // Initialize font face.
+    FT_Face face;
+    error = FT_New_Face(library, inFilePath, 0, &face);
+    if (error)
+    {
+        LOG(1, "FT_New_Face error: %d \n", error);
+        return -1;
+    }
+
+    // Stores a single genreated font size to be written into the GPB
+    struct FontData
+    {
+        // Array of glyphs for a font
+        TTFGlyph glyphArray[END_INDEX - START_INDEX];
+
+        // Stores final height of a row required to render all glyphs
+        int fontSize;
+
+        // Actual size of the underlying glyphs (may be different from fontSize)
+        int glyphSize;
+
+        // Font texture
+        unsigned char* imageBuffer;
+        unsigned int imageWidth;
+        unsigned int imageHeight;
+
+        FontData() : fontSize(0), glyphSize(0), imageBuffer(NULL), imageWidth(0), imageHeight(0)
+        {
+        }
+
+        ~FontData()
+        {
+            if (imageBuffer)
+                free(imageBuffer);
+        }
+    };
+    std::vector<FontData*> fonts;
+
+    for (size_t fontIndex = 0, count = fontSizes.size(); fontIndex < count; ++fontIndex)
+    {
+        unsigned int fontSize = fontSizes[fontIndex];
+
+        FontData* font = new FontData();
+        font->fontSize = fontSize;
+
+        TTFGlyph* glyphArray = font->glyphArray;
+
+        int rowSize = 0;
+        int glyphSize = 0;
+        int actualfontHeight = 0;
+
+        FT_GlyphSlot slot = NULL;
+        FT_Int32 loadFlags = FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT;
+
+        // We want to generate fonts that fit exactly the requested pixels size.
+        // Since free type (due to modern fonts) does not directly correlate requested
+        // size to glyph size, we'll brute-force attempt to set the largest font size
+        // possible that will fit within the requested pixel size.
+        for (unsigned int requestedSize = fontSize; requestedSize > 0; --requestedSize)
+        {
+            // Set the pixel size.
+            error = FT_Set_Char_Size( face, 0, requestedSize * 64, 0, 0 );
+            if (error)
+            {
+                LOG(1, "FT_Set_Pixel_Sizes error: %d \n", error);
+                return -1;
+            }
+
+            // Save glyph information (slot contains the actual glyph bitmap).
+            slot = face->glyph;
+
+            rowSize = 0;
+            glyphSize = 0;
+            actualfontHeight = 0;
+
+            // Find the width of the image.
+            for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ++ascii)
+            {
+                // Load glyph image into the slot (erase previous one)
+                error = FT_Load_Char(face, ascii, loadFlags);
+                if (error)
+                {
+                    LOG(1, "FT_Load_Char error : %d \n", error);
+                }
+
+                int bitmapRows = slot->bitmap.rows;
+                actualfontHeight = (actualfontHeight < bitmapRows) ? bitmapRows : actualfontHeight;
+
+                if (slot->bitmap.rows > slot->bitmap_top)
+                {
+                    bitmapRows += (slot->bitmap.rows - slot->bitmap_top);
+                }
+                rowSize = (rowSize < bitmapRows) ? bitmapRows : rowSize;
+            }
+
+            // Have we found a pixel size that fits?
+            if (rowSize <= (int)fontSize)
+            {
+                glyphSize = rowSize;
+                rowSize = fontSize;
+                break;
+            }
+        }
+
+        if (slot == NULL || glyphSize == 0)
+        {
+            LOG(1, "Cannot generate a font of the requested size: %d\n", fontSize);
+            return -1;
+        }
+
+        // Include padding in the rowSize.
+        rowSize += GLYPH_PADDING;
+
+        // Initialize with padding.
+        int penX = 0;
+        int penY = 0;
+        int row = 0;
+
+        double powerOf2 = 2;
+        unsigned int imageWidth = 0;
+        unsigned int imageHeight = 0;
+        bool textureSizeFound = false;
+
+        int advance;
+        int i;
+
+        while (textureSizeFound == false)
+        {
+            imageWidth =  (unsigned int)pow(2.0, powerOf2);
+            imageHeight = (unsigned int)pow(2.0, powerOf2);
+            penX = 0;
+            penY = 0;
+            row = 0;
+
+            // Find out the squared texture size that would fit all the require font glyphs.
+            i = 0;
+            for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ++ascii)
+            {
+                // Load glyph image into the slot (erase the previous one).
+                error = FT_Load_Char(face, ascii, loadFlags);
+                if (error)
+                {
+                    LOG(1, "FT_Load_Char error : %d \n", error);
+                }
+                // Glyph image.
+                int glyphWidth = slot->bitmap.pitch;
+                int glyphHeight = slot->bitmap.rows;
+
+                advance = glyphWidth + GLYPH_PADDING; 
+
+                // If we reach the end of the image wrap aroud to the next row.
+                if ((penX + advance) > (int)imageWidth)
+                {
+                    penX = 0;
+                    row += 1;
+                    penY = row * rowSize;
+                    if (penY + rowSize > (int)imageHeight)
+                    {
+                        powerOf2++;
+                        break;
+                    }
+                }
+
+                // penY should include the glyph offsets.
+                penY += (actualfontHeight - glyphHeight) + (glyphHeight - slot->bitmap_top);
+
+                // Set the pen position for the next glyph
+                penX += advance; // Move X to next glyph position
+                // Move Y back to the top of the row.
+                penY = row * rowSize;
+
+                if (ascii == (END_INDEX - 1))
+                {
+                    textureSizeFound = true;
+                }
+                i++;
+            }
+        }
+
+        // Try further to find a tighter texture size.
+        powerOf2 = 1;
+        for (;;)
+        {
+            if ((penY + rowSize) >= pow(2.0, powerOf2))
+            {
+                powerOf2++;
+            }
+            else
+            {
+                imageHeight = (int)pow(2.0, powerOf2);
+                break;
+            }
+        }
+
+        // Allocate temporary image buffer to draw the glyphs into.
+        unsigned char* imageBuffer = (unsigned char*)malloc(imageWidth * imageHeight);
+        memset(imageBuffer, 0, imageWidth * imageHeight);
+        penX = 0;
+        penY = 0;
+        row = 0;
+        i = 0;
+        for (unsigned char ascii = START_INDEX; ascii < END_INDEX; ++ascii)
+        {
+            // Load glyph image into the slot (erase the previous one).
+            error = FT_Load_Char(face, ascii, loadFlags);
+            if (error)
+            {
+                LOG(1, "FT_Load_Char error : %d \n", error);
+            }
+
+            // Glyph image.
+            unsigned char* glyphBuffer =  slot->bitmap.buffer;
+            int glyphWidth = slot->bitmap.pitch;
+            int glyphHeight = slot->bitmap.rows;
+
+            advance = glyphWidth + GLYPH_PADDING;
+
+            // If we reach the end of the image wrap aroud to the next row.
+            if ((penX + advance) > (int)imageWidth)
+            {
+                penX = 0;
+                row += 1;
+                penY = row * rowSize;
+                if (penY + rowSize > (int)imageHeight)
+                {
+                    free(imageBuffer);
+                    LOG(1, "Image size exceeded!");
+                    return -1;
+                }
+            }
+
+            // penY should include the glyph offsets.
+            penY += (actualfontHeight - glyphHeight) + (glyphHeight - slot->bitmap_top);
+
+            // Draw the glyph to the bitmap with a one pixel padding.
+            drawBitmap(imageBuffer, penX, penY, imageWidth, glyphBuffer, glyphWidth, glyphHeight);
+
+            // Move Y back to the top of the row.
+            penY = row * rowSize;
+
+            glyphArray[i].index = ascii;
+            glyphArray[i].width = advance - GLYPH_PADDING;
+
+            // Generate UV coords.
+            glyphArray[i].uvCoords[0] = (float)penX / (float)imageWidth;
+            glyphArray[i].uvCoords[1] = (float)penY / (float)imageHeight;
+            glyphArray[i].uvCoords[2] = (float)(penX + advance - GLYPH_PADDING) / (float)imageWidth;
+            glyphArray[i].uvCoords[3] = (float)(penY + rowSize - GLYPH_PADDING) / (float)imageHeight;
+
+            // Set the pen position for the next glyph
+            penX += advance;
+            i++;
+        }
+
+        font->glyphSize = glyphSize;
+        font->imageBuffer = imageBuffer;
+        font->imageWidth = imageWidth;
+        font->imageHeight = imageHeight;
+        fonts.push_back(font);
+    }
+
+    // File header and version.
+    FILE *gpbFp = fopen(outFilePath, "wb");    
+    char fileHeader[9]     = {'\xAB', 'G', 'P', 'B', '\xBB', '\r', '\n', '\x1A', '\n'};
+    fwrite(fileHeader, sizeof(char), 9, gpbFp);
+    fwrite(gameplay::GPB_VERSION, sizeof(char), 2, gpbFp);
+
+    // Write Ref table (for a single font)
+    writeUint(gpbFp, 1);                // Ref[] count
+    writeString(gpbFp, id);             // Ref id
+    writeUint(gpbFp, 128);              // Ref type
+    writeUint(gpbFp, ftell(gpbFp) + 4); // Ref offset (current pos + 4 bytes)
+
+    // Family name.
+    writeString(gpbFp, face->family_name);
+
+    // Style.
+    // TODO: Switch based on TTF style name and write appropriate font style unsigned int for now just hardcoding to 0 = PLAIN.
+    writeUint(gpbFp, 0);
+
+    // Number of included font sizes (GPB version 1.3+)
+    writeUint(gpbFp, (unsigned int)fonts.size());
+
+    for (size_t i = 0, count = fonts.size(); i < count; ++i)
+    {
+        FontData* font = fonts[i];
+
+        // Font size (pixels).
+        writeUint(gpbFp, font->fontSize);
+
+        // Character set. TODO: Empty for now
+        writeString(gpbFp, "");
+
+        // Glyphs.
+        unsigned int glyphSetSize = END_INDEX - START_INDEX;
+        writeUint(gpbFp, glyphSetSize);
+        fwrite(&font->glyphArray, sizeof(TTFGlyph), glyphSetSize, gpbFp);
+
+        // Image dimensions
+        unsigned int imageSize = font->imageWidth * font->imageHeight;
+        writeUint(gpbFp, font->imageWidth);
+        writeUint(gpbFp, font->imageHeight);
+        writeUint(gpbFp, imageSize);
+
+        FILE* previewFp = NULL;
+        std::string pgmFilePath;
+        if (fontpreview)
+        {
+            // Save out a pgm monochome image file for preview
+            std::ostringstream pgmFilePathStream;
+            pgmFilePathStream << getFilenameNoExt(outFilePath) << "-" << font->fontSize << ".pgm";
+            pgmFilePath = pgmFilePathStream.str();
+            previewFp = fopen(pgmFilePath.c_str(), "wb");
+            fprintf(previewFp, "P5 %u %u 255\n", font->imageWidth, font->imageHeight);
+        }
+
+        if (fontFormat == Font::DISTANCE_FIELD)
+        {
+            // Flip height and width since the distance field map generator is column-wise.
+            unsigned char* distanceFieldBuffer = createDistanceFields(font->imageBuffer, font->imageHeight, font->imageWidth);
+
+            fwrite(distanceFieldBuffer, sizeof(unsigned char), imageSize, gpbFp);
+            writeUint(gpbFp, Font::DISTANCE_FIELD);
+
+            if (previewFp)
+            {
+                fwrite((const char*)distanceFieldBuffer, sizeof(unsigned char), imageSize, previewFp);
+                fclose(previewFp);
+            }
+
+            free(distanceFieldBuffer);
+        }
+        else
+        {
+            fwrite(font->imageBuffer, sizeof(unsigned char), imageSize, gpbFp);
+            writeUint(gpbFp, Font::BITMAP);
+
+            if (previewFp)
+            {
+                fwrite((const char*)font->imageBuffer, sizeof(unsigned char), font->imageWidth * font->imageHeight, previewFp);
+                fclose(previewFp);
+            }
+        }
+
+        if (previewFp)
+        {
+            fclose(previewFp);
+            LOG(1, "%s.pgm preview image created successfully. \n", getBaseName(pgmFilePath).c_str());
+        }
+    }
+
+    // Close file.
+    fclose(gpbFp);
+
+    LOG(1, "%s.gpb created successfully. \n", getBaseName(outFilePath).c_str());
+
+    for (size_t i = 0, count = fonts.size(); i < count; ++i)
+    {
+        delete fonts[i];
+    }
+
+    FT_Done_Face(face);
+    FT_Done_FreeType(library);
+    return 0;
+}
+
+}

+ 34 - 34
tools/encoder/src/TTFFontEncoder.h

@@ -1,34 +1,34 @@
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include "Font.h"
-
-#define START_INDEX     32
-#define END_INDEX       127
-#define GLYPH_PADDING   4
-
-namespace gameplay
-{
-
-// Structure of TTF Glyph.
-class TTFGlyph
-{
-public:
-    unsigned int index;
-    unsigned int width;
-    float uvCoords[4];
-};
-
-/**
- * Writes the font gpb file.
- * 
- * @param inFilePath Input file path to the tiff file.
- * @param outFilePath Output file path to write the gpb to.
- * @param fontSizes List of sizes to generate for the font.
- * @param id ID string of the font in the ref table.
- * @param fontpreview True if the pgm font preview file should be written. (For debugging)
- * 
- * @return 0 if successful, -1 if error.
- */
-int writeFont(const char* inFilePath, const char* outFilePath, std::vector<unsigned int>& fontSize, const char* id, bool fontpreview, Font::FontFormat fontFormat);
-
-}
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include "Font.h"
+
+#define START_INDEX     32
+#define END_INDEX       127
+#define GLYPH_PADDING   4
+
+namespace gameplay
+{
+
+// Structure of TTF Glyph.
+class TTFGlyph
+{
+public:
+    unsigned int index;
+    unsigned int width;
+    float uvCoords[4];
+};
+
+/**
+ * Writes the font gpb file.
+ * 
+ * @param inFilePath Input file path to the tiff file.
+ * @param outFilePath Output file path to write the gpb to.
+ * @param fontSizes List of sizes to generate for the font.
+ * @param id ID string of the font in the ref table.
+ * @param fontpreview True if the pgm font preview file should be written. (For debugging)
+ * 
+ * @return 0 if successful, -1 if error.
+ */
+int writeFont(const char* inFilePath, const char* outFilePath, std::vector<unsigned int>& fontSize, const char* id, bool fontpreview, Font::FontFormat fontFormat);
+
+}

+ 69 - 69
tools/encoder/src/Transform.cpp

@@ -1,70 +1,70 @@
-#include "Base.h"
-#include "Transform.h"
-
-namespace gameplay
-{
-
-const char* Transform::getPropertyString(unsigned int prop)
-{
-    switch (prop)
-    {
-        case ANIMATE_SCALE:
-            return "ANIMATE_SCALE";
-        case ANIMATE_SCALE_X:
-            return "ANIMATE_SCALE_X";
-        case ANIMATE_SCALE_Y: 
-            return "ANIMATE_SCALE_Y";
-        case ANIMATE_SCALE_Z:
-            return "ANIMATE_SCALE_Z";
-        case ANIMATE_ROTATE:
-            return "ANIMATE_ROTATE";
-        case ANIMATE_TRANSLATE: 
-            return "ANIMATE_TRANSLATE";
-        case ANIMATE_TRANSLATE_X:
-            return "ANIMATE_TRANSLATE_X";
-        case ANIMATE_TRANSLATE_Y: 
-            return "ANIMATE_TRANSLATE_Y";
-        case ANIMATE_TRANSLATE_Z: 
-            return "ANIMATE_TRANSLATE_Z";
-        case ANIMATE_ROTATE_TRANSLATE: 
-            return "ANIMATE_ROTATE_TRANSLATE";
-        case ANIMATE_SCALE_ROTATE_TRANSLATE: 
-            return "ANIMATE_SCALE_ROTATE_TRANSLATE";
-        case ANIMATE_SCALE_TRANSLATE:
-            return "ANIMATE_SCALE_TRANSLATE";
-        case ANIMATE_SCALE_ROTATE:
-            return "ANIMATE_SCALE_ROTATE";
-        default:
-            return "";
-    }
-}
-
-unsigned int Transform::getPropertySize(unsigned int prop)
-{
-    switch (prop)
-    {
-        case ANIMATE_SCALE_ROTATE_TRANSLATE:
-            return 10;
-        case ANIMATE_ROTATE_TRANSLATE:
-        case ANIMATE_SCALE_ROTATE:
-            return 7;
-        case ANIMATE_SCALE_TRANSLATE:
-            return 6;
-        case ANIMATE_ROTATE:
-            return 4;
-        case ANIMATE_SCALE:
-        case ANIMATE_TRANSLATE:
-            return 3;
-        case ANIMATE_SCALE_X:
-        case ANIMATE_SCALE_Y:
-        case ANIMATE_SCALE_Z:
-        case ANIMATE_TRANSLATE_X:
-        case ANIMATE_TRANSLATE_Y:
-        case ANIMATE_TRANSLATE_Z:
-            return 1;
-        default:
-            return 0;
-    }
-}
-
+#include "Base.h"
+#include "Transform.h"
+
+namespace gameplay
+{
+
+const char* Transform::getPropertyString(unsigned int prop)
+{
+    switch (prop)
+    {
+        case ANIMATE_SCALE:
+            return "ANIMATE_SCALE";
+        case ANIMATE_SCALE_X:
+            return "ANIMATE_SCALE_X";
+        case ANIMATE_SCALE_Y: 
+            return "ANIMATE_SCALE_Y";
+        case ANIMATE_SCALE_Z:
+            return "ANIMATE_SCALE_Z";
+        case ANIMATE_ROTATE:
+            return "ANIMATE_ROTATE";
+        case ANIMATE_TRANSLATE: 
+            return "ANIMATE_TRANSLATE";
+        case ANIMATE_TRANSLATE_X:
+            return "ANIMATE_TRANSLATE_X";
+        case ANIMATE_TRANSLATE_Y: 
+            return "ANIMATE_TRANSLATE_Y";
+        case ANIMATE_TRANSLATE_Z: 
+            return "ANIMATE_TRANSLATE_Z";
+        case ANIMATE_ROTATE_TRANSLATE: 
+            return "ANIMATE_ROTATE_TRANSLATE";
+        case ANIMATE_SCALE_ROTATE_TRANSLATE: 
+            return "ANIMATE_SCALE_ROTATE_TRANSLATE";
+        case ANIMATE_SCALE_TRANSLATE:
+            return "ANIMATE_SCALE_TRANSLATE";
+        case ANIMATE_SCALE_ROTATE:
+            return "ANIMATE_SCALE_ROTATE";
+        default:
+            return "";
+    }
+}
+
+unsigned int Transform::getPropertySize(unsigned int prop)
+{
+    switch (prop)
+    {
+        case ANIMATE_SCALE_ROTATE_TRANSLATE:
+            return 10;
+        case ANIMATE_ROTATE_TRANSLATE:
+        case ANIMATE_SCALE_ROTATE:
+            return 7;
+        case ANIMATE_SCALE_TRANSLATE:
+            return 6;
+        case ANIMATE_ROTATE:
+            return 4;
+        case ANIMATE_SCALE:
+        case ANIMATE_TRANSLATE:
+            return 3;
+        case ANIMATE_SCALE_X:
+        case ANIMATE_SCALE_Y:
+        case ANIMATE_SCALE_Z:
+        case ANIMATE_TRANSLATE_X:
+        case ANIMATE_TRANSLATE_Y:
+        case ANIMATE_TRANSLATE_Z:
+            return 1;
+        default:
+            return 0;
+    }
+}
+
 }

+ 69 - 69
tools/encoder/src/Transform.h

@@ -1,69 +1,69 @@
-#ifndef TRANSFORM_H_
-#define TRANSFORM_H_
-
-namespace gameplay
-{
-
-class Transform
-{
-public:
-
-    enum TransformProperties
-    {
-        /**
-         * Scale animation property. Data=sx,sy,sz
-         */
-        ANIMATE_SCALE = 1,
-        ANIMATE_SCALE_X = 2,
-        ANIMATE_SCALE_Y = 3,
-        ANIMATE_SCALE_Z = 4,
-
-        /**
-         * Rotation animation property. Data=qx,qy,qz,qw (as quaternion).
-         */
-        ANIMATE_ROTATE = 8,
-
-        /**
-         * Translation animation property. Data=tx,ty,tz
-         */
-        ANIMATE_TRANSLATE = 9,
-        ANIMATE_TRANSLATE_X = 10,
-        ANIMATE_TRANSLATE_Y = 11,
-        ANIMATE_TRANSLATE_Z = 12,
-
-        /**
-         * Rotation + Translation animation property(Rigid Body). Data=qx,qy,qz,qw,tx,ty,tz
-         */
-        ANIMATE_ROTATE_TRANSLATE = 16,
-
-        /**
-         * Scale, Rotation + Translation animation property. Data=sx,sy,sz,qx,qy,qz,qw,tx,ty,tz
-         */
-        ANIMATE_SCALE_ROTATE_TRANSLATE = 17,
-
-        /**
-         * Scale + Translation animation property. Data=sx,sy,sz,tx,ty,tz
-         */
-        ANIMATE_SCALE_TRANSLATE = 18,
-
-        /**
-         * Scale + Rotation animation property. Data=sx,sy,sz,qx,qy,qz,qw
-         */
-        ANIMATE_SCALE_ROTATE = 19
-    };
-
-    /**
-     * Returns the string representation of the given TransformProperty.
-     */
-    static const char* getPropertyString(unsigned int prop);
-
-    /**
-     * Returns the number of floats for the given property or zero if not a valid property.
-     */
-    static unsigned int getPropertySize(unsigned int prop);
-
-};
-
-}
-
-#endif
+#ifndef TRANSFORM_H_
+#define TRANSFORM_H_
+
+namespace gameplay
+{
+
+class Transform
+{
+public:
+
+    enum TransformProperties
+    {
+        /**
+         * Scale animation property. Data=sx,sy,sz
+         */
+        ANIMATE_SCALE = 1,
+        ANIMATE_SCALE_X = 2,
+        ANIMATE_SCALE_Y = 3,
+        ANIMATE_SCALE_Z = 4,
+
+        /**
+         * Rotation animation property. Data=qx,qy,qz,qw (as quaternion).
+         */
+        ANIMATE_ROTATE = 8,
+
+        /**
+         * Translation animation property. Data=tx,ty,tz
+         */
+        ANIMATE_TRANSLATE = 9,
+        ANIMATE_TRANSLATE_X = 10,
+        ANIMATE_TRANSLATE_Y = 11,
+        ANIMATE_TRANSLATE_Z = 12,
+
+        /**
+         * Rotation + Translation animation property(Rigid Body). Data=qx,qy,qz,qw,tx,ty,tz
+         */
+        ANIMATE_ROTATE_TRANSLATE = 16,
+
+        /**
+         * Scale, Rotation + Translation animation property. Data=sx,sy,sz,qx,qy,qz,qw,tx,ty,tz
+         */
+        ANIMATE_SCALE_ROTATE_TRANSLATE = 17,
+
+        /**
+         * Scale + Translation animation property. Data=sx,sy,sz,tx,ty,tz
+         */
+        ANIMATE_SCALE_TRANSLATE = 18,
+
+        /**
+         * Scale + Rotation animation property. Data=sx,sy,sz,qx,qy,qz,qw
+         */
+        ANIMATE_SCALE_ROTATE = 19
+    };
+
+    /**
+     * Returns the string representation of the given TransformProperty.
+     */
+    static const char* getPropertyString(unsigned int prop);
+
+    /**
+     * Returns the number of floats for the given property or zero if not a valid property.
+     */
+    static unsigned int getPropertySize(unsigned int prop);
+
+};
+
+}
+
+#endif

+ 271 - 271
tools/encoder/src/Vector2.cpp

@@ -1,271 +1,271 @@
-#include "Base.h"
-#include "Vector2.h"
-
-namespace gameplay
-{
-
-Vector2::Vector2()
-    : x(0.0f), y(0.0f)
-{
-}
-
-Vector2::Vector2(float x, float y)
-{
-    set(x, y);
-}
-
-Vector2::Vector2(float* array)
-{
-    set(array);
-}
-
-Vector2::Vector2(const Vector2& p1, const Vector2& p2)
-{
-    set(p1, p2);
-}
-
-Vector2::Vector2(const Vector2& copy)
-{
-    set(copy);
-}
-
-Vector2::~Vector2()
-{
-}
-
-const Vector2& Vector2::zero()
-{
-    static Vector2 value(0.0f, 0.0f);
-    return value;
-}
-
-const Vector2& Vector2::one()
-{
-    static Vector2 value(1.0f, 1.0f);
-    return value;
-}
-
-const Vector2& Vector2::unitX()
-{
-    static Vector2 value(1.0f, 0.0f);
-    return value;
-}
-
-const Vector2& Vector2::unitY()
-{
-    static Vector2 value(0.0f, 1.0f);
-    return value;
-}
-
-bool Vector2::isZero() const
-{
-    return x == 0.0f && y == 0.0f;
-}
-
-bool Vector2::isOne() const
-{
-    return x == 1.0f && y == 1.0f;
-}
-
-float Vector2::angle(const Vector2& v1, const Vector2& v2)
-{
-    float dz = v1.x * v2.y - v1.y * v2.x;
-    return atan2f(fabsf(dz) + MATH_FLOAT_SMALL, dot(v1, v2));
-}
-
-void Vector2::add(const Vector2& v)
-{
-    x += v.x;
-    y += v.y;
-}
-
-void Vector2::add(const Vector2& v1, const Vector2& v2, Vector2* dst)
-{
-    assert(dst);
-
-    dst->x = v1.x + v2.x;
-    dst->y = v1.y + v2.y;
-}
-
-void Vector2::clamp(const Vector2& min, const Vector2& max)
-{
-    assert(!( min.x > max.x || min.y > max.y ));
-
-    // Clamp the x value.
-    if ( x < min.x )
-        x = min.x;
-    if ( x > max.x )
-        x = max.x;
-
-    // Clamp the y value.
-    if ( y < min.y )
-        y = min.y;
-    if ( y > max.y )
-        y = max.y;
-}
-
-void Vector2::clamp(const Vector2& v, const Vector2& min, const Vector2& max, Vector2* dst)
-{
-    assert(dst);
-    assert(!( min.x > max.x || min.y > max.y ));
-
-    // Clamp the x value.
-    dst->x = v.x;
-    if ( dst->x < min.x )
-        dst->x = min.x;
-    if ( dst->x > max.x )
-        dst->x = max.x;
-
-    // Clamp the y value.
-    dst->y = v.y;
-    if ( dst->y < min.y )
-        dst->y = min.y;
-    if ( dst->y > max.y )
-        dst->y = max.y;
-}
-
-float Vector2::distance(const Vector2& v) const
-{
-    float dx = v.x - x;
-    float dy = v.y - y;
-
-    return sqrt(dx * dx + dy * dy);
-}
-
-float Vector2::distanceSquared(const Vector2& v) const
-{
-    float dx = v.x - x;
-    float dy = v.y - y;
-    return (dx * dx + dy * dy);
-}
-
-float Vector2::dot(const Vector2& v)
-{
-    return (x * v.x + y * v.y);
-}
-
-float Vector2::dot(const Vector2& v1, const Vector2& v2)
-{
-    return (v1.x * v2.x + v1.y * v2.y);
-}
-
-float Vector2::length() const
-{
-    return sqrt(x * x + y * y);
-}
-
-float Vector2::lengthSquared() const
-{
-    return (x * x + y * y);
-}
-
-void Vector2::negate()
-{
-    x = -x;
-    y = -y;
-}
-
-void Vector2::normalize()
-{
-    normalize(this);
-}
-
-void Vector2::normalize(Vector2* dst)
-{
-    assert(dst);
-
-    if (dst != this)
-    {
-        dst->x = x;
-        dst->y = y;
-    }
-
-    float n = x * x + y * y;
-    // Already normalized.
-    if (n == 1.0f)
-        return;
-
-    n = sqrt(n);
-    // Too close to zero.
-    if (n < MATH_TOLERANCE)
-        return;
-
-    n = 1.0f / n;
-    dst->x *= n;
-    dst->y *= n;
-}
-
-void Vector2::scale(float scalar)
-{
-    x *= scalar;
-    y *= scalar;
-}
-
-void Vector2::scale(const Vector2& scale)
-{
-    x *= scale.x;
-    y *= scale.y;
-}
-
-void Vector2::rotate(const Vector2& point, float angle)
-{
-    float sinAngle = sin(angle);
-    float cosAngle = cos(angle);
-
-    if (point.isZero())
-    {
-        float tempX = x * cosAngle - y * sinAngle;
-        y = y * cosAngle + x * sinAngle;
-        x = tempX;
-    }
-    else
-    {
-        float tempX = x - point.x;
-        float tempY = y - point.y;
-
-        x = tempX * cosAngle - tempY * sinAngle + point.x;
-        y = tempY * cosAngle + tempX * sinAngle + point.y;
-    }
-}
-
-void Vector2::set(float x, float y)
-{
-    this->x = x;
-    this->y = y;
-}
-
-void Vector2::set(float* array)
-{
-    assert(array);
-
-    x = array[0];
-    y = array[1];
-}
-
-void Vector2::set(const Vector2& v)
-{
-    this->x = v.x;
-    this->y = v.y;
-}
-
-void Vector2::set(const Vector2& p1, const Vector2& p2)
-{
-     x = p2.x - p1.x;
-     y = p2.y - p1.y;
-}
-
-void Vector2::subtract(const Vector2& v)
-{
-    x -= v.x;
-    y -= v.y;
-}
-
-void Vector2::subtract(const Vector2& v1, const Vector2& v2, Vector2* dst)
-{
-    assert(dst);
-
-    dst->x = v1.x - v2.x;
-    dst->y = v1.y - v2.y;
-}
-
-}
+#include "Base.h"
+#include "Vector2.h"
+
+namespace gameplay
+{
+
+Vector2::Vector2()
+    : x(0.0f), y(0.0f)
+{
+}
+
+Vector2::Vector2(float x, float y)
+{
+    set(x, y);
+}
+
+Vector2::Vector2(float* array)
+{
+    set(array);
+}
+
+Vector2::Vector2(const Vector2& p1, const Vector2& p2)
+{
+    set(p1, p2);
+}
+
+Vector2::Vector2(const Vector2& copy)
+{
+    set(copy);
+}
+
+Vector2::~Vector2()
+{
+}
+
+const Vector2& Vector2::zero()
+{
+    static Vector2 value(0.0f, 0.0f);
+    return value;
+}
+
+const Vector2& Vector2::one()
+{
+    static Vector2 value(1.0f, 1.0f);
+    return value;
+}
+
+const Vector2& Vector2::unitX()
+{
+    static Vector2 value(1.0f, 0.0f);
+    return value;
+}
+
+const Vector2& Vector2::unitY()
+{
+    static Vector2 value(0.0f, 1.0f);
+    return value;
+}
+
+bool Vector2::isZero() const
+{
+    return x == 0.0f && y == 0.0f;
+}
+
+bool Vector2::isOne() const
+{
+    return x == 1.0f && y == 1.0f;
+}
+
+float Vector2::angle(const Vector2& v1, const Vector2& v2)
+{
+    float dz = v1.x * v2.y - v1.y * v2.x;
+    return atan2f(fabsf(dz) + MATH_FLOAT_SMALL, dot(v1, v2));
+}
+
+void Vector2::add(const Vector2& v)
+{
+    x += v.x;
+    y += v.y;
+}
+
+void Vector2::add(const Vector2& v1, const Vector2& v2, Vector2* dst)
+{
+    assert(dst);
+
+    dst->x = v1.x + v2.x;
+    dst->y = v1.y + v2.y;
+}
+
+void Vector2::clamp(const Vector2& min, const Vector2& max)
+{
+    assert(!( min.x > max.x || min.y > max.y ));
+
+    // Clamp the x value.
+    if ( x < min.x )
+        x = min.x;
+    if ( x > max.x )
+        x = max.x;
+
+    // Clamp the y value.
+    if ( y < min.y )
+        y = min.y;
+    if ( y > max.y )
+        y = max.y;
+}
+
+void Vector2::clamp(const Vector2& v, const Vector2& min, const Vector2& max, Vector2* dst)
+{
+    assert(dst);
+    assert(!( min.x > max.x || min.y > max.y ));
+
+    // Clamp the x value.
+    dst->x = v.x;
+    if ( dst->x < min.x )
+        dst->x = min.x;
+    if ( dst->x > max.x )
+        dst->x = max.x;
+
+    // Clamp the y value.
+    dst->y = v.y;
+    if ( dst->y < min.y )
+        dst->y = min.y;
+    if ( dst->y > max.y )
+        dst->y = max.y;
+}
+
+float Vector2::distance(const Vector2& v) const
+{
+    float dx = v.x - x;
+    float dy = v.y - y;
+
+    return sqrt(dx * dx + dy * dy);
+}
+
+float Vector2::distanceSquared(const Vector2& v) const
+{
+    float dx = v.x - x;
+    float dy = v.y - y;
+    return (dx * dx + dy * dy);
+}
+
+float Vector2::dot(const Vector2& v)
+{
+    return (x * v.x + y * v.y);
+}
+
+float Vector2::dot(const Vector2& v1, const Vector2& v2)
+{
+    return (v1.x * v2.x + v1.y * v2.y);
+}
+
+float Vector2::length() const
+{
+    return sqrt(x * x + y * y);
+}
+
+float Vector2::lengthSquared() const
+{
+    return (x * x + y * y);
+}
+
+void Vector2::negate()
+{
+    x = -x;
+    y = -y;
+}
+
+void Vector2::normalize()
+{
+    normalize(this);
+}
+
+void Vector2::normalize(Vector2* dst)
+{
+    assert(dst);
+
+    if (dst != this)
+    {
+        dst->x = x;
+        dst->y = y;
+    }
+
+    float n = x * x + y * y;
+    // Already normalized.
+    if (n == 1.0f)
+        return;
+
+    n = sqrt(n);
+    // Too close to zero.
+    if (n < MATH_TOLERANCE)
+        return;
+
+    n = 1.0f / n;
+    dst->x *= n;
+    dst->y *= n;
+}
+
+void Vector2::scale(float scalar)
+{
+    x *= scalar;
+    y *= scalar;
+}
+
+void Vector2::scale(const Vector2& scale)
+{
+    x *= scale.x;
+    y *= scale.y;
+}
+
+void Vector2::rotate(const Vector2& point, float angle)
+{
+    float sinAngle = sin(angle);
+    float cosAngle = cos(angle);
+
+    if (point.isZero())
+    {
+        float tempX = x * cosAngle - y * sinAngle;
+        y = y * cosAngle + x * sinAngle;
+        x = tempX;
+    }
+    else
+    {
+        float tempX = x - point.x;
+        float tempY = y - point.y;
+
+        x = tempX * cosAngle - tempY * sinAngle + point.x;
+        y = tempY * cosAngle + tempX * sinAngle + point.y;
+    }
+}
+
+void Vector2::set(float x, float y)
+{
+    this->x = x;
+    this->y = y;
+}
+
+void Vector2::set(float* array)
+{
+    assert(array);
+
+    x = array[0];
+    y = array[1];
+}
+
+void Vector2::set(const Vector2& v)
+{
+    this->x = v.x;
+    this->y = v.y;
+}
+
+void Vector2::set(const Vector2& p1, const Vector2& p2)
+{
+     x = p2.x - p1.x;
+     y = p2.y - p1.y;
+}
+
+void Vector2::subtract(const Vector2& v)
+{
+    x -= v.x;
+    y -= v.y;
+}
+
+void Vector2::subtract(const Vector2& v1, const Vector2& v2, Vector2* dst)
+{
+    assert(dst);
+
+    dst->x = v1.x - v2.x;
+    dst->y = v1.y - v2.y;
+}
+
+}

+ 413 - 413
tools/encoder/src/Vector2.h

@@ -1,413 +1,413 @@
-#ifndef VECTOR2_H_
-#define VECTOR2_H_
-
-namespace gameplay
-{
-
-class Matrix;
-
-/**
- * Defines a 2-element floating point vector.
- */
-class Vector2
-{
-public:
-
-    /**
-     * The x coordinate.
-     */
-    float x;
-
-    /**
-     * The y coordinate.
-     */
-    float y;
-
-    /**
-     * Constructs a new vector initialized to all zeros.
-     */
-    Vector2();
-
-    /**
-     * Constructs a new vector initialized to the specified values.
-     *
-     * @param x The x coordinate.
-     * @param y The y coordinate.
-     */
-    Vector2(float x, float y);
-
-    /**
-     * Constructs a new vector from the values in the specified array.
-     *
-     * @param array An array containing the elements of the vector in the order x, y.
-     */
-    Vector2(float* array);
-
-    /**
-     * Constructs a vector that describes the direction between the specified points.
-     *
-     * @param p1 The first point.
-     * @param p2 The second point.
-     */
-    Vector2(const Vector2& p1, const Vector2& p2);
-
-    /**
-     * Constructs a new vector that is a copy of the specified vector.
-     *
-     * @param copy The vector to copy.
-     */
-    Vector2(const Vector2& copy);
-
-    /**
-     * Destructor.
-     */
-    ~Vector2();
-
-    /**
-     * Returns the zero vector.
-     *
-     * @return The 2-element vector of 0s.
-     */
-    static const Vector2& zero();
-
-    /**
-     * Returns the one vector.
-     *
-     * @return The 2-element vector of 1s.
-     */
-    static const Vector2& one();
-
-    /**
-     * Returns the unit x vector.
-     *
-     * @return The 2-element unit vector along the x axis.
-     */
-    static const Vector2& unitX();
-
-    /**
-     * Returns the unit y vector.
-     *
-     * @return The 2-element unit vector along the y axis.
-     */
-    static const Vector2& unitY();
-
-    /**
-     * Indicates whether this vector contains all zeros.
-     *
-     * @return true if this vector contains all zeros, false otherwise.
-     */
-    bool isZero() const;
-
-    /**
-     * Indicates whether this vector contains all ones.
-     *
-     * @return true if this vector contains all ones, false otherwise.
-     */
-    bool isOne() const;
-
-    /**
-     * Returns the angle (in radians) between the specified vectors.
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * 
-     * @return The angle between the two vectors (in radians).
-     */
-    static float angle(const Vector2& v1, const Vector2& v2);
-
-    /**
-     * Adds the elements of the specified vector to this one.
-     *
-     * @param v The vector to add.
-     */
-    void add(const Vector2& v);
-
-    /**
-     * Adds the specified vectors and stores the result in dst.
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * @param dst A vector to store the result in.
-     */
-    static void add(const Vector2& v1, const Vector2& v2, Vector2* dst);
-
-    /**
-     * Clamps this vector within the specified range.
-     *
-     * @param min The minimum value.
-     * @param max The maximum value.
-     */
-    void clamp(const Vector2& min, const Vector2& max);
-
-    /**
-     * Clamps the specified vector within the specified range and returns it in dst.
-     *
-     * @param v The vector to clamp.
-     * @param min The minimum value.
-     * @param max The maximum value.
-     * @param dst A vector to store the result in.
-     */
-    static void clamp(const Vector2& v, const Vector2& min, const Vector2& max, Vector2* dst);
-
-    /**
-     * Returns the distance between this vector and v.
-     *
-     * @param v The other vector.
-     * 
-     * @return The distance between this vector and v.
-     * 
-     * @see distanceSquared
-     */
-    float distance(const Vector2& v) const;
-
-    /**
-     * Returns the squared distance between this vector and v.
-     *
-     * When it is not necessary to get the exact distance between
-     * two vectors (for example, when simply comparing the
-     * distance between different vectors), it is advised to use
-     * this method instead of distance.
-     *
-     * @param v The other vector.
-     * 
-     * @return The squared distance between this vector and v.
-     * 
-     * @see distance
-     */
-    float distanceSquared(const Vector2& v) const;
-
-    /**
-     * Returns the dot product of this vector and the specified vector.
-     *
-     * @param v The vector to compute the dot product with.
-     * 
-     * @return The dot product.
-     */
-    float dot(const Vector2& v);
-
-    /**
-     * Returns the dot product between the specified vectors.
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * 
-     * @return The dot product between the vectors.
-     */
-    static float dot(const Vector2& v1, const Vector2& v2);
-
-    /**
-     * Computes the length of this vector.
-     *
-     * @return The length of the vector.
-     * 
-     * @see lengthSquared
-     */
-    float length() const;
-
-    /**
-     * Returns the squared length of this vector.
-     *
-     * When it is not necessary to get the exact length of a
-     * vector (for example, when simply comparing the lengths of
-     * different vectors), it is advised to use this method
-     * instead of length.
-     *
-     * @return The squared length of the vector.
-     * 
-     * @see length
-     */
-    float lengthSquared() const;
-
-    /**
-     * Negates this vector.
-     */
-    void negate();
-
-    /**
-     * Normalizes this vector.
-     *
-     * This method normalizes this Vector2 so that it is of
-     * unit length (in other words, the length of the vector
-     * after calling this method will be 1.0f). If the vector
-     * already has unit length or if the length of the vector
-     * is zero, this method does nothing.
-     */
-    void normalize();
-
-    /**
-     * Normalizes this vector and stores the result in dst.
-     *
-     * If the vector already has unit length or if the length
-     * of the vector is zero, this method simply copies the
-     * current vector into dst.
-     *
-     * @param dst The destination vector.
-     */
-    void normalize(Vector2* dst);
-
-    /**
-     * Scales all elements of this vector by the specified value.
-     *
-     * @param scalar The scalar value.
-     */
-    void scale(float scalar);
-
-    /**
-     * Scales each element of this vector by the matching component of scale.
-     *
-     * @param scale The vector to scale by.
-     */
-    void scale(const Vector2& scale);
-
-    /**
-     * Rotates this vector by angle (specified in radians) around the given point.
-     *
-     * @param point The point to rotate around.
-     * @param angle The angle to rotate by (in radians).
-     */
-    void rotate(const Vector2& point, float angle);
-
-    /**
-     * Sets the elements of this vector to the specified values.
-     *
-     * @param x The new x coordinate.
-     * @param y The new y coordinate.
-     */
-    void set(float x, float y);
-
-    /**
-     * Sets the elements of this vector from the values in the specified array.
-     *
-     * @param array An array containing the elements of the vector in the order x, y.
-     */
-    void set(float* array);
-
-    /**
-     * Sets the elements of this vector to those in the specified vector.
-     *
-     * @param v The vector to copy.
-     */
-    void set(const Vector2& v);
-
-    /**
-     * Sets this vector to the directional vector between the specified points.
-     * 
-     * @param p1 The first point.
-     * @param p2 The second point.
-     */
-    void set(const Vector2& p1, const Vector2& p2);
-
-    /**
-     * Subtracts this vector and the specified vector as (this - v)
-     * and stores the result in this vector.
-     *
-     * @param v The vector to subtract.
-     */
-    void subtract(const Vector2& v);
-
-    /**
-     * Subtracts the specified vectors and stores the result in dst.
-     * The resulting vector is computed as (v1 - v2).
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * @param dst The destination vector.
-     */
-    static void subtract(const Vector2& v1, const Vector2& v2, Vector2* dst);
-
-    /**
-     * Calculates the sum of this vector with the given vector.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @param v The vector to add.
-     * @return The vector sum.
-     */
-    inline Vector2 operator+(const Vector2& v);
-
-    /**
-     * Adds the given vector to this vector.
-     * 
-     * @param v The vector to add.
-     * @return This vector, after the addition occurs.
-     */
-    inline Vector2& operator+=(const Vector2& v);
-
-    /**
-     * Calculates the sum of this vector with the given vector.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @param v The vector to add.
-     * @return The vector sum.
-     */
-    inline Vector2 operator-(const Vector2& v);
-
-    /**
-     * Subtracts the given vector from this vector.
-     * 
-     * @param v The vector to subtract.
-     * @return This vector, after the subtraction occurs.
-     */
-    inline Vector2& operator-=(const Vector2& v);
-
-    /**
-     * Calculates the negation of this vector.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @return The negation of this vector.
-     */
-    inline Vector2 operator-();
-
-    /**
-     * Calculates the scalar product of this vector with the given value.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @param x The value to scale by.
-     * @return The scaled vector.
-     */
-    inline Vector2 operator*(float x);
-
-    /**
-     * Scales this vector by the given value.
-     * 
-     * @param x The value to scale by.
-     * @return This vector, after the scale occurs.
-     */
-    inline Vector2& operator*=(float x);
-
-    /**
-     * Determines if this vector is less than the given vector.
-     * 
-     * @param v The vector to compare against.
-     * 
-     * @return True if this vector is less than the given vector, false otherwise.
-     */
-    inline bool operator<(const Vector2& v) const;
-
-    /**
-     * Determines if this vector is equal to the given vector.
-     * 
-     * @param v The vector to compare against.
-     * 
-     * @return True if this vector is equal to the given vector, false otherwise.
-     */
-    inline bool operator==(const Vector2& v) const;
-};
-
-/**
- * Calculates the scalar product of the given vector with the given value.
- * 
- * @param x The value to scale by.
- * @param v The vector to scale.
- * @return The scaled vector.
- */
-inline Vector2 operator*(float x, const Vector2& v);
-
-}
-
-#include "Vector2.inl"
-
-#endif
+#ifndef VECTOR2_H_
+#define VECTOR2_H_
+
+namespace gameplay
+{
+
+class Matrix;
+
+/**
+ * Defines a 2-element floating point vector.
+ */
+class Vector2
+{
+public:
+
+    /**
+     * The x coordinate.
+     */
+    float x;
+
+    /**
+     * The y coordinate.
+     */
+    float y;
+
+    /**
+     * Constructs a new vector initialized to all zeros.
+     */
+    Vector2();
+
+    /**
+     * Constructs a new vector initialized to the specified values.
+     *
+     * @param x The x coordinate.
+     * @param y The y coordinate.
+     */
+    Vector2(float x, float y);
+
+    /**
+     * Constructs a new vector from the values in the specified array.
+     *
+     * @param array An array containing the elements of the vector in the order x, y.
+     */
+    Vector2(float* array);
+
+    /**
+     * Constructs a vector that describes the direction between the specified points.
+     *
+     * @param p1 The first point.
+     * @param p2 The second point.
+     */
+    Vector2(const Vector2& p1, const Vector2& p2);
+
+    /**
+     * Constructs a new vector that is a copy of the specified vector.
+     *
+     * @param copy The vector to copy.
+     */
+    Vector2(const Vector2& copy);
+
+    /**
+     * Destructor.
+     */
+    ~Vector2();
+
+    /**
+     * Returns the zero vector.
+     *
+     * @return The 2-element vector of 0s.
+     */
+    static const Vector2& zero();
+
+    /**
+     * Returns the one vector.
+     *
+     * @return The 2-element vector of 1s.
+     */
+    static const Vector2& one();
+
+    /**
+     * Returns the unit x vector.
+     *
+     * @return The 2-element unit vector along the x axis.
+     */
+    static const Vector2& unitX();
+
+    /**
+     * Returns the unit y vector.
+     *
+     * @return The 2-element unit vector along the y axis.
+     */
+    static const Vector2& unitY();
+
+    /**
+     * Indicates whether this vector contains all zeros.
+     *
+     * @return true if this vector contains all zeros, false otherwise.
+     */
+    bool isZero() const;
+
+    /**
+     * Indicates whether this vector contains all ones.
+     *
+     * @return true if this vector contains all ones, false otherwise.
+     */
+    bool isOne() const;
+
+    /**
+     * Returns the angle (in radians) between the specified vectors.
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * 
+     * @return The angle between the two vectors (in radians).
+     */
+    static float angle(const Vector2& v1, const Vector2& v2);
+
+    /**
+     * Adds the elements of the specified vector to this one.
+     *
+     * @param v The vector to add.
+     */
+    void add(const Vector2& v);
+
+    /**
+     * Adds the specified vectors and stores the result in dst.
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * @param dst A vector to store the result in.
+     */
+    static void add(const Vector2& v1, const Vector2& v2, Vector2* dst);
+
+    /**
+     * Clamps this vector within the specified range.
+     *
+     * @param min The minimum value.
+     * @param max The maximum value.
+     */
+    void clamp(const Vector2& min, const Vector2& max);
+
+    /**
+     * Clamps the specified vector within the specified range and returns it in dst.
+     *
+     * @param v The vector to clamp.
+     * @param min The minimum value.
+     * @param max The maximum value.
+     * @param dst A vector to store the result in.
+     */
+    static void clamp(const Vector2& v, const Vector2& min, const Vector2& max, Vector2* dst);
+
+    /**
+     * Returns the distance between this vector and v.
+     *
+     * @param v The other vector.
+     * 
+     * @return The distance between this vector and v.
+     * 
+     * @see distanceSquared
+     */
+    float distance(const Vector2& v) const;
+
+    /**
+     * Returns the squared distance between this vector and v.
+     *
+     * When it is not necessary to get the exact distance between
+     * two vectors (for example, when simply comparing the
+     * distance between different vectors), it is advised to use
+     * this method instead of distance.
+     *
+     * @param v The other vector.
+     * 
+     * @return The squared distance between this vector and v.
+     * 
+     * @see distance
+     */
+    float distanceSquared(const Vector2& v) const;
+
+    /**
+     * Returns the dot product of this vector and the specified vector.
+     *
+     * @param v The vector to compute the dot product with.
+     * 
+     * @return The dot product.
+     */
+    float dot(const Vector2& v);
+
+    /**
+     * Returns the dot product between the specified vectors.
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * 
+     * @return The dot product between the vectors.
+     */
+    static float dot(const Vector2& v1, const Vector2& v2);
+
+    /**
+     * Computes the length of this vector.
+     *
+     * @return The length of the vector.
+     * 
+     * @see lengthSquared
+     */
+    float length() const;
+
+    /**
+     * Returns the squared length of this vector.
+     *
+     * When it is not necessary to get the exact length of a
+     * vector (for example, when simply comparing the lengths of
+     * different vectors), it is advised to use this method
+     * instead of length.
+     *
+     * @return The squared length of the vector.
+     * 
+     * @see length
+     */
+    float lengthSquared() const;
+
+    /**
+     * Negates this vector.
+     */
+    void negate();
+
+    /**
+     * Normalizes this vector.
+     *
+     * This method normalizes this Vector2 so that it is of
+     * unit length (in other words, the length of the vector
+     * after calling this method will be 1.0f). If the vector
+     * already has unit length or if the length of the vector
+     * is zero, this method does nothing.
+     */
+    void normalize();
+
+    /**
+     * Normalizes this vector and stores the result in dst.
+     *
+     * If the vector already has unit length or if the length
+     * of the vector is zero, this method simply copies the
+     * current vector into dst.
+     *
+     * @param dst The destination vector.
+     */
+    void normalize(Vector2* dst);
+
+    /**
+     * Scales all elements of this vector by the specified value.
+     *
+     * @param scalar The scalar value.
+     */
+    void scale(float scalar);
+
+    /**
+     * Scales each element of this vector by the matching component of scale.
+     *
+     * @param scale The vector to scale by.
+     */
+    void scale(const Vector2& scale);
+
+    /**
+     * Rotates this vector by angle (specified in radians) around the given point.
+     *
+     * @param point The point to rotate around.
+     * @param angle The angle to rotate by (in radians).
+     */
+    void rotate(const Vector2& point, float angle);
+
+    /**
+     * Sets the elements of this vector to the specified values.
+     *
+     * @param x The new x coordinate.
+     * @param y The new y coordinate.
+     */
+    void set(float x, float y);
+
+    /**
+     * Sets the elements of this vector from the values in the specified array.
+     *
+     * @param array An array containing the elements of the vector in the order x, y.
+     */
+    void set(float* array);
+
+    /**
+     * Sets the elements of this vector to those in the specified vector.
+     *
+     * @param v The vector to copy.
+     */
+    void set(const Vector2& v);
+
+    /**
+     * Sets this vector to the directional vector between the specified points.
+     * 
+     * @param p1 The first point.
+     * @param p2 The second point.
+     */
+    void set(const Vector2& p1, const Vector2& p2);
+
+    /**
+     * Subtracts this vector and the specified vector as (this - v)
+     * and stores the result in this vector.
+     *
+     * @param v The vector to subtract.
+     */
+    void subtract(const Vector2& v);
+
+    /**
+     * Subtracts the specified vectors and stores the result in dst.
+     * The resulting vector is computed as (v1 - v2).
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * @param dst The destination vector.
+     */
+    static void subtract(const Vector2& v1, const Vector2& v2, Vector2* dst);
+
+    /**
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
+     */
+    inline Vector2 operator+(const Vector2& v);
+
+    /**
+     * Adds the given vector to this vector.
+     * 
+     * @param v The vector to add.
+     * @return This vector, after the addition occurs.
+     */
+    inline Vector2& operator+=(const Vector2& v);
+
+    /**
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
+     */
+    inline Vector2 operator-(const Vector2& v);
+
+    /**
+     * Subtracts the given vector from this vector.
+     * 
+     * @param v The vector to subtract.
+     * @return This vector, after the subtraction occurs.
+     */
+    inline Vector2& operator-=(const Vector2& v);
+
+    /**
+     * Calculates the negation of this vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @return The negation of this vector.
+     */
+    inline Vector2 operator-();
+
+    /**
+     * Calculates the scalar product of this vector with the given value.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param x The value to scale by.
+     * @return The scaled vector.
+     */
+    inline Vector2 operator*(float x);
+
+    /**
+     * Scales this vector by the given value.
+     * 
+     * @param x The value to scale by.
+     * @return This vector, after the scale occurs.
+     */
+    inline Vector2& operator*=(float x);
+
+    /**
+     * Determines if this vector is less than the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is less than the given vector, false otherwise.
+     */
+    inline bool operator<(const Vector2& v) const;
+
+    /**
+     * Determines if this vector is equal to the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is equal to the given vector, false otherwise.
+     */
+    inline bool operator==(const Vector2& v) const;
+};
+
+/**
+ * Calculates the scalar product of the given vector with the given value.
+ * 
+ * @param x The value to scale by.
+ * @param v The vector to scale.
+ * @return The scaled vector.
+ */
+inline Vector2 operator*(float x, const Vector2& v);
+
+}
+
+#include "Vector2.inl"
+
+#endif

+ 77 - 77
tools/encoder/src/Vector2.inl

@@ -1,77 +1,77 @@
-/** 
- * Vector2.inl
- */
-
-#include "Vector2.h"
-
-namespace gameplay
-{
-
-inline Vector2 Vector2::operator+(const Vector2& v)
-{
-    Vector2 result(*this);
-    result.add(v);
-    return result;
-}
-
-inline Vector2& Vector2::operator+=(const Vector2& v)
-{
-    add(v);
-    return *this;
-}
-
-inline Vector2 Vector2::operator-(const Vector2& v)
-{
-    Vector2 result(*this);
-    result.subtract(v);
-    return result;
-}
-
-inline Vector2& Vector2::operator-=(const Vector2& v)
-{
-    subtract(v);
-    return *this;
-}
-
-inline Vector2 Vector2::operator-()
-{
-    Vector2 result(*this);
-    result.negate();
-    return result;
-}
-
-inline Vector2 Vector2::operator*(float x)
-{
-    Vector2 result(*this);
-    result.scale(x);
-    return result;
-}
-
-inline Vector2& Vector2::operator*=(float x)
-{
-    scale(x);
-    return *this;
-}
-
-inline bool Vector2::operator<(const Vector2& v) const
-{
-    if (x == v.x)
-    {
-        return y < v.y;
-    }
-    return x < v.x;
-}
-
-inline bool Vector2::operator==(const Vector2& v) const
-{
-    return x==v.x && y==v.y;
-}
-
-inline Vector2 operator*(float x, const Vector2& v)
-{
-    Vector2 result(v);
-    result.scale(x);
-    return result;
-}
-
-}
+/** 
+ * Vector2.inl
+ */
+
+#include "Vector2.h"
+
+namespace gameplay
+{
+
+inline Vector2 Vector2::operator+(const Vector2& v)
+{
+    Vector2 result(*this);
+    result.add(v);
+    return result;
+}
+
+inline Vector2& Vector2::operator+=(const Vector2& v)
+{
+    add(v);
+    return *this;
+}
+
+inline Vector2 Vector2::operator-(const Vector2& v)
+{
+    Vector2 result(*this);
+    result.subtract(v);
+    return result;
+}
+
+inline Vector2& Vector2::operator-=(const Vector2& v)
+{
+    subtract(v);
+    return *this;
+}
+
+inline Vector2 Vector2::operator-()
+{
+    Vector2 result(*this);
+    result.negate();
+    return result;
+}
+
+inline Vector2 Vector2::operator*(float x)
+{
+    Vector2 result(*this);
+    result.scale(x);
+    return result;
+}
+
+inline Vector2& Vector2::operator*=(float x)
+{
+    scale(x);
+    return *this;
+}
+
+inline bool Vector2::operator<(const Vector2& v) const
+{
+    if (x == v.x)
+    {
+        return y < v.y;
+    }
+    return x < v.x;
+}
+
+inline bool Vector2::operator==(const Vector2& v) const
+{
+    return x==v.x && y==v.y;
+}
+
+inline Vector2 operator*(float x, const Vector2& v)
+{
+    Vector2 result(v);
+    result.scale(x);
+    return result;
+}
+
+}

+ 318 - 318
tools/encoder/src/Vector3.cpp

@@ -1,318 +1,318 @@
-#include "Base.h"
-#include "Vector3.h"
-
-namespace gameplay
-{
-
-Vector3::Vector3()
-    : x(0.0f), y(0.0f), z(0.0f)
-{
-}
-
-Vector3::Vector3(float x, float y, float z)
-{
-    set(x, y, z);
-}
-
-Vector3::Vector3(float* array)
-{
-    set(array);
-}
-
-Vector3::Vector3(const Vector3& p1, const Vector3& p2)
-{
-    set(p1, p2);
-}
-
-Vector3::Vector3(const Vector3& copy)
-{
-    set(copy);
-}
-
-Vector3 Vector3::fromColor(unsigned int color)
-{
-    float components[3];
-    int componentIndex = 0;
-    for (int i = 2; i >= 0; --i)
-    {
-        int component = (color >> i*8) & 0x0000ff;
-
-        components[componentIndex++] = static_cast<float>(component) / 255.0f;
-    }
-
-    Vector3 value(components);
-    return value;
-}
-
-Vector3::~Vector3()
-{
-}
-
-const Vector3& Vector3::zero()
-{
-    static Vector3 value(0.0f, 0.0f, 0.0f);
-    return value;
-}
-
-const Vector3& Vector3::one()
-{
-    static Vector3 value(1.0f, 1.0f, 1.0f);
-    return value;
-}
-
-const Vector3& Vector3::unitX()
-{
-    static Vector3 value(1.0f, 0.0f, 0.0f);
-    return value;
-}
-
-const Vector3& Vector3::unitY()
-{
-    static Vector3 value(0.0f, 1.0f, 0.0f);
-    return value;
-}
-
-const Vector3& Vector3::unitZ()
-{
-    static Vector3 value(0.0f, 0.0f, 1.0f);
-    return value;
-}
-
-bool Vector3::isZero() const
-{
-    return x == 0.0f && y == 0.0f && z == 0.0f;
-}
-
-bool Vector3::isOne() const
-{
-    return x == 1.0f && y == 1.0f && z == 1.0f;
-}
-
-float Vector3::angle(const Vector3& v1, const Vector3& v2)
-{
-    float dx = v1.y * v2.z - v1.z * v2.y;
-    float dy = v1.z * v2.x - v1.x * v2.z;
-    float dz = v1.x * v2.y - v1.y * v2.x;
-
-    return atan2f(sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
-}
-
-void Vector3::add(const Vector3& v)
-{
-    x += v.x;
-    y += v.y;
-    z += v.z;
-}
-
-void Vector3::add(const Vector3& v1, const Vector3& v2, Vector3* dst)
-{
-    assert(dst);
-
-    dst->x = v1.x + v2.x;
-    dst->y = v1.y + v2.y;
-    dst->z = v1.z + v2.z;
-}
-
-void Vector3::clamp(const Vector3& min, const Vector3& max)
-{
-    assert(!( min.x > max.x || min.y > max.y || min.z > max.z));
-
-    // Clamp the x value.
-    if ( x < min.x )
-        x = min.x;
-    if ( x > max.x )
-        x = max.x;
-
-    // Clamp the y value.
-    if ( y < min.y )
-        y = min.y;
-    if ( y > max.y )
-        y = max.y;
-
-    // Clamp the z value.
-    if ( z < min.z )
-        z = min.z;
-    if ( z > max.z )
-        z = max.z;
-}
-
-void Vector3::clamp(const Vector3& v, const Vector3& min, const Vector3& max, Vector3* dst)
-{
-    assert(dst);
-    assert(!( min.x > max.x || min.y > max.y || min.z > max.z));
-
-    // Clamp the x value.
-    dst->x = v.x;
-    if ( dst->x < min.x )
-        dst->x = min.x;
-    if ( dst->x > max.x )
-        dst->x = max.x;
-
-    // Clamp the y value.
-    dst->y = v.y;
-    if ( dst->y < min.y )
-        dst->y = min.y;
-    if ( dst->y > max.y )
-        dst->y = max.y;
-
-    // Clamp the z value.
-    dst->z = v.z;
-    if ( dst->z < min.z )
-        dst->z = min.z;
-    if ( dst->z > max.z )
-        dst->z = max.z;
-}
-
-void Vector3::cross(const Vector3& v)
-{
-    float tx = (y * v.z) - (z * v.y);
-    float ty = (z * v.x) - (x * v.z);
-    float tz = (x * v.y) - (y * v.x);
-    x = tx;
-    y = ty;
-    z = tz;
-}
-
-void Vector3::cross(const Vector3& v1, const Vector3& v2, Vector3* dst)
-{
-    assert(dst);
-
-    float x = (v1.y * v2.z) - (v1.z * v2.y);
-    float y = (v1.z * v2.x) - (v1.x * v2.z);
-    float z = (v1.x * v2.y) - (v1.y * v2.x);
-    dst->x = x;
-    dst->y = y;
-    dst->z = z;
-}
-
-float Vector3::distance(const Vector3& v) const
-{
-    float dx = v.x - x;
-    float dy = v.y - y;
-    float dz = v.z - z;
-
-    return sqrt(dx * dx + dy * dy + dz * dz);
-}
-
-float Vector3::distanceSquared(const Vector3& v) const
-{
-    float dx = v.x - x;
-    float dy = v.y - y;
-    float dz = v.z - z;
-
-    return (dx * dx + dy * dy + dz * dz);
-}
-
-float Vector3::dot(const Vector3& v)
-{
-    return (x * v.x + y * v.y + z * v.z);
-}
-
-float Vector3::dot(const Vector3& v1, const Vector3& v2)
-{
-    return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
-}
-
-float Vector3::length() const
-{
-    return sqrt(x * x + y * y + z * z);
-}
-
-float Vector3::lengthSquared() const
-{
-    return (x * x + y * y + z * z);
-}
-
-void Vector3::negate()
-{
-    x = -x;
-    y = -y;
-    z = -z;
-}
-
-void Vector3::normalize()
-{
-    normalize(this);
-}
-
-void Vector3::normalize(Vector3* dst) const
-{
-    assert(dst);
-
-    if (dst != this)
-    {
-        dst->x = x;
-        dst->y = y;
-        dst->z = z;
-    }
-
-    float n = x * x + y * y + z * z;
-    // Already normalized.
-    if (n == 1.0f)
-        return;
-
-    n = sqrt(n);
-    // Too close to zero.
-    if (n < MATH_TOLERANCE)
-        return;
-
-    n = 1.0f / n;
-    dst->x *= n;
-    dst->y *= n;
-    dst->z *= n;
-}
-
-void Vector3::scale(float scalar)
-{
-    x *= scalar;
-    y *= scalar;
-    z *= scalar;
-}
-
-void Vector3::set(float x, float y, float z)
-{
-    this->x = x;
-    this->y = y;
-    this->z = z;
-}
-
-void Vector3::set(float* array)
-{
-    assert(array);
-
-    x = array[0];
-    y = array[1];
-    z = array[2];
-}
-
-void Vector3::set(const Vector3& v)
-{
-    this->x = v.x;
-    this->y = v.y;
-    this->z = v.z;
-}
-
-void Vector3::set(const Vector3& p1, const Vector3& p2)
-{
-    x = p2.x - p1.x;
-    y = p2.y - p1.y;
-    z = p2.z - p1.z;
-}
-
-void Vector3::subtract(const Vector3& v)
-{
-    x -= v.x;
-    y -= v.y;
-    z -= v.z;
-}
-
-void Vector3::subtract(const Vector3& v1, const Vector3& v2, Vector3* dst)
-{
-    assert(dst);
-
-    dst->x = v1.x - v2.x;
-    dst->y = v1.y - v2.y;
-    dst->z = v1.z - v2.z;
-}
-
-}
+#include "Base.h"
+#include "Vector3.h"
+
+namespace gameplay
+{
+
+Vector3::Vector3()
+    : x(0.0f), y(0.0f), z(0.0f)
+{
+}
+
+Vector3::Vector3(float x, float y, float z)
+{
+    set(x, y, z);
+}
+
+Vector3::Vector3(float* array)
+{
+    set(array);
+}
+
+Vector3::Vector3(const Vector3& p1, const Vector3& p2)
+{
+    set(p1, p2);
+}
+
+Vector3::Vector3(const Vector3& copy)
+{
+    set(copy);
+}
+
+Vector3 Vector3::fromColor(unsigned int color)
+{
+    float components[3];
+    int componentIndex = 0;
+    for (int i = 2; i >= 0; --i)
+    {
+        int component = (color >> i*8) & 0x0000ff;
+
+        components[componentIndex++] = static_cast<float>(component) / 255.0f;
+    }
+
+    Vector3 value(components);
+    return value;
+}
+
+Vector3::~Vector3()
+{
+}
+
+const Vector3& Vector3::zero()
+{
+    static Vector3 value(0.0f, 0.0f, 0.0f);
+    return value;
+}
+
+const Vector3& Vector3::one()
+{
+    static Vector3 value(1.0f, 1.0f, 1.0f);
+    return value;
+}
+
+const Vector3& Vector3::unitX()
+{
+    static Vector3 value(1.0f, 0.0f, 0.0f);
+    return value;
+}
+
+const Vector3& Vector3::unitY()
+{
+    static Vector3 value(0.0f, 1.0f, 0.0f);
+    return value;
+}
+
+const Vector3& Vector3::unitZ()
+{
+    static Vector3 value(0.0f, 0.0f, 1.0f);
+    return value;
+}
+
+bool Vector3::isZero() const
+{
+    return x == 0.0f && y == 0.0f && z == 0.0f;
+}
+
+bool Vector3::isOne() const
+{
+    return x == 1.0f && y == 1.0f && z == 1.0f;
+}
+
+float Vector3::angle(const Vector3& v1, const Vector3& v2)
+{
+    float dx = v1.y * v2.z - v1.z * v2.y;
+    float dy = v1.z * v2.x - v1.x * v2.z;
+    float dz = v1.x * v2.y - v1.y * v2.x;
+
+    return atan2f(sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
+}
+
+void Vector3::add(const Vector3& v)
+{
+    x += v.x;
+    y += v.y;
+    z += v.z;
+}
+
+void Vector3::add(const Vector3& v1, const Vector3& v2, Vector3* dst)
+{
+    assert(dst);
+
+    dst->x = v1.x + v2.x;
+    dst->y = v1.y + v2.y;
+    dst->z = v1.z + v2.z;
+}
+
+void Vector3::clamp(const Vector3& min, const Vector3& max)
+{
+    assert(!( min.x > max.x || min.y > max.y || min.z > max.z));
+
+    // Clamp the x value.
+    if ( x < min.x )
+        x = min.x;
+    if ( x > max.x )
+        x = max.x;
+
+    // Clamp the y value.
+    if ( y < min.y )
+        y = min.y;
+    if ( y > max.y )
+        y = max.y;
+
+    // Clamp the z value.
+    if ( z < min.z )
+        z = min.z;
+    if ( z > max.z )
+        z = max.z;
+}
+
+void Vector3::clamp(const Vector3& v, const Vector3& min, const Vector3& max, Vector3* dst)
+{
+    assert(dst);
+    assert(!( min.x > max.x || min.y > max.y || min.z > max.z));
+
+    // Clamp the x value.
+    dst->x = v.x;
+    if ( dst->x < min.x )
+        dst->x = min.x;
+    if ( dst->x > max.x )
+        dst->x = max.x;
+
+    // Clamp the y value.
+    dst->y = v.y;
+    if ( dst->y < min.y )
+        dst->y = min.y;
+    if ( dst->y > max.y )
+        dst->y = max.y;
+
+    // Clamp the z value.
+    dst->z = v.z;
+    if ( dst->z < min.z )
+        dst->z = min.z;
+    if ( dst->z > max.z )
+        dst->z = max.z;
+}
+
+void Vector3::cross(const Vector3& v)
+{
+    float tx = (y * v.z) - (z * v.y);
+    float ty = (z * v.x) - (x * v.z);
+    float tz = (x * v.y) - (y * v.x);
+    x = tx;
+    y = ty;
+    z = tz;
+}
+
+void Vector3::cross(const Vector3& v1, const Vector3& v2, Vector3* dst)
+{
+    assert(dst);
+
+    float x = (v1.y * v2.z) - (v1.z * v2.y);
+    float y = (v1.z * v2.x) - (v1.x * v2.z);
+    float z = (v1.x * v2.y) - (v1.y * v2.x);
+    dst->x = x;
+    dst->y = y;
+    dst->z = z;
+}
+
+float Vector3::distance(const Vector3& v) const
+{
+    float dx = v.x - x;
+    float dy = v.y - y;
+    float dz = v.z - z;
+
+    return sqrt(dx * dx + dy * dy + dz * dz);
+}
+
+float Vector3::distanceSquared(const Vector3& v) const
+{
+    float dx = v.x - x;
+    float dy = v.y - y;
+    float dz = v.z - z;
+
+    return (dx * dx + dy * dy + dz * dz);
+}
+
+float Vector3::dot(const Vector3& v)
+{
+    return (x * v.x + y * v.y + z * v.z);
+}
+
+float Vector3::dot(const Vector3& v1, const Vector3& v2)
+{
+    return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
+}
+
+float Vector3::length() const
+{
+    return sqrt(x * x + y * y + z * z);
+}
+
+float Vector3::lengthSquared() const
+{
+    return (x * x + y * y + z * z);
+}
+
+void Vector3::negate()
+{
+    x = -x;
+    y = -y;
+    z = -z;
+}
+
+void Vector3::normalize()
+{
+    normalize(this);
+}
+
+void Vector3::normalize(Vector3* dst) const
+{
+    assert(dst);
+
+    if (dst != this)
+    {
+        dst->x = x;
+        dst->y = y;
+        dst->z = z;
+    }
+
+    float n = x * x + y * y + z * z;
+    // Already normalized.
+    if (n == 1.0f)
+        return;
+
+    n = sqrt(n);
+    // Too close to zero.
+    if (n < MATH_TOLERANCE)
+        return;
+
+    n = 1.0f / n;
+    dst->x *= n;
+    dst->y *= n;
+    dst->z *= n;
+}
+
+void Vector3::scale(float scalar)
+{
+    x *= scalar;
+    y *= scalar;
+    z *= scalar;
+}
+
+void Vector3::set(float x, float y, float z)
+{
+    this->x = x;
+    this->y = y;
+    this->z = z;
+}
+
+void Vector3::set(float* array)
+{
+    assert(array);
+
+    x = array[0];
+    y = array[1];
+    z = array[2];
+}
+
+void Vector3::set(const Vector3& v)
+{
+    this->x = v.x;
+    this->y = v.y;
+    this->z = v.z;
+}
+
+void Vector3::set(const Vector3& p1, const Vector3& p2)
+{
+    x = p2.x - p1.x;
+    y = p2.y - p1.y;
+    z = p2.z - p1.z;
+}
+
+void Vector3::subtract(const Vector3& v)
+{
+    x -= v.x;
+    y -= v.y;
+    z -= v.z;
+}
+
+void Vector3::subtract(const Vector3& v1, const Vector3& v2, Vector3* dst)
+{
+    assert(dst);
+
+    dst->x = v1.x - v2.x;
+    dst->y = v1.y - v2.y;
+    dst->z = v1.z - v2.z;
+}
+
+}

+ 443 - 443
tools/encoder/src/Vector3.h

@@ -1,443 +1,443 @@
-#ifndef VECTOR3_H_
-#define VECTOR3_H_
-
-namespace gameplay
-{
-
-class Matrix;
-class Quaternion;
-
-/**
- * Defines a 3-element floating point vector.
- *
- * When using a vector to represent a surface normal,
- * the vector should typically be normalized.
- * Other uses of directional vectors may wish to leave
- * the magnitude of the vector intact. When used as a point,
- * the elements of the vector represent a position in 3D space.
- */
-class Vector3
-{
-public:
-
-    /**
-     * The x-coordinate.
-     */
-    float x;
-
-    /**
-     * The y-coordinate.
-     */
-    float y;
-
-    /**
-     * The z-coordinate.
-     */
-    float z;
-
-    /**
-     * Constructs a new vector initialized to all zeros.
-     */
-    Vector3();
-
-    /**
-     * Constructs a new vector initialized to the specified values.
-     *
-     * @param x The x coordinate.
-     * @param y The y coordinate.
-     * @param z The z coordinate.
-     */
-    Vector3(float x, float y, float z);
-
-    /**
-     * Constructs a new vector from the values in the specified array.
-     *
-     * @param array An array containing the elements of the vector in the order x, y, z.
-     */
-    Vector3(float* array);
-
-    /**
-     * Constructs a vector that describes the direction between the specified points.
-     *
-     * @param p1 The first point.
-     * @param p2 The second point.
-     */
-    Vector3(const Vector3& p1, const Vector3& p2);
-
-    /**
-     * Constructs a new vector that is a copy of the specified vector.
-     *
-     * @param copy The vector to copy.
-     */
-    Vector3(const Vector3& copy);
-
-    /**
-     * Creates a new vector from an integer interpreted as an RGB value.
-     * E.g. 0xff0000 represents red or the vector (1, 0, 0).
-     *
-     * @param color The integer to interpret as an RGB value.
-     *
-     * @return A vector corresponding to the interpreted RGB color.
-     */
-    static Vector3 fromColor(unsigned int color);
-
-    /**
-     * Destructor.
-     */
-    ~Vector3();
-
-    /**
-     * Returns the zero vector.
-     *
-     * @return The 3-element vector of 0s.
-     */
-    static const Vector3& zero();
-
-    /**
-     * Returns the one vector.
-     *
-     * @return The 3-element vector of 1s.
-     */
-    static const Vector3& one();
-
-    /**
-     * Returns the unit x vector.
-     *
-     * @return The 3-element unit vector along the x axis.
-     */
-    static const Vector3& unitX();
-
-    /**
-     * Returns the unit y vector.
-     *
-     * @return The 3-element unit vector along the y axis.
-     */
-    static const Vector3& unitY();
-
-    /**
-     * Returns the unit z vector.
-     *
-     * @return The 3-element unit vector along the z axis.
-     */
-    static const Vector3& unitZ();
-
-    /**
-     * Indicates whether this vector contains all zeros.
-     *
-     * @return true if this vector contains all zeros, false otherwise.
-     */
-    bool isZero() const;
-
-    /**
-     * Indicates whether this vector contains all ones.
-     *
-     * @return true if this vector contains all ones, false otherwise.
-     */
-    bool isOne() const;
-
-    /**
-     * Returns the angle (in radians) between the specified vectors.
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * 
-     * @return The angle between the two vectors (in radians).
-     */
-    static float angle(const Vector3& v1, const Vector3& v2);
-
-
-    /**
-     * Adds the elements of the specified vector to this one.
-     *
-     * @param v The vector to add.
-     */
-    void add(const Vector3& v);
-
-    /**
-     * Adds the specified vectors and stores the result in dst.
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * @param dst A vector to store the result in.
-     */
-    static void add(const Vector3& v1, const Vector3& v2, Vector3* dst);
-
-    /**
-     * Clamps this vector within the specified range.
-     *
-     * @param min The minimum value.
-     * @param max The maximum value.
-     */
-    void clamp(const Vector3& min, const Vector3& max);
-
-    /**
-     * Clamps the specified vector within the specified range and returns it in dst.
-     *
-     * @param v The vector to clamp.
-     * @param min The minimum value.
-     * @param max The maximum value.
-     * @param dst A vector to store the result in.
-     */
-    static void clamp(const Vector3& v, const Vector3& min, const Vector3& max, Vector3* dst);
-
-    /**
-     * Sets this vector to the cross product between itself and the specified vector.
-     *
-     * @param v The vector to compute the cross product with.
-     */
-    void cross(const Vector3& v);
-
-    /**
-     * Computes the cross product of the specified vectors and stores the result in dst.
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * @param dst A vector to store the result in.
-     */
-    static void cross(const Vector3& v1, const Vector3& v2, Vector3* dst);
-
-    /**
-     * Returns the distance between this vector and v.
-     *
-     * @param v The other vector.
-     * 
-     * @return The distance between this vector and v.
-     * 
-     * @see distanceSquared
-     */
-    float distance(const Vector3& v) const;
-
-    /**
-     * Returns the squared distance between this vector and v.
-     *
-     * When it is not necessary to get the exact distance between
-     * two vectors (for example, when simply comparing the
-     * distance between different vectors), it is advised to use
-     * this method instead of distance.
-     *
-     * @param v The other vector.
-     * 
-     * @return The squared distance between this vector and v.
-     * 
-     * @see distance
-     */
-    float distanceSquared(const Vector3& v) const;
-
-    /**
-     * Returns the dot product of this vector and the specified vector.
-     *
-     * @param v The vector to compute the dot product with.
-     * 
-     * @return The dot product.
-     */
-    float dot(const Vector3& v);
-
-    /**
-     * Returns the dot product between the specified vectors.
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * 
-     * @return The dot product between the vectors.
-     */
-    static float dot(const Vector3& v1, const Vector3& v2);
-
-    /**
-     * Computes the length of this vector.
-     *
-     * @return The length of the vector.
-     * 
-     * @see lengthSquared
-     */
-    float length() const;
-
-    /**
-     * Returns the squared length of this vector.
-     *
-     * When it is not necessary to get the exact length of a
-     * vector (for example, when simply comparing the lengths of
-     * different vectors), it is advised to use this method
-     * instead of length.
-     *
-     * @return The squared length of the vector.
-     * 
-     * @see length
-     */
-    float lengthSquared() const;
-
-    /**
-     * Negates this vector.
-     */
-    void negate();
-
-    /**
-     * Normalizes this vector.
-     *
-     * This method normalizes this Vector3 so that it is of
-     * unit length (in other words, the length of the vector
-     * after calling this method will be 1.0f). If the vector
-     * already has unit length or if the length of the vector
-     * is zero, this method does nothing.
-     */
-    void normalize();
-
-    /**
-     * Normalizes this vector and stores the result in dst.
-     *
-     * If the vector already has unit length or if the length
-     * of the vector is zero, this method simply copies the
-     * current vector into dst.
-     *
-     * @param dst The destination vector.
-     */
-    void normalize(Vector3* dst) const;
-
-    /**
-     * Scales all elements of this vector by the specified value.
-     *
-     * @param scalar The scalar value.
-     */
-    void scale(float scalar);
-
-    /**
-     * Sets the elements of this vector to the specified values.
-     *
-     * @param x The new x coordinate.
-     * @param y The new y coordinate.
-     * @param z The new z coordinate.
-     */
-    void set(float x, float y, float z);
-
-    /**
-     * Sets the elements of this vector from the values in the specified array.
-     *
-     * @param array An array containing the elements of the vector in the order x, y, z.
-     */
-    void set(float* array);
-
-    /**
-     * Sets the elements of this vector to those in the specified vector.
-     *
-     * @param v The vector to copy.
-     */
-    void set(const Vector3& v);
-
-    /**
-     * Sets this vector to the directional vector between the specified points.
-     */
-    void set(const Vector3& p1, const Vector3& p2);
-
-    /**
-     * Subtracts this vector and the specified vector as (this - v)
-     * and stores the result in this vector.
-     *
-     * @param v The vector to subtract.
-     */
-    void subtract(const Vector3& v);
-
-    /**
-     * Subtracts the specified vectors and stores the result in dst.
-     * The resulting vector is computed as (v1 - v2).
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * @param dst The destination vector.
-     */
-    static void subtract(const Vector3& v1, const Vector3& v2, Vector3* dst);
-
-    /**
-     * Calculates the sum of this vector with the given vector.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @param v The vector to add.
-     * @return The vector sum.
-     */
-    inline Vector3 operator+(const Vector3& v);
-
-    /**
-     * Adds the given vector to this vector.
-     * 
-     * @param v The vector to add.
-     * @return This vector, after the addition occurs.
-     */
-    inline Vector3& operator+=(const Vector3& v);
-
-    /**
-     * Calculates the sum of this vector with the given vector.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @param v The vector to add.
-     * @return The vector sum.
-     */
-    inline Vector3 operator-(const Vector3& v);
-
-    /**
-     * Subtracts the given vector from this vector.
-     * 
-     * @param v The vector to subtract.
-     * @return This vector, after the subtraction occurs.
-     */
-    inline Vector3& operator-=(const Vector3& v);
-
-    /**
-     * Calculates the negation of this vector.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @return The negation of this vector.
-     */
-    inline Vector3 operator-();
-
-    /**
-     * Calculates the scalar product of this vector with the given value.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @param x The value to scale by.
-     * @return The scaled vector.
-     */
-    inline Vector3 operator*(float x);
-
-    /**
-     * Scales this vector by the given value.
-     * 
-     * @param x The value to scale by.
-     * @return This vector, after the scale occurs.
-     */
-    inline Vector3& operator*=(float x);
-
-    /**
-     * Determines if this vector is less than the given vector.
-     * 
-     * @param v The vector to compare against.
-     * 
-     * @return True if this vector is less than the given vector, false otherwise.
-     */
-    inline bool operator<(const Vector3& v) const;
-
-    /**
-     * Determines if this vector is equal to the given vector.
-     * 
-     * @param v The vector to compare against.
-     * 
-     * @return True if this vector is equal to the given vector, false otherwise.
-     */
-    inline bool operator==(const Vector3& v) const;
-};
-
-/**
- * Calculates the scalar product of the given vector with the given value.
- * 
- * @param x The value to scale by.
- * @param v The vector to scale.
- * @return The scaled vector.
- */
-inline Vector3 operator*(float x, const Vector3& v);
-
-}
-
-#include "Vector3.inl"
-
-#endif
+#ifndef VECTOR3_H_
+#define VECTOR3_H_
+
+namespace gameplay
+{
+
+class Matrix;
+class Quaternion;
+
+/**
+ * Defines a 3-element floating point vector.
+ *
+ * When using a vector to represent a surface normal,
+ * the vector should typically be normalized.
+ * Other uses of directional vectors may wish to leave
+ * the magnitude of the vector intact. When used as a point,
+ * the elements of the vector represent a position in 3D space.
+ */
+class Vector3
+{
+public:
+
+    /**
+     * The x-coordinate.
+     */
+    float x;
+
+    /**
+     * The y-coordinate.
+     */
+    float y;
+
+    /**
+     * The z-coordinate.
+     */
+    float z;
+
+    /**
+     * Constructs a new vector initialized to all zeros.
+     */
+    Vector3();
+
+    /**
+     * Constructs a new vector initialized to the specified values.
+     *
+     * @param x The x coordinate.
+     * @param y The y coordinate.
+     * @param z The z coordinate.
+     */
+    Vector3(float x, float y, float z);
+
+    /**
+     * Constructs a new vector from the values in the specified array.
+     *
+     * @param array An array containing the elements of the vector in the order x, y, z.
+     */
+    Vector3(float* array);
+
+    /**
+     * Constructs a vector that describes the direction between the specified points.
+     *
+     * @param p1 The first point.
+     * @param p2 The second point.
+     */
+    Vector3(const Vector3& p1, const Vector3& p2);
+
+    /**
+     * Constructs a new vector that is a copy of the specified vector.
+     *
+     * @param copy The vector to copy.
+     */
+    Vector3(const Vector3& copy);
+
+    /**
+     * Creates a new vector from an integer interpreted as an RGB value.
+     * E.g. 0xff0000 represents red or the vector (1, 0, 0).
+     *
+     * @param color The integer to interpret as an RGB value.
+     *
+     * @return A vector corresponding to the interpreted RGB color.
+     */
+    static Vector3 fromColor(unsigned int color);
+
+    /**
+     * Destructor.
+     */
+    ~Vector3();
+
+    /**
+     * Returns the zero vector.
+     *
+     * @return The 3-element vector of 0s.
+     */
+    static const Vector3& zero();
+
+    /**
+     * Returns the one vector.
+     *
+     * @return The 3-element vector of 1s.
+     */
+    static const Vector3& one();
+
+    /**
+     * Returns the unit x vector.
+     *
+     * @return The 3-element unit vector along the x axis.
+     */
+    static const Vector3& unitX();
+
+    /**
+     * Returns the unit y vector.
+     *
+     * @return The 3-element unit vector along the y axis.
+     */
+    static const Vector3& unitY();
+
+    /**
+     * Returns the unit z vector.
+     *
+     * @return The 3-element unit vector along the z axis.
+     */
+    static const Vector3& unitZ();
+
+    /**
+     * Indicates whether this vector contains all zeros.
+     *
+     * @return true if this vector contains all zeros, false otherwise.
+     */
+    bool isZero() const;
+
+    /**
+     * Indicates whether this vector contains all ones.
+     *
+     * @return true if this vector contains all ones, false otherwise.
+     */
+    bool isOne() const;
+
+    /**
+     * Returns the angle (in radians) between the specified vectors.
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * 
+     * @return The angle between the two vectors (in radians).
+     */
+    static float angle(const Vector3& v1, const Vector3& v2);
+
+
+    /**
+     * Adds the elements of the specified vector to this one.
+     *
+     * @param v The vector to add.
+     */
+    void add(const Vector3& v);
+
+    /**
+     * Adds the specified vectors and stores the result in dst.
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * @param dst A vector to store the result in.
+     */
+    static void add(const Vector3& v1, const Vector3& v2, Vector3* dst);
+
+    /**
+     * Clamps this vector within the specified range.
+     *
+     * @param min The minimum value.
+     * @param max The maximum value.
+     */
+    void clamp(const Vector3& min, const Vector3& max);
+
+    /**
+     * Clamps the specified vector within the specified range and returns it in dst.
+     *
+     * @param v The vector to clamp.
+     * @param min The minimum value.
+     * @param max The maximum value.
+     * @param dst A vector to store the result in.
+     */
+    static void clamp(const Vector3& v, const Vector3& min, const Vector3& max, Vector3* dst);
+
+    /**
+     * Sets this vector to the cross product between itself and the specified vector.
+     *
+     * @param v The vector to compute the cross product with.
+     */
+    void cross(const Vector3& v);
+
+    /**
+     * Computes the cross product of the specified vectors and stores the result in dst.
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * @param dst A vector to store the result in.
+     */
+    static void cross(const Vector3& v1, const Vector3& v2, Vector3* dst);
+
+    /**
+     * Returns the distance between this vector and v.
+     *
+     * @param v The other vector.
+     * 
+     * @return The distance between this vector and v.
+     * 
+     * @see distanceSquared
+     */
+    float distance(const Vector3& v) const;
+
+    /**
+     * Returns the squared distance between this vector and v.
+     *
+     * When it is not necessary to get the exact distance between
+     * two vectors (for example, when simply comparing the
+     * distance between different vectors), it is advised to use
+     * this method instead of distance.
+     *
+     * @param v The other vector.
+     * 
+     * @return The squared distance between this vector and v.
+     * 
+     * @see distance
+     */
+    float distanceSquared(const Vector3& v) const;
+
+    /**
+     * Returns the dot product of this vector and the specified vector.
+     *
+     * @param v The vector to compute the dot product with.
+     * 
+     * @return The dot product.
+     */
+    float dot(const Vector3& v);
+
+    /**
+     * Returns the dot product between the specified vectors.
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * 
+     * @return The dot product between the vectors.
+     */
+    static float dot(const Vector3& v1, const Vector3& v2);
+
+    /**
+     * Computes the length of this vector.
+     *
+     * @return The length of the vector.
+     * 
+     * @see lengthSquared
+     */
+    float length() const;
+
+    /**
+     * Returns the squared length of this vector.
+     *
+     * When it is not necessary to get the exact length of a
+     * vector (for example, when simply comparing the lengths of
+     * different vectors), it is advised to use this method
+     * instead of length.
+     *
+     * @return The squared length of the vector.
+     * 
+     * @see length
+     */
+    float lengthSquared() const;
+
+    /**
+     * Negates this vector.
+     */
+    void negate();
+
+    /**
+     * Normalizes this vector.
+     *
+     * This method normalizes this Vector3 so that it is of
+     * unit length (in other words, the length of the vector
+     * after calling this method will be 1.0f). If the vector
+     * already has unit length or if the length of the vector
+     * is zero, this method does nothing.
+     */
+    void normalize();
+
+    /**
+     * Normalizes this vector and stores the result in dst.
+     *
+     * If the vector already has unit length or if the length
+     * of the vector is zero, this method simply copies the
+     * current vector into dst.
+     *
+     * @param dst The destination vector.
+     */
+    void normalize(Vector3* dst) const;
+
+    /**
+     * Scales all elements of this vector by the specified value.
+     *
+     * @param scalar The scalar value.
+     */
+    void scale(float scalar);
+
+    /**
+     * Sets the elements of this vector to the specified values.
+     *
+     * @param x The new x coordinate.
+     * @param y The new y coordinate.
+     * @param z The new z coordinate.
+     */
+    void set(float x, float y, float z);
+
+    /**
+     * Sets the elements of this vector from the values in the specified array.
+     *
+     * @param array An array containing the elements of the vector in the order x, y, z.
+     */
+    void set(float* array);
+
+    /**
+     * Sets the elements of this vector to those in the specified vector.
+     *
+     * @param v The vector to copy.
+     */
+    void set(const Vector3& v);
+
+    /**
+     * Sets this vector to the directional vector between the specified points.
+     */
+    void set(const Vector3& p1, const Vector3& p2);
+
+    /**
+     * Subtracts this vector and the specified vector as (this - v)
+     * and stores the result in this vector.
+     *
+     * @param v The vector to subtract.
+     */
+    void subtract(const Vector3& v);
+
+    /**
+     * Subtracts the specified vectors and stores the result in dst.
+     * The resulting vector is computed as (v1 - v2).
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * @param dst The destination vector.
+     */
+    static void subtract(const Vector3& v1, const Vector3& v2, Vector3* dst);
+
+    /**
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
+     */
+    inline Vector3 operator+(const Vector3& v);
+
+    /**
+     * Adds the given vector to this vector.
+     * 
+     * @param v The vector to add.
+     * @return This vector, after the addition occurs.
+     */
+    inline Vector3& operator+=(const Vector3& v);
+
+    /**
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
+     */
+    inline Vector3 operator-(const Vector3& v);
+
+    /**
+     * Subtracts the given vector from this vector.
+     * 
+     * @param v The vector to subtract.
+     * @return This vector, after the subtraction occurs.
+     */
+    inline Vector3& operator-=(const Vector3& v);
+
+    /**
+     * Calculates the negation of this vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @return The negation of this vector.
+     */
+    inline Vector3 operator-();
+
+    /**
+     * Calculates the scalar product of this vector with the given value.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param x The value to scale by.
+     * @return The scaled vector.
+     */
+    inline Vector3 operator*(float x);
+
+    /**
+     * Scales this vector by the given value.
+     * 
+     * @param x The value to scale by.
+     * @return This vector, after the scale occurs.
+     */
+    inline Vector3& operator*=(float x);
+
+    /**
+     * Determines if this vector is less than the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is less than the given vector, false otherwise.
+     */
+    inline bool operator<(const Vector3& v) const;
+
+    /**
+     * Determines if this vector is equal to the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is equal to the given vector, false otherwise.
+     */
+    inline bool operator==(const Vector3& v) const;
+};
+
+/**
+ * Calculates the scalar product of the given vector with the given value.
+ * 
+ * @param x The value to scale by.
+ * @param v The vector to scale.
+ * @return The scaled vector.
+ */
+inline Vector3 operator*(float x, const Vector3& v);
+
+}
+
+#include "Vector3.inl"
+
+#endif

+ 82 - 82
tools/encoder/src/Vector3.inl

@@ -1,82 +1,82 @@
-/** 
- * Vector3.inl
- */
-
-#include "Vector3.h"
-#include "Matrix.h"
-
-namespace gameplay
-{
-
-inline Vector3 Vector3::operator+(const Vector3& v)
-{
-    Vector3 result(*this);
-    result.add(v);
-    return result;
-}
-
-inline Vector3& Vector3::operator+=(const Vector3& v)
-{
-    add(v);
-    return *this;
-}
-
-inline Vector3 Vector3::operator-(const Vector3& v)
-{
-    Vector3 result(*this);
-    result.subtract(v);
-    return result;
-}
-
-inline Vector3& Vector3::operator-=(const Vector3& v)
-{
-    subtract(v);
-    return *this;
-}
-
-inline Vector3 Vector3::operator-()
-{
-    Vector3 result(*this);
-    result.negate();
-    return result;
-}
-
-inline Vector3 Vector3::operator*(float x)
-{
-    Vector3 result(*this);
-    result.scale(x);
-    return result;
-}
-
-inline Vector3& Vector3::operator*=(float x)
-{
-    scale(x);
-    return *this;
-}
-
-inline bool Vector3::operator<(const Vector3& v) const
-{
-    if (x == v.x)
-    {
-        if (y == v.y)
-        {
-            return z < v.z;
-        }
-        return y < v.y;
-    }
-    return x < v.x;
-}
-
-inline bool Vector3::operator==(const Vector3& v) const
-{
-    return x==v.x && y==v.y && z==v.z;
-}
-
-inline Vector3 operator*(float x, const Vector3& v)
-{
-    Vector3 result(v);
-    result.scale(x);
-    return result;
-}
-
-}
+/** 
+ * Vector3.inl
+ */
+
+#include "Vector3.h"
+#include "Matrix.h"
+
+namespace gameplay
+{
+
+inline Vector3 Vector3::operator+(const Vector3& v)
+{
+    Vector3 result(*this);
+    result.add(v);
+    return result;
+}
+
+inline Vector3& Vector3::operator+=(const Vector3& v)
+{
+    add(v);
+    return *this;
+}
+
+inline Vector3 Vector3::operator-(const Vector3& v)
+{
+    Vector3 result(*this);
+    result.subtract(v);
+    return result;
+}
+
+inline Vector3& Vector3::operator-=(const Vector3& v)
+{
+    subtract(v);
+    return *this;
+}
+
+inline Vector3 Vector3::operator-()
+{
+    Vector3 result(*this);
+    result.negate();
+    return result;
+}
+
+inline Vector3 Vector3::operator*(float x)
+{
+    Vector3 result(*this);
+    result.scale(x);
+    return result;
+}
+
+inline Vector3& Vector3::operator*=(float x)
+{
+    scale(x);
+    return *this;
+}
+
+inline bool Vector3::operator<(const Vector3& v) const
+{
+    if (x == v.x)
+    {
+        if (y == v.y)
+        {
+            return z < v.z;
+        }
+        return y < v.y;
+    }
+    return x < v.x;
+}
+
+inline bool Vector3::operator==(const Vector3& v) const
+{
+    return x==v.x && y==v.y && z==v.z;
+}
+
+inline Vector3 operator*(float x, const Vector3& v)
+{
+    Vector3 result(v);
+    result.scale(x);
+    return result;
+}
+
+}

+ 330 - 330
tools/encoder/src/Vector4.cpp

@@ -1,330 +1,330 @@
-#include "Base.h"
-#include "Vector4.h"
-
-namespace gameplay
-{
-
-Vector4::Vector4()
-    : x(0.0f), y(0.0f), z(0.0f), w(0.0f)
-{
-}
-
-Vector4::Vector4(float x, float y, float z, float w)
-{
-    set(x, y, z, w);
-}
-
-Vector4::Vector4(float* src)
-{
-    set(src);
-}
-
-Vector4::Vector4(const Vector4& p1, const Vector4& p2)
-{
-    set(p1, p2);
-}
-
-Vector4::Vector4(const Vector4& copy)
-{
-    set(copy);
-}
-
-Vector4 Vector4::fromColor(unsigned int color)
-{
-    float components[4];
-    int componentIndex = 0;
-    for (int i = 3; i >= 0; --i)
-    {
-        int component = (color >> i*8) & 0x000000ff;
-
-        components[componentIndex++] = static_cast<float>(component) / 255.0f;
-    }
-
-    Vector4 value(components);
-    return value;
-}
-
-Vector4::~Vector4()
-{
-}
-
-const Vector4& Vector4::zero()
-{
-    static Vector4 value(0.0f, 0.0f, 0.0f, 0.0f);
-    return value;
-}
-
-const Vector4& Vector4::one()
-{
-    static Vector4 value(1.0f, 1.0f, 1.0f, 1.0f);
-    return value;
-}
-
-const Vector4& Vector4::unitX()
-{
-    static Vector4 value(1.0f, 0.0f, 0.0f, 0.0f);
-    return value;
-}
-
-const Vector4& Vector4::unitY()
-{
-    static Vector4 value(0.0f, 1.0f, 0.0f, 0.0f);
-    return value;
-}
-
-const Vector4& Vector4::unitZ()
-{
-    static Vector4 value(0.0f, 0.0f, 1.0f, 0.0f);
-    return value;
-}
-
-const Vector4& Vector4::unitW()
-{
-    static Vector4 value(0.0f, 0.0f, 0.0f, 1.0f);
-    return value;
-}
-
-bool Vector4::isZero() const
-{
-    return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f;
-}
-
-bool Vector4::isOne() const
-{
-    return x == 1.0f && y == 1.0f && z == 1.0f && w == 1.0f;
-}
-
-float Vector4::angle(const Vector4& v1, const Vector4& v2)
-{
-    float dx = v1.w * v2.x - v1.x * v2.w - v1.y * v2.z + v1.z * v2.y;
-    float dy = v1.w * v2.y - v1.y * v2.w - v1.z * v2.x + v1.x * v2.z;
-    float dz = v1.w * v2.z - v1.z * v2.w - v1.x * v2.y + v1.y * v2.x;
-
-    return atan2f(sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
-}
-
-void Vector4::add(const Vector4& v)
-{
-    x += v.x;
-    y += v.y;
-    z += v.z;
-    w += v.w;
-}
-
-void Vector4::add(const Vector4& v1, const Vector4& v2, Vector4* dst)
-{
-    assert(dst);
-
-    dst->x = v1.x + v2.x;
-    dst->y = v1.y + v2.y;
-    dst->z = v1.z + v2.z;
-    dst->w = v1.w + v2.w;
-}
-
-void Vector4::clamp(const Vector4& min, const Vector4& max)
-{
-    assert(!( min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w));
-
-    // Clamp the x value.
-    if ( x < min.x )
-        x = min.x;
-    if ( x > max.x )
-        x = max.x;
-
-    // Clamp the y value.
-    if ( y < min.y )
-        y = min.y;
-    if ( y > max.y )
-        y = max.y;
-
-    // Clamp the z value.
-    if ( z < min.z )
-        z = min.z;
-    if ( z > max.z )
-        z = max.z;
-
-    // Clamp the z value.
-    if ( w < min.w )
-        w = min.w;
-    if ( w > max.w )
-        w = max.w;
-}
-
-void Vector4::clamp(const Vector4& v, const Vector4& min, const Vector4& max, Vector4* dst)
-{
-    assert(dst);
-    assert(!( min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w));
-
-    // Clamp the x value.
-    dst->x = v.x;
-    if ( dst->x < min.x )
-        dst->x = min.x;
-    if ( dst->x > max.x )
-        dst->x = max.x;
-
-    // Clamp the y value.
-    dst->y = v.y;
-    if ( dst->y < min.y )
-        dst->y = min.y;
-    if ( dst->y > max.y )
-        dst->y = max.y;
-
-    // Clamp the z value.
-    dst->z = v.z;
-    if ( dst->z < min.z )
-        dst->z = min.z;
-    if ( dst->z > max.z )
-        dst->z = max.z;
-
-    // Clamp the w value.
-    dst->w = v.w;
-    if ( dst->w < min.w )
-        dst->w = min.w;
-    if ( dst->w > max.w )
-        dst->w = max.w;
-}
-
-float Vector4::distance(const Vector4& v) const
-{
-    float dx = v.x - x;
-    float dy = v.y - y;
-    float dz = v.z - z;
-    float dw = v.w - w;
-
-    return sqrt(dx * dx + dy * dy + dz * dz + dw * dw);
-}
-
-float Vector4::distanceSquared(const Vector4& v) const
-{
-    float dx = v.x - x;
-    float dy = v.y - y;
-    float dz = v.z - z;
-    float dw = v.w - w;
-
-    return (dx * dx + dy * dy + dz * dz + dw * dw);
-}
-
-float Vector4::dot(const Vector4& v)
-{
-    return (x * v.x + y * v.y + z * v.z + w * v.w);
-}
-
-float Vector4::dot(const Vector4& v1, const Vector4& v2)
-{
-    return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w);
-}
-
-float Vector4::length() const
-{
-    return sqrt(x * x + y * y + z * z + w * w);
-}
-
-
-float Vector4::lengthSquared() const
-{
-    return (x * x + y * y + z * z + w * w);
-}
-
-void Vector4::negate()
-{
-    x = -x;
-    y = -y;
-    z = -z;
-    w = -w;
-}
-
-void Vector4::normalize()
-{
-    normalize(this);
-}
-
-void Vector4::normalize(Vector4* dst)
-{
-    assert(dst);
-
-    if (dst != this)
-    {
-        dst->x = x;
-        dst->y = y;
-        dst->z = z;
-        dst->w = w;
-    }
-
-    float n = x * x + y * y + z * z + w * w;
-    // Already normalized.
-    if (n == 1.0f)
-        return;
-
-    n = sqrt(n);
-    // Too close to zero.
-    if (n < MATH_TOLERANCE)
-        return;
-
-    n = 1.0f / n;
-    dst->x *= n;
-    dst->y *= n;
-    dst->z *= n;
-    dst->w *= n;
-}
-
-void Vector4::scale(float scalar)
-{
-    x *= scalar;
-    y *= scalar;
-    z *= scalar;
-    w *= scalar;
-}
-
-void Vector4::set(float x, float y, float z, float w)
-{
-    this->x = x;
-    this->y = y;
-    this->z = z;
-    this->w = w;
-}
-
-void Vector4::set(float* array)
-{
-    assert(array);
-
-    x = array[0];
-    y = array[1];
-    z = array[2];
-    w = array[3];
-}
-
-void Vector4::set(const Vector4& v)
-{
-    this->x = v.x;
-    this->y = v.y;
-    this->z = v.z;
-    this->w = v.w;
-}
-
-void Vector4::set(const Vector4& p1, const Vector4& p2)
-{
-    x = p2.x - p1.x;
-    y = p2.y - p1.y;
-    z = p2.z - p1.z;
-    w = p2.w - p1.w;
-}
-
-void Vector4::subtract(const Vector4& v)
-{
-    x -= v.x;
-    y -= v.y;
-    z -= v.z;
-    w -= v.w;
-}
-
-void Vector4::subtract(const Vector4& v1, const Vector4& v2, Vector4* dst)
-{
-    assert(dst);
-
-    dst->x = v1.x - v2.x;
-    dst->y = v1.y - v2.y;
-    dst->z = v1.z - v2.z;
-    dst->w = v1.w - v2.w;
-}
-
-}
+#include "Base.h"
+#include "Vector4.h"
+
+namespace gameplay
+{
+
+Vector4::Vector4()
+    : x(0.0f), y(0.0f), z(0.0f), w(0.0f)
+{
+}
+
+Vector4::Vector4(float x, float y, float z, float w)
+{
+    set(x, y, z, w);
+}
+
+Vector4::Vector4(float* src)
+{
+    set(src);
+}
+
+Vector4::Vector4(const Vector4& p1, const Vector4& p2)
+{
+    set(p1, p2);
+}
+
+Vector4::Vector4(const Vector4& copy)
+{
+    set(copy);
+}
+
+Vector4 Vector4::fromColor(unsigned int color)
+{
+    float components[4];
+    int componentIndex = 0;
+    for (int i = 3; i >= 0; --i)
+    {
+        int component = (color >> i*8) & 0x000000ff;
+
+        components[componentIndex++] = static_cast<float>(component) / 255.0f;
+    }
+
+    Vector4 value(components);
+    return value;
+}
+
+Vector4::~Vector4()
+{
+}
+
+const Vector4& Vector4::zero()
+{
+    static Vector4 value(0.0f, 0.0f, 0.0f, 0.0f);
+    return value;
+}
+
+const Vector4& Vector4::one()
+{
+    static Vector4 value(1.0f, 1.0f, 1.0f, 1.0f);
+    return value;
+}
+
+const Vector4& Vector4::unitX()
+{
+    static Vector4 value(1.0f, 0.0f, 0.0f, 0.0f);
+    return value;
+}
+
+const Vector4& Vector4::unitY()
+{
+    static Vector4 value(0.0f, 1.0f, 0.0f, 0.0f);
+    return value;
+}
+
+const Vector4& Vector4::unitZ()
+{
+    static Vector4 value(0.0f, 0.0f, 1.0f, 0.0f);
+    return value;
+}
+
+const Vector4& Vector4::unitW()
+{
+    static Vector4 value(0.0f, 0.0f, 0.0f, 1.0f);
+    return value;
+}
+
+bool Vector4::isZero() const
+{
+    return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f;
+}
+
+bool Vector4::isOne() const
+{
+    return x == 1.0f && y == 1.0f && z == 1.0f && w == 1.0f;
+}
+
+float Vector4::angle(const Vector4& v1, const Vector4& v2)
+{
+    float dx = v1.w * v2.x - v1.x * v2.w - v1.y * v2.z + v1.z * v2.y;
+    float dy = v1.w * v2.y - v1.y * v2.w - v1.z * v2.x + v1.x * v2.z;
+    float dz = v1.w * v2.z - v1.z * v2.w - v1.x * v2.y + v1.y * v2.x;
+
+    return atan2f(sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
+}
+
+void Vector4::add(const Vector4& v)
+{
+    x += v.x;
+    y += v.y;
+    z += v.z;
+    w += v.w;
+}
+
+void Vector4::add(const Vector4& v1, const Vector4& v2, Vector4* dst)
+{
+    assert(dst);
+
+    dst->x = v1.x + v2.x;
+    dst->y = v1.y + v2.y;
+    dst->z = v1.z + v2.z;
+    dst->w = v1.w + v2.w;
+}
+
+void Vector4::clamp(const Vector4& min, const Vector4& max)
+{
+    assert(!( min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w));
+
+    // Clamp the x value.
+    if ( x < min.x )
+        x = min.x;
+    if ( x > max.x )
+        x = max.x;
+
+    // Clamp the y value.
+    if ( y < min.y )
+        y = min.y;
+    if ( y > max.y )
+        y = max.y;
+
+    // Clamp the z value.
+    if ( z < min.z )
+        z = min.z;
+    if ( z > max.z )
+        z = max.z;
+
+    // Clamp the z value.
+    if ( w < min.w )
+        w = min.w;
+    if ( w > max.w )
+        w = max.w;
+}
+
+void Vector4::clamp(const Vector4& v, const Vector4& min, const Vector4& max, Vector4* dst)
+{
+    assert(dst);
+    assert(!( min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w));
+
+    // Clamp the x value.
+    dst->x = v.x;
+    if ( dst->x < min.x )
+        dst->x = min.x;
+    if ( dst->x > max.x )
+        dst->x = max.x;
+
+    // Clamp the y value.
+    dst->y = v.y;
+    if ( dst->y < min.y )
+        dst->y = min.y;
+    if ( dst->y > max.y )
+        dst->y = max.y;
+
+    // Clamp the z value.
+    dst->z = v.z;
+    if ( dst->z < min.z )
+        dst->z = min.z;
+    if ( dst->z > max.z )
+        dst->z = max.z;
+
+    // Clamp the w value.
+    dst->w = v.w;
+    if ( dst->w < min.w )
+        dst->w = min.w;
+    if ( dst->w > max.w )
+        dst->w = max.w;
+}
+
+float Vector4::distance(const Vector4& v) const
+{
+    float dx = v.x - x;
+    float dy = v.y - y;
+    float dz = v.z - z;
+    float dw = v.w - w;
+
+    return sqrt(dx * dx + dy * dy + dz * dz + dw * dw);
+}
+
+float Vector4::distanceSquared(const Vector4& v) const
+{
+    float dx = v.x - x;
+    float dy = v.y - y;
+    float dz = v.z - z;
+    float dw = v.w - w;
+
+    return (dx * dx + dy * dy + dz * dz + dw * dw);
+}
+
+float Vector4::dot(const Vector4& v)
+{
+    return (x * v.x + y * v.y + z * v.z + w * v.w);
+}
+
+float Vector4::dot(const Vector4& v1, const Vector4& v2)
+{
+    return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w);
+}
+
+float Vector4::length() const
+{
+    return sqrt(x * x + y * y + z * z + w * w);
+}
+
+
+float Vector4::lengthSquared() const
+{
+    return (x * x + y * y + z * z + w * w);
+}
+
+void Vector4::negate()
+{
+    x = -x;
+    y = -y;
+    z = -z;
+    w = -w;
+}
+
+void Vector4::normalize()
+{
+    normalize(this);
+}
+
+void Vector4::normalize(Vector4* dst)
+{
+    assert(dst);
+
+    if (dst != this)
+    {
+        dst->x = x;
+        dst->y = y;
+        dst->z = z;
+        dst->w = w;
+    }
+
+    float n = x * x + y * y + z * z + w * w;
+    // Already normalized.
+    if (n == 1.0f)
+        return;
+
+    n = sqrt(n);
+    // Too close to zero.
+    if (n < MATH_TOLERANCE)
+        return;
+
+    n = 1.0f / n;
+    dst->x *= n;
+    dst->y *= n;
+    dst->z *= n;
+    dst->w *= n;
+}
+
+void Vector4::scale(float scalar)
+{
+    x *= scalar;
+    y *= scalar;
+    z *= scalar;
+    w *= scalar;
+}
+
+void Vector4::set(float x, float y, float z, float w)
+{
+    this->x = x;
+    this->y = y;
+    this->z = z;
+    this->w = w;
+}
+
+void Vector4::set(float* array)
+{
+    assert(array);
+
+    x = array[0];
+    y = array[1];
+    z = array[2];
+    w = array[3];
+}
+
+void Vector4::set(const Vector4& v)
+{
+    this->x = v.x;
+    this->y = v.y;
+    this->z = v.z;
+    this->w = v.w;
+}
+
+void Vector4::set(const Vector4& p1, const Vector4& p2)
+{
+    x = p2.x - p1.x;
+    y = p2.y - p1.y;
+    z = p2.z - p1.z;
+    w = p2.w - p1.w;
+}
+
+void Vector4::subtract(const Vector4& v)
+{
+    x -= v.x;
+    y -= v.y;
+    z -= v.z;
+    w -= v.w;
+}
+
+void Vector4::subtract(const Vector4& v1, const Vector4& v2, Vector4* dst)
+{
+    assert(dst);
+
+    dst->x = v1.x - v2.x;
+    dst->y = v1.y - v2.y;
+    dst->z = v1.z - v2.z;
+    dst->w = v1.w - v2.w;
+}
+
+}

+ 438 - 438
tools/encoder/src/Vector4.h

@@ -1,438 +1,438 @@
-#ifndef VECTOR4_H_
-#define VECTOR4_H_
-
-namespace gameplay
-{
-
-class Matrix;
-
-/**
- * Defines 4-element floating point vector.
- */
-class Vector4
-{
-public:
-
-    /**
-     * The x-coordinate.
-     */
-    float x;
-
-    /**
-     * The y-coordinate.
-     */
-    float y;
-
-    /**
-     * The z-coordinate.
-     */
-    float z;
-
-    /**
-     * The w-coordinate.
-     */
-    float w;
-
-    /**
-     * Constructs a new vector initialized to all zeros.
-     */
-    Vector4();
-
-    /**
-     * Constructs a new vector initialized to the specified values.
-     *
-     * @param x The x coordinate.
-     * @param y The y coordinate.
-     * @param z The z coordinate.
-     * @param w The w coordinate.
-     */
-    Vector4(float x, float y, float z, float w);
-
-    /**
-     * Constructs a new vector from the values in the specified array.
-     *
-     * @param array An array containing the elements of the vector in the order x, y, z, w.
-     */
-    Vector4(float* array);
-
-    /**
-     * Constructs a vector that describes the direction between the specified points.
-     *
-     * @param p1 The first point.
-     * @param p2 The second point.
-     */
-    Vector4(const Vector4& p1, const Vector4& p2);
-
-    /**
-     * Constructor.
-     *
-     * Creates a new vector that is a copy of the specified vector.
-     *
-     * @param copy The vector to copy.
-     */
-    Vector4(const Vector4& copy);
-
-    /**
-     * Creates a new vector from an integer interpreted as an RGBA value.
-     * E.g. 0xff0000ff represents opaque red or the vector (1, 0, 0, 1).
-     *
-     * @param color The integer to interpret as an RGBA value.
-     *
-     * @return A vector corresponding to the interpreted RGBA color.
-     */
-    static Vector4 fromColor(unsigned int color);
-
-    /**
-     * Destructor.
-     */
-    ~Vector4();
-
-    /**
-     * Returns the zero vector.
-     *
-     * @return The 4-element vector of 0s.
-     */
-    static const Vector4& zero();
-
-    /**
-     * Returns the one vector.
-     *
-     * @return The 4-element vector of 1s.
-     */
-    static const Vector4& one();
-
-    /**
-     * Returns the unit x vector.
-     *
-     * @return The 4-element unit vector along the x axis.
-     */
-    static const Vector4& unitX();
-
-    /**
-     * Returns the unit y vector.
-     *
-     * @return The 4-element unit vector along the y axis.
-     */
-    static const Vector4& unitY();
-
-    /**
-     * Returns the unit z vector.
-     *
-     * @return The 4-element unit vector along the z axis.
-     */
-    static const Vector4& unitZ();
-
-    /**
-     * Returns the unit w vector.
-     *
-     * @return The 4-element unit vector along the w axis.
-     */
-    static const Vector4& unitW();
-
-    /**
-     * Indicates whether this vector contains all zeros.
-     *
-     * @return true if this vector contains all zeros, false otherwise.
-     */
-    bool isZero() const;
-
-    /**
-     * Indicates whether this vector contains all ones.
-     *
-     * @return true if this vector contains all ones, false otherwise.
-     */
-    bool isOne() const;
-
-    /**
-     * Returns the angle (in radians) between the specified vectors.
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * 
-     * @return The angle between the two vectors (in radians).
-     */
-    static float angle(const Vector4& v1, const Vector4& v2);
-
-    /**
-     * Adds the elements of the specified vector to this one.
-     *
-     * @param v The vector to add.
-     */
-    void add(const Vector4& v);
-
-    /**
-     * Adds the specified vectors and stores the result in dst.
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * @param dst A vector to store the result in.
-     */
-    static void add(const Vector4& v1, const Vector4& v2, Vector4* dst);
-
-    /**
-     * Clamps this vector within the specified range.
-     *
-     * @param min The minimum value.
-     * @param max The maximum value.
-     */
-    void clamp(const Vector4& min, const Vector4& max);
-
-    /**
-     * Clamps the specified vector within the specified range and returns it in dst.
-     *
-     * @param v The vector to clamp.
-     * @param min The minimum value.
-     * @param max The maximum value.
-     * @param dst A vector to store the result in.
-     */
-    static void clamp(const Vector4& v, const Vector4& min, const Vector4& max, Vector4* dst);
-
-    /**
-     * Returns the distance between this vector and v.
-     *
-     * @param v The other vector.
-     * 
-     * @return The distance between this vector and v.
-     * 
-     * @see distanceSquared
-     */
-    float distance(const Vector4& v) const;
-
-    /**
-     * Returns the squared distance between this vector and v.
-     *
-     * When it is not necessary to get the exact distance between
-     * two vectors (for example, when simply comparing the
-     * distance between different vectors), it is advised to use
-     * this method instead of distance.
-     *
-     * @param v The other vector.
-     * 
-     * @return The squared distance between this vector and v.
-     * 
-     * @see distance
-     */
-    float distanceSquared(const Vector4& v) const;
-
-    /**
-     * Returns the dot product of this vector and the specified vector.
-     *
-     * @param v The vector to compute the dot product with.
-     * 
-     * @return The dot product.
-     */
-    float dot(const Vector4& v);
-
-    /**
-     * Returns the dot product between the specified vectors.
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * 
-     * @return The dot product between the vectors.
-     */
-    static float dot(const Vector4& v1, const Vector4& v2);
-
-    /**
-     * Computes the length of this vector.
-     *
-     * @return The length of the vector.
-     * 
-     * @see lengthSquared
-     */
-    float length() const;
-
-    /**
-     * Returns the squared length of this vector.
-     *
-     * When it is not necessary to get the exact length of a
-     * vector (for example, when simply comparing the lengths of
-     * different vectors), it is advised to use this method
-     * instead of length.
-     *
-     * @return The squared length of the vector.
-     * 
-     * @see length
-     */
-    float lengthSquared() const;
-
-    /**
-     * Negates this vector.
-     */
-    void negate();
-
-    /**
-     * Normalizes this vector.
-     *
-     * This method normalizes this Vector4 so that it is of
-     * unit length (in other words, the length of the vector
-     * after calling this method will be 1.0f). If the vector
-     * already has unit length or if the length of the vector
-     * is zero, this method does nothing.
-     */
-    void normalize();
-
-    /**
-     * Normalizes this vector and stores the result in dst.
-     *
-     * If the vector already has unit length or if the length
-     * of the vector is zero, this method simply copies the
-     * current vector into dst.
-     *
-     * @param dst The destination vector.
-     */
-    void normalize(Vector4* dst);
-
-    /**
-     * Scales all elements of this vector by the specified value.
-     *
-     * @param scalar The scalar value.
-     */
-    void scale(float scalar);
-
-    /**
-     * Sets the elements of this vector to the specified values.
-     *
-     * @param x The new x coordinate.
-     * @param y The new y coordinate.
-     * @param z The new z coordinate.
-     * @param w The new w coordinate.
-     */
-    void set(float x, float y, float z, float w);
-
-    /**
-     * Sets the elements of this vector from the values in the specified array.
-     *
-     * @param array An array containing the elements of the vector in the order x, y, z, w.
-     */
-    void set(float* array);
-
-    /**
-     * Sets the elements of this vector to those in the specified vector.
-     *
-     * @param v The vector to copy.
-     */
-    void set(const Vector4& v);
-
-    /**
-     * Sets this vector to the directional vector between the specified points.
-     * 
-     * @param p1 The first point.
-     * @param p2 The second point.
-     */
-    void set(const Vector4& p1, const Vector4& p2);
-
-    /**
-     * Subtracts this vector and the specified vector as (this - v)
-     * and stores the result in this vector.
-     *
-     * @param v The vector to subtract.
-     */
-    void subtract(const Vector4& v);
-
-    /**
-     * Subtracts the specified vectors and stores the result in dst.
-     * The resulting vector is computed as (v1 - v2).
-     *
-     * @param v1 The first vector.
-     * @param v2 The second vector.
-     * @param dst The destination vector.
-     */
-    static void subtract(const Vector4& v1, const Vector4& v2, Vector4* dst);
-
-    /**
-     * Calculates the sum of this vector with the given vector.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @param v The vector to add.
-     * @return The vector sum.
-     */
-    inline Vector4 operator+(const Vector4& v);
-
-    /**
-     * Adds the given vector to this vector.
-     * 
-     * @param v The vector to add.
-     * @return This vector, after the addition occurs.
-     */
-    inline Vector4& operator+=(const Vector4& v);
-
-    /**
-     * Calculates the sum of this vector with the given vector.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @param v The vector to add.
-     * @return The vector sum.
-     */
-    inline Vector4 operator-(const Vector4& v);
-
-    /**
-     * Subtracts the given vector from this vector.
-     * 
-     * @param v The vector to subtract.
-     * @return This vector, after the subtraction occurs.
-     */
-    inline Vector4& operator-=(const Vector4& v);
-
-    /**
-     * Calculates the negation of this vector.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @return The negation of this vector.
-     */
-    inline Vector4 operator-();
-
-    /**
-     * Calculates the scalar product of this vector with the given value.
-     * 
-     * Note: this does not modify this vector.
-     * 
-     * @param x The value to scale by.
-     * @return The scaled vector.
-     */
-    inline Vector4 operator*(float x);
-
-    /**
-     * Scales this vector by the given value.
-     * 
-     * @param x The value to scale by.
-     * @return This vector, after the scale occurs.
-     */
-    inline Vector4& operator*=(float x);
-
-    /**
-     * Determines if this vector is less than the given vector.
-     * 
-     * @param v The vector to compare against.
-     * 
-     * @return True if this vector is less than the given vector, false otherwise.
-     */
-    inline bool operator<(const Vector4& v) const;
-
-    /**
-     * Determines if this vector is equal to the given vector.
-     * 
-     * @param v The vector to compare against.
-     * 
-     * @return True if this vector is equal to the given vector, false otherwise.
-     */
-    inline bool operator==(const Vector4& v) const;
-};
-
-/**
- * Calculates the scalar product of the given vector with the given value.
- * 
- * @param x The value to scale by.
- * @param v The vector to scale.
- * @return The scaled vector.
- */
-inline Vector4 operator*(float x, const Vector4& v);
-
-}
-
-#include "Vector4.inl"
-
-#endif
+#ifndef VECTOR4_H_
+#define VECTOR4_H_
+
+namespace gameplay
+{
+
+class Matrix;
+
+/**
+ * Defines 4-element floating point vector.
+ */
+class Vector4
+{
+public:
+
+    /**
+     * The x-coordinate.
+     */
+    float x;
+
+    /**
+     * The y-coordinate.
+     */
+    float y;
+
+    /**
+     * The z-coordinate.
+     */
+    float z;
+
+    /**
+     * The w-coordinate.
+     */
+    float w;
+
+    /**
+     * Constructs a new vector initialized to all zeros.
+     */
+    Vector4();
+
+    /**
+     * Constructs a new vector initialized to the specified values.
+     *
+     * @param x The x coordinate.
+     * @param y The y coordinate.
+     * @param z The z coordinate.
+     * @param w The w coordinate.
+     */
+    Vector4(float x, float y, float z, float w);
+
+    /**
+     * Constructs a new vector from the values in the specified array.
+     *
+     * @param array An array containing the elements of the vector in the order x, y, z, w.
+     */
+    Vector4(float* array);
+
+    /**
+     * Constructs a vector that describes the direction between the specified points.
+     *
+     * @param p1 The first point.
+     * @param p2 The second point.
+     */
+    Vector4(const Vector4& p1, const Vector4& p2);
+
+    /**
+     * Constructor.
+     *
+     * Creates a new vector that is a copy of the specified vector.
+     *
+     * @param copy The vector to copy.
+     */
+    Vector4(const Vector4& copy);
+
+    /**
+     * Creates a new vector from an integer interpreted as an RGBA value.
+     * E.g. 0xff0000ff represents opaque red or the vector (1, 0, 0, 1).
+     *
+     * @param color The integer to interpret as an RGBA value.
+     *
+     * @return A vector corresponding to the interpreted RGBA color.
+     */
+    static Vector4 fromColor(unsigned int color);
+
+    /**
+     * Destructor.
+     */
+    ~Vector4();
+
+    /**
+     * Returns the zero vector.
+     *
+     * @return The 4-element vector of 0s.
+     */
+    static const Vector4& zero();
+
+    /**
+     * Returns the one vector.
+     *
+     * @return The 4-element vector of 1s.
+     */
+    static const Vector4& one();
+
+    /**
+     * Returns the unit x vector.
+     *
+     * @return The 4-element unit vector along the x axis.
+     */
+    static const Vector4& unitX();
+
+    /**
+     * Returns the unit y vector.
+     *
+     * @return The 4-element unit vector along the y axis.
+     */
+    static const Vector4& unitY();
+
+    /**
+     * Returns the unit z vector.
+     *
+     * @return The 4-element unit vector along the z axis.
+     */
+    static const Vector4& unitZ();
+
+    /**
+     * Returns the unit w vector.
+     *
+     * @return The 4-element unit vector along the w axis.
+     */
+    static const Vector4& unitW();
+
+    /**
+     * Indicates whether this vector contains all zeros.
+     *
+     * @return true if this vector contains all zeros, false otherwise.
+     */
+    bool isZero() const;
+
+    /**
+     * Indicates whether this vector contains all ones.
+     *
+     * @return true if this vector contains all ones, false otherwise.
+     */
+    bool isOne() const;
+
+    /**
+     * Returns the angle (in radians) between the specified vectors.
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * 
+     * @return The angle between the two vectors (in radians).
+     */
+    static float angle(const Vector4& v1, const Vector4& v2);
+
+    /**
+     * Adds the elements of the specified vector to this one.
+     *
+     * @param v The vector to add.
+     */
+    void add(const Vector4& v);
+
+    /**
+     * Adds the specified vectors and stores the result in dst.
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * @param dst A vector to store the result in.
+     */
+    static void add(const Vector4& v1, const Vector4& v2, Vector4* dst);
+
+    /**
+     * Clamps this vector within the specified range.
+     *
+     * @param min The minimum value.
+     * @param max The maximum value.
+     */
+    void clamp(const Vector4& min, const Vector4& max);
+
+    /**
+     * Clamps the specified vector within the specified range and returns it in dst.
+     *
+     * @param v The vector to clamp.
+     * @param min The minimum value.
+     * @param max The maximum value.
+     * @param dst A vector to store the result in.
+     */
+    static void clamp(const Vector4& v, const Vector4& min, const Vector4& max, Vector4* dst);
+
+    /**
+     * Returns the distance between this vector and v.
+     *
+     * @param v The other vector.
+     * 
+     * @return The distance between this vector and v.
+     * 
+     * @see distanceSquared
+     */
+    float distance(const Vector4& v) const;
+
+    /**
+     * Returns the squared distance between this vector and v.
+     *
+     * When it is not necessary to get the exact distance between
+     * two vectors (for example, when simply comparing the
+     * distance between different vectors), it is advised to use
+     * this method instead of distance.
+     *
+     * @param v The other vector.
+     * 
+     * @return The squared distance between this vector and v.
+     * 
+     * @see distance
+     */
+    float distanceSquared(const Vector4& v) const;
+
+    /**
+     * Returns the dot product of this vector and the specified vector.
+     *
+     * @param v The vector to compute the dot product with.
+     * 
+     * @return The dot product.
+     */
+    float dot(const Vector4& v);
+
+    /**
+     * Returns the dot product between the specified vectors.
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * 
+     * @return The dot product between the vectors.
+     */
+    static float dot(const Vector4& v1, const Vector4& v2);
+
+    /**
+     * Computes the length of this vector.
+     *
+     * @return The length of the vector.
+     * 
+     * @see lengthSquared
+     */
+    float length() const;
+
+    /**
+     * Returns the squared length of this vector.
+     *
+     * When it is not necessary to get the exact length of a
+     * vector (for example, when simply comparing the lengths of
+     * different vectors), it is advised to use this method
+     * instead of length.
+     *
+     * @return The squared length of the vector.
+     * 
+     * @see length
+     */
+    float lengthSquared() const;
+
+    /**
+     * Negates this vector.
+     */
+    void negate();
+
+    /**
+     * Normalizes this vector.
+     *
+     * This method normalizes this Vector4 so that it is of
+     * unit length (in other words, the length of the vector
+     * after calling this method will be 1.0f). If the vector
+     * already has unit length or if the length of the vector
+     * is zero, this method does nothing.
+     */
+    void normalize();
+
+    /**
+     * Normalizes this vector and stores the result in dst.
+     *
+     * If the vector already has unit length or if the length
+     * of the vector is zero, this method simply copies the
+     * current vector into dst.
+     *
+     * @param dst The destination vector.
+     */
+    void normalize(Vector4* dst);
+
+    /**
+     * Scales all elements of this vector by the specified value.
+     *
+     * @param scalar The scalar value.
+     */
+    void scale(float scalar);
+
+    /**
+     * Sets the elements of this vector to the specified values.
+     *
+     * @param x The new x coordinate.
+     * @param y The new y coordinate.
+     * @param z The new z coordinate.
+     * @param w The new w coordinate.
+     */
+    void set(float x, float y, float z, float w);
+
+    /**
+     * Sets the elements of this vector from the values in the specified array.
+     *
+     * @param array An array containing the elements of the vector in the order x, y, z, w.
+     */
+    void set(float* array);
+
+    /**
+     * Sets the elements of this vector to those in the specified vector.
+     *
+     * @param v The vector to copy.
+     */
+    void set(const Vector4& v);
+
+    /**
+     * Sets this vector to the directional vector between the specified points.
+     * 
+     * @param p1 The first point.
+     * @param p2 The second point.
+     */
+    void set(const Vector4& p1, const Vector4& p2);
+
+    /**
+     * Subtracts this vector and the specified vector as (this - v)
+     * and stores the result in this vector.
+     *
+     * @param v The vector to subtract.
+     */
+    void subtract(const Vector4& v);
+
+    /**
+     * Subtracts the specified vectors and stores the result in dst.
+     * The resulting vector is computed as (v1 - v2).
+     *
+     * @param v1 The first vector.
+     * @param v2 The second vector.
+     * @param dst The destination vector.
+     */
+    static void subtract(const Vector4& v1, const Vector4& v2, Vector4* dst);
+
+    /**
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
+     */
+    inline Vector4 operator+(const Vector4& v);
+
+    /**
+     * Adds the given vector to this vector.
+     * 
+     * @param v The vector to add.
+     * @return This vector, after the addition occurs.
+     */
+    inline Vector4& operator+=(const Vector4& v);
+
+    /**
+     * Calculates the sum of this vector with the given vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param v The vector to add.
+     * @return The vector sum.
+     */
+    inline Vector4 operator-(const Vector4& v);
+
+    /**
+     * Subtracts the given vector from this vector.
+     * 
+     * @param v The vector to subtract.
+     * @return This vector, after the subtraction occurs.
+     */
+    inline Vector4& operator-=(const Vector4& v);
+
+    /**
+     * Calculates the negation of this vector.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @return The negation of this vector.
+     */
+    inline Vector4 operator-();
+
+    /**
+     * Calculates the scalar product of this vector with the given value.
+     * 
+     * Note: this does not modify this vector.
+     * 
+     * @param x The value to scale by.
+     * @return The scaled vector.
+     */
+    inline Vector4 operator*(float x);
+
+    /**
+     * Scales this vector by the given value.
+     * 
+     * @param x The value to scale by.
+     * @return This vector, after the scale occurs.
+     */
+    inline Vector4& operator*=(float x);
+
+    /**
+     * Determines if this vector is less than the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is less than the given vector, false otherwise.
+     */
+    inline bool operator<(const Vector4& v) const;
+
+    /**
+     * Determines if this vector is equal to the given vector.
+     * 
+     * @param v The vector to compare against.
+     * 
+     * @return True if this vector is equal to the given vector, false otherwise.
+     */
+    inline bool operator==(const Vector4& v) const;
+};
+
+/**
+ * Calculates the scalar product of the given vector with the given value.
+ * 
+ * @param x The value to scale by.
+ * @param v The vector to scale.
+ * @return The scaled vector.
+ */
+inline Vector4 operator*(float x, const Vector4& v);
+
+}
+
+#include "Vector4.inl"
+
+#endif

+ 89 - 89
tools/encoder/src/Vector4.inl

@@ -1,89 +1,89 @@
-/** 
- * Vector4.inl
- */
-
-#include "Matrix.h"
-#include "Vector4.h"
-
-namespace gameplay
-{
-
-inline Vector4 Vector4::operator+(const Vector4& v)
-{
-    Vector4 result(*this);
-    result.add(v);
-    return result;
-}
-
-inline Vector4& Vector4::operator+=(const Vector4& v)
-{
-    add(v);
-    return *this;
-}
-
-inline Vector4 Vector4::operator-(const Vector4& v)
-{
-    Vector4 result(*this);
-    result.subtract(v);
-    return result;
-}
-
-inline Vector4& Vector4::operator-=(const Vector4& v)
-{
-    subtract(v);
-    return *this;
-}
-
-inline Vector4 Vector4::operator-()
-{
-    Vector4 result(*this);
-    result.negate();
-    return result;
-}
-
-inline Vector4 Vector4::operator*(float x)
-{
-    Vector4 result(*this);
-    result.scale(x);
-    return result;
-}
-
-inline Vector4& Vector4::operator*=(float x)
-{
-    scale(x);
-    return *this;
-}
-
-inline bool Vector4::operator<(const Vector4& v) const
-{
-    if (x == v.x)
-    {
-        if (y == v.y)
-        {
-            if (z < v.z)
-            {
-                if (w < v.w)
-                {
-                    return w < v.w;
-                }
-            }
-            return z < v.z;
-        }
-        return y < v.y;
-    }
-    return x < v.x;
-}
-
-inline bool Vector4::operator==(const Vector4& v) const
-{
-    return x==v.x && y==v.y && z==v.z && w==v.w;
-}
-
-inline Vector4 operator*(float x, const Vector4& v)
-{
-    Vector4 result(v);
-    result.scale(x);
-    return result;
-}
-
-}
+/** 
+ * Vector4.inl
+ */
+
+#include "Matrix.h"
+#include "Vector4.h"
+
+namespace gameplay
+{
+
+inline Vector4 Vector4::operator+(const Vector4& v)
+{
+    Vector4 result(*this);
+    result.add(v);
+    return result;
+}
+
+inline Vector4& Vector4::operator+=(const Vector4& v)
+{
+    add(v);
+    return *this;
+}
+
+inline Vector4 Vector4::operator-(const Vector4& v)
+{
+    Vector4 result(*this);
+    result.subtract(v);
+    return result;
+}
+
+inline Vector4& Vector4::operator-=(const Vector4& v)
+{
+    subtract(v);
+    return *this;
+}
+
+inline Vector4 Vector4::operator-()
+{
+    Vector4 result(*this);
+    result.negate();
+    return result;
+}
+
+inline Vector4 Vector4::operator*(float x)
+{
+    Vector4 result(*this);
+    result.scale(x);
+    return result;
+}
+
+inline Vector4& Vector4::operator*=(float x)
+{
+    scale(x);
+    return *this;
+}
+
+inline bool Vector4::operator<(const Vector4& v) const
+{
+    if (x == v.x)
+    {
+        if (y == v.y)
+        {
+            if (z < v.z)
+            {
+                if (w < v.w)
+                {
+                    return w < v.w;
+                }
+            }
+            return z < v.z;
+        }
+        return y < v.y;
+    }
+    return x < v.x;
+}
+
+inline bool Vector4::operator==(const Vector4& v) const
+{
+    return x==v.x && y==v.y && z==v.z && w==v.w;
+}
+
+inline Vector4 operator*(float x, const Vector4& v)
+{
+    Vector4 result(v);
+    result.scale(x);
+    return result;
+}
+
+}

+ 125 - 125
tools/encoder/src/Vertex.cpp

@@ -1,125 +1,125 @@
-#include "Base.h"
-#include "Vertex.h"
-
-namespace gameplay
-{
-
-Vertex::Vertex(void)
-    : hasNormal(false), hasTangent(false), hasBinormal(false), hasDiffuse(false), hasWeights(false)
-{
-    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
-        hasTexCoord[i] = false;
-}
-
-Vertex::~Vertex(void)
-{
-}
-
-unsigned int Vertex::byteSize() const
-{
-    unsigned int count = POSITION_COUNT;
-    if (hasNormal)
-        count += NORMAL_COUNT;
-    if (hasTangent)
-        count += TANGENT_COUNT;
-    if (hasBinormal)
-        count += BINORMAL_COUNT;
-    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
-    {
-        if (hasTexCoord[i])
-            count += TEXCOORD_COUNT;
-    }
-    if (hasWeights)
-        count += BLEND_WEIGHTS_COUNT + BLEND_INDICES_COUNT;
-    if (hasDiffuse)
-        count += DIFFUSE_COUNT;
-    return count * sizeof(float);
-}
-
-void Vertex::writeBinary(FILE* file) const
-{
-    writeVectorBinary(position, file);
-    if (hasNormal)
-    {
-        writeVectorBinary(normal, file);
-    }
-    if (hasTangent)
-    {
-        writeVectorBinary(tangent, file);
-    }
-    if (hasBinormal)
-    {
-        writeVectorBinary(binormal, file);
-    }
-    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
-    {
-        if (hasTexCoord[i])
-        {
-            writeVectorBinary(texCoord[i], file);
-        }
-    }
-    if (hasDiffuse)
-    {
-        writeVectorBinary(diffuse, file);
-    }
-    if (hasWeights)
-    {
-        writeVectorBinary(blendWeights, file);
-        writeVectorBinary(blendIndices, file);
-    }
-}
-
-void Vertex::writeText(FILE* file) const
-{
-    write("// position\n", file);
-    writeVectorText(position, file);
-    if (hasNormal)
-    {
-        write("// normal\n", file);
-        writeVectorText(normal, file);
-    }
-    if (hasTangent)
-    {
-        write("// tanget\n", file);
-        writeVectorText(tangent, file);
-    }
-    if (hasBinormal)
-    {
-        write("// binormal\n", file);
-        writeVectorText(binormal, file);
-    }
-    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
-    {
-        if (hasTexCoord[i])
-        {
-            write("// texCoord\n", file);
-            writeVectorText(texCoord[i], file);
-        }
-    }
-    if (hasDiffuse)
-    {
-        write("// diffuse\n", file);
-        writeVectorText(diffuse, file);
-    }
-    if (hasWeights)
-    {
-        write("// blendWeights\n", file);
-        writeVectorText(blendWeights, file);
-        write("// blendIndices\n", file);
-        writeVectorText(blendIndices, file);
-    }
-}
-
-void Vertex::normalizeBlendWeight()
-{
-    float total = blendWeights.x + blendWeights.y + blendWeights.z + blendWeights.w;
-    if (total > 0.0f)
-    {
-        blendWeights.x = blendWeights.x / total;
-        blendWeights.y = blendWeights.y / total;
-        blendWeights.z = blendWeights.z / total;
-        blendWeights.w = blendWeights.w / total;
-    }   
-}
-
-}
+#include "Base.h"
+#include "Vertex.h"
+
+namespace gameplay
+{
+
+Vertex::Vertex(void)
+    : hasNormal(false), hasTangent(false), hasBinormal(false), hasDiffuse(false), hasWeights(false)
+{
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+        hasTexCoord[i] = false;
+}
+
+Vertex::~Vertex(void)
+{
+}
+
+unsigned int Vertex::byteSize() const
+{
+    unsigned int count = POSITION_COUNT;
+    if (hasNormal)
+        count += NORMAL_COUNT;
+    if (hasTangent)
+        count += TANGENT_COUNT;
+    if (hasBinormal)
+        count += BINORMAL_COUNT;
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+    {
+        if (hasTexCoord[i])
+            count += TEXCOORD_COUNT;
+    }
+    if (hasWeights)
+        count += BLEND_WEIGHTS_COUNT + BLEND_INDICES_COUNT;
+    if (hasDiffuse)
+        count += DIFFUSE_COUNT;
+    return count * sizeof(float);
+}
+
+void Vertex::writeBinary(FILE* file) const
+{
+    writeVectorBinary(position, file);
+    if (hasNormal)
+    {
+        writeVectorBinary(normal, file);
+    }
+    if (hasTangent)
+    {
+        writeVectorBinary(tangent, file);
+    }
+    if (hasBinormal)
+    {
+        writeVectorBinary(binormal, file);
+    }
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+    {
+        if (hasTexCoord[i])
+        {
+            writeVectorBinary(texCoord[i], file);
+        }
+    }
+    if (hasDiffuse)
+    {
+        writeVectorBinary(diffuse, file);
+    }
+    if (hasWeights)
+    {
+        writeVectorBinary(blendWeights, file);
+        writeVectorBinary(blendIndices, file);
+    }
+}
+
+void Vertex::writeText(FILE* file) const
+{
+    write("// position\n", file);
+    writeVectorText(position, file);
+    if (hasNormal)
+    {
+        write("// normal\n", file);
+        writeVectorText(normal, file);
+    }
+    if (hasTangent)
+    {
+        write("// tanget\n", file);
+        writeVectorText(tangent, file);
+    }
+    if (hasBinormal)
+    {
+        write("// binormal\n", file);
+        writeVectorText(binormal, file);
+    }
+    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+    {
+        if (hasTexCoord[i])
+        {
+            write("// texCoord\n", file);
+            writeVectorText(texCoord[i], file);
+        }
+    }
+    if (hasDiffuse)
+    {
+        write("// diffuse\n", file);
+        writeVectorText(diffuse, file);
+    }
+    if (hasWeights)
+    {
+        write("// blendWeights\n", file);
+        writeVectorText(blendWeights, file);
+        write("// blendIndices\n", file);
+        writeVectorText(blendIndices, file);
+    }
+}
+
+void Vertex::normalizeBlendWeight()
+{
+    float total = blendWeights.x + blendWeights.y + blendWeights.z + blendWeights.w;
+    if (total > 0.0f)
+    {
+        blendWeights.x = blendWeights.x / total;
+        blendWeights.y = blendWeights.y / total;
+        blendWeights.z = blendWeights.z / total;
+        blendWeights.w = blendWeights.w / total;
+    }   
+}
+
+}

+ 121 - 121
tools/encoder/src/Vertex.h

@@ -1,121 +1,121 @@
-#ifndef VERTEX_H_
-#define VERTEX_H_
-
-#include "FileIO.h"
-#include "Vector2.h"
-#include "Vector3.h"
-#include "Vector4.h"
-
-// Maximum number of supported UV sets
-#define MAX_UV_SETS 8
-
-namespace gameplay
-{
-
-class Vertex
-{
-public:
-
-    static const unsigned int POSITION_COUNT = 3;
-    static const unsigned int NORMAL_COUNT = 3;
-    static const unsigned int TANGENT_COUNT = 3;
-    static const unsigned int BINORMAL_COUNT = 3;
-    static const unsigned int TEXCOORD_COUNT = 2;
-    static const unsigned int DIFFUSE_COUNT = 4;
-    static const unsigned int BLEND_WEIGHTS_COUNT = 4;
-    static const unsigned int BLEND_INDICES_COUNT = 4;
-
-    /**
-     * Constructor.
-     */
-    Vertex(void);
-
-    /**
-     * Destructor.
-     */
-    ~Vertex(void);
-
-    Vector3 position;
-    Vector3 normal;
-    Vector3 tangent;
-    Vector3 binormal;
-    Vector2 texCoord[MAX_UV_SETS];
-    Vector4 diffuse;
-
-    Vector4 blendWeights;
-    Vector4 blendIndices;
-
-    bool hasNormal, hasTangent, hasBinormal, hasTexCoord[MAX_UV_SETS], hasDiffuse, hasWeights;
-
-    inline bool operator<(const Vertex& v) const
-    {
-        if (position == v.position)
-        {
-            if (normal == v.normal)
-            {
-                if (tangent == v.tangent)
-                {
-                    if (binormal == v.binormal)
-                    {
-                        if (diffuse == v.diffuse)
-                        {
-                            if (blendWeights == v.blendWeights)
-                            {
-                                if (blendIndices == v.blendIndices)
-                                {
-                                    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
-                                    {
-                                        if (!(texCoord[i] == v.texCoord[i]))
-                                            return texCoord[i] < v.texCoord[i];
-                                    }
-                                    return false;
-                                }
-                                return blendIndices < v.blendIndices;
-                            }
-                            return blendWeights < v.blendWeights;
-                        }
-                        return diffuse < v.diffuse;
-                    }
-                    return binormal < v.binormal;
-                }
-                return tangent < v.tangent;
-            }
-            return normal < v.normal;
-        }
-        return position < v.position;
-    }
-
-    inline bool operator==(const Vertex& v) const
-    {
-        for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
-        {
-            if (!(texCoord[i] == v.texCoord[i]))
-                return false;
-        }
-        return position==v.position && normal==v.normal && tangent==v.tangent && binormal==v.binormal &&
-            diffuse==v.diffuse && blendWeights==v.blendWeights && blendIndices==v.blendIndices;
-    }
-
-    /**
-     * Returns the size of this vertex in bytes.
-     */
-    unsigned int byteSize() const;
-
-    /**
-     * Writes this vertex to the binary file stream.
-     */
-    void writeBinary(FILE* file) const;
-
-    /**
-     * Writes this vertex to a text file stream.
-     */
-    void writeText(FILE* file) const;
-
-    /**
-     * Normalizes the blend weights of this vertex so that they add up to 1.0.
-     */
-    void normalizeBlendWeight();
-};
-}
-
-#endif
+#ifndef VERTEX_H_
+#define VERTEX_H_
+
+#include "FileIO.h"
+#include "Vector2.h"
+#include "Vector3.h"
+#include "Vector4.h"
+
+// Maximum number of supported UV sets
+#define MAX_UV_SETS 8
+
+namespace gameplay
+{
+
+class Vertex
+{
+public:
+
+    static const unsigned int POSITION_COUNT = 3;
+    static const unsigned int NORMAL_COUNT = 3;
+    static const unsigned int TANGENT_COUNT = 3;
+    static const unsigned int BINORMAL_COUNT = 3;
+    static const unsigned int TEXCOORD_COUNT = 2;
+    static const unsigned int DIFFUSE_COUNT = 4;
+    static const unsigned int BLEND_WEIGHTS_COUNT = 4;
+    static const unsigned int BLEND_INDICES_COUNT = 4;
+
+    /**
+     * Constructor.
+     */
+    Vertex(void);
+
+    /**
+     * Destructor.
+     */
+    ~Vertex(void);
+
+    Vector3 position;
+    Vector3 normal;
+    Vector3 tangent;
+    Vector3 binormal;
+    Vector2 texCoord[MAX_UV_SETS];
+    Vector4 diffuse;
+
+    Vector4 blendWeights;
+    Vector4 blendIndices;
+
+    bool hasNormal, hasTangent, hasBinormal, hasTexCoord[MAX_UV_SETS], hasDiffuse, hasWeights;
+
+    inline bool operator<(const Vertex& v) const
+    {
+        if (position == v.position)
+        {
+            if (normal == v.normal)
+            {
+                if (tangent == v.tangent)
+                {
+                    if (binormal == v.binormal)
+                    {
+                        if (diffuse == v.diffuse)
+                        {
+                            if (blendWeights == v.blendWeights)
+                            {
+                                if (blendIndices == v.blendIndices)
+                                {
+                                    for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+                                    {
+                                        if (!(texCoord[i] == v.texCoord[i]))
+                                            return texCoord[i] < v.texCoord[i];
+                                    }
+                                    return false;
+                                }
+                                return blendIndices < v.blendIndices;
+                            }
+                            return blendWeights < v.blendWeights;
+                        }
+                        return diffuse < v.diffuse;
+                    }
+                    return binormal < v.binormal;
+                }
+                return tangent < v.tangent;
+            }
+            return normal < v.normal;
+        }
+        return position < v.position;
+    }
+
+    inline bool operator==(const Vertex& v) const
+    {
+        for (unsigned int i = 0; i < MAX_UV_SETS; ++i)
+        {
+            if (!(texCoord[i] == v.texCoord[i]))
+                return false;
+        }
+        return position==v.position && normal==v.normal && tangent==v.tangent && binormal==v.binormal &&
+            diffuse==v.diffuse && blendWeights==v.blendWeights && blendIndices==v.blendIndices;
+    }
+
+    /**
+     * Returns the size of this vertex in bytes.
+     */
+    unsigned int byteSize() const;
+
+    /**
+     * Writes this vertex to the binary file stream.
+     */
+    void writeBinary(FILE* file) const;
+
+    /**
+     * Writes this vertex to a text file stream.
+     */
+    void writeText(FILE* file) const;
+
+    /**
+     * Normalizes the blend weights of this vertex so that they add up to 1.0.
+     */
+    void normalizeBlendWeight();
+};
+}
+
+#endif

+ 76 - 76
tools/encoder/src/VertexElement.cpp

@@ -1,76 +1,76 @@
-#include "Base.h"
-#include "VertexElement.h"
-
-namespace gameplay
-{
-
-VertexElement::VertexElement(unsigned int t, unsigned int c) :
-    usage(t),
-    size(c)
-{
-}
-
-VertexElement::~VertexElement(void)
-{
-}
-const char* VertexElement::getElementName(void) const
-{
-    return "VertexElement";
-}
-
-void VertexElement::writeBinary(FILE* file)
-{
-    Object::writeBinary(file);
-    write(usage, file);
-    write(size, file);
-}
-void VertexElement::writeText(FILE* file)
-{
-    fprintElementStart(file);
-    fprintfElement(file, "usage", usageStr(usage));
-    fprintfElement(file, "size", size);
-    fprintElementEnd(file);
-}
-
-const char* VertexElement::usageStr(unsigned int usage)
-{
-    switch (usage)
-    {
-        case UNKNOWN:
-            return "UNKNOWN";
-        case POSITION:
-            return "POSITION";
-        case NORMAL:
-            return "NORMAL";
-        case COLOR:
-            return "COLOR";
-        case TANGENT:
-            return "TANGENT";
-        case BINORMAL:
-            return "BINORMAL";
-        case BLENDWEIGHTS:
-            return "BLENDWEIGHTS";
-        case BLENDINDICES:
-            return "BLENDINDICES";
-        case TEXCOORD0:
-            return "TEXCOORD0";
-        case TEXCOORD1:
-            return "TEXCOORD1";
-        case TEXCOORD2:
-            return "TEXCOORD2";
-        case TEXCOORD3:
-            return "TEXCOORD3";
-        case TEXCOORD4:
-            return "TEXCOORD4";
-        case TEXCOORD5:
-            return "TEXCOORD5";
-        case TEXCOORD6:
-            return "TEXCOORD6";
-        case TEXCOORD7:
-            return "TEXCOORD7";
-        default:
-            return "";
-    }
-}
-
-}
+#include "Base.h"
+#include "VertexElement.h"
+
+namespace gameplay
+{
+
+VertexElement::VertexElement(unsigned int t, unsigned int c) :
+    usage(t),
+    size(c)
+{
+}
+
+VertexElement::~VertexElement(void)
+{
+}
+const char* VertexElement::getElementName(void) const
+{
+    return "VertexElement";
+}
+
+void VertexElement::writeBinary(FILE* file)
+{
+    Object::writeBinary(file);
+    write(usage, file);
+    write(size, file);
+}
+void VertexElement::writeText(FILE* file)
+{
+    fprintElementStart(file);
+    fprintfElement(file, "usage", usageStr(usage));
+    fprintfElement(file, "size", size);
+    fprintElementEnd(file);
+}
+
+const char* VertexElement::usageStr(unsigned int usage)
+{
+    switch (usage)
+    {
+        case UNKNOWN:
+            return "UNKNOWN";
+        case POSITION:
+            return "POSITION";
+        case NORMAL:
+            return "NORMAL";
+        case COLOR:
+            return "COLOR";
+        case TANGENT:
+            return "TANGENT";
+        case BINORMAL:
+            return "BINORMAL";
+        case BLENDWEIGHTS:
+            return "BLENDWEIGHTS";
+        case BLENDINDICES:
+            return "BLENDINDICES";
+        case TEXCOORD0:
+            return "TEXCOORD0";
+        case TEXCOORD1:
+            return "TEXCOORD1";
+        case TEXCOORD2:
+            return "TEXCOORD2";
+        case TEXCOORD3:
+            return "TEXCOORD3";
+        case TEXCOORD4:
+            return "TEXCOORD4";
+        case TEXCOORD5:
+            return "TEXCOORD5";
+        case TEXCOORD6:
+            return "TEXCOORD6";
+        case TEXCOORD7:
+            return "TEXCOORD7";
+        default:
+            return "";
+    }
+}
+
+}

+ 35 - 35
tools/encoder/src/VertexElement.h

@@ -1,35 +1,35 @@
-#ifndef VERTEXELEMENT_H_
-#define VERTEXELEMENT_H_
-
-#include "Object.h"
-
-namespace gameplay
-{
-
-class VertexElement : public Object
-{
-public:
-
-    /**
-     * Constructor.
-     */
-    VertexElement(unsigned int t, unsigned int c);
-
-    /**
-     * Destructor.
-     */
-    virtual ~VertexElement(void);
-
-    virtual const char* getElementName(void) const;
-    virtual void writeBinary(FILE* file);
-    virtual void writeText(FILE* file);
-
-    static const char* usageStr(unsigned int usage);
-
-    unsigned int usage;
-    unsigned int size;
-};
-
-}
-
-#endif
+#ifndef VERTEXELEMENT_H_
+#define VERTEXELEMENT_H_
+
+#include "Object.h"
+
+namespace gameplay
+{
+
+class VertexElement : public Object
+{
+public:
+
+    /**
+     * Constructor.
+     */
+    VertexElement(unsigned int t, unsigned int c);
+
+    /**
+     * Destructor.
+     */
+    virtual ~VertexElement(void);
+
+    virtual const char* getElementName(void) const;
+    virtual void writeBinary(FILE* file);
+    virtual void writeText(FILE* file);
+
+    static const char* usageStr(unsigned int usage);
+
+    unsigned int usage;
+    unsigned int size;
+};
+
+}
+
+#endif

+ 170 - 170
tools/encoder/src/main.cpp

@@ -1,170 +1,170 @@
-#include "Base.h"
-#include "FBXSceneEncoder.h"
-#include "TTFFontEncoder.h"
-#include "GPBDecoder.h"
-#include "EncoderArguments.h"
-#include "NormalMapGenerator.h"
-#include "Font.h"
-
-using namespace gameplay;
-
-#define FONT_SIZE_DISTANCEFIELD 48
-
-/**
- * Prompts the user for a font size until a valid font size is entered.
- * 
- * @return A valid font size.
- */
-static std::vector<unsigned int> promptUserFontSize()
-{
-    static const int lowerBound = 8;
-    static const int upperBound = 96;
-    std::vector<unsigned int> fontSizes;
-    bool parseError = false;
-    char buffer[4096];
-    do
-    {
-        parseError = false;
-        fontSizes.clear();
-
-        // Prompt for font sizes
-        printf("Enter a comma-separated list of font sizes (pixels) to generate:\n");
-        std::cin.getline(buffer, 4096);
-
-        // Parse comma-separated list of fonts sizes and validate
-        char* ptr = const_cast<char*>(buffer);
-        std::string sizeStr;
-        while (ptr)
-        {
-            char* end = strchr(ptr, ',');
-            if (end)
-            {
-                sizeStr = std::string(ptr, end - ptr);
-                ptr = end + 1;
-            }
-            else
-            {
-                sizeStr = ptr;
-                ptr = NULL;
-            }
-            if (sizeStr.length() > 0)
-            {
-                int size = atoi(sizeStr.c_str());
-                if (size < lowerBound || size > upperBound)
-                {
-                    printf("Invalid font size: %d. Must be between %d-%d.\n", size, lowerBound, upperBound);
-                    parseError = true;
-                    continue;
-                }
-                fontSizes.push_back((unsigned int)size);
-            }
-        }
-    } while (parseError);
-
-    return fontSizes;
-}
-
-
-/**
- * Main application entry point.
- *
- * @param argc The number of command line arguments
- * @param argv The array of command line arguments.
- *
- * usage:   gameplay-encoder[options] <file_list>
- * example: gameplay-encoder C:/assets/duck.fbx
- * example: gameplay-encoder -i boy duck.fbx
- *
- * @stod: Improve argument parsing.
- */
-int main(int argc, const char** argv)
-{
-    EncoderArguments arguments(argc, argv);
-
-    if (arguments.parseErrorOccured())
-    {
-        arguments.printUsage();
-        return 0;
-    }
-
-    // Check if the file exists.
-    if (!arguments.fileExists())
-    {
-        LOG(1, "Error: File not found: %s\n", arguments.getFilePathPointer());
-        return -1;
-    }
-
-    // File exists
-    LOG(1, "Encoding file: %s\n", arguments.getFilePathPointer());
-
-    switch (arguments.getFileFormat())
-    {
-    case EncoderArguments::FILEFORMAT_DAE:
-        {
-            LOG(1, "Error: Collada support has been removed. Convert your DAE file to FBX.\n");
-            return -1;
-        }
-    case EncoderArguments::FILEFORMAT_FBX:
-        {
-            std::string realpath(arguments.getFilePath());
-            FBXSceneEncoder fbxEncoder;
-            fbxEncoder.write(realpath, arguments);
-            break;
-        }
-    case EncoderArguments::FILEFORMAT_TTF:
-        {
-            std::vector<unsigned int> fontSizes = arguments.getFontSizes();
-            
-            Font::FontFormat fontFormat = arguments.getFontFormat();
-            if (fontFormat == Font::BITMAP)
-            {
-                if (fontSizes.size() == 0)
-                {
-                    fontSizes = promptUserFontSize();
-                }
-            }
-            else
-            {
-                // Distance fields use size
-                if (fontSizes.size() == 0)
-                {
-                    fontSizes.push_back(FONT_SIZE_DISTANCEFIELD);
-                }
-            }
-            std::string id = getBaseName(arguments.getFilePath());
-            writeFont(arguments.getFilePath().c_str(), arguments.getOutputFilePath().c_str(), fontSizes, id.c_str(), arguments.fontPreviewEnabled(), fontFormat);
-            break;
-        }
-    case EncoderArguments::FILEFORMAT_GPB:
-        {
-            std::string realpath(arguments.getFilePath());
-            GPBDecoder decoder;
-            decoder.readBinary(realpath);
-            break;
-        }
-    case EncoderArguments::FILEFORMAT_PNG:
-    case EncoderArguments::FILEFORMAT_RAW:
-        {
-            if (arguments.normalMapGeneration())
-            {
-                int x, y;
-                arguments.getHeightmapResolution(&x, &y);
-                NormalMapGenerator generator(arguments.getFilePath().c_str(), arguments.getOutputFilePath().c_str(), x, y, arguments.getHeightmapWorldSize());
-                generator.generate();
-            }
-            else
-            {
-                LOG(1, "Error: Nothing to do for specified file format. Did you forget an option?\n");
-                return -1;
-            }
-            break;
-        }
-   default:
-        {
-            LOG(1, "Error: Unsupported file format: %s\n", arguments.getFilePathPointer());
-            return -1;
-        }
-    }
-
-    return 0;
-}
+#include "Base.h"
+#include "FBXSceneEncoder.h"
+#include "TTFFontEncoder.h"
+#include "GPBDecoder.h"
+#include "EncoderArguments.h"
+#include "NormalMapGenerator.h"
+#include "Font.h"
+
+using namespace gameplay;
+
+#define FONT_SIZE_DISTANCEFIELD 48
+
+/**
+ * Prompts the user for a font size until a valid font size is entered.
+ * 
+ * @return A valid font size.
+ */
+static std::vector<unsigned int> promptUserFontSize()
+{
+    static const int lowerBound = 8;
+    static const int upperBound = 96;
+    std::vector<unsigned int> fontSizes;
+    bool parseError = false;
+    char buffer[4096];
+    do
+    {
+        parseError = false;
+        fontSizes.clear();
+
+        // Prompt for font sizes
+        printf("Enter a comma-separated list of font sizes (pixels) to generate:\n");
+        std::cin.getline(buffer, 4096);
+
+        // Parse comma-separated list of fonts sizes and validate
+        char* ptr = const_cast<char*>(buffer);
+        std::string sizeStr;
+        while (ptr)
+        {
+            char* end = strchr(ptr, ',');
+            if (end)
+            {
+                sizeStr = std::string(ptr, end - ptr);
+                ptr = end + 1;
+            }
+            else
+            {
+                sizeStr = ptr;
+                ptr = NULL;
+            }
+            if (sizeStr.length() > 0)
+            {
+                int size = atoi(sizeStr.c_str());
+                if (size < lowerBound || size > upperBound)
+                {
+                    printf("Invalid font size: %d. Must be between %d-%d.\n", size, lowerBound, upperBound);
+                    parseError = true;
+                    continue;
+                }
+                fontSizes.push_back((unsigned int)size);
+            }
+        }
+    } while (parseError);
+
+    return fontSizes;
+}
+
+
+/**
+ * Main application entry point.
+ *
+ * @param argc The number of command line arguments
+ * @param argv The array of command line arguments.
+ *
+ * usage:   gameplay-encoder[options] <file_list>
+ * example: gameplay-encoder C:/assets/duck.fbx
+ * example: gameplay-encoder -i boy duck.fbx
+ *
+ * @stod: Improve argument parsing.
+ */
+int main(int argc, const char** argv)
+{
+    EncoderArguments arguments(argc, argv);
+
+    if (arguments.parseErrorOccured())
+    {
+        arguments.printUsage();
+        return 0;
+    }
+
+    // Check if the file exists.
+    if (!arguments.fileExists())
+    {
+        LOG(1, "Error: File not found: %s\n", arguments.getFilePathPointer());
+        return -1;
+    }
+
+    // File exists
+    LOG(1, "Encoding file: %s\n", arguments.getFilePathPointer());
+
+    switch (arguments.getFileFormat())
+    {
+    case EncoderArguments::FILEFORMAT_DAE:
+        {
+            LOG(1, "Error: Collada support has been removed. Convert your DAE file to FBX.\n");
+            return -1;
+        }
+    case EncoderArguments::FILEFORMAT_FBX:
+        {
+            std::string realpath(arguments.getFilePath());
+            FBXSceneEncoder fbxEncoder;
+            fbxEncoder.write(realpath, arguments);
+            break;
+        }
+    case EncoderArguments::FILEFORMAT_TTF:
+        {
+            std::vector<unsigned int> fontSizes = arguments.getFontSizes();
+            
+            Font::FontFormat fontFormat = arguments.getFontFormat();
+            if (fontFormat == Font::BITMAP)
+            {
+                if (fontSizes.size() == 0)
+                {
+                    fontSizes = promptUserFontSize();
+                }
+            }
+            else
+            {
+                // Distance fields use size
+                if (fontSizes.size() == 0)
+                {
+                    fontSizes.push_back(FONT_SIZE_DISTANCEFIELD);
+                }
+            }
+            std::string id = getBaseName(arguments.getFilePath());
+            writeFont(arguments.getFilePath().c_str(), arguments.getOutputFilePath().c_str(), fontSizes, id.c_str(), arguments.fontPreviewEnabled(), fontFormat);
+            break;
+        }
+    case EncoderArguments::FILEFORMAT_GPB:
+        {
+            std::string realpath(arguments.getFilePath());
+            GPBDecoder decoder;
+            decoder.readBinary(realpath);
+            break;
+        }
+    case EncoderArguments::FILEFORMAT_PNG:
+    case EncoderArguments::FILEFORMAT_RAW:
+        {
+            if (arguments.normalMapGeneration())
+            {
+                int x, y;
+                arguments.getHeightmapResolution(&x, &y);
+                NormalMapGenerator generator(arguments.getFilePath().c_str(), arguments.getOutputFilePath().c_str(), x, y, arguments.getHeightmapWorldSize());
+                generator.generate();
+            }
+            else
+            {
+                LOG(1, "Error: Nothing to do for specified file format. Did you forget an option?\n");
+                return -1;
+            }
+            break;
+        }
+   default:
+        {
+            LOG(1, "Error: Unsupported file format: %s\n", arguments.getFilePathPointer());
+            return -1;
+        }
+    }
+
+    return 0;
+}

+ 20 - 20
tools/luagen/gameplay-luagen.sln

@@ -1,20 +1,20 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gameplay-luagen", "gameplay-luagen.vcxproj", "{CA137C5D-FDE1-4095-926A-59E8472504BF}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Win32 = Debug|Win32
-		Release|Win32 = Release|Win32
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{CA137C5D-FDE1-4095-926A-59E8472504BF}.Debug|Win32.ActiveCfg = Debug|Win32
-		{CA137C5D-FDE1-4095-926A-59E8472504BF}.Debug|Win32.Build.0 = Debug|Win32
-		{CA137C5D-FDE1-4095-926A-59E8472504BF}.Release|Win32.ActiveCfg = Release|Win32
-		{CA137C5D-FDE1-4095-926A-59E8472504BF}.Release|Win32.Build.0 = Release|Win32
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gameplay-luagen", "gameplay-luagen.vcxproj", "{CA137C5D-FDE1-4095-926A-59E8472504BF}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CA137C5D-FDE1-4095-926A-59E8472504BF}.Debug|Win32.ActiveCfg = Debug|Win32
+		{CA137C5D-FDE1-4095-926A-59E8472504BF}.Debug|Win32.Build.0 = Debug|Win32
+		{CA137C5D-FDE1-4095-926A-59E8472504BF}.Release|Win32.ActiveCfg = Release|Win32
+		{CA137C5D-FDE1-4095-926A-59E8472504BF}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 47 - 47
tools/luagen/gameplay-luagen.vcxproj.filters

@@ -1,48 +1,48 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="src">
-      <UniqueIdentifier>{ff86fc9c-4adf-479c-bcfc-fef8919ed4c1}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="src\ClassBinding.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\DebugNew.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\FunctionBinding.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\Generator.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-    <ClCompile Include="src\main.cpp">
-      <Filter>src</Filter>
-    </ClCompile>
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="src\Base.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\ClassBinding.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\DebugNew.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\EnumBinding.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\FunctionBinding.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\Generator.h">
-      <Filter>src</Filter>
-    </ClInclude>
-    <ClInclude Include="src\TypedefBinding.h">
-      <Filter>src</Filter>
-    </ClInclude>
-  </ItemGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="src">
+      <UniqueIdentifier>{ff86fc9c-4adf-479c-bcfc-fef8919ed4c1}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\ClassBinding.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\DebugNew.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\FunctionBinding.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\Generator.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\main.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="src\Base.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\ClassBinding.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\DebugNew.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\EnumBinding.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\FunctionBinding.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\Generator.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\TypedefBinding.h">
+      <Filter>src</Filter>
+    </ClInclude>
+  </ItemGroup>
 </Project>

+ 12 - 12
tools/luagen/gameplay-luagen.vcxproj.user

@@ -1,13 +1,13 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LocalDebuggerCommandArguments>"$(ProjectDir)xml/" "$(ProjectDir)../../gameplay/src/lua/" gameplay</LocalDebuggerCommandArguments>
-    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
-    <LocalDebuggerCommand>$(TargetPath)</LocalDebuggerCommand>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LocalDebuggerCommandArguments>"$(ProjectDir)xml/" "$(ProjectDir)../../gameplay/src/lua/" gameplay</LocalDebuggerCommandArguments>
-    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
-    <LocalDebuggerCommand>$(TargetPath)</LocalDebuggerCommand>
-  </PropertyGroup>
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LocalDebuggerCommandArguments>"$(ProjectDir)xml/" "$(ProjectDir)../../gameplay/src/lua/" gameplay</LocalDebuggerCommandArguments>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+    <LocalDebuggerCommand>$(TargetPath)</LocalDebuggerCommand>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LocalDebuggerCommandArguments>"$(ProjectDir)xml/" "$(ProjectDir)../../gameplay/src/lua/" gameplay</LocalDebuggerCommandArguments>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+    <LocalDebuggerCommand>$(TargetPath)</LocalDebuggerCommand>
+  </PropertyGroup>
 </Project>

+ 1 - 1
tools/luagen/generate-doxygen-xml.bat

@@ -1,2 +1,2 @@
-del /Q .\xml\*
+del /Q .\xml\*
 doxygen gameplay-luagen.doxyfile

+ 90 - 90
tools/luagen/src/Base.h

@@ -1,91 +1,91 @@
-#include <algorithm>
-#include <cassert>
-#include <fstream>
-#include <iostream>
-#include <sstream>
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-#include <sys/types.h>
-#include <sys/stat.h>
-using namespace std;
-
-#define LUA_GLOBAL_FILENAME "lua_Global"
-#define LUA_ALL_BINDINGS_FILENAME "lua_all_bindings"
-#define LUA_OBJECT "gameplay::ScriptUtil::LuaObject"
-#define SCOPE_REPLACEMENT ""
-#define SCOPE_REPLACEMENT_SIZE strlen(SCOPE_REPLACEMENT)
-#define REF_CLASS_NAME "Ref"
-
-#ifdef WIN32
-#include <windows.h>
-#pragma warning(disable : 4996)
-#pragma warning(disable : 4244)
-#pragma warning(disable : 4345)
-#else
-#include <dirent.h>
-#endif
-
-// Object deletion macro
-#define SAFE_DELETE(x) \
-    { \
-        delete x; \
-        x = NULL; \
-    }
-
-// Array deletion macro
-#define SAFE_DELETE_ARRAY(x) \
-    { \
-        delete[] x; \
-        x = NULL; \
-    }
-
-extern void printError(const char* format, ...);
-
-extern void writeFile(const string& path, const string& text);
-
-extern std::vector<string> generatedFiles;
-
-// Current function macro.
-#ifdef WIN32
-#define __current__func__ __FUNCTION__
-#else
-#define __current__func__ __func__
-#endif
-
-// Assert macros.
-#ifdef _DEBUG
-#define GP_ASSERT(expression) do { \
-    if (!(expression)) \
-    { \
-        printError("%s -- Assertion '" #expression "' failed.\n", __current__func__); \
-        assert(expression); \
-    } } while (0)
-#else
-#define GP_ASSERT(expression)
-#endif
-
-// Error macro.
-#ifdef GP_ERRORS_AS_WARNINGS
-#define GP_ERROR GP_WARN
-#else
-#define GP_ERROR(...) do \
-    { \
-        printError("%s -- ", __current__func__); \
-        printError(__VA_ARGS__); \
-        printError("\n"); \
-        assert(0); \
-        std::exit(-1); \
-    } while (0)
-#endif
-
-// Warning macro.
-#define GP_WARN(...) do \
-    { \
-        printError("%s -- ", __current__func__); \
-        printError(__VA_ARGS__); \
-        printError("\n"); \
-    } while (0)
-
+#include <algorithm>
+#include <cassert>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include <sys/types.h>
+#include <sys/stat.h>
+using namespace std;
+
+#define LUA_GLOBAL_FILENAME "lua_Global"
+#define LUA_ALL_BINDINGS_FILENAME "lua_all_bindings"
+#define LUA_OBJECT "gameplay::ScriptUtil::LuaObject"
+#define SCOPE_REPLACEMENT ""
+#define SCOPE_REPLACEMENT_SIZE strlen(SCOPE_REPLACEMENT)
+#define REF_CLASS_NAME "Ref"
+
+#ifdef WIN32
+#include <windows.h>
+#pragma warning(disable : 4996)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4345)
+#else
+#include <dirent.h>
+#endif
+
+// Object deletion macro
+#define SAFE_DELETE(x) \
+    { \
+        delete x; \
+        x = NULL; \
+    }
+
+// Array deletion macro
+#define SAFE_DELETE_ARRAY(x) \
+    { \
+        delete[] x; \
+        x = NULL; \
+    }
+
+extern void printError(const char* format, ...);
+
+extern void writeFile(const string& path, const string& text);
+
+extern std::vector<string> generatedFiles;
+
+// Current function macro.
+#ifdef WIN32
+#define __current__func__ __FUNCTION__
+#else
+#define __current__func__ __func__
+#endif
+
+// Assert macros.
+#ifdef _DEBUG
+#define GP_ASSERT(expression) do { \
+    if (!(expression)) \
+    { \
+        printError("%s -- Assertion '" #expression "' failed.\n", __current__func__); \
+        assert(expression); \
+    } } while (0)
+#else
+#define GP_ASSERT(expression)
+#endif
+
+// Error macro.
+#ifdef GP_ERRORS_AS_WARNINGS
+#define GP_ERROR GP_WARN
+#else
+#define GP_ERROR(...) do \
+    { \
+        printError("%s -- ", __current__func__); \
+        printError(__VA_ARGS__); \
+        printError("\n"); \
+        assert(0); \
+        std::exit(-1); \
+    } while (0)
+#endif
+
+// Warning macro.
+#define GP_WARN(...) do \
+    { \
+        printError("%s -- ", __current__func__); \
+        printError(__VA_ARGS__); \
+        printError("\n"); \
+    } while (0)
+
 #include "DebugNew.h"

+ 297 - 297
tools/luagen/src/ClassBinding.cpp

@@ -1,298 +1,298 @@
-#include "ClassBinding.h"
-#include "Generator.h"
-
-static void generateInstanceGetter(ostream& o, const string& classname, const string& uniquename)
-{
-    o << "static " << classname << "* getInstance(lua_State* state)\n";
-    o << "{\n";
-    o << "    void* userdata = luaL_checkudata(state, 1, \"" << uniquename << "\");\n";
-    o << "    luaL_argcheck(state, userdata != NULL, 1, \"\'" << uniquename << "\' expected.\");\n";
-    o << "    return (" << classname << "*)((" << LUA_OBJECT << "*)userdata)->instance;\n";
-    o << "}\n\n";
-}
-
-ClassBinding::ClassBinding(string classname, string refId) : classname(classname),
-    refId(refId), inaccessibleConstructor(false), inaccessibleDestructor(false)
-{
-    // Get the class's name and namespace.
-    this->classname = Generator::getInstance()->getClassNameAndNamespace(classname, &ns);
-
-    // Calculate the unique name for the class.
-    uniquename = Generator::getUniqueName(this->classname);
-}
-
-void ClassBinding::write(string dir, const set<string>& includes, string* bindingNS)
-{
-    // Calculate the constructor string.
-    size_t index = uniquename.rfind(SCOPE_REPLACEMENT);
-    string constructorString = "";
-    string* constructorUniqueName = NULL;
-    if (index != uniquename.npos && index != uniquename.length())
-        constructorString += uniquename.substr(index + SCOPE_REPLACEMENT_SIZE);
-    else
-        constructorString += uniquename;
-
-    // Generate a constructor function if there isn't one
-    // and the class doesn't have an inaccessible constructor.
-    FunctionBinding b(classname, uniquename);
-    b.name = constructorString;
-    b.returnParam = FunctionBinding::Param(FunctionBinding::Param::TYPE_CONSTRUCTOR, FunctionBinding::Param::KIND_POINTER, refId);
-    b.type = FunctionBinding::MEMBER_FUNCTION;
-    b.own = true;
-
-    map<string, vector<FunctionBinding> >::iterator iter = bindings.find(b.getFunctionName());
-    if (iter == bindings.end())
-    {
-        if (!inaccessibleConstructor)
-        {
-            bindings[b.getFunctionName()].push_back(b);
-            constructorUniqueName = new string(b.getFunctionName());
-        }
-    }
-    else
-    {
-        constructorUniqueName = new string(iter->second[0].getFunctionName());
-    }
-
-    // Calculate the destructor string.
-    index = uniquename.rfind(SCOPE_REPLACEMENT);
-    string destructorString = "~";
-    string* destructorUniqueName = NULL;
-    if (index != uniquename.npos && index != uniquename.length())
-        destructorString += uniquename.substr(index + SCOPE_REPLACEMENT_SIZE);
-    else
-        destructorString += uniquename;
-
-    // Generate a destructor function if there isn't one
-    // and the class doesn't have an inaccessible destructor
-    // or the class is derived from Ref.
-    b = FunctionBinding(classname, uniquename);
-    b.name = destructorString;
-    b.returnParam = FunctionBinding::Param(FunctionBinding::Param::TYPE_DESTRUCTOR);
-    b.type = FunctionBinding::MEMBER_FUNCTION;
-
-    iter = bindings.find(b.getFunctionName());
-    if (iter == bindings.end())
-    {
-        if (!inaccessibleDestructor || Generator::getInstance()->isRef(classname))
-        {
-            bindings[b.getFunctionName()].push_back(b);
-            destructorUniqueName = new string(b.getFunctionName());
-        }
-    }
-    else
-    {
-        destructorUniqueName = new string(iter->second[0].getFunctionName());
-    }
-
-    // Write out the header.
-    {
-        string path = dir + string("lua_") + uniquename + string(".h");
-        ostringstream o;
-        if (!o)
-        {
-            GP_ERROR("Failed to open file '%s' for generating Lua bindings.", path.c_str());
-            return;
-        }
-
-        string includeGuard = string("lua_") + uniquename + string("_H_");
-        transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
-        o << "#ifndef " << includeGuard << "\n";
-        o << "#define " << includeGuard << "\n\n";
-
-        if (bindingNS)
-        {
-            o << "namespace " << *bindingNS << "\n";
-            o << "{\n\n";
-        }
-
-        o << "// Lua bindings for " << classname << ".\n";
-            
-        // Write out the binding functions declarations.
-        iter = bindings.begin();
-        for (; iter != bindings.end(); iter++)
-        {
-            o << "int " << iter->second[0].getFunctionName() << "(lua_State* state);\n";
-        }
-        o << "\n";
-
-        // Write out the signature of the function used to register the class with Lua.
-        o << "void luaRegister_" << uniquename << "();\n\n";
-
-        if (bindingNS)
-            o << "}\n\n";
-        o << "#endif\n";
-
-        writeFile(path, o.str());
-    }
-
-    // Write out the implementation.
-    {
-        string path = dir + string("lua_") + uniquename + string(".cpp");
-        ostringstream o;
-        if (!o)
-        {
-            GP_ERROR("Failed to open file '%s' for generating Lua bindings.", path.c_str());
-            return;
-        }
-        
-        o << "#include \"Base.h\"\n";
-        o << "#include \"ScriptController.h\"\n";
-        o << "#include \"lua_" << uniquename << ".h\"\n";
-
-        // Ensure we include the original class header, even 
-        // if the list of includes doesn't have it.
-        if (includes.find(include) == includes.end())
-            o << "#include \"" << include << "\"\n";
-
-        for (set<string>::iterator includeIter = includes.begin(); includeIter != includes.end(); includeIter++)
-        {
-            o << "#include \"" << *includeIter << "\"\n";
-        }
-        o << "\n";
-        
-
-        // If the original class is part of a namespace and we aren't generating into that namespace,
-        // include its member with a 'using' statement.
-        if (ns.length() > 0 && (!bindingNS || (*bindingNS != ns)))
-        {
-            o << "using " << ns << ";\n\n";
-        }
-
-        if (bindingNS)
-        {
-            o << "namespace " << *bindingNS << "\n";
-            o << "{\n\n";
-        }
-
-        // Write out the function used to register the class with Lua.
-        o << "void luaRegister_" << uniquename << "()\n";
-        o << "{\n";
-        
-        // Get the member functions ready to bind.
-        iter = bindings.begin();
-        bool hasMembers = false;
-        for (; iter != bindings.end(); iter++)
-        {
-            for (unsigned int i = 0, count = iter->second.size(); i < count; i++)
-            {
-                if (iter->second[i].type == FunctionBinding::MEMBER_FUNCTION ||
-                    iter->second[i].type == FunctionBinding::MEMBER_CONSTANT ||
-                    iter->second[i].type == FunctionBinding::MEMBER_VARIABLE)
-                {
-                    hasMembers = true;
-                    break;
-                }
-            }
-
-            if (hasMembers)
-                break;
-        }
-        if (hasMembers)
-        {
-            o << "    const luaL_Reg lua_members[] = \n";
-            o << "    {\n";
-            iter = bindings.begin();
-            for (; iter != bindings.end(); iter++)
-            {
-                for (unsigned int i = 0, count = iter->second.size(); i < count; i++)
-                {
-                    if ((iter->second[i].type == FunctionBinding::MEMBER_FUNCTION ||
-                        iter->second[i].type == FunctionBinding::MEMBER_CONSTANT ||
-                        iter->second[i].type == FunctionBinding::MEMBER_VARIABLE) &&
-                        iter->second[i].returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR &&
-                        iter->second[i].returnParam.type != FunctionBinding::Param::TYPE_DESTRUCTOR)
-                    {
-                        o << "        {\"" << iter->second[i].name << "\", " << iter->second[i].getFunctionName() << "},\n";
-                        break;
-                    }
-                }
-            }
-            o << "        {NULL, NULL}\n";
-            o << "    };\n";
-        }
-        else
-        {
-            o << "    const luaL_Reg* lua_members = NULL;\n";
-        }
-
-        // Get the static functions ready to bind.
-        iter = bindings.begin();
-        bool hasStatics = false;
-        for (; iter != bindings.end(); iter++)
-        {
-            for (unsigned int i = 0, count = iter->second.size(); i < count; i++)
-            {
-                if (iter->second[i].type == FunctionBinding::STATIC_FUNCTION ||
-                    iter->second[i].type == FunctionBinding::STATIC_CONSTANT ||
-                    iter->second[i].type == FunctionBinding::STATIC_VARIABLE)
-                {
-                    hasStatics = true;
-                    break;
-                }
-            }
-
-            if (hasStatics)
-                break;
-        }
-        if (hasStatics)
-        {
-            o << "    const luaL_Reg lua_statics[] = \n";
-            o << "    {\n";
-            iter = bindings.begin();
-            for (; iter != bindings.end(); iter++)
-            {
-                for (unsigned int i = 0, count = iter->second.size(); i < count; i++)
-                {
-                    if (iter->second[i].type == FunctionBinding::STATIC_FUNCTION ||
-                    iter->second[i].type == FunctionBinding::STATIC_CONSTANT ||
-                    iter->second[i].type == FunctionBinding::STATIC_VARIABLE)
-                    {
-                        o << "        {\"" << iter->second[i].name << "\", " << iter->second[i].getFunctionName() << "},\n";
-                        break;
-                    }
-                }
-            }
-            o << "        {NULL, NULL}\n";
-            o << "    };\n";
-        }
-        else
-        {
-            o << "    const luaL_Reg* lua_statics = NULL;\n";
-        }
-
-        // Output the scope path for the class (used for inner classes).
-        vector<string> scopePath = Generator::getScopePath(classname, ns);
-        o << "    std::vector<std::string> scopePath;\n";
-        for (vector<string>::iterator scopeIter = scopePath.begin(); scopeIter != scopePath.end(); scopeIter++)
-        {
-            o << "    scopePath.push_back(\"" << *scopeIter << "\");\n";
-        }
-
-        // Register the class (its member and static functions and constructor and destructor).
-        o << "\n    gameplay::ScriptUtil::registerClass(\"" << uniquename << "\", lua_members, ";
-        o << ((constructorUniqueName) ? *constructorUniqueName : "NULL") << ", ";
-        o << ((destructorUniqueName) ? *destructorUniqueName : "NULL") << ", ";
-        o << "lua_statics, scopePath);\n";
-        o << "}\n\n";
-
-        // Write out the function used to get the instance for
-        // calling member functions and variables.
-        generateInstanceGetter(o, classname, uniquename);
-
-        // Write out the binding functions.
-        iter = bindings.begin();
-        for (; iter != bindings.end(); iter++)
-        {
-            FunctionBinding::write(o, iter->second);
-        }
-
-        if (bindingNS)
-            o << "}\n";
-
-        writeFile(path, o.str());
-    }
-
-    SAFE_DELETE(constructorUniqueName);
-    SAFE_DELETE(destructorUniqueName);
+#include "ClassBinding.h"
+#include "Generator.h"
+
+static void generateInstanceGetter(ostream& o, const string& classname, const string& uniquename)
+{
+    o << "static " << classname << "* getInstance(lua_State* state)\n";
+    o << "{\n";
+    o << "    void* userdata = luaL_checkudata(state, 1, \"" << uniquename << "\");\n";
+    o << "    luaL_argcheck(state, userdata != NULL, 1, \"\'" << uniquename << "\' expected.\");\n";
+    o << "    return (" << classname << "*)((" << LUA_OBJECT << "*)userdata)->instance;\n";
+    o << "}\n\n";
+}
+
+ClassBinding::ClassBinding(string classname, string refId) : classname(classname),
+    refId(refId), inaccessibleConstructor(false), inaccessibleDestructor(false)
+{
+    // Get the class's name and namespace.
+    this->classname = Generator::getInstance()->getClassNameAndNamespace(classname, &ns);
+
+    // Calculate the unique name for the class.
+    uniquename = Generator::getUniqueName(this->classname);
+}
+
+void ClassBinding::write(string dir, const set<string>& includes, string* bindingNS)
+{
+    // Calculate the constructor string.
+    size_t index = uniquename.rfind(SCOPE_REPLACEMENT);
+    string constructorString = "";
+    string* constructorUniqueName = NULL;
+    if (index != uniquename.npos && index != uniquename.length())
+        constructorString += uniquename.substr(index + SCOPE_REPLACEMENT_SIZE);
+    else
+        constructorString += uniquename;
+
+    // Generate a constructor function if there isn't one
+    // and the class doesn't have an inaccessible constructor.
+    FunctionBinding b(classname, uniquename);
+    b.name = constructorString;
+    b.returnParam = FunctionBinding::Param(FunctionBinding::Param::TYPE_CONSTRUCTOR, FunctionBinding::Param::KIND_POINTER, refId);
+    b.type = FunctionBinding::MEMBER_FUNCTION;
+    b.own = true;
+
+    map<string, vector<FunctionBinding> >::iterator iter = bindings.find(b.getFunctionName());
+    if (iter == bindings.end())
+    {
+        if (!inaccessibleConstructor)
+        {
+            bindings[b.getFunctionName()].push_back(b);
+            constructorUniqueName = new string(b.getFunctionName());
+        }
+    }
+    else
+    {
+        constructorUniqueName = new string(iter->second[0].getFunctionName());
+    }
+
+    // Calculate the destructor string.
+    index = uniquename.rfind(SCOPE_REPLACEMENT);
+    string destructorString = "~";
+    string* destructorUniqueName = NULL;
+    if (index != uniquename.npos && index != uniquename.length())
+        destructorString += uniquename.substr(index + SCOPE_REPLACEMENT_SIZE);
+    else
+        destructorString += uniquename;
+
+    // Generate a destructor function if there isn't one
+    // and the class doesn't have an inaccessible destructor
+    // or the class is derived from Ref.
+    b = FunctionBinding(classname, uniquename);
+    b.name = destructorString;
+    b.returnParam = FunctionBinding::Param(FunctionBinding::Param::TYPE_DESTRUCTOR);
+    b.type = FunctionBinding::MEMBER_FUNCTION;
+
+    iter = bindings.find(b.getFunctionName());
+    if (iter == bindings.end())
+    {
+        if (!inaccessibleDestructor || Generator::getInstance()->isRef(classname))
+        {
+            bindings[b.getFunctionName()].push_back(b);
+            destructorUniqueName = new string(b.getFunctionName());
+        }
+    }
+    else
+    {
+        destructorUniqueName = new string(iter->second[0].getFunctionName());
+    }
+
+    // Write out the header.
+    {
+        string path = dir + string("lua_") + uniquename + string(".h");
+        ostringstream o;
+        if (!o)
+        {
+            GP_ERROR("Failed to open file '%s' for generating Lua bindings.", path.c_str());
+            return;
+        }
+
+        string includeGuard = string("lua_") + uniquename + string("_H_");
+        transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
+        o << "#ifndef " << includeGuard << "\n";
+        o << "#define " << includeGuard << "\n\n";
+
+        if (bindingNS)
+        {
+            o << "namespace " << *bindingNS << "\n";
+            o << "{\n\n";
+        }
+
+        o << "// Lua bindings for " << classname << ".\n";
+            
+        // Write out the binding functions declarations.
+        iter = bindings.begin();
+        for (; iter != bindings.end(); iter++)
+        {
+            o << "int " << iter->second[0].getFunctionName() << "(lua_State* state);\n";
+        }
+        o << "\n";
+
+        // Write out the signature of the function used to register the class with Lua.
+        o << "void luaRegister_" << uniquename << "();\n\n";
+
+        if (bindingNS)
+            o << "}\n\n";
+        o << "#endif\n";
+
+        writeFile(path, o.str());
+    }
+
+    // Write out the implementation.
+    {
+        string path = dir + string("lua_") + uniquename + string(".cpp");
+        ostringstream o;
+        if (!o)
+        {
+            GP_ERROR("Failed to open file '%s' for generating Lua bindings.", path.c_str());
+            return;
+        }
+        
+        o << "#include \"Base.h\"\n";
+        o << "#include \"ScriptController.h\"\n";
+        o << "#include \"lua_" << uniquename << ".h\"\n";
+
+        // Ensure we include the original class header, even 
+        // if the list of includes doesn't have it.
+        if (includes.find(include) == includes.end())
+            o << "#include \"" << include << "\"\n";
+
+        for (set<string>::iterator includeIter = includes.begin(); includeIter != includes.end(); includeIter++)
+        {
+            o << "#include \"" << *includeIter << "\"\n";
+        }
+        o << "\n";
+        
+
+        // If the original class is part of a namespace and we aren't generating into that namespace,
+        // include its member with a 'using' statement.
+        if (ns.length() > 0 && (!bindingNS || (*bindingNS != ns)))
+        {
+            o << "using " << ns << ";\n\n";
+        }
+
+        if (bindingNS)
+        {
+            o << "namespace " << *bindingNS << "\n";
+            o << "{\n\n";
+        }
+
+        // Write out the function used to register the class with Lua.
+        o << "void luaRegister_" << uniquename << "()\n";
+        o << "{\n";
+        
+        // Get the member functions ready to bind.
+        iter = bindings.begin();
+        bool hasMembers = false;
+        for (; iter != bindings.end(); iter++)
+        {
+            for (unsigned int i = 0, count = iter->second.size(); i < count; i++)
+            {
+                if (iter->second[i].type == FunctionBinding::MEMBER_FUNCTION ||
+                    iter->second[i].type == FunctionBinding::MEMBER_CONSTANT ||
+                    iter->second[i].type == FunctionBinding::MEMBER_VARIABLE)
+                {
+                    hasMembers = true;
+                    break;
+                }
+            }
+
+            if (hasMembers)
+                break;
+        }
+        if (hasMembers)
+        {
+            o << "    const luaL_Reg lua_members[] = \n";
+            o << "    {\n";
+            iter = bindings.begin();
+            for (; iter != bindings.end(); iter++)
+            {
+                for (unsigned int i = 0, count = iter->second.size(); i < count; i++)
+                {
+                    if ((iter->second[i].type == FunctionBinding::MEMBER_FUNCTION ||
+                        iter->second[i].type == FunctionBinding::MEMBER_CONSTANT ||
+                        iter->second[i].type == FunctionBinding::MEMBER_VARIABLE) &&
+                        iter->second[i].returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR &&
+                        iter->second[i].returnParam.type != FunctionBinding::Param::TYPE_DESTRUCTOR)
+                    {
+                        o << "        {\"" << iter->second[i].name << "\", " << iter->second[i].getFunctionName() << "},\n";
+                        break;
+                    }
+                }
+            }
+            o << "        {NULL, NULL}\n";
+            o << "    };\n";
+        }
+        else
+        {
+            o << "    const luaL_Reg* lua_members = NULL;\n";
+        }
+
+        // Get the static functions ready to bind.
+        iter = bindings.begin();
+        bool hasStatics = false;
+        for (; iter != bindings.end(); iter++)
+        {
+            for (unsigned int i = 0, count = iter->second.size(); i < count; i++)
+            {
+                if (iter->second[i].type == FunctionBinding::STATIC_FUNCTION ||
+                    iter->second[i].type == FunctionBinding::STATIC_CONSTANT ||
+                    iter->second[i].type == FunctionBinding::STATIC_VARIABLE)
+                {
+                    hasStatics = true;
+                    break;
+                }
+            }
+
+            if (hasStatics)
+                break;
+        }
+        if (hasStatics)
+        {
+            o << "    const luaL_Reg lua_statics[] = \n";
+            o << "    {\n";
+            iter = bindings.begin();
+            for (; iter != bindings.end(); iter++)
+            {
+                for (unsigned int i = 0, count = iter->second.size(); i < count; i++)
+                {
+                    if (iter->second[i].type == FunctionBinding::STATIC_FUNCTION ||
+                    iter->second[i].type == FunctionBinding::STATIC_CONSTANT ||
+                    iter->second[i].type == FunctionBinding::STATIC_VARIABLE)
+                    {
+                        o << "        {\"" << iter->second[i].name << "\", " << iter->second[i].getFunctionName() << "},\n";
+                        break;
+                    }
+                }
+            }
+            o << "        {NULL, NULL}\n";
+            o << "    };\n";
+        }
+        else
+        {
+            o << "    const luaL_Reg* lua_statics = NULL;\n";
+        }
+
+        // Output the scope path for the class (used for inner classes).
+        vector<string> scopePath = Generator::getScopePath(classname, ns);
+        o << "    std::vector<std::string> scopePath;\n";
+        for (vector<string>::iterator scopeIter = scopePath.begin(); scopeIter != scopePath.end(); scopeIter++)
+        {
+            o << "    scopePath.push_back(\"" << *scopeIter << "\");\n";
+        }
+
+        // Register the class (its member and static functions and constructor and destructor).
+        o << "\n    gameplay::ScriptUtil::registerClass(\"" << uniquename << "\", lua_members, ";
+        o << ((constructorUniqueName) ? *constructorUniqueName : "NULL") << ", ";
+        o << ((destructorUniqueName) ? *destructorUniqueName : "NULL") << ", ";
+        o << "lua_statics, scopePath);\n";
+        o << "}\n\n";
+
+        // Write out the function used to get the instance for
+        // calling member functions and variables.
+        generateInstanceGetter(o, classname, uniquename);
+
+        // Write out the binding functions.
+        iter = bindings.begin();
+        for (; iter != bindings.end(); iter++)
+        {
+            FunctionBinding::write(o, iter->second);
+        }
+
+        if (bindingNS)
+            o << "}\n";
+
+        writeFile(path, o.str());
+    }
+
+    SAFE_DELETE(constructorUniqueName);
+    SAFE_DELETE(destructorUniqueName);
 }

+ 51 - 51
tools/luagen/src/ClassBinding.h

@@ -1,51 +1,51 @@
-#ifndef CLASSBINDING_H_
-#define CLASSBINDING_H_
-
-#include "Base.h"
-#include "FunctionBinding.h"
-
-/**
- * Represents the script binding for a class.
- */
-struct ClassBinding
-{
-    /**
-     * Constructor.
-     * 
-     * @param classname The name of the class.
-     * @param refId The reference ID for the class (generated by Doxygen).
-     */
-    ClassBinding(string classname = "", string refId = "");
-
-    /**
-     * Writes out the generated Lua bindings in C++ to the given directory.
-     * 
-     * @param dir The directory to write the bindings files (.h and .cpp) to.
-     * @param includes The includes for the class.
-     * @param bindingNS The namespace to generate the Lua bindings within.
-     */
-    void write(string dir, const set<string>& includes, string* bindingNS = NULL);
-
-    /** Holds all the public function bindings of the class. */
-    map<string, vector<FunctionBinding> > bindings;
-    /** Holds bindings for hidden functions of the class (protected/private). */
-    map<string, vector<FunctionBinding> > hidden;
-    /** Holds the name(s) of the derived class(es). */
-    vector<string> derived;
-    /** Holds the name of the class. */
-    string classname;
-    /** Holds the class's unique name (used only in the script bindings). */
-    string uniquename;
-    /** Holds the class's (Doxygen-generated) reference id. */
-    string refId;
-    /** Holds the needed include for the original class declaration. */
-    string include;
-    /** Holds whether the class has an inaccessible (protected/private) constructor (or has a pure-virtual method). */
-    bool inaccessibleConstructor;
-    /** Holds whether the class has an inaccessible (protected/private) destructor. */
-    bool inaccessibleDestructor;
-    /** Holds the class' namespace (if it has one). */
-    string ns;
-};
-
-#endif
+#ifndef CLASSBINDING_H_
+#define CLASSBINDING_H_
+
+#include "Base.h"
+#include "FunctionBinding.h"
+
+/**
+ * Represents the script binding for a class.
+ */
+struct ClassBinding
+{
+    /**
+     * Constructor.
+     * 
+     * @param classname The name of the class.
+     * @param refId The reference ID for the class (generated by Doxygen).
+     */
+    ClassBinding(string classname = "", string refId = "");
+
+    /**
+     * Writes out the generated Lua bindings in C++ to the given directory.
+     * 
+     * @param dir The directory to write the bindings files (.h and .cpp) to.
+     * @param includes The includes for the class.
+     * @param bindingNS The namespace to generate the Lua bindings within.
+     */
+    void write(string dir, const set<string>& includes, string* bindingNS = NULL);
+
+    /** Holds all the public function bindings of the class. */
+    map<string, vector<FunctionBinding> > bindings;
+    /** Holds bindings for hidden functions of the class (protected/private). */
+    map<string, vector<FunctionBinding> > hidden;
+    /** Holds the name(s) of the derived class(es). */
+    vector<string> derived;
+    /** Holds the name of the class. */
+    string classname;
+    /** Holds the class's unique name (used only in the script bindings). */
+    string uniquename;
+    /** Holds the class's (Doxygen-generated) reference id. */
+    string refId;
+    /** Holds the needed include for the original class declaration. */
+    string include;
+    /** Holds whether the class has an inaccessible (protected/private) constructor (or has a pure-virtual method). */
+    bool inaccessibleConstructor;
+    /** Holds whether the class has an inaccessible (protected/private) destructor. */
+    bool inaccessibleDestructor;
+    /** Holds the class' namespace (if it has one). */
+    string ns;
+};
+
+#endif

+ 302 - 302
tools/luagen/src/DebugNew.cpp

@@ -1,302 +1,302 @@
-#include <new>
-#include <exception>
-#include <cstdio>
-#include <cstdarg>
-
-#ifdef WIN32
-#include <windows.h>
-#include <dbghelp.h>
-#pragma comment(lib,"dbghelp.lib")
-
-#define MAX_STACK_FRAMES 16
-bool __trackStackTrace = false;
-#endif
-
-struct MemoryAllocationRecord
-{
-    unsigned long address;          // address returned to the caller after allocation
-    unsigned int size;              // size of the allocation request
-    const char* file;               // source file of allocation request
-    int line;                       // source line of the allocation request
-    MemoryAllocationRecord* next;
-    MemoryAllocationRecord* prev;
-#ifdef WIN32
-    bool trackStackTrace;
-    unsigned int pc[MAX_STACK_FRAMES];
-#endif
-};
-
-MemoryAllocationRecord* __memoryAllocations = 0;
-int __memoryAllocationCount = 0;
-
-void* debugAlloc(std::size_t size, const char* file, int line);
-void debugFree(void* p);
-
-#ifdef _MSC_VER
-#pragma warning( disable : 4290 )
-#endif
-
-void* operator new (std::size_t size, const char* file, int line)
-{
-    return debugAlloc(size, file, line);
-}
-
-void* operator new[] (std::size_t size, const char* file, int line)
-{
-    return operator new (size, file, line);
-}
-
-void* operator new (std::size_t size) throw(std::bad_alloc)
-{
-    return operator new (size, "", 0);
-}
-
-void* operator new[] (std::size_t size) throw(std::bad_alloc)
-{
-    return operator new (size, "", 0);
-}
-
-void* operator new (std::size_t size, const std::nothrow_t&) throw()
-{
-    return operator new (size, "", 0);
-}
-
-void* operator new[] (std::size_t size, const std::nothrow_t&) throw()
-{
-    return operator new (size, "", 0);
-}
-
-void operator delete (void* p) throw()
-{
-    debugFree(p);
-}
-
-void operator delete[] (void* p) throw()
-{
-    operator delete (p);
-}
-
-void operator delete (void* p, const char* file, int line) throw()
-{
-    operator delete (p);
-}
-
-void operator delete[] (void* p, const char* file, int line) throw()
-{
-    operator delete (p);
-}
-
-#ifdef _MSC_VER
-#pragma warning( default : 4290 )
-#endif
-
-// Include Base.h (needed for logging macros) AFTER new operator impls
-#include "Base.h"
-
-void* debugAlloc(std::size_t size, const char* file, int line)
-{
-    // Allocate memory + size for a MemoryAlloctionRecord
-    unsigned char* mem = (unsigned char*)malloc(size + sizeof(MemoryAllocationRecord));
-
-    MemoryAllocationRecord* rec = (MemoryAllocationRecord*)mem;
-
-    // Move memory pointer past record
-    mem += sizeof(MemoryAllocationRecord);
-
-    rec->address = (unsigned long)mem;
-    rec->size = size;
-    rec->file = file;
-    rec->line = line;
-    rec->next = __memoryAllocations;
-    rec->prev = 0;
-
-    // Capture the stack frame (up to MAX_STACK_FRAMES) if we 
-    // are running on Windows and the user has enabled it.
-#if defined(WIN32)
-    rec->trackStackTrace = __trackStackTrace;
-    if (rec->trackStackTrace)
-    {
-        static bool initialized = false;
-        if (!initialized)
-        {
-            if (!SymInitialize(GetCurrentProcess(), NULL, true))
-                printError("Stack trace tracking will not work.\n");
-            initialized = true;
-        }
-    
-        // Get the current context (state of EBP, EIP, ESP registers).
-        static CONTEXT context;
-        RtlCaptureContext(&context);
-    
-        static STACKFRAME64 stackFrame;
-        memset(&stackFrame, 0, sizeof(STACKFRAME64));
-
-        // Initialize the stack frame based on the machine architecture.
-#ifdef _M_IX86
-        static const DWORD machineType = IMAGE_FILE_MACHINE_I386;
-        stackFrame.AddrPC.Offset = context.Eip;
-        stackFrame.AddrPC.Mode = AddrModeFlat;
-        stackFrame.AddrFrame.Offset = context.Ebp;
-        stackFrame.AddrFrame.Mode = AddrModeFlat;
-        stackFrame.AddrStack.Offset = context.Esp;
-        stackFrame.AddrStack.Mode = AddrModeFlat;
-#else
-#error "Machine architecture not supported!"
-#endif
-
-        // Walk up the stack and store the program counters.
-        memset(rec->pc, 0, sizeof(rec->pc));
-        for (int i = 0; i < MAX_STACK_FRAMES; i++)
-        {
-            rec->pc[i] = stackFrame.AddrPC.Offset;
-            if (!StackWalk64(machineType, GetCurrentProcess(), GetCurrentThread(), &stackFrame,
-                &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
-            {
-                break;
-            }
-        }
-    }
-#endif
-
-    if (__memoryAllocations)
-        __memoryAllocations->prev = rec;
-    __memoryAllocations = rec;
-    ++__memoryAllocationCount;
-
-    return mem;
-}
-
-void debugFree(void* p)
-{
-    if (p == 0)
-        return;
-
-    // Backup passed in pointer to access memory allocation record
-    void* mem = ((unsigned char*)p) - sizeof(MemoryAllocationRecord);
-
-    MemoryAllocationRecord* rec = (MemoryAllocationRecord*)mem;
-
-    // Sanity check: ensure that address in record matches passed in address
-    if (rec->address != (unsigned long)p)
-    {
-        printError("[memory] CORRUPTION: Attempting to free memory address with invalid memory allocation record.\n");
-        return;
-    }
-
-    // Link this item out
-    if (__memoryAllocations == rec)
-        __memoryAllocations = rec->next;
-    if (rec->prev)
-        rec->prev->next = rec->next;
-    if (rec->next)
-        rec->next->prev = rec->prev;
-    --__memoryAllocationCount;
-
-    // Free the address from the original alloc location (before mem allocation record)
-    free(mem);
-}
-
-#ifdef WIN32
-void printStackTrace(MemoryAllocationRecord* rec)
-{
-    const unsigned int bufferSize = 512;
-
-    // Resolve the program counter to the corresponding function names.
-    unsigned int pc;
-    for (int i = 0; i < MAX_STACK_FRAMES; i++)
-    {
-        // Check to see if we are at the end of the stack trace.
-        pc = rec->pc[i];
-        if (pc == 0)
-            break;
-
-        // Get the function name.
-        unsigned char buffer[sizeof(IMAGEHLP_SYMBOL64) + bufferSize];
-        IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)buffer;
-        DWORD64 displacement;
-        memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + bufferSize);
-        symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
-        symbol->MaxNameLength = bufferSize;
-        if (!SymGetSymFromAddr64(GetCurrentProcess(), pc, &displacement, symbol))
-        {
-            printError("[memory] STACK TRACE: <unknown location>\n");
-        }
-        else
-        {
-            symbol->Name[bufferSize - 1] = '\0';
-
-            // Check if we need to go further up the stack.
-            if (strncmp(symbol->Name, "operator new", 12) == 0)
-            {
-                // In operator new or new[], keep going...
-            }
-            else
-            {
-                // Get the file and line number.
-                if (pc != 0)
-                {
-                    IMAGEHLP_LINE64 line;
-                    DWORD displacement;
-                    memset(&line, 0, sizeof(line));
-                    line.SizeOfStruct = sizeof(line);
-                    if (!SymGetLineFromAddr64(GetCurrentProcess(), pc, &displacement, &line))
-                    {
-                        printError("[memory] STACK TRACE: %s - <unknown file>:<unknown line number>\n", symbol->Name);
-                    }
-                    else
-                    {
-                        const char* file = strrchr(line.FileName, '\\');
-                        if(!file) 
-                            file = line.FileName;
-                        else
-                            file++;
-                        
-                        printError("[memory] STACK TRACE: %s - %s:%d\n", symbol->Name, file, line.LineNumber);
-                    }
-                }
-            }
-        }
-    }
-}
-#endif
-
-extern void printMemoryLeaks()
-{
-    // Dump general heap memory leaks
-    if (__memoryAllocationCount == 0)
-    {
-        printError("[memory] All HEAP allocations successfully cleaned up (no leaks detected).\n");
-    }
-    else
-    {
-        printError("[memory] WARNING: %d HEAP allocations still active in memory.\n", __memoryAllocationCount);
-        MemoryAllocationRecord* rec = __memoryAllocations;
-        while (rec)
-        {
-#ifdef WIN32
-            if (rec->trackStackTrace)
-            {
-                printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d:\n", rec->address, rec->size);
-                printStackTrace(rec);
-            }
-            else
-                printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d from line %d in file '%s'.\n", rec->address, rec->size, rec->line, rec->file);
-#else
-                printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d from line %d in file '%s'.\n", rec->address, rec->size, rec->line, rec->file);
-#endif
-            rec = rec->next;
-        }
-    }
-}
-
-#if defined(WIN32)
-void setTrackStackTrace(bool trackStackTrace)
-{
-    __trackStackTrace = trackStackTrace;
-}
-
-void toggleTrackStackTrace()
-{
-    __trackStackTrace = !__trackStackTrace;
-}
-#endif
+#include <new>
+#include <exception>
+#include <cstdio>
+#include <cstdarg>
+
+#ifdef WIN32
+#include <windows.h>
+#include <dbghelp.h>
+#pragma comment(lib,"dbghelp.lib")
+
+#define MAX_STACK_FRAMES 16
+bool __trackStackTrace = false;
+#endif
+
+struct MemoryAllocationRecord
+{
+    unsigned long address;          // address returned to the caller after allocation
+    unsigned int size;              // size of the allocation request
+    const char* file;               // source file of allocation request
+    int line;                       // source line of the allocation request
+    MemoryAllocationRecord* next;
+    MemoryAllocationRecord* prev;
+#ifdef WIN32
+    bool trackStackTrace;
+    unsigned int pc[MAX_STACK_FRAMES];
+#endif
+};
+
+MemoryAllocationRecord* __memoryAllocations = 0;
+int __memoryAllocationCount = 0;
+
+void* debugAlloc(std::size_t size, const char* file, int line);
+void debugFree(void* p);
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4290 )
+#endif
+
+void* operator new (std::size_t size, const char* file, int line)
+{
+    return debugAlloc(size, file, line);
+}
+
+void* operator new[] (std::size_t size, const char* file, int line)
+{
+    return operator new (size, file, line);
+}
+
+void* operator new (std::size_t size) throw(std::bad_alloc)
+{
+    return operator new (size, "", 0);
+}
+
+void* operator new[] (std::size_t size) throw(std::bad_alloc)
+{
+    return operator new (size, "", 0);
+}
+
+void* operator new (std::size_t size, const std::nothrow_t&) throw()
+{
+    return operator new (size, "", 0);
+}
+
+void* operator new[] (std::size_t size, const std::nothrow_t&) throw()
+{
+    return operator new (size, "", 0);
+}
+
+void operator delete (void* p) throw()
+{
+    debugFree(p);
+}
+
+void operator delete[] (void* p) throw()
+{
+    operator delete (p);
+}
+
+void operator delete (void* p, const char* file, int line) throw()
+{
+    operator delete (p);
+}
+
+void operator delete[] (void* p, const char* file, int line) throw()
+{
+    operator delete (p);
+}
+
+#ifdef _MSC_VER
+#pragma warning( default : 4290 )
+#endif
+
+// Include Base.h (needed for logging macros) AFTER new operator impls
+#include "Base.h"
+
+void* debugAlloc(std::size_t size, const char* file, int line)
+{
+    // Allocate memory + size for a MemoryAlloctionRecord
+    unsigned char* mem = (unsigned char*)malloc(size + sizeof(MemoryAllocationRecord));
+
+    MemoryAllocationRecord* rec = (MemoryAllocationRecord*)mem;
+
+    // Move memory pointer past record
+    mem += sizeof(MemoryAllocationRecord);
+
+    rec->address = (unsigned long)mem;
+    rec->size = size;
+    rec->file = file;
+    rec->line = line;
+    rec->next = __memoryAllocations;
+    rec->prev = 0;
+
+    // Capture the stack frame (up to MAX_STACK_FRAMES) if we 
+    // are running on Windows and the user has enabled it.
+#if defined(WIN32)
+    rec->trackStackTrace = __trackStackTrace;
+    if (rec->trackStackTrace)
+    {
+        static bool initialized = false;
+        if (!initialized)
+        {
+            if (!SymInitialize(GetCurrentProcess(), NULL, true))
+                printError("Stack trace tracking will not work.\n");
+            initialized = true;
+        }
+    
+        // Get the current context (state of EBP, EIP, ESP registers).
+        static CONTEXT context;
+        RtlCaptureContext(&context);
+    
+        static STACKFRAME64 stackFrame;
+        memset(&stackFrame, 0, sizeof(STACKFRAME64));
+
+        // Initialize the stack frame based on the machine architecture.
+#ifdef _M_IX86
+        static const DWORD machineType = IMAGE_FILE_MACHINE_I386;
+        stackFrame.AddrPC.Offset = context.Eip;
+        stackFrame.AddrPC.Mode = AddrModeFlat;
+        stackFrame.AddrFrame.Offset = context.Ebp;
+        stackFrame.AddrFrame.Mode = AddrModeFlat;
+        stackFrame.AddrStack.Offset = context.Esp;
+        stackFrame.AddrStack.Mode = AddrModeFlat;
+#else
+#error "Machine architecture not supported!"
+#endif
+
+        // Walk up the stack and store the program counters.
+        memset(rec->pc, 0, sizeof(rec->pc));
+        for (int i = 0; i < MAX_STACK_FRAMES; i++)
+        {
+            rec->pc[i] = stackFrame.AddrPC.Offset;
+            if (!StackWalk64(machineType, GetCurrentProcess(), GetCurrentThread(), &stackFrame,
+                &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
+            {
+                break;
+            }
+        }
+    }
+#endif
+
+    if (__memoryAllocations)
+        __memoryAllocations->prev = rec;
+    __memoryAllocations = rec;
+    ++__memoryAllocationCount;
+
+    return mem;
+}
+
+void debugFree(void* p)
+{
+    if (p == 0)
+        return;
+
+    // Backup passed in pointer to access memory allocation record
+    void* mem = ((unsigned char*)p) - sizeof(MemoryAllocationRecord);
+
+    MemoryAllocationRecord* rec = (MemoryAllocationRecord*)mem;
+
+    // Sanity check: ensure that address in record matches passed in address
+    if (rec->address != (unsigned long)p)
+    {
+        printError("[memory] CORRUPTION: Attempting to free memory address with invalid memory allocation record.\n");
+        return;
+    }
+
+    // Link this item out
+    if (__memoryAllocations == rec)
+        __memoryAllocations = rec->next;
+    if (rec->prev)
+        rec->prev->next = rec->next;
+    if (rec->next)
+        rec->next->prev = rec->prev;
+    --__memoryAllocationCount;
+
+    // Free the address from the original alloc location (before mem allocation record)
+    free(mem);
+}
+
+#ifdef WIN32
+void printStackTrace(MemoryAllocationRecord* rec)
+{
+    const unsigned int bufferSize = 512;
+
+    // Resolve the program counter to the corresponding function names.
+    unsigned int pc;
+    for (int i = 0; i < MAX_STACK_FRAMES; i++)
+    {
+        // Check to see if we are at the end of the stack trace.
+        pc = rec->pc[i];
+        if (pc == 0)
+            break;
+
+        // Get the function name.
+        unsigned char buffer[sizeof(IMAGEHLP_SYMBOL64) + bufferSize];
+        IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)buffer;
+        DWORD64 displacement;
+        memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + bufferSize);
+        symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+        symbol->MaxNameLength = bufferSize;
+        if (!SymGetSymFromAddr64(GetCurrentProcess(), pc, &displacement, symbol))
+        {
+            printError("[memory] STACK TRACE: <unknown location>\n");
+        }
+        else
+        {
+            symbol->Name[bufferSize - 1] = '\0';
+
+            // Check if we need to go further up the stack.
+            if (strncmp(symbol->Name, "operator new", 12) == 0)
+            {
+                // In operator new or new[], keep going...
+            }
+            else
+            {
+                // Get the file and line number.
+                if (pc != 0)
+                {
+                    IMAGEHLP_LINE64 line;
+                    DWORD displacement;
+                    memset(&line, 0, sizeof(line));
+                    line.SizeOfStruct = sizeof(line);
+                    if (!SymGetLineFromAddr64(GetCurrentProcess(), pc, &displacement, &line))
+                    {
+                        printError("[memory] STACK TRACE: %s - <unknown file>:<unknown line number>\n", symbol->Name);
+                    }
+                    else
+                    {
+                        const char* file = strrchr(line.FileName, '\\');
+                        if(!file) 
+                            file = line.FileName;
+                        else
+                            file++;
+                        
+                        printError("[memory] STACK TRACE: %s - %s:%d\n", symbol->Name, file, line.LineNumber);
+                    }
+                }
+            }
+        }
+    }
+}
+#endif
+
+extern void printMemoryLeaks()
+{
+    // Dump general heap memory leaks
+    if (__memoryAllocationCount == 0)
+    {
+        printError("[memory] All HEAP allocations successfully cleaned up (no leaks detected).\n");
+    }
+    else
+    {
+        printError("[memory] WARNING: %d HEAP allocations still active in memory.\n", __memoryAllocationCount);
+        MemoryAllocationRecord* rec = __memoryAllocations;
+        while (rec)
+        {
+#ifdef WIN32
+            if (rec->trackStackTrace)
+            {
+                printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d:\n", rec->address, rec->size);
+                printStackTrace(rec);
+            }
+            else
+                printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d from line %d in file '%s'.\n", rec->address, rec->size, rec->line, rec->file);
+#else
+                printError("[memory] LEAK: HEAP allocation leak at address %#x of size %d from line %d in file '%s'.\n", rec->address, rec->size, rec->line, rec->file);
+#endif
+            rec = rec->next;
+        }
+    }
+}
+
+#if defined(WIN32)
+void setTrackStackTrace(bool trackStackTrace)
+{
+    __trackStackTrace = trackStackTrace;
+}
+
+void toggleTrackStackTrace()
+{
+    __trackStackTrace = !__trackStackTrace;
+}
+#endif

+ 50 - 50
tools/luagen/src/DebugNew.h

@@ -1,50 +1,50 @@
-#ifndef DEBUGNEW_H_
-#define DEBUGNEW_H_
-
-#include <new>
-#include <exception>
-
-#define TRACK_MEMORY() \
-    static struct MemoryTrackerClass { ~MemoryTrackerClass() { printMemoryLeaks(); system("pause"); } } m
-
-// Prints all heap and reference leaks to stderr.
-extern void printMemoryLeaks();
-
-// global new/delete operator overloads
-#ifdef _MSC_VER
-#pragma warning( disable : 4290 ) // C++ exception specification ignored.
-#endif
-void* operator new (std::size_t size, const char* file, int line);
-void* operator new[] (std::size_t size, const char* file, int line);
-void* operator new (std::size_t size) throw(std::bad_alloc);
-void* operator new[] (std::size_t size) throw(std::bad_alloc);
-void* operator new (std::size_t size, const std::nothrow_t&) throw();
-void* operator new[] (std::size_t size, const std::nothrow_t&) throw();
-void operator delete (void* p) throw();
-void operator delete[] (void* p) throw();
-void operator delete (void* p, const char* file, int line) throw();
-void operator delete[] (void* p, const char* file, int line) throw();
-#ifdef _MSC_VER
-#pragma warning( default : 4290 )
-#endif
-
-// Re-define new to use versions with file and line number
-#define DEBUG_NEW new (__FILE__, __LINE__)
-#define new DEBUG_NEW
-
-#endif
-
-#if defined(WIN32)
-
-/**
- * Sets whether stack traces are tracked on memory allocations or not.
- * 
- * @param trackStackTrace Whether to track the stack trace on memory allocations.
- */
-void setTrackStackTrace(bool trackStackTrace);
-
-/**
- * Toggles stack trace tracking on memory allocations.
- */
-void toggleTrackStackTrace();
-#endif
+#ifndef DEBUGNEW_H_
+#define DEBUGNEW_H_
+
+#include <new>
+#include <exception>
+
+#define TRACK_MEMORY() \
+    static struct MemoryTrackerClass { ~MemoryTrackerClass() { printMemoryLeaks(); system("pause"); } } m
+
+// Prints all heap and reference leaks to stderr.
+extern void printMemoryLeaks();
+
+// global new/delete operator overloads
+#ifdef _MSC_VER
+#pragma warning( disable : 4290 ) // C++ exception specification ignored.
+#endif
+void* operator new (std::size_t size, const char* file, int line);
+void* operator new[] (std::size_t size, const char* file, int line);
+void* operator new (std::size_t size) throw(std::bad_alloc);
+void* operator new[] (std::size_t size) throw(std::bad_alloc);
+void* operator new (std::size_t size, const std::nothrow_t&) throw();
+void* operator new[] (std::size_t size, const std::nothrow_t&) throw();
+void operator delete (void* p) throw();
+void operator delete[] (void* p) throw();
+void operator delete (void* p, const char* file, int line) throw();
+void operator delete[] (void* p, const char* file, int line) throw();
+#ifdef _MSC_VER
+#pragma warning( default : 4290 )
+#endif
+
+// Re-define new to use versions with file and line number
+#define DEBUG_NEW new (__FILE__, __LINE__)
+#define new DEBUG_NEW
+
+#endif
+
+#if defined(WIN32)
+
+/**
+ * Sets whether stack traces are tracked on memory allocations or not.
+ * 
+ * @param trackStackTrace Whether to track the stack trace on memory allocations.
+ */
+void setTrackStackTrace(bool trackStackTrace);
+
+/**
+ * Toggles stack trace tracking on memory allocations.
+ */
+void toggleTrackStackTrace();
+#endif

+ 16 - 16
tools/luagen/src/EnumBinding.h

@@ -1,16 +1,16 @@
-#ifndef ENUMBINDING_H
-#define ENUMBINDING_H
-
-#include "Base.h"
-
-/**
- * Represents a script binding for an enumeration.
- */
-struct EnumBinding
-{
-    vector<string> values;
-    vector<string> scopePath;
-    string include;
-};
-
-#endif
+#ifndef ENUMBINDING_H
+#define ENUMBINDING_H
+
+#include "Base.h"
+
+/**
+ * Represents a script binding for an enumeration.
+ */
+struct EnumBinding
+{
+    vector<string> values;
+    vector<string> scopePath;
+    string include;
+};
+
+#endif

+ 1032 - 1032
tools/luagen/src/FunctionBinding.cpp

@@ -1,1032 +1,1032 @@
-#include "FunctionBinding.h"
-#include "Generator.h"
-
-
-// Helper functions.
-static inline void outputLuaTypeCheckInstance(ostream& o);
-static inline void outputLuaTypeCheck(ostream& o, int index, const FunctionBinding::Param& p = 
-    FunctionBinding::Param(FunctionBinding::Param::TYPE_OBJECT, FunctionBinding::Param::KIND_POINTER));
-static inline void indent(ostream& o, int indentLevel);
-static inline void outputBindingInvocation(ostream& o, const FunctionBinding& b, unsigned int paramCount, unsigned int indentLevel, int numBindings);
-static inline void outputGetParam(ostream& o, const FunctionBinding::Param& p, int i, int indentLevel, bool offsetIndex, int numBindings);
-static inline void outputMatchedBinding(ostream& o, const FunctionBinding& b, unsigned int paramCount, unsigned int indentLevel, int numBindings);
-static inline void outputReturnValue(ostream& o, const FunctionBinding& b, int indentLevel);
-static inline std::string getTypeName(const FunctionBinding::Param& param);
-
-FunctionBinding::Param::Param(FunctionBinding::Param::Type type, Kind kind, const string& info) : 
-    type(type), kind(kind), info(info), hasDefaultValue(false), levelsOfIndirection(0)
-{
-}
-
-bool FunctionBinding::Param::operator==(const Param& p) const
-{
-    return this->type == p.type && this->kind == p.kind && this->info == p.info;
-}
-
-bool FunctionBinding::Param::operator!=(const Param& p) const
-{
-    return !(*this == p);
-}
-
-FunctionBinding::FunctionBinding(string classname, string uniquename) : classname(classname), uniquename(uniquename), name(""), own(false)
-{
-}
-
-string FunctionBinding::getFunctionName() const
-{
-    if (functionName.length() == 0)
-    {
-        functionName = "lua_";
-        functionName += uniquename;
-    
-        if (type == STATIC_FUNCTION ||
-            type == STATIC_CONSTANT ||
-            type == STATIC_VARIABLE)
-            functionName += "_static";
-        functionName += "_";
-
-        if (returnParam.type == Param::TYPE_CONSTRUCTOR)
-            functionName += "_init";
-        else if (returnParam.type == Param::TYPE_DESTRUCTOR)
-            functionName += "_gc";
-        else
-        {
-            size_t i = name.rfind("::");
-            if (i != name.npos)
-                functionName += name.substr(i + 2);
-            else
-                functionName += name;
-        }
-    }
-
-    return functionName;
-}
-
-unsigned int FunctionBinding::getMinParamCount() const
-{
-    for (unsigned int i = 0; i < paramTypes.size(); i++)
-    {
-        if (paramTypes[i].hasDefaultValue)
-            return i;
-    }
-    return paramTypes.size();
-}
-
-void FunctionBinding::write(ostream& o, const vector<FunctionBinding>& bindings)
-{
-    GP_ASSERT(bindings.size() > 0);
-
-    if (bindings[0].getFunctionName() == "lua_AudioListener_static_getInstance")
-    {
-        int i = 0;
-    }
-
-    // Print the function signature.
-    o << "int " << bindings[0].getFunctionName() << "(lua_State* state)\n";
-    o << "{\n";
-
-    if (bindings.size() == 1 && bindings[0].type == FunctionBinding::MEMBER_VARIABLE)
-    {
-        // Validate the parameter count.
-        o << "    // Validate the number of parameters.\n";
-        o << "    if (lua_gettop(state) > 2)\n";
-        o << "    {\n";
-        o << "        lua_pushstring(state, \"Invalid number of parameters (expected 1 or 2).\");\n";
-        o << "        lua_error(state);\n";
-        o << "    }\n\n";
-        
-        // Get or set the member variable depending on the number of parameters.
-        o << "    " << bindings[0].classname << "* instance = getInstance(state);\n";
-        o << "    if (lua_gettop(state) == 2)\n";
-        o << "    {\n";
-        outputGetParam(o, bindings[0].returnParam, 1, 2, false, 1);
-
-        if (bindings[0].returnParam.kind == FunctionBinding::Param::KIND_POINTER &&
-            bindings[0].returnParam.type != FunctionBinding::Param::TYPE_OBJECT &&
-            bindings[0].returnParam.info.size() > 0)
-        {
-            o << "        memcpy(instance->" << bindings[0].name << ", param2, sizeof(";
-            o << FunctionBinding::Param(bindings[0].returnParam.type) << ") * " << bindings[0].returnParam.info << ");\n";
-        }
-        else
-        {
-            o << "        instance->" << bindings[0].name << " = ";
-            if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT &&
-                bindings[0].returnParam.kind != FunctionBinding::Param::KIND_POINTER)
-            {
-                o << "*";
-            }
-            o << "param2;\n";
-        }
-
-        o << "        return 0;\n";
-        o << "    }\n";
-        o << "    else\n";
-        o << "    {\n";
-        
-        // Pass the return value back to Lua.
-        if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT)
-        {
-            switch (bindings[0].returnParam.kind)
-            {
-            case FunctionBinding::Param::KIND_POINTER:
-                o << "        void* returnPtr = (void*)instance->" << bindings[0].name << ";\n";
-                break;
-            case FunctionBinding::Param::KIND_VALUE:
-                o << "        void* returnPtr = (void*)new " << bindings[0].returnParam << "(instance->" << bindings[0].name << ");\n";
-                break;
-            case FunctionBinding::Param::KIND_REFERENCE:
-                o << "        void* returnPtr = (void*)&(instance->" << bindings[0].name << ");\n";
-                break;
-            default:
-                GP_ERROR("Invalid return value kind '%d'.", bindings[0].returnParam.kind);
-                break;
-            }
-        }
-        else
-        {
-            o << "        " << bindings[0].returnParam << " result = instance->" << bindings[0].name << ";\n";
-        }
-        outputReturnValue(o, bindings[0], 2);
-        o << "    }\n";
-        o << "}\n\n";
-    }
-    else if (bindings.size() == 1 && 
-        (bindings[0].type == FunctionBinding::STATIC_VARIABLE ||
-        bindings[0].type == FunctionBinding::GLOBAL_VARIABLE))
-    {
-        // Validate the parameter count.
-        o << "    // Validate the number of parameters.\n";
-        o << "    if (lua_gettop(state) > 1)\n";
-        o << "    {\n";
-        o << "        lua_pushstring(state, \"Invalid number of parameters (expected 0 or 1).\");\n";
-        o << "        lua_error(state);\n";
-        o << "    }\n\n";
-        
-        // Get or set the static variable depending on the number of parameters.
-        o << "    if (lua_gettop(state) == 1)\n";
-        o << "    {\n";
-        outputGetParam(o, bindings[0].returnParam, 0, 2, false, 1);
-
-        if (bindings[0].returnParam.kind == FunctionBinding::Param::KIND_POINTER &&
-            bindings[0].returnParam.type != FunctionBinding::Param::TYPE_OBJECT &&
-            bindings[0].returnParam.info.size() > 0)
-        {
-            o << "        memcpy(";
-            if (bindings[0].classname.size() > 0)
-                o << bindings[0].classname << "::";
-            o << bindings[0].name << ", param1, sizeof(";
-            o << FunctionBinding::Param(bindings[0].returnParam.type) << ") * " << bindings[0].returnParam.info << ");\n";
-        }
-        else
-        {
-            o << "        ";
-            if (bindings[0].classname.size() > 0)
-                o << bindings[0].classname << "::";
-            o << bindings[0].name << " = ";
-            if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT &&
-                bindings[0].returnParam.kind != FunctionBinding::Param::KIND_POINTER)
-            {
-                o << "*";
-            }
-            o << "param1;\n";
-        }
-        o << "        return 0;\n";
-        o << "    }\n";
-        o << "    else\n";
-        o << "    {\n";
-        
-        // Pass the return value back to Lua.
-        if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT)
-        {
-            switch (bindings[0].returnParam.kind)
-            {
-            case FunctionBinding::Param::KIND_POINTER:
-                o << "        void* returnPtr = (void*)";
-                if (bindings[0].classname.size() > 0)
-                    o << bindings[0].classname << "::";
-                o << bindings[0].name << ";\n";
-                break;
-            case FunctionBinding::Param::KIND_VALUE:
-                o << "        void* returnPtr = (void*)new " << bindings[0].returnParam << "(";
-                if (bindings[0].classname.size() > 0)
-                    o << bindings[0].classname << "::";
-                o << bindings[0].name << ");\n";
-                break;
-            case FunctionBinding::Param::KIND_REFERENCE:
-                o << "        void* returnPtr = (void*)&(";
-                if (bindings[0].classname.size() > 0)
-                    o << bindings[0].classname << "::";
-                o << bindings[0].name << ");\n";
-                break;
-            default:
-                GP_ERROR("Invalid return value kind '%d'.", bindings[0].returnParam.kind);
-                break;
-            }
-        }
-        else
-        {
-            o << "        " << bindings[0].returnParam << " result = ";
-            if (bindings[0].classname.size() > 0)
-                o << bindings[0].classname << "::";
-            o << bindings[0].name << ";\n";
-        }
-        outputReturnValue(o, bindings[0], 2);
-        o << "    }\n";
-        o << "}\n\n";
-    }
-    else if (bindings.size() == 1 && bindings[0].type == FunctionBinding::MEMBER_CONSTANT)
-    {
-        // Validate the parameter count.
-        o << "    // Validate the number of parameters.\n";
-        o << "    if (lua_gettop(state) > 1)\n";
-        o << "    {\n";
-        o << "        lua_pushstring(state, \"Invalid number of parameters (expected 1).\");\n";
-        o << "        lua_error(state);\n";
-        o << "    }\n\n";
-        
-        // Pass the return value back to Lua.
-        o << "    " << bindings[0].classname << "* instance = getInstance(state);\n";
-        if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT)
-        {
-            switch (bindings[0].returnParam.kind)
-            {
-            case FunctionBinding::Param::KIND_POINTER:
-                o << "    void* returnPtr = (void*)instance->" << bindings[0].name << ";\n";
-                break;
-            case FunctionBinding::Param::KIND_VALUE:
-                o << "    void* returnPtr = (void*)new " << bindings[0].returnParam << "(instance->" << bindings[0].name << ");\n";
-                break;
-            case FunctionBinding::Param::KIND_REFERENCE:
-                o << "    void* returnPtr = (void*)&(instance->" << bindings[0].name << ");\n";
-                break;
-            default:
-                GP_ERROR("Invalid return value kind '%d'.", bindings[0].returnParam.kind);
-                break;
-            }
-        }
-        else
-        {
-            o << "    " << bindings[0].returnParam << " result = instance->" << bindings[0].name << ";\n";
-        }
-        outputReturnValue(o, bindings[0], 1);
-        o << "}\n\n";
-    }
-    else if (bindings.size() == 1 && 
-        (bindings[0].type == FunctionBinding::STATIC_CONSTANT ||
-        bindings[0].type == FunctionBinding::GLOBAL_CONSTANT))
-    {
-        // Validate the parameter count.
-        o << "    // Validate the number of parameters.\n";
-        o << "    if (lua_gettop(state) > 0)\n";
-        o << "    {\n";
-        o << "        lua_pushstring(state, \"Invalid number of parameters (expected 0).\");\n";
-        o << "        lua_error(state);\n";
-        o << "    }\n\n";
-        
-        // Pass the return value back to Lua.
-        if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT)
-        {
-            switch (bindings[0].returnParam.kind)
-            {
-            case FunctionBinding::Param::KIND_POINTER:
-                o << "    void* returnPtr = (void*)";
-                if (bindings[0].classname.size() > 0)
-                    o << bindings[0].classname << "::";
-                o << bindings[0].name << ";\n";
-                break;
-            case FunctionBinding::Param::KIND_VALUE:
-                o << "    void* returnPtr = (void*)new " << bindings[0].returnParam << "(";
-                if (bindings[0].classname.size() > 0)
-                    o << bindings[0].classname << "::";
-                o << bindings[0].name << ");\n";
-                break;
-            case FunctionBinding::Param::KIND_REFERENCE:
-                o << "    void* returnPtr = (void*)&(";
-                if (bindings[0].classname.size() > 0)
-                    o << bindings[0].classname << "::";
-                o << bindings[0].name << ");\n";
-                break;
-            default:
-                GP_ERROR("Invalid return value kind '%d'.", bindings[0].returnParam.kind);
-                break;
-            }
-        }
-        else
-        {
-            o << "    " << bindings[0].returnParam << " result = ";
-            if (bindings[0].classname.size() > 0)
-                o << bindings[0].classname << "::";
-            o << bindings[0].name << ";\n";
-        }
-        outputReturnValue(o, bindings[0], 1);
-        o << "}\n\n";
-    }
-    else
-    {
-        // Get all valid parameter counts.
-        unsigned int paramCountOffset;
-        map<unsigned int, vector<const FunctionBinding*> > paramCounts;
-        for (unsigned int i = 0, count = bindings.size(); i < count; i++)
-        {
-            unsigned int minParamCount = bindings[i].getMinParamCount();
-            paramCountOffset = (bindings[i].type == FunctionBinding::MEMBER_FUNCTION && bindings[i].returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR) ? 1 : 0;
-            paramCounts[minParamCount + paramCountOffset].push_back(&bindings[i]);
-
-            if (minParamCount < bindings[i].paramTypes.size())
-            {
-                for (unsigned int c = minParamCount + 1; c <= bindings[i].paramTypes.size(); c++)
-                {
-                    paramCounts[c + paramCountOffset].push_back(&bindings[i]);
-                }
-            }
-        }
-        
-        // Get the parameter count.
-        o << "    // Get the number of parameters.\n";
-        o << "    int paramCount = lua_gettop(state);\n\n";
-        
-        // Retrieve all the parameters and attempt to match them to a valid binding,
-        // notifying the user if the number of parameters is invalid.
-        o << "    // Attempt to match the parameters to a valid binding.\n";
-        o << "    switch (paramCount)\n";
-        o << "    {\n";
-        map<unsigned int, vector<const FunctionBinding*> >::iterator iter;
-        unsigned int checkCount = 0;
-        for (iter = paramCounts.begin(); iter != paramCounts.end(); iter++)
-        {
-            o << "        case " << iter->first << ":\n";
-            o << "        {\n";
-
-            for (unsigned int i = 0, count = iter->second.size(); i < count; i++)
-            {
-                // Only indent if there are parameters.
-                if (iter->first > 0)
-                    indent(o, 3);
-
-                outputMatchedBinding(o, *(iter->second[i]), iter->first, 3, bindings.size());
-            }
-
-            // Only print an else clause with error report if there are parameters.
-            if (iter->first > 0)
-            {
-                indent(o, 3);
-                o << "lua_pushstring(state, \"" << bindings[0].getFunctionName();
-                o << " - Failed to match the given parameters to a valid function signature.\");\n";
-                indent(o, 3);
-                o << "lua_error(state);\n";
-            }
-            
-            o << "            break;\n";
-            o << "        }\n";
-        }
-        
-        o << "        default:\n";
-        o << "        {\n";
-        o << "            lua_pushstring(state, \"Invalid number of parameters (expected "; 
-        for (iter = paramCounts.begin(), checkCount = 1; iter != paramCounts.end(); iter++)
-        {
-            if (checkCount == paramCounts.size() && paramCounts.size() > 1)
-                o << " or ";
-            o << iter->first;
-            checkCount++;
-
-            if (checkCount < paramCounts.size())
-                o << ", ";
-        }
-        o << ").\");\n";
-        o << "            lua_error(state);\n";
-        o << "            break;\n";
-        o << "        }\n";
-        o << "    }\n";
-        o << "    return 0;\n";
-        o << "}\n\n";
-    }
-}
-
-bool FunctionBinding::signaturesMatch(const FunctionBinding& b1, const FunctionBinding& b2)
-{
-    if (b1.type == b2.type)
-    {
-        bool namesMatch = b1.name == b2.name;
-
-        // Ignore class qualifiers on member function bindings (to support inherited overloaded bindings).
-        if (b1.type == FunctionBinding::MEMBER_CONSTANT ||
-            b1.type == FunctionBinding::MEMBER_FUNCTION ||
-            b1.type == FunctionBinding::MEMBER_VARIABLE)
-        {
-            string b1name = b1.name;
-            string b2name = b2.name;
-            size_t i = b1name.rfind("::");
-            if (i != b1name.npos)
-                b1name = b1name.substr(i + 2);
-            i = b2name.rfind("::");
-            if (i != b2name.npos)
-                b2name = b2name.substr(i + 2);
-    
-            namesMatch = b1name == b2name;
-        }
-
-        // Check the binding's name, parameter types and return value type.
-        if (namesMatch)
-        {
-            if (b1.paramTypes.size() != b2.paramTypes.size())
-                return false;
-
-            for (unsigned int i = 0, count = b1.paramTypes.size(); i < count; i++)
-            {
-                if (b1.paramTypes[i] != b2.paramTypes[i])
-                    return false;
-            }
-
-            return true;
-        }
-    }
-    return false;
-}
-
-static inline std::string getTypeName(const FunctionBinding::Param& param)
-{
-    switch (param.type)
-    {
-    case FunctionBinding::Param::TYPE_VOID:
-        return "void";
-    case FunctionBinding::Param::TYPE_BOOL:
-        return "bool";
-    case FunctionBinding::Param::TYPE_CHAR:
-        return "char";
-    case FunctionBinding::Param::TYPE_SHORT:
-        return "short";
-    case FunctionBinding::Param::TYPE_INT:
-        return "int";
-    case FunctionBinding::Param::TYPE_LONG:
-        return "long";
-    case FunctionBinding::Param::TYPE_UCHAR:
-        return "unsigned char";
-    case FunctionBinding::Param::TYPE_USHORT:
-        return "unsigned short";
-    case FunctionBinding::Param::TYPE_UINT:
-        return "unsigned int";
-    case FunctionBinding::Param::TYPE_ULONG:
-        return "unsigned long";
-    case FunctionBinding::Param::TYPE_FLOAT:
-        return "float";
-    case FunctionBinding::Param::TYPE_DOUBLE:
-        return "double";
-    case FunctionBinding::Param::TYPE_ENUM:
-        return Generator::getInstance()->getIdentifier(param.info).c_str();
-    case FunctionBinding::Param::TYPE_STRING:
-        if (param.info == "string")
-            return "std::string";
-        else
-            return "const char";
-    case FunctionBinding::Param::TYPE_OBJECT:
-    case FunctionBinding::Param::TYPE_CONSTRUCTOR:
-        return Generator::getInstance()->getIdentifier(param.info).c_str();
-    case FunctionBinding::Param::TYPE_UNRECOGNIZED:
-        return param.info.c_str();
-    case FunctionBinding::Param::TYPE_DESTRUCTOR:
-    default:
-        return "";
-    }
-}
-
-ostream& operator<<(ostream& o, const FunctionBinding::Param& param)
-{
-    o << getTypeName(param);
-
-    if (param.kind == FunctionBinding::Param::KIND_POINTER)
-    {
-        for (int i = 0; i < param.levelsOfIndirection; ++i)
-            o << "*";
-    }
-
-    return o;
-}
-
-// ---------------------------------------------
-// Helper functions
-
-static inline void outputLuaTypeCheckInstance(ostream& o)
-{
-    o << "(lua_type(state, 1) == LUA_TUSERDATA)";
-}
-
-static inline void outputLuaTypeCheck(ostream& o, int index, const FunctionBinding::Param& p)
-{
-    switch (p.type)
-    {
-    case FunctionBinding::Param::TYPE_BOOL:
-        if (p.kind == FunctionBinding::Param::KIND_POINTER) 
-        {
-            o << "(lua_type(state, " << index << ") == LUA_TTABLE || ";
-            o << "lua_type(state, " << index << ") == LUA_TLIGHTUSERDATA)";
-        }
-        else
-        {
-            o << "lua_type(state, " << index << ") == LUA_TBOOLEAN";
-        }
-        break;
-    case FunctionBinding::Param::TYPE_CHAR:
-    case FunctionBinding::Param::TYPE_SHORT:
-    case FunctionBinding::Param::TYPE_INT:
-    case FunctionBinding::Param::TYPE_LONG:
-    case FunctionBinding::Param::TYPE_UCHAR:
-    case FunctionBinding::Param::TYPE_USHORT:
-    case FunctionBinding::Param::TYPE_UINT:
-    case FunctionBinding::Param::TYPE_ULONG:
-    case FunctionBinding::Param::TYPE_FLOAT:
-    case FunctionBinding::Param::TYPE_DOUBLE:
-        if (p.kind == FunctionBinding::Param::KIND_POINTER) 
-        {
-            o << "(lua_type(state, " << index << ") == LUA_TTABLE || ";
-            o << "lua_type(state, " << index << ") == LUA_TLIGHTUSERDATA)";
-        }
-        else
-        {
-            o << "lua_type(state, " << index << ") == LUA_TNUMBER";
-        }
-        break;
-    case FunctionBinding::Param::TYPE_STRING:
-    case FunctionBinding::Param::TYPE_ENUM:
-        o << "(lua_type(state, " << index << ") == LUA_TSTRING || ";
-        o << "lua_type(state, " << index << ") == LUA_TNIL)";
-        break;
-    case FunctionBinding::Param::TYPE_OBJECT:
-        o << "(lua_type(state, " << index << ") == LUA_TUSERDATA || ";
-        if (p.kind == FunctionBinding::Param::KIND_POINTER)
-            o << "lua_type(state, " << index << ") == LUA_TTABLE || ";
-        o << "lua_type(state, " << index << ") == LUA_TNIL)";
-        break;
-    case FunctionBinding::Param::TYPE_CONSTRUCTOR:
-    case FunctionBinding::Param::TYPE_DESTRUCTOR:
-    case FunctionBinding::Param::TYPE_VOID:
-    case FunctionBinding::Param::TYPE_VARARGS:
-    default:
-        o << "lua_type(state, " << index << ") == LUA_TNONE";
-    }
-}
-
-static inline void indent(ostream& o, int indentLevel)
-{
-    for (int k = 0; k < indentLevel; k++)
-        o << "    ";
-}
-
-static inline void outputBindingInvocation(ostream& o, const FunctionBinding& b, unsigned int paramCount, unsigned int indentLevel, int numBindings)
-{
-    bool isNonStatic = (b.type == FunctionBinding::MEMBER_FUNCTION && b.returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR);
-
-    // Get the passed in parameters.
-    for (unsigned int i = 0, count = paramCount - (isNonStatic ? 1 : 0); i < count; i++)
-    {
-        outputGetParam(o, b.paramTypes[i], i, indentLevel, isNonStatic, numBindings);
-    }
-
-    // Get the instance for member functions.
-    if ((b.type == FunctionBinding::MEMBER_FUNCTION) &&
-        b.returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR &&
-        b.returnParam.type != FunctionBinding::Param::TYPE_DESTRUCTOR)
-    {
-        indent(o, indentLevel);
-        o << b.classname << "* instance = getInstance(state);\n";
-    }
-
-    if (b.returnParam.type == FunctionBinding::Param::TYPE_DESTRUCTOR)
-    {
-        indent(o, indentLevel);
-        o << "void* userdata = luaL_checkudata(state, 1, \"" << Generator::getUniqueName(b.classname) << "\");\n";
-        indent(o, indentLevel);
-        o << "luaL_argcheck(state, userdata != NULL, 1, \"\'" << Generator::getUniqueName(b.classname) << "\' expected.\");\n";
-        indent(o, indentLevel);
-        o << LUA_OBJECT << "* object = (" << LUA_OBJECT << "*)userdata;\n";
-        indent(o, indentLevel);
-        o << "if (object->owns)\n";
-        indent(o, indentLevel);
-        o << "{\n";
-        indent(o, indentLevel + 1);
-        o << b.classname << "* instance = (" << b.classname << "*)object->instance;\n";
-        if (Generator::getInstance()->isRef(b.classname))
-        {
-            indent(o, indentLevel + 1);
-            o << "SAFE_RELEASE(instance);\n";
-        }
-        else
-        {
-            indent(o, indentLevel + 1);
-            o << "SAFE_DELETE(instance);\n";
-        }
-        indent(o, indentLevel);
-        o << "}\n";
-    }
-    else
-    {
-        // Create a variable to hold the return type (if appropriate).
-        if (!(b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR || 
-            b.returnParam.type == FunctionBinding::Param::TYPE_VOID || 
-            b.returnParam.type == FunctionBinding::Param::TYPE_OBJECT))
-        {
-            indent(o, indentLevel);
-            o << b.returnParam << " result = ";
-        }
-
-        // For functions that return objects, create the appropriate user data in Lua.
-        if (b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR || b.returnParam.type == FunctionBinding::Param::TYPE_OBJECT)
-        {
-            indent(o, indentLevel);
-            switch (b.returnParam.kind)
-            {
-            case FunctionBinding::Param::KIND_POINTER:
-                o << "void* returnPtr = (void*)";
-                break;
-            case FunctionBinding::Param::KIND_VALUE:
-                o << "void* returnPtr = (void*)new " << b.returnParam << "(";
-                break;
-            case FunctionBinding::Param::KIND_REFERENCE:
-                o << "void* returnPtr = (void*)&(";
-                break;
-            default:
-                GP_ERROR("Invalid return value kind '%d'.", b.returnParam.kind);
-                break;
-            }
-        }
-
-        if (b.type == FunctionBinding::STATIC_FUNCTION)
-        {
-            if (b.returnParam.type == FunctionBinding::Param::TYPE_VOID)
-                indent(o, indentLevel);
-            o << b.classname << "::" << b.name << "(";
-        }
-        else if (b.type == FunctionBinding::GLOBAL_FUNCTION)
-        {
-            if (b.returnParam.type == FunctionBinding::Param::TYPE_VOID)
-                indent(o, indentLevel);
-            o << b.name << "(";
-        }
-        else if (b.type == FunctionBinding::MEMBER_FUNCTION)
-        {
-            if (b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
-            {
-                o << "new " << Generator::getInstance()->getIdentifier(b.returnParam.info) << "(";
-            }
-            else
-            {
-                if (b.returnParam.type == FunctionBinding::Param::TYPE_VOID)
-                    indent(o, indentLevel);
-                o << "instance->" << b.name << "(";
-            }
-        }
-
-        // Pass the arguments.
-        for (unsigned int i = 0, count = paramCount - ((isNonStatic) ? 1 : 0); i < count; i++)
-        {
-            if (b.paramTypes[i].type == FunctionBinding::Param::TYPE_OBJECT && b.paramTypes[i].kind != FunctionBinding::Param::KIND_POINTER)
-                o << "*";
-            o << "param" << i + 1;
-
-            if (i != count - 1)
-                o << ", ";
-        }
-
-        // Output the matching parenthesis for the case where a non-pointer object is being returned.
-        if (b.returnParam.type == FunctionBinding::Param::TYPE_OBJECT && b.returnParam.kind != FunctionBinding::Param::KIND_POINTER)
-            o << ")";
-
-        o << ");\n";
-    }
-
-    outputReturnValue(o, b, indentLevel);
-}
-
-void writeObjectTemplateType(ostream& o, const FunctionBinding::Param& p)
-{
-    o << getTypeName(p);
-    for (int i = 0; i < p.levelsOfIndirection-1; ++i)
-        o << "*";
-}
-
-void writePointerParameter(ostream& o, const char* primitiveType, const FunctionBinding::Param& p, int paramNum, int luaParamIndex, int indentLevel)
-{
-    o << "gameplay::ScriptUtil::LuaArray<";
-    writeObjectTemplateType(o, p);
-    //o << "> param" << paramNum << "Pointer = gameplay::ScriptUtil::get" << primitiveType << "Pointer(" << luaParamIndex << ");\n";
-    o << "> param" << paramNum << " = gameplay::ScriptUtil::get" << primitiveType << "Pointer(" << luaParamIndex << ");\n";
-    //indent(o, indentLevel);
-    //o << p << " param" << paramNum << " = (" << p << ")param" << paramNum << "Pointer;\n";
-}
-
-static inline void outputGetParam(ostream& o, const FunctionBinding::Param& p, int i, int indentLevel, bool offsetIndex, int numBindings)
-{
-    indent(o, indentLevel);
-    o << "// Get parameter " << i + 1 << " off the stack.\n";
-
-    int paramIndex = (offsetIndex) ? i + 2 : i + 1;
-
-    switch (p.type)
-    {
-    case FunctionBinding::Param::TYPE_BOOL:
-        indent(o, indentLevel);
-        if (p.kind == FunctionBinding::Param::KIND_POINTER)
-            writePointerParameter(o, "Bool", p, i+1, paramIndex, indentLevel);
-        else
-            o << p << " param" << i+1 << " = gameplay::ScriptUtil::luaCheckBool(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_CHAR:
-        indent(o, indentLevel);
-        o << p << " param" << i+1 << " = (char)luaL_checkint(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_SHORT:
-        indent(o, indentLevel);
-        if (p.kind == FunctionBinding::Param::KIND_POINTER)
-            writePointerParameter(o, "Short", p, i+1, paramIndex, indentLevel);
-        else
-            o << p << " param" << i+1 << " = (short)luaL_checkint(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_INT:
-        indent(o, indentLevel);
-        if (p.kind == FunctionBinding::Param::KIND_POINTER)
-            writePointerParameter(o, "Int", p, i+1, paramIndex, indentLevel);
-        else
-            o << p << " param" << i+1 << " = (int)luaL_checkint(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_LONG:
-        indent(o, indentLevel);
-        if (p.kind == FunctionBinding::Param::KIND_POINTER)
-            writePointerParameter(o, "Long", p, i+1, paramIndex, indentLevel);
-        else
-            o << p << " param" << i+1 << " = (long)luaL_checklong(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_UCHAR:
-        indent(o, indentLevel);
-        if (p.kind == FunctionBinding::Param::KIND_POINTER)
-            writePointerParameter(o, "UnsignedChar", p, i+1, paramIndex, indentLevel);
-        else
-            o << p << " param" << i+1 << " = (unsigned char)luaL_checkunsigned(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_USHORT:
-        indent(o, indentLevel);
-        if (p.kind == FunctionBinding::Param::KIND_POINTER)
-            writePointerParameter(o, "UnsignedShort", p, i+1, paramIndex, indentLevel);
-        else
-            o << p << " param" << i+1 << " = (unsigned short)luaL_checkunsigned(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_UINT:
-        indent(o, indentLevel);
-        if (p.kind == FunctionBinding::Param::KIND_POINTER)
-            writePointerParameter(o, "UnsignedInt", p, i+1, paramIndex, indentLevel);
-        else
-            o << p << " param" << i+1 << " = (unsigned int)luaL_checkunsigned(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_ULONG:
-        indent(o, indentLevel);
-        if (p.kind == FunctionBinding::Param::KIND_POINTER)
-            writePointerParameter(o, "UnsignedLong", p, i+1, paramIndex, indentLevel);
-        else
-            o << p << " param" << i+1 << " = (unsigned long)luaL_checkunsigned(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_FLOAT:
-        indent(o, indentLevel);
-        if (p.kind == FunctionBinding::Param::KIND_POINTER)
-            writePointerParameter(o, "Float", p, i+1, paramIndex, indentLevel);
-        else
-            o << p << " param" << i+1 << " = (float)luaL_checknumber(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_DOUBLE:
-        indent(o, indentLevel);
-        if (p.kind == FunctionBinding::Param::KIND_POINTER)
-            writePointerParameter(o, "Double", p, i+1, paramIndex, indentLevel);
-        else
-            o << p << " param" << i+1 << " = (double)luaL_checknumber(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_STRING:
-        indent(o, indentLevel);
-        o << p << " param" << i+1 << " = gameplay::ScriptUtil::getString(" << paramIndex << ", " << ((p.info == "string") ? "true" : "false") << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_ENUM:
-        indent(o, indentLevel);
-        o << p << " param" << i+1 << " = (" << p << ")lua_enumFromString_" << Generator::getInstance()->getUniqueNameFromRef(p.info) << "(luaL_checkstring(state, " << paramIndex << "));\n";
-        break;
-    case FunctionBinding::Param::TYPE_UNRECOGNIZED:
-        // Attempt to retrieve the unrecognized type as an unsigned integer.
-        indent(o, indentLevel);
-        o << "GP_WARN(\"Attempting to get parameter " << i + 1 << " with unrecognized type " << p.info << " as an unsigned integer.\");\n";
-        indent(o, indentLevel);
-        o << p << " param" << i+1 << " = (" << p.info << ")luaL_checkunsigned(state, " << paramIndex << ");\n";
-        break;
-    case FunctionBinding::Param::TYPE_OBJECT:
-        {
-            indent(o, indentLevel);
-            o << "bool param" << i + 1 << "Valid;\n";
-            indent(o, indentLevel);
-            o << "gameplay::ScriptUtil::LuaArray<";
-            writeObjectTemplateType(o, p);
-            //o << "> param" << i+1 << "Pointer = gameplay::ScriptUtil::getObjectPointer<";
-            o << "> param" << i+1 << " = gameplay::ScriptUtil::getObjectPointer<";
-            writeObjectTemplateType(o, p);
-            o << ">(" << paramIndex;
-            o << ", \"" << Generator::getInstance()->getUniqueNameFromRef(p.info) << "\", ";
-            o << ((p.kind != FunctionBinding::Param::KIND_POINTER) ? "true" : "false") << ", &param" << i + 1 << "Valid);\n";
-            indent(o, indentLevel);
-            //writeObjectTemplateType(o, p);
-            //o << "* param" << i+1 << " = (";
-            //writeObjectTemplateType(o, p);
-            //o << "*)param" << i+1 << "Pointer;\n";
-            //indent(o, indentLevel);
-            o << "if (!param" << i + 1 << "Valid)\n";
-            if (numBindings > 1)
-            {
-                indent(o, indentLevel + 1);
-                o << "break;\n";
-            }
-            else
-            {
-                indent(o, indentLevel);
-                o << "{\n";
-                indent(o, indentLevel + 1);
-                o << "lua_pushstring(state, \"Failed to convert parameter " << i + 1 << " to type '" << getTypeName(p) << "'.\");\n";
-                indent(o, indentLevel + 1);
-                o << "lua_error(state);\n";
-                indent(o, indentLevel);
-                o << "}\n";
-            }
-        }
-        break;
-    case FunctionBinding::Param::TYPE_CONSTRUCTOR:
-    case FunctionBinding::Param::TYPE_DESTRUCTOR:
-    case FunctionBinding::Param::TYPE_VOID:
-    default:
-        // Ignore these cases.
-        break;
-    }
-
-    o << "\n";
-}
-
-static inline void outputMatchedBinding(ostream& o, const FunctionBinding& b, unsigned int paramCount, unsigned int indentLevel, int numBindings)
-{
-    bool isNonStatic = (b.type == FunctionBinding::MEMBER_FUNCTION && b.returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR);
-
-    // If the current invocation of the function takes zero parameters, then invoke the binding.
-    if (paramCount == 0)
-    {
-        outputBindingInvocation(o, b, paramCount, indentLevel, numBindings);
-    }
-    else
-    {
-        // NOTE: The way this currently works may cause some issues since Lua
-        // has a smaller set of types than C++. There may be cases where functions
-        // that take types with less precision (i.e. int vs. float) are called
-        // when the user in fact wanted to call the version with more precision.
-        // (this will only happen for overloaded functions).
-
-        if (numBindings > 1)
-        {
-            o << "do\n";
-            indent(o, indentLevel);
-            o << "{\n";
-            indent(o, ++indentLevel);
-        }
-
-        o << "if (";
-        for (unsigned int i = 0, count = paramCount; i < count; i++)
-        {
-            if (isNonStatic && i == 0)
-            {
-                // This is always the "this / self" pointer for a member function
-                outputLuaTypeCheckInstance(o);
-            }
-            else
-            {
-                // Function parameter
-                outputLuaTypeCheck(o, i + 1, b.paramTypes[(isNonStatic ? i - 1 : i)]);
-            }
-
-            if (i == count - 1)
-                o << ")\n";
-            else
-            {
-                o << " &&\n";
-                indent(o, indentLevel + 1);
-            }
-        }
-        indent(o, indentLevel);
-        o << "{\n";
-            
-        outputBindingInvocation(o, b, paramCount, indentLevel + 1, numBindings);
-
-        indent(o, indentLevel);
-        o << "}\n";
-
-        if (numBindings > 1)
-        {
-            indent(o, --indentLevel);
-            o << "} while (0);\n";
-        }
-
-        o << "\n";
-    }
-}
-
-static inline void outputReturnValue(ostream& o, const FunctionBinding& b, int indentLevel)
-{
-    // Pass the return value back to Lua.
-    if (!(b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR || 
-        b.returnParam.type == FunctionBinding::Param::TYPE_DESTRUCTOR ||
-        b.returnParam.type == FunctionBinding::Param::TYPE_VOID || 
-        b.returnParam.type == FunctionBinding::Param::TYPE_OBJECT))
-    {
-        o << "\n";
-        indent(o, indentLevel);
-        o << "// Push the return value onto the stack.\n";
-
-        // If the return type is a basic type pointer, return it as light user data.
-        if (b.returnParam.type != FunctionBinding::Param::TYPE_ENUM &&
-            b.returnParam.type != FunctionBinding::Param::TYPE_STRING &&
-            b.returnParam.kind == FunctionBinding::Param::KIND_POINTER)
-        {
-            indent(o, indentLevel);
-            o << "lua_pushlightuserdata(state, result);\n";
-            indent(o, indentLevel);
-            o << "return 1;\n";
-            return;
-        }
-    }
-
-    indent(o, indentLevel);
-    switch (b.returnParam.type)
-    {
-    case FunctionBinding::Param::TYPE_BOOL:
-        o << "lua_pushboolean(state, result);\n";
-        break;
-    case FunctionBinding::Param::TYPE_CHAR:
-    case FunctionBinding::Param::TYPE_SHORT:
-    case FunctionBinding::Param::TYPE_INT:
-    case FunctionBinding::Param::TYPE_LONG:
-        o << "lua_pushinteger(state, result);\n";
-        break;
-    case FunctionBinding::Param::TYPE_UNRECOGNIZED:
-        o << "GP_WARN(\"Attempting to return value with unrecognized type " << b.returnParam.info << " as an unsigned integer.\");\n";
-        indent(o, indentLevel);
-    case FunctionBinding::Param::TYPE_UCHAR:
-    case FunctionBinding::Param::TYPE_USHORT:
-    case FunctionBinding::Param::TYPE_UINT:
-    case FunctionBinding::Param::TYPE_ULONG:
-        o << "lua_pushunsigned(state, result);\n";
-        break;
-    case FunctionBinding::Param::TYPE_FLOAT:
-    case FunctionBinding::Param::TYPE_DOUBLE:
-        o << "lua_pushnumber(state, result);\n";
-        break;
-    case FunctionBinding::Param::TYPE_ENUM:
-        o << "lua_pushstring(state, lua_stringFromEnum_" << Generator::getInstance()->getUniqueNameFromRef(b.returnParam.info) << "(result));\n";
-        break;
-    case FunctionBinding::Param::TYPE_STRING:
-        if (b.returnParam.info == "string")
-            o << "lua_pushstring(state, result.c_str());\n";
-        else
-            o << "lua_pushstring(state, result);\n";
-        break;
-    case FunctionBinding::Param::TYPE_OBJECT:
-    case FunctionBinding::Param::TYPE_CONSTRUCTOR:
-        o << "if (returnPtr)\n";
-        indent(o, indentLevel);
-        o << "{\n";
-        indent(o, indentLevel + 1);
-        o << LUA_OBJECT << "* object = (" << LUA_OBJECT << "*)lua_newuserdata(state, sizeof(" << LUA_OBJECT << "));\n";
-        indent(o, indentLevel + 1);
-        o << "object->instance = returnPtr;\n";
-        indent(o, indentLevel + 1);
-        o << "object->owns = ";
-        if (b.own || (b.returnParam.type == FunctionBinding::Param::TYPE_OBJECT && b.returnParam.kind == FunctionBinding::Param::KIND_VALUE))
-            o << "true";
-        else
-            o << "false";
-        o << ";\n";
-        indent(o, indentLevel + 1);
-        o << "luaL_getmetatable(state, \"" << Generator::getInstance()->getUniqueNameFromRef(b.returnParam.info) << "\");\n";
-        indent(o, indentLevel + 1);
-        o << "lua_setmetatable(state, -2);\n";
-        indent(o, indentLevel);
-        o << "}\n";
-        indent(o, indentLevel);
-        o << "else\n";
-        indent(o, indentLevel);
-        o << "{\n";
-        indent(o, indentLevel + 1);
-        o << "lua_pushnil(state);\n";
-        indent(o, indentLevel);
-        o << "}\n";
-        break;
-    case FunctionBinding::Param::TYPE_DESTRUCTOR:
-    case FunctionBinding::Param::TYPE_VOID:
-    default:
-        o << "\n";
-        indent(o, indentLevel);
-        o << "return 0;\n";
-        return;
-    }
-
-    o << "\n";
-    indent(o, indentLevel);
-    o << "return 1;\n";
-}
+#include "FunctionBinding.h"
+#include "Generator.h"
+
+
+// Helper functions.
+static inline void outputLuaTypeCheckInstance(ostream& o);
+static inline void outputLuaTypeCheck(ostream& o, int index, const FunctionBinding::Param& p = 
+    FunctionBinding::Param(FunctionBinding::Param::TYPE_OBJECT, FunctionBinding::Param::KIND_POINTER));
+static inline void indent(ostream& o, int indentLevel);
+static inline void outputBindingInvocation(ostream& o, const FunctionBinding& b, unsigned int paramCount, unsigned int indentLevel, int numBindings);
+static inline void outputGetParam(ostream& o, const FunctionBinding::Param& p, int i, int indentLevel, bool offsetIndex, int numBindings);
+static inline void outputMatchedBinding(ostream& o, const FunctionBinding& b, unsigned int paramCount, unsigned int indentLevel, int numBindings);
+static inline void outputReturnValue(ostream& o, const FunctionBinding& b, int indentLevel);
+static inline std::string getTypeName(const FunctionBinding::Param& param);
+
+FunctionBinding::Param::Param(FunctionBinding::Param::Type type, Kind kind, const string& info) : 
+    type(type), kind(kind), info(info), hasDefaultValue(false), levelsOfIndirection(0)
+{
+}
+
+bool FunctionBinding::Param::operator==(const Param& p) const
+{
+    return this->type == p.type && this->kind == p.kind && this->info == p.info;
+}
+
+bool FunctionBinding::Param::operator!=(const Param& p) const
+{
+    return !(*this == p);
+}
+
+FunctionBinding::FunctionBinding(string classname, string uniquename) : classname(classname), uniquename(uniquename), name(""), own(false)
+{
+}
+
+string FunctionBinding::getFunctionName() const
+{
+    if (functionName.length() == 0)
+    {
+        functionName = "lua_";
+        functionName += uniquename;
+    
+        if (type == STATIC_FUNCTION ||
+            type == STATIC_CONSTANT ||
+            type == STATIC_VARIABLE)
+            functionName += "_static";
+        functionName += "_";
+
+        if (returnParam.type == Param::TYPE_CONSTRUCTOR)
+            functionName += "_init";
+        else if (returnParam.type == Param::TYPE_DESTRUCTOR)
+            functionName += "_gc";
+        else
+        {
+            size_t i = name.rfind("::");
+            if (i != name.npos)
+                functionName += name.substr(i + 2);
+            else
+                functionName += name;
+        }
+    }
+
+    return functionName;
+}
+
+unsigned int FunctionBinding::getMinParamCount() const
+{
+    for (unsigned int i = 0; i < paramTypes.size(); i++)
+    {
+        if (paramTypes[i].hasDefaultValue)
+            return i;
+    }
+    return paramTypes.size();
+}
+
+void FunctionBinding::write(ostream& o, const vector<FunctionBinding>& bindings)
+{
+    GP_ASSERT(bindings.size() > 0);
+
+    if (bindings[0].getFunctionName() == "lua_AudioListener_static_getInstance")
+    {
+        int i = 0;
+    }
+
+    // Print the function signature.
+    o << "int " << bindings[0].getFunctionName() << "(lua_State* state)\n";
+    o << "{\n";
+
+    if (bindings.size() == 1 && bindings[0].type == FunctionBinding::MEMBER_VARIABLE)
+    {
+        // Validate the parameter count.
+        o << "    // Validate the number of parameters.\n";
+        o << "    if (lua_gettop(state) > 2)\n";
+        o << "    {\n";
+        o << "        lua_pushstring(state, \"Invalid number of parameters (expected 1 or 2).\");\n";
+        o << "        lua_error(state);\n";
+        o << "    }\n\n";
+        
+        // Get or set the member variable depending on the number of parameters.
+        o << "    " << bindings[0].classname << "* instance = getInstance(state);\n";
+        o << "    if (lua_gettop(state) == 2)\n";
+        o << "    {\n";
+        outputGetParam(o, bindings[0].returnParam, 1, 2, false, 1);
+
+        if (bindings[0].returnParam.kind == FunctionBinding::Param::KIND_POINTER &&
+            bindings[0].returnParam.type != FunctionBinding::Param::TYPE_OBJECT &&
+            bindings[0].returnParam.info.size() > 0)
+        {
+            o << "        memcpy(instance->" << bindings[0].name << ", param2, sizeof(";
+            o << FunctionBinding::Param(bindings[0].returnParam.type) << ") * " << bindings[0].returnParam.info << ");\n";
+        }
+        else
+        {
+            o << "        instance->" << bindings[0].name << " = ";
+            if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT &&
+                bindings[0].returnParam.kind != FunctionBinding::Param::KIND_POINTER)
+            {
+                o << "*";
+            }
+            o << "param2;\n";
+        }
+
+        o << "        return 0;\n";
+        o << "    }\n";
+        o << "    else\n";
+        o << "    {\n";
+        
+        // Pass the return value back to Lua.
+        if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT)
+        {
+            switch (bindings[0].returnParam.kind)
+            {
+            case FunctionBinding::Param::KIND_POINTER:
+                o << "        void* returnPtr = (void*)instance->" << bindings[0].name << ";\n";
+                break;
+            case FunctionBinding::Param::KIND_VALUE:
+                o << "        void* returnPtr = (void*)new " << bindings[0].returnParam << "(instance->" << bindings[0].name << ");\n";
+                break;
+            case FunctionBinding::Param::KIND_REFERENCE:
+                o << "        void* returnPtr = (void*)&(instance->" << bindings[0].name << ");\n";
+                break;
+            default:
+                GP_ERROR("Invalid return value kind '%d'.", bindings[0].returnParam.kind);
+                break;
+            }
+        }
+        else
+        {
+            o << "        " << bindings[0].returnParam << " result = instance->" << bindings[0].name << ";\n";
+        }
+        outputReturnValue(o, bindings[0], 2);
+        o << "    }\n";
+        o << "}\n\n";
+    }
+    else if (bindings.size() == 1 && 
+        (bindings[0].type == FunctionBinding::STATIC_VARIABLE ||
+        bindings[0].type == FunctionBinding::GLOBAL_VARIABLE))
+    {
+        // Validate the parameter count.
+        o << "    // Validate the number of parameters.\n";
+        o << "    if (lua_gettop(state) > 1)\n";
+        o << "    {\n";
+        o << "        lua_pushstring(state, \"Invalid number of parameters (expected 0 or 1).\");\n";
+        o << "        lua_error(state);\n";
+        o << "    }\n\n";
+        
+        // Get or set the static variable depending on the number of parameters.
+        o << "    if (lua_gettop(state) == 1)\n";
+        o << "    {\n";
+        outputGetParam(o, bindings[0].returnParam, 0, 2, false, 1);
+
+        if (bindings[0].returnParam.kind == FunctionBinding::Param::KIND_POINTER &&
+            bindings[0].returnParam.type != FunctionBinding::Param::TYPE_OBJECT &&
+            bindings[0].returnParam.info.size() > 0)
+        {
+            o << "        memcpy(";
+            if (bindings[0].classname.size() > 0)
+                o << bindings[0].classname << "::";
+            o << bindings[0].name << ", param1, sizeof(";
+            o << FunctionBinding::Param(bindings[0].returnParam.type) << ") * " << bindings[0].returnParam.info << ");\n";
+        }
+        else
+        {
+            o << "        ";
+            if (bindings[0].classname.size() > 0)
+                o << bindings[0].classname << "::";
+            o << bindings[0].name << " = ";
+            if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT &&
+                bindings[0].returnParam.kind != FunctionBinding::Param::KIND_POINTER)
+            {
+                o << "*";
+            }
+            o << "param1;\n";
+        }
+        o << "        return 0;\n";
+        o << "    }\n";
+        o << "    else\n";
+        o << "    {\n";
+        
+        // Pass the return value back to Lua.
+        if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT)
+        {
+            switch (bindings[0].returnParam.kind)
+            {
+            case FunctionBinding::Param::KIND_POINTER:
+                o << "        void* returnPtr = (void*)";
+                if (bindings[0].classname.size() > 0)
+                    o << bindings[0].classname << "::";
+                o << bindings[0].name << ";\n";
+                break;
+            case FunctionBinding::Param::KIND_VALUE:
+                o << "        void* returnPtr = (void*)new " << bindings[0].returnParam << "(";
+                if (bindings[0].classname.size() > 0)
+                    o << bindings[0].classname << "::";
+                o << bindings[0].name << ");\n";
+                break;
+            case FunctionBinding::Param::KIND_REFERENCE:
+                o << "        void* returnPtr = (void*)&(";
+                if (bindings[0].classname.size() > 0)
+                    o << bindings[0].classname << "::";
+                o << bindings[0].name << ");\n";
+                break;
+            default:
+                GP_ERROR("Invalid return value kind '%d'.", bindings[0].returnParam.kind);
+                break;
+            }
+        }
+        else
+        {
+            o << "        " << bindings[0].returnParam << " result = ";
+            if (bindings[0].classname.size() > 0)
+                o << bindings[0].classname << "::";
+            o << bindings[0].name << ";\n";
+        }
+        outputReturnValue(o, bindings[0], 2);
+        o << "    }\n";
+        o << "}\n\n";
+    }
+    else if (bindings.size() == 1 && bindings[0].type == FunctionBinding::MEMBER_CONSTANT)
+    {
+        // Validate the parameter count.
+        o << "    // Validate the number of parameters.\n";
+        o << "    if (lua_gettop(state) > 1)\n";
+        o << "    {\n";
+        o << "        lua_pushstring(state, \"Invalid number of parameters (expected 1).\");\n";
+        o << "        lua_error(state);\n";
+        o << "    }\n\n";
+        
+        // Pass the return value back to Lua.
+        o << "    " << bindings[0].classname << "* instance = getInstance(state);\n";
+        if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT)
+        {
+            switch (bindings[0].returnParam.kind)
+            {
+            case FunctionBinding::Param::KIND_POINTER:
+                o << "    void* returnPtr = (void*)instance->" << bindings[0].name << ";\n";
+                break;
+            case FunctionBinding::Param::KIND_VALUE:
+                o << "    void* returnPtr = (void*)new " << bindings[0].returnParam << "(instance->" << bindings[0].name << ");\n";
+                break;
+            case FunctionBinding::Param::KIND_REFERENCE:
+                o << "    void* returnPtr = (void*)&(instance->" << bindings[0].name << ");\n";
+                break;
+            default:
+                GP_ERROR("Invalid return value kind '%d'.", bindings[0].returnParam.kind);
+                break;
+            }
+        }
+        else
+        {
+            o << "    " << bindings[0].returnParam << " result = instance->" << bindings[0].name << ";\n";
+        }
+        outputReturnValue(o, bindings[0], 1);
+        o << "}\n\n";
+    }
+    else if (bindings.size() == 1 && 
+        (bindings[0].type == FunctionBinding::STATIC_CONSTANT ||
+        bindings[0].type == FunctionBinding::GLOBAL_CONSTANT))
+    {
+        // Validate the parameter count.
+        o << "    // Validate the number of parameters.\n";
+        o << "    if (lua_gettop(state) > 0)\n";
+        o << "    {\n";
+        o << "        lua_pushstring(state, \"Invalid number of parameters (expected 0).\");\n";
+        o << "        lua_error(state);\n";
+        o << "    }\n\n";
+        
+        // Pass the return value back to Lua.
+        if (bindings[0].returnParam.type == FunctionBinding::Param::TYPE_OBJECT)
+        {
+            switch (bindings[0].returnParam.kind)
+            {
+            case FunctionBinding::Param::KIND_POINTER:
+                o << "    void* returnPtr = (void*)";
+                if (bindings[0].classname.size() > 0)
+                    o << bindings[0].classname << "::";
+                o << bindings[0].name << ";\n";
+                break;
+            case FunctionBinding::Param::KIND_VALUE:
+                o << "    void* returnPtr = (void*)new " << bindings[0].returnParam << "(";
+                if (bindings[0].classname.size() > 0)
+                    o << bindings[0].classname << "::";
+                o << bindings[0].name << ");\n";
+                break;
+            case FunctionBinding::Param::KIND_REFERENCE:
+                o << "    void* returnPtr = (void*)&(";
+                if (bindings[0].classname.size() > 0)
+                    o << bindings[0].classname << "::";
+                o << bindings[0].name << ");\n";
+                break;
+            default:
+                GP_ERROR("Invalid return value kind '%d'.", bindings[0].returnParam.kind);
+                break;
+            }
+        }
+        else
+        {
+            o << "    " << bindings[0].returnParam << " result = ";
+            if (bindings[0].classname.size() > 0)
+                o << bindings[0].classname << "::";
+            o << bindings[0].name << ";\n";
+        }
+        outputReturnValue(o, bindings[0], 1);
+        o << "}\n\n";
+    }
+    else
+    {
+        // Get all valid parameter counts.
+        unsigned int paramCountOffset;
+        map<unsigned int, vector<const FunctionBinding*> > paramCounts;
+        for (unsigned int i = 0, count = bindings.size(); i < count; i++)
+        {
+            unsigned int minParamCount = bindings[i].getMinParamCount();
+            paramCountOffset = (bindings[i].type == FunctionBinding::MEMBER_FUNCTION && bindings[i].returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR) ? 1 : 0;
+            paramCounts[minParamCount + paramCountOffset].push_back(&bindings[i]);
+
+            if (minParamCount < bindings[i].paramTypes.size())
+            {
+                for (unsigned int c = minParamCount + 1; c <= bindings[i].paramTypes.size(); c++)
+                {
+                    paramCounts[c + paramCountOffset].push_back(&bindings[i]);
+                }
+            }
+        }
+        
+        // Get the parameter count.
+        o << "    // Get the number of parameters.\n";
+        o << "    int paramCount = lua_gettop(state);\n\n";
+        
+        // Retrieve all the parameters and attempt to match them to a valid binding,
+        // notifying the user if the number of parameters is invalid.
+        o << "    // Attempt to match the parameters to a valid binding.\n";
+        o << "    switch (paramCount)\n";
+        o << "    {\n";
+        map<unsigned int, vector<const FunctionBinding*> >::iterator iter;
+        unsigned int checkCount = 0;
+        for (iter = paramCounts.begin(); iter != paramCounts.end(); iter++)
+        {
+            o << "        case " << iter->first << ":\n";
+            o << "        {\n";
+
+            for (unsigned int i = 0, count = iter->second.size(); i < count; i++)
+            {
+                // Only indent if there are parameters.
+                if (iter->first > 0)
+                    indent(o, 3);
+
+                outputMatchedBinding(o, *(iter->second[i]), iter->first, 3, bindings.size());
+            }
+
+            // Only print an else clause with error report if there are parameters.
+            if (iter->first > 0)
+            {
+                indent(o, 3);
+                o << "lua_pushstring(state, \"" << bindings[0].getFunctionName();
+                o << " - Failed to match the given parameters to a valid function signature.\");\n";
+                indent(o, 3);
+                o << "lua_error(state);\n";
+            }
+            
+            o << "            break;\n";
+            o << "        }\n";
+        }
+        
+        o << "        default:\n";
+        o << "        {\n";
+        o << "            lua_pushstring(state, \"Invalid number of parameters (expected "; 
+        for (iter = paramCounts.begin(), checkCount = 1; iter != paramCounts.end(); iter++)
+        {
+            if (checkCount == paramCounts.size() && paramCounts.size() > 1)
+                o << " or ";
+            o << iter->first;
+            checkCount++;
+
+            if (checkCount < paramCounts.size())
+                o << ", ";
+        }
+        o << ").\");\n";
+        o << "            lua_error(state);\n";
+        o << "            break;\n";
+        o << "        }\n";
+        o << "    }\n";
+        o << "    return 0;\n";
+        o << "}\n\n";
+    }
+}
+
+bool FunctionBinding::signaturesMatch(const FunctionBinding& b1, const FunctionBinding& b2)
+{
+    if (b1.type == b2.type)
+    {
+        bool namesMatch = b1.name == b2.name;
+
+        // Ignore class qualifiers on member function bindings (to support inherited overloaded bindings).
+        if (b1.type == FunctionBinding::MEMBER_CONSTANT ||
+            b1.type == FunctionBinding::MEMBER_FUNCTION ||
+            b1.type == FunctionBinding::MEMBER_VARIABLE)
+        {
+            string b1name = b1.name;
+            string b2name = b2.name;
+            size_t i = b1name.rfind("::");
+            if (i != b1name.npos)
+                b1name = b1name.substr(i + 2);
+            i = b2name.rfind("::");
+            if (i != b2name.npos)
+                b2name = b2name.substr(i + 2);
+    
+            namesMatch = b1name == b2name;
+        }
+
+        // Check the binding's name, parameter types and return value type.
+        if (namesMatch)
+        {
+            if (b1.paramTypes.size() != b2.paramTypes.size())
+                return false;
+
+            for (unsigned int i = 0, count = b1.paramTypes.size(); i < count; i++)
+            {
+                if (b1.paramTypes[i] != b2.paramTypes[i])
+                    return false;
+            }
+
+            return true;
+        }
+    }
+    return false;
+}
+
+static inline std::string getTypeName(const FunctionBinding::Param& param)
+{
+    switch (param.type)
+    {
+    case FunctionBinding::Param::TYPE_VOID:
+        return "void";
+    case FunctionBinding::Param::TYPE_BOOL:
+        return "bool";
+    case FunctionBinding::Param::TYPE_CHAR:
+        return "char";
+    case FunctionBinding::Param::TYPE_SHORT:
+        return "short";
+    case FunctionBinding::Param::TYPE_INT:
+        return "int";
+    case FunctionBinding::Param::TYPE_LONG:
+        return "long";
+    case FunctionBinding::Param::TYPE_UCHAR:
+        return "unsigned char";
+    case FunctionBinding::Param::TYPE_USHORT:
+        return "unsigned short";
+    case FunctionBinding::Param::TYPE_UINT:
+        return "unsigned int";
+    case FunctionBinding::Param::TYPE_ULONG:
+        return "unsigned long";
+    case FunctionBinding::Param::TYPE_FLOAT:
+        return "float";
+    case FunctionBinding::Param::TYPE_DOUBLE:
+        return "double";
+    case FunctionBinding::Param::TYPE_ENUM:
+        return Generator::getInstance()->getIdentifier(param.info).c_str();
+    case FunctionBinding::Param::TYPE_STRING:
+        if (param.info == "string")
+            return "std::string";
+        else
+            return "const char";
+    case FunctionBinding::Param::TYPE_OBJECT:
+    case FunctionBinding::Param::TYPE_CONSTRUCTOR:
+        return Generator::getInstance()->getIdentifier(param.info).c_str();
+    case FunctionBinding::Param::TYPE_UNRECOGNIZED:
+        return param.info.c_str();
+    case FunctionBinding::Param::TYPE_DESTRUCTOR:
+    default:
+        return "";
+    }
+}
+
+ostream& operator<<(ostream& o, const FunctionBinding::Param& param)
+{
+    o << getTypeName(param);
+
+    if (param.kind == FunctionBinding::Param::KIND_POINTER)
+    {
+        for (int i = 0; i < param.levelsOfIndirection; ++i)
+            o << "*";
+    }
+
+    return o;
+}
+
+// ---------------------------------------------
+// Helper functions
+
+static inline void outputLuaTypeCheckInstance(ostream& o)
+{
+    o << "(lua_type(state, 1) == LUA_TUSERDATA)";
+}
+
+static inline void outputLuaTypeCheck(ostream& o, int index, const FunctionBinding::Param& p)
+{
+    switch (p.type)
+    {
+    case FunctionBinding::Param::TYPE_BOOL:
+        if (p.kind == FunctionBinding::Param::KIND_POINTER) 
+        {
+            o << "(lua_type(state, " << index << ") == LUA_TTABLE || ";
+            o << "lua_type(state, " << index << ") == LUA_TLIGHTUSERDATA)";
+        }
+        else
+        {
+            o << "lua_type(state, " << index << ") == LUA_TBOOLEAN";
+        }
+        break;
+    case FunctionBinding::Param::TYPE_CHAR:
+    case FunctionBinding::Param::TYPE_SHORT:
+    case FunctionBinding::Param::TYPE_INT:
+    case FunctionBinding::Param::TYPE_LONG:
+    case FunctionBinding::Param::TYPE_UCHAR:
+    case FunctionBinding::Param::TYPE_USHORT:
+    case FunctionBinding::Param::TYPE_UINT:
+    case FunctionBinding::Param::TYPE_ULONG:
+    case FunctionBinding::Param::TYPE_FLOAT:
+    case FunctionBinding::Param::TYPE_DOUBLE:
+        if (p.kind == FunctionBinding::Param::KIND_POINTER) 
+        {
+            o << "(lua_type(state, " << index << ") == LUA_TTABLE || ";
+            o << "lua_type(state, " << index << ") == LUA_TLIGHTUSERDATA)";
+        }
+        else
+        {
+            o << "lua_type(state, " << index << ") == LUA_TNUMBER";
+        }
+        break;
+    case FunctionBinding::Param::TYPE_STRING:
+    case FunctionBinding::Param::TYPE_ENUM:
+        o << "(lua_type(state, " << index << ") == LUA_TSTRING || ";
+        o << "lua_type(state, " << index << ") == LUA_TNIL)";
+        break;
+    case FunctionBinding::Param::TYPE_OBJECT:
+        o << "(lua_type(state, " << index << ") == LUA_TUSERDATA || ";
+        if (p.kind == FunctionBinding::Param::KIND_POINTER)
+            o << "lua_type(state, " << index << ") == LUA_TTABLE || ";
+        o << "lua_type(state, " << index << ") == LUA_TNIL)";
+        break;
+    case FunctionBinding::Param::TYPE_CONSTRUCTOR:
+    case FunctionBinding::Param::TYPE_DESTRUCTOR:
+    case FunctionBinding::Param::TYPE_VOID:
+    case FunctionBinding::Param::TYPE_VARARGS:
+    default:
+        o << "lua_type(state, " << index << ") == LUA_TNONE";
+    }
+}
+
+static inline void indent(ostream& o, int indentLevel)
+{
+    for (int k = 0; k < indentLevel; k++)
+        o << "    ";
+}
+
+static inline void outputBindingInvocation(ostream& o, const FunctionBinding& b, unsigned int paramCount, unsigned int indentLevel, int numBindings)
+{
+    bool isNonStatic = (b.type == FunctionBinding::MEMBER_FUNCTION && b.returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR);
+
+    // Get the passed in parameters.
+    for (unsigned int i = 0, count = paramCount - (isNonStatic ? 1 : 0); i < count; i++)
+    {
+        outputGetParam(o, b.paramTypes[i], i, indentLevel, isNonStatic, numBindings);
+    }
+
+    // Get the instance for member functions.
+    if ((b.type == FunctionBinding::MEMBER_FUNCTION) &&
+        b.returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR &&
+        b.returnParam.type != FunctionBinding::Param::TYPE_DESTRUCTOR)
+    {
+        indent(o, indentLevel);
+        o << b.classname << "* instance = getInstance(state);\n";
+    }
+
+    if (b.returnParam.type == FunctionBinding::Param::TYPE_DESTRUCTOR)
+    {
+        indent(o, indentLevel);
+        o << "void* userdata = luaL_checkudata(state, 1, \"" << Generator::getUniqueName(b.classname) << "\");\n";
+        indent(o, indentLevel);
+        o << "luaL_argcheck(state, userdata != NULL, 1, \"\'" << Generator::getUniqueName(b.classname) << "\' expected.\");\n";
+        indent(o, indentLevel);
+        o << LUA_OBJECT << "* object = (" << LUA_OBJECT << "*)userdata;\n";
+        indent(o, indentLevel);
+        o << "if (object->owns)\n";
+        indent(o, indentLevel);
+        o << "{\n";
+        indent(o, indentLevel + 1);
+        o << b.classname << "* instance = (" << b.classname << "*)object->instance;\n";
+        if (Generator::getInstance()->isRef(b.classname))
+        {
+            indent(o, indentLevel + 1);
+            o << "SAFE_RELEASE(instance);\n";
+        }
+        else
+        {
+            indent(o, indentLevel + 1);
+            o << "SAFE_DELETE(instance);\n";
+        }
+        indent(o, indentLevel);
+        o << "}\n";
+    }
+    else
+    {
+        // Create a variable to hold the return type (if appropriate).
+        if (!(b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR || 
+            b.returnParam.type == FunctionBinding::Param::TYPE_VOID || 
+            b.returnParam.type == FunctionBinding::Param::TYPE_OBJECT))
+        {
+            indent(o, indentLevel);
+            o << b.returnParam << " result = ";
+        }
+
+        // For functions that return objects, create the appropriate user data in Lua.
+        if (b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR || b.returnParam.type == FunctionBinding::Param::TYPE_OBJECT)
+        {
+            indent(o, indentLevel);
+            switch (b.returnParam.kind)
+            {
+            case FunctionBinding::Param::KIND_POINTER:
+                o << "void* returnPtr = (void*)";
+                break;
+            case FunctionBinding::Param::KIND_VALUE:
+                o << "void* returnPtr = (void*)new " << b.returnParam << "(";
+                break;
+            case FunctionBinding::Param::KIND_REFERENCE:
+                o << "void* returnPtr = (void*)&(";
+                break;
+            default:
+                GP_ERROR("Invalid return value kind '%d'.", b.returnParam.kind);
+                break;
+            }
+        }
+
+        if (b.type == FunctionBinding::STATIC_FUNCTION)
+        {
+            if (b.returnParam.type == FunctionBinding::Param::TYPE_VOID)
+                indent(o, indentLevel);
+            o << b.classname << "::" << b.name << "(";
+        }
+        else if (b.type == FunctionBinding::GLOBAL_FUNCTION)
+        {
+            if (b.returnParam.type == FunctionBinding::Param::TYPE_VOID)
+                indent(o, indentLevel);
+            o << b.name << "(";
+        }
+        else if (b.type == FunctionBinding::MEMBER_FUNCTION)
+        {
+            if (b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
+            {
+                o << "new " << Generator::getInstance()->getIdentifier(b.returnParam.info) << "(";
+            }
+            else
+            {
+                if (b.returnParam.type == FunctionBinding::Param::TYPE_VOID)
+                    indent(o, indentLevel);
+                o << "instance->" << b.name << "(";
+            }
+        }
+
+        // Pass the arguments.
+        for (unsigned int i = 0, count = paramCount - ((isNonStatic) ? 1 : 0); i < count; i++)
+        {
+            if (b.paramTypes[i].type == FunctionBinding::Param::TYPE_OBJECT && b.paramTypes[i].kind != FunctionBinding::Param::KIND_POINTER)
+                o << "*";
+            o << "param" << i + 1;
+
+            if (i != count - 1)
+                o << ", ";
+        }
+
+        // Output the matching parenthesis for the case where a non-pointer object is being returned.
+        if (b.returnParam.type == FunctionBinding::Param::TYPE_OBJECT && b.returnParam.kind != FunctionBinding::Param::KIND_POINTER)
+            o << ")";
+
+        o << ");\n";
+    }
+
+    outputReturnValue(o, b, indentLevel);
+}
+
+void writeObjectTemplateType(ostream& o, const FunctionBinding::Param& p)
+{
+    o << getTypeName(p);
+    for (int i = 0; i < p.levelsOfIndirection-1; ++i)
+        o << "*";
+}
+
+void writePointerParameter(ostream& o, const char* primitiveType, const FunctionBinding::Param& p, int paramNum, int luaParamIndex, int indentLevel)
+{
+    o << "gameplay::ScriptUtil::LuaArray<";
+    writeObjectTemplateType(o, p);
+    //o << "> param" << paramNum << "Pointer = gameplay::ScriptUtil::get" << primitiveType << "Pointer(" << luaParamIndex << ");\n";
+    o << "> param" << paramNum << " = gameplay::ScriptUtil::get" << primitiveType << "Pointer(" << luaParamIndex << ");\n";
+    //indent(o, indentLevel);
+    //o << p << " param" << paramNum << " = (" << p << ")param" << paramNum << "Pointer;\n";
+}
+
+static inline void outputGetParam(ostream& o, const FunctionBinding::Param& p, int i, int indentLevel, bool offsetIndex, int numBindings)
+{
+    indent(o, indentLevel);
+    o << "// Get parameter " << i + 1 << " off the stack.\n";
+
+    int paramIndex = (offsetIndex) ? i + 2 : i + 1;
+
+    switch (p.type)
+    {
+    case FunctionBinding::Param::TYPE_BOOL:
+        indent(o, indentLevel);
+        if (p.kind == FunctionBinding::Param::KIND_POINTER)
+            writePointerParameter(o, "Bool", p, i+1, paramIndex, indentLevel);
+        else
+            o << p << " param" << i+1 << " = gameplay::ScriptUtil::luaCheckBool(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_CHAR:
+        indent(o, indentLevel);
+        o << p << " param" << i+1 << " = (char)luaL_checkint(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_SHORT:
+        indent(o, indentLevel);
+        if (p.kind == FunctionBinding::Param::KIND_POINTER)
+            writePointerParameter(o, "Short", p, i+1, paramIndex, indentLevel);
+        else
+            o << p << " param" << i+1 << " = (short)luaL_checkint(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_INT:
+        indent(o, indentLevel);
+        if (p.kind == FunctionBinding::Param::KIND_POINTER)
+            writePointerParameter(o, "Int", p, i+1, paramIndex, indentLevel);
+        else
+            o << p << " param" << i+1 << " = (int)luaL_checkint(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_LONG:
+        indent(o, indentLevel);
+        if (p.kind == FunctionBinding::Param::KIND_POINTER)
+            writePointerParameter(o, "Long", p, i+1, paramIndex, indentLevel);
+        else
+            o << p << " param" << i+1 << " = (long)luaL_checklong(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_UCHAR:
+        indent(o, indentLevel);
+        if (p.kind == FunctionBinding::Param::KIND_POINTER)
+            writePointerParameter(o, "UnsignedChar", p, i+1, paramIndex, indentLevel);
+        else
+            o << p << " param" << i+1 << " = (unsigned char)luaL_checkunsigned(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_USHORT:
+        indent(o, indentLevel);
+        if (p.kind == FunctionBinding::Param::KIND_POINTER)
+            writePointerParameter(o, "UnsignedShort", p, i+1, paramIndex, indentLevel);
+        else
+            o << p << " param" << i+1 << " = (unsigned short)luaL_checkunsigned(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_UINT:
+        indent(o, indentLevel);
+        if (p.kind == FunctionBinding::Param::KIND_POINTER)
+            writePointerParameter(o, "UnsignedInt", p, i+1, paramIndex, indentLevel);
+        else
+            o << p << " param" << i+1 << " = (unsigned int)luaL_checkunsigned(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_ULONG:
+        indent(o, indentLevel);
+        if (p.kind == FunctionBinding::Param::KIND_POINTER)
+            writePointerParameter(o, "UnsignedLong", p, i+1, paramIndex, indentLevel);
+        else
+            o << p << " param" << i+1 << " = (unsigned long)luaL_checkunsigned(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_FLOAT:
+        indent(o, indentLevel);
+        if (p.kind == FunctionBinding::Param::KIND_POINTER)
+            writePointerParameter(o, "Float", p, i+1, paramIndex, indentLevel);
+        else
+            o << p << " param" << i+1 << " = (float)luaL_checknumber(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_DOUBLE:
+        indent(o, indentLevel);
+        if (p.kind == FunctionBinding::Param::KIND_POINTER)
+            writePointerParameter(o, "Double", p, i+1, paramIndex, indentLevel);
+        else
+            o << p << " param" << i+1 << " = (double)luaL_checknumber(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_STRING:
+        indent(o, indentLevel);
+        o << p << " param" << i+1 << " = gameplay::ScriptUtil::getString(" << paramIndex << ", " << ((p.info == "string") ? "true" : "false") << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_ENUM:
+        indent(o, indentLevel);
+        o << p << " param" << i+1 << " = (" << p << ")lua_enumFromString_" << Generator::getInstance()->getUniqueNameFromRef(p.info) << "(luaL_checkstring(state, " << paramIndex << "));\n";
+        break;
+    case FunctionBinding::Param::TYPE_UNRECOGNIZED:
+        // Attempt to retrieve the unrecognized type as an unsigned integer.
+        indent(o, indentLevel);
+        o << "GP_WARN(\"Attempting to get parameter " << i + 1 << " with unrecognized type " << p.info << " as an unsigned integer.\");\n";
+        indent(o, indentLevel);
+        o << p << " param" << i+1 << " = (" << p.info << ")luaL_checkunsigned(state, " << paramIndex << ");\n";
+        break;
+    case FunctionBinding::Param::TYPE_OBJECT:
+        {
+            indent(o, indentLevel);
+            o << "bool param" << i + 1 << "Valid;\n";
+            indent(o, indentLevel);
+            o << "gameplay::ScriptUtil::LuaArray<";
+            writeObjectTemplateType(o, p);
+            //o << "> param" << i+1 << "Pointer = gameplay::ScriptUtil::getObjectPointer<";
+            o << "> param" << i+1 << " = gameplay::ScriptUtil::getObjectPointer<";
+            writeObjectTemplateType(o, p);
+            o << ">(" << paramIndex;
+            o << ", \"" << Generator::getInstance()->getUniqueNameFromRef(p.info) << "\", ";
+            o << ((p.kind != FunctionBinding::Param::KIND_POINTER) ? "true" : "false") << ", &param" << i + 1 << "Valid);\n";
+            indent(o, indentLevel);
+            //writeObjectTemplateType(o, p);
+            //o << "* param" << i+1 << " = (";
+            //writeObjectTemplateType(o, p);
+            //o << "*)param" << i+1 << "Pointer;\n";
+            //indent(o, indentLevel);
+            o << "if (!param" << i + 1 << "Valid)\n";
+            if (numBindings > 1)
+            {
+                indent(o, indentLevel + 1);
+                o << "break;\n";
+            }
+            else
+            {
+                indent(o, indentLevel);
+                o << "{\n";
+                indent(o, indentLevel + 1);
+                o << "lua_pushstring(state, \"Failed to convert parameter " << i + 1 << " to type '" << getTypeName(p) << "'.\");\n";
+                indent(o, indentLevel + 1);
+                o << "lua_error(state);\n";
+                indent(o, indentLevel);
+                o << "}\n";
+            }
+        }
+        break;
+    case FunctionBinding::Param::TYPE_CONSTRUCTOR:
+    case FunctionBinding::Param::TYPE_DESTRUCTOR:
+    case FunctionBinding::Param::TYPE_VOID:
+    default:
+        // Ignore these cases.
+        break;
+    }
+
+    o << "\n";
+}
+
+static inline void outputMatchedBinding(ostream& o, const FunctionBinding& b, unsigned int paramCount, unsigned int indentLevel, int numBindings)
+{
+    bool isNonStatic = (b.type == FunctionBinding::MEMBER_FUNCTION && b.returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR);
+
+    // If the current invocation of the function takes zero parameters, then invoke the binding.
+    if (paramCount == 0)
+    {
+        outputBindingInvocation(o, b, paramCount, indentLevel, numBindings);
+    }
+    else
+    {
+        // NOTE: The way this currently works may cause some issues since Lua
+        // has a smaller set of types than C++. There may be cases where functions
+        // that take types with less precision (i.e. int vs. float) are called
+        // when the user in fact wanted to call the version with more precision.
+        // (this will only happen for overloaded functions).
+
+        if (numBindings > 1)
+        {
+            o << "do\n";
+            indent(o, indentLevel);
+            o << "{\n";
+            indent(o, ++indentLevel);
+        }
+
+        o << "if (";
+        for (unsigned int i = 0, count = paramCount; i < count; i++)
+        {
+            if (isNonStatic && i == 0)
+            {
+                // This is always the "this / self" pointer for a member function
+                outputLuaTypeCheckInstance(o);
+            }
+            else
+            {
+                // Function parameter
+                outputLuaTypeCheck(o, i + 1, b.paramTypes[(isNonStatic ? i - 1 : i)]);
+            }
+
+            if (i == count - 1)
+                o << ")\n";
+            else
+            {
+                o << " &&\n";
+                indent(o, indentLevel + 1);
+            }
+        }
+        indent(o, indentLevel);
+        o << "{\n";
+            
+        outputBindingInvocation(o, b, paramCount, indentLevel + 1, numBindings);
+
+        indent(o, indentLevel);
+        o << "}\n";
+
+        if (numBindings > 1)
+        {
+            indent(o, --indentLevel);
+            o << "} while (0);\n";
+        }
+
+        o << "\n";
+    }
+}
+
+static inline void outputReturnValue(ostream& o, const FunctionBinding& b, int indentLevel)
+{
+    // Pass the return value back to Lua.
+    if (!(b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR || 
+        b.returnParam.type == FunctionBinding::Param::TYPE_DESTRUCTOR ||
+        b.returnParam.type == FunctionBinding::Param::TYPE_VOID || 
+        b.returnParam.type == FunctionBinding::Param::TYPE_OBJECT))
+    {
+        o << "\n";
+        indent(o, indentLevel);
+        o << "// Push the return value onto the stack.\n";
+
+        // If the return type is a basic type pointer, return it as light user data.
+        if (b.returnParam.type != FunctionBinding::Param::TYPE_ENUM &&
+            b.returnParam.type != FunctionBinding::Param::TYPE_STRING &&
+            b.returnParam.kind == FunctionBinding::Param::KIND_POINTER)
+        {
+            indent(o, indentLevel);
+            o << "lua_pushlightuserdata(state, result);\n";
+            indent(o, indentLevel);
+            o << "return 1;\n";
+            return;
+        }
+    }
+
+    indent(o, indentLevel);
+    switch (b.returnParam.type)
+    {
+    case FunctionBinding::Param::TYPE_BOOL:
+        o << "lua_pushboolean(state, result);\n";
+        break;
+    case FunctionBinding::Param::TYPE_CHAR:
+    case FunctionBinding::Param::TYPE_SHORT:
+    case FunctionBinding::Param::TYPE_INT:
+    case FunctionBinding::Param::TYPE_LONG:
+        o << "lua_pushinteger(state, result);\n";
+        break;
+    case FunctionBinding::Param::TYPE_UNRECOGNIZED:
+        o << "GP_WARN(\"Attempting to return value with unrecognized type " << b.returnParam.info << " as an unsigned integer.\");\n";
+        indent(o, indentLevel);
+    case FunctionBinding::Param::TYPE_UCHAR:
+    case FunctionBinding::Param::TYPE_USHORT:
+    case FunctionBinding::Param::TYPE_UINT:
+    case FunctionBinding::Param::TYPE_ULONG:
+        o << "lua_pushunsigned(state, result);\n";
+        break;
+    case FunctionBinding::Param::TYPE_FLOAT:
+    case FunctionBinding::Param::TYPE_DOUBLE:
+        o << "lua_pushnumber(state, result);\n";
+        break;
+    case FunctionBinding::Param::TYPE_ENUM:
+        o << "lua_pushstring(state, lua_stringFromEnum_" << Generator::getInstance()->getUniqueNameFromRef(b.returnParam.info) << "(result));\n";
+        break;
+    case FunctionBinding::Param::TYPE_STRING:
+        if (b.returnParam.info == "string")
+            o << "lua_pushstring(state, result.c_str());\n";
+        else
+            o << "lua_pushstring(state, result);\n";
+        break;
+    case FunctionBinding::Param::TYPE_OBJECT:
+    case FunctionBinding::Param::TYPE_CONSTRUCTOR:
+        o << "if (returnPtr)\n";
+        indent(o, indentLevel);
+        o << "{\n";
+        indent(o, indentLevel + 1);
+        o << LUA_OBJECT << "* object = (" << LUA_OBJECT << "*)lua_newuserdata(state, sizeof(" << LUA_OBJECT << "));\n";
+        indent(o, indentLevel + 1);
+        o << "object->instance = returnPtr;\n";
+        indent(o, indentLevel + 1);
+        o << "object->owns = ";
+        if (b.own || (b.returnParam.type == FunctionBinding::Param::TYPE_OBJECT && b.returnParam.kind == FunctionBinding::Param::KIND_VALUE))
+            o << "true";
+        else
+            o << "false";
+        o << ";\n";
+        indent(o, indentLevel + 1);
+        o << "luaL_getmetatable(state, \"" << Generator::getInstance()->getUniqueNameFromRef(b.returnParam.info) << "\");\n";
+        indent(o, indentLevel + 1);
+        o << "lua_setmetatable(state, -2);\n";
+        indent(o, indentLevel);
+        o << "}\n";
+        indent(o, indentLevel);
+        o << "else\n";
+        indent(o, indentLevel);
+        o << "{\n";
+        indent(o, indentLevel + 1);
+        o << "lua_pushnil(state);\n";
+        indent(o, indentLevel);
+        o << "}\n";
+        break;
+    case FunctionBinding::Param::TYPE_DESTRUCTOR:
+    case FunctionBinding::Param::TYPE_VOID:
+    default:
+        o << "\n";
+        indent(o, indentLevel);
+        o << "return 0;\n";
+        return;
+    }
+
+    o << "\n";
+    indent(o, indentLevel);
+    o << "return 1;\n";
+}

+ 167 - 167
tools/luagen/src/FunctionBinding.h

@@ -1,167 +1,167 @@
-#ifndef FUNCTIONBINDING_H_
-#define FUNCTIONBINDING_H_
-
-#include "Base.h"
-
-/**
- * Represents a binding from a function or variable to a function within the script runtime.
- */
-struct FunctionBinding
-{
-    /**
-     * Represents the type of the binding.
-     */
-    enum Type
-    {
-        GLOBAL_FUNCTION,
-        GLOBAL_VARIABLE,
-        GLOBAL_CONSTANT,
-        STATIC_FUNCTION,
-        STATIC_VARIABLE,
-        STATIC_CONSTANT,
-        MEMBER_FUNCTION,
-        MEMBER_VARIABLE,
-        MEMBER_CONSTANT
-    };
-
-    /**
-     * Represents either a parameter or a return value.
-     */
-    struct Param
-    {
-        /**
-         * Represents the type of parameter or return value.
-         */
-        enum Type
-        {
-            TYPE_CONSTRUCTOR,
-            TYPE_DESTRUCTOR,
-            TYPE_VOID,
-            TYPE_BOOL,
-            TYPE_CHAR,
-            TYPE_SHORT,
-            TYPE_INT,
-            TYPE_LONG,
-            TYPE_UCHAR,
-            TYPE_USHORT,
-            TYPE_UINT,
-            TYPE_ULONG,
-            TYPE_FLOAT,
-            TYPE_DOUBLE,
-            TYPE_STRING,
-            TYPE_OBJECT,
-            TYPE_ENUM,
-            TYPE_UNRECOGNIZED,
-            TYPE_VARARGS
-        };
-
-        /** 
-         * Represents the kind or nature of the parameter/return value.
-         */
-        enum Kind
-        {
-            KIND_VALUE,
-            KIND_REFERENCE,
-            KIND_POINTER
-        };
-
-        /**
-         * Constructor.
-         * 
-         * @param type The type of the parameter.
-         * @param kind The kind of the parameter.
-         * @param info The extra info of the parameter (optional).
-         */
-        Param(Type type = TYPE_VOID, Kind kind = KIND_VALUE, const string& info = "");
-
-        /**
-         * Equality operator.
-         * 
-         * @param p The param to compare to.
-         * @return True if the parameters are equal; false otherwise.
-         */
-        bool operator==(const Param& p) const;
-
-        /**
-         * Inequality operator.
-         * 
-         * @param p The param to compare to.
-         * @return True if the parameters are not equal; false otherwise.
-         */
-        bool operator!=(const Param& p) const;
-
-        /** The type of the parameter. */
-        Type type;
-        /** The kind of the parameter. */
-        Kind kind;
-        /** Extra info (either the class name for a pointer 
-        type or whether a string type is a std::string or a C-string). */
-        string info;
-        /** Whether the parameter has a default value. */
-        bool hasDefaultValue;
-        /** For pointer types, the number of levels of indirection */
-        int levelsOfIndirection;
-    };
-
-    /**
-     * Constructor.
-     *
-     * @param classname The name of the class that owns this binding.
-     * @param uniquename The class's unique name (used only in the script bindings).
-     */
-    FunctionBinding(string classname = "", string uniquename = "");
-
-    /**
-     * Retrieves the C++ function name for the script binding.
-     * 
-     * @return The C++ function name for the script binding.
-     */
-    string getFunctionName() const;
-
-    /**
-     * Gets the minimum number of parameters needed to call 
-     * the function that the binding corresponds to.
-     * 
-     * @return The minimum number of parameters.
-     */
-    unsigned int getMinParamCount() const;
-
-    /**
-     * Writes out the script binding for the given set of binding objects
-     * (the given set corresponds to all overloaded versions of a function).
-     * 
-     * @param o The output stream to write to.
-     * @param bindings The set of binding objects.
-     */
-    static void write(ostream& o, const vector<FunctionBinding>& bindings);
-
-    /**
-     * Retrieves whether the given two bindings have matching signatures.
-     * 
-     * @param b1 The first binding.
-     * @param b2 The second binding.
-     * @return True if the signatures match; false otherwise.
-     */
-    static bool signaturesMatch(const FunctionBinding& b1, const FunctionBinding& b2);
-
-    /** The binding's type. */
-    Type type;
-    /** The binding's return value. */
-    Param returnParam;
-    /** The binding's parameters. */
-    vector<Param> paramTypes;
-    /** The name of the class that owns this binding. */
-    string classname;
-    /** Holds the class's unique name (used only in the script bindings). */
-    string uniquename;
-    /** The name of the binding (function or variable name). */
-    string name;
-    /** Holds the unique name of the C++ function that implements the Lua binding. */
-    mutable string functionName;
-    /** Holds whether the binding's return value is a object that is owned by whomever calls the function. */
-    bool own;
-};
-
-ostream& operator<<(ostream& o, const FunctionBinding::Param& param);
-
-#endif
+#ifndef FUNCTIONBINDING_H_
+#define FUNCTIONBINDING_H_
+
+#include "Base.h"
+
+/**
+ * Represents a binding from a function or variable to a function within the script runtime.
+ */
+struct FunctionBinding
+{
+    /**
+     * Represents the type of the binding.
+     */
+    enum Type
+    {
+        GLOBAL_FUNCTION,
+        GLOBAL_VARIABLE,
+        GLOBAL_CONSTANT,
+        STATIC_FUNCTION,
+        STATIC_VARIABLE,
+        STATIC_CONSTANT,
+        MEMBER_FUNCTION,
+        MEMBER_VARIABLE,
+        MEMBER_CONSTANT
+    };
+
+    /**
+     * Represents either a parameter or a return value.
+     */
+    struct Param
+    {
+        /**
+         * Represents the type of parameter or return value.
+         */
+        enum Type
+        {
+            TYPE_CONSTRUCTOR,
+            TYPE_DESTRUCTOR,
+            TYPE_VOID,
+            TYPE_BOOL,
+            TYPE_CHAR,
+            TYPE_SHORT,
+            TYPE_INT,
+            TYPE_LONG,
+            TYPE_UCHAR,
+            TYPE_USHORT,
+            TYPE_UINT,
+            TYPE_ULONG,
+            TYPE_FLOAT,
+            TYPE_DOUBLE,
+            TYPE_STRING,
+            TYPE_OBJECT,
+            TYPE_ENUM,
+            TYPE_UNRECOGNIZED,
+            TYPE_VARARGS
+        };
+
+        /** 
+         * Represents the kind or nature of the parameter/return value.
+         */
+        enum Kind
+        {
+            KIND_VALUE,
+            KIND_REFERENCE,
+            KIND_POINTER
+        };
+
+        /**
+         * Constructor.
+         * 
+         * @param type The type of the parameter.
+         * @param kind The kind of the parameter.
+         * @param info The extra info of the parameter (optional).
+         */
+        Param(Type type = TYPE_VOID, Kind kind = KIND_VALUE, const string& info = "");
+
+        /**
+         * Equality operator.
+         * 
+         * @param p The param to compare to.
+         * @return True if the parameters are equal; false otherwise.
+         */
+        bool operator==(const Param& p) const;
+
+        /**
+         * Inequality operator.
+         * 
+         * @param p The param to compare to.
+         * @return True if the parameters are not equal; false otherwise.
+         */
+        bool operator!=(const Param& p) const;
+
+        /** The type of the parameter. */
+        Type type;
+        /** The kind of the parameter. */
+        Kind kind;
+        /** Extra info (either the class name for a pointer 
+        type or whether a string type is a std::string or a C-string). */
+        string info;
+        /** Whether the parameter has a default value. */
+        bool hasDefaultValue;
+        /** For pointer types, the number of levels of indirection */
+        int levelsOfIndirection;
+    };
+
+    /**
+     * Constructor.
+     *
+     * @param classname The name of the class that owns this binding.
+     * @param uniquename The class's unique name (used only in the script bindings).
+     */
+    FunctionBinding(string classname = "", string uniquename = "");
+
+    /**
+     * Retrieves the C++ function name for the script binding.
+     * 
+     * @return The C++ function name for the script binding.
+     */
+    string getFunctionName() const;
+
+    /**
+     * Gets the minimum number of parameters needed to call 
+     * the function that the binding corresponds to.
+     * 
+     * @return The minimum number of parameters.
+     */
+    unsigned int getMinParamCount() const;
+
+    /**
+     * Writes out the script binding for the given set of binding objects
+     * (the given set corresponds to all overloaded versions of a function).
+     * 
+     * @param o The output stream to write to.
+     * @param bindings The set of binding objects.
+     */
+    static void write(ostream& o, const vector<FunctionBinding>& bindings);
+
+    /**
+     * Retrieves whether the given two bindings have matching signatures.
+     * 
+     * @param b1 The first binding.
+     * @param b2 The second binding.
+     * @return True if the signatures match; false otherwise.
+     */
+    static bool signaturesMatch(const FunctionBinding& b1, const FunctionBinding& b2);
+
+    /** The binding's type. */
+    Type type;
+    /** The binding's return value. */
+    Param returnParam;
+    /** The binding's parameters. */
+    vector<Param> paramTypes;
+    /** The name of the class that owns this binding. */
+    string classname;
+    /** Holds the class's unique name (used only in the script bindings). */
+    string uniquename;
+    /** The name of the binding (function or variable name). */
+    string name;
+    /** Holds the unique name of the C++ function that implements the Lua binding. */
+    mutable string functionName;
+    /** Holds whether the binding's return value is a object that is owned by whomever calls the function. */
+    bool own;
+};
+
+ostream& operator<<(ostream& o, const FunctionBinding::Param& param);
+
+#endif

+ 1985 - 1985
tools/luagen/src/Generator.cpp

@@ -1,1985 +1,1985 @@
-#include "Generator.h"
-
-Generator* Generator::__instance = NULL;
-
-// Warning flags.
-static bool __printTemplateWarning = false;
-static bool __printVarargWarning = false;
-static bool __printOperatorWarning = false;
-
-// Utility functions (local to this file).
-static string trim(const string& str);
-static string stripTypeQualifiers(const string& typeStr, FunctionBinding::Param::Kind& kind, int& levelsOfIndirection);
-static inline bool isWantedFileNormal(const string& s);
-static inline bool isNamespaceFile(const string& s);
-static inline bool isGeneratedBindingFile(const string& s);
-static bool getFileList(string directory, vector<string>& files, bool (*isWantedFile)(const string& s));
-static bool isReservedKeyword(string name);
-
-Generator* Generator::getInstance()
-{
-    if (!__instance)
-        __instance = new Generator();
-
-    return __instance;
-}
-
-void Generator::releaseInstance()
-{
-    SAFE_DELETE(__instance);
-}
-
-string Generator::getUniqueName(string name)
-{
-    // Calculate the unique name for the given identifier (class, struct, enum, etc).
-    string uniquename = name;
-    size_t i = uniquename.find("::");
-    while (i != uniquename.npos)
-    {
-        uniquename.replace(i, 2, SCOPE_REPLACEMENT);
-        i = uniquename.find("::");
-    }
-
-    return uniquename;
-}
-
-string Generator::getUniqueNameFromRef(string refId)
-{
-    return getUniqueName(getIdentifier(refId));
-}
-
-vector<string> Generator::getScopePath(string classname, string ns)
-{
-    size_t i = classname.find("::");
-    vector<string> scopePath;
-    while (i != classname.npos)
-    {
-        string scope = classname.substr(0, i);
-        if (scope != ns)
-            scopePath.push_back(scope);
-        classname = classname.substr(i + 2);
-        i = classname.find("::");
-    }
-
-    return scopePath;
-}
-
-string Generator::getIdentifier(string refId)
-{
-    if (_refIds.find(refId) != _refIds.end())
-        return _refIds[refId];
-    return refId;
-}
-
-string Generator::getClassNameAndNamespace(string classname, string* ns)
-{
-    size_t index = classname.find("::");
-    if (index != classname.npos)
-    {
-        string classNS = classname.substr(0, index);
-        if (_namespaces.find(classNS) != _namespaces.end())
-        {
-            if (ns)
-                *ns = classNS;
-
-            string tmp = classname.substr(index + 2);
-            if (_namespaces[classNS].find(tmp) != _namespaces[classNS].end())
-                return classname.substr(index + 2);
-            else
-            {
-                size_t tmpIndex = tmp.find("::");
-                if (tmpIndex != tmp.npos)
-                {
-                    tmp = tmp.substr(0, tmpIndex);
-                    if (_namespaces[classNS].find(tmp) != _namespaces[classNS].end())
-                    {
-                        _namespaces[classNS].insert(classname.substr(index + 2));
-                        return classname.substr(index + 2);
-                    }
-                }
-            }
-        }
-    }
-
-    return classname;
-}
-
-void Generator::setIdentifier(string refId, string id)
-{
-    _refIds[refId] = id;
-}
-
-bool Generator::isDerived(const ClassBinding& c, string classname)
-{
-    for (unsigned int i = 0; i < c.derived.size(); i++)
-    {
-        // If the derived class is not in the ref ID table, then it
-        // is a hidden (protected, private, etc.) class, so don't consider it.
-        if (_refIds.find(c.derived[i]) != _refIds.end())
-        {
-            const string& derivedClassName = getIdentifier(c.derived[i]);
-            if (derivedClassName == classname || 
-                (_classes.find(derivedClassName) != _classes.end() &&
-                isDerived(_classes[derivedClassName], classname)))
-            {
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
-bool Generator::isRef(string classname)
-{
-    // Check if the class is derived from Ref.
-    for (unsigned int i = 0; i < _topLevelBaseClasses.size(); i++)
-    {
-        if (_topLevelBaseClasses[i] == REF_CLASS_NAME)
-        {
-            return isDerived(_classes[_topLevelBaseClasses[i]], classname);
-        }
-    }
-    return classname == REF_CLASS_NAME;
-}
-
-string Generator::getCompoundName(XMLElement* node)
-{
-    // Get the name of the namespace, class, struct, or file that we are processing.
-    XMLElement* nameElement = node->FirstChildElement("compoundname");
-    if (!nameElement)
-    {
-        GP_ERROR("Missing 'compoundname' child node of 'compounddef' node for XML document '%s'.", _file);
-        return "";
-    }
-    const char* text = nameElement->GetText();
-    if (!text)
-    {
-        GP_ERROR("The 'compoundname' node is empty for XML document '%s'.", _file);
-        return "";
-    }
-
-    return string(text);
-}
-
-void Generator::run(string inDir, string outDir, string* bindingNS)
-{
-    // Set the output directory.
-    _outDir = outDir;
-
-    // Get a list of all .cpp and .h files in the output directory so
-    // we can delete them before generating new bindings.
-    vector<string> oldBindingsFiles;
-    getFileList(outDir, oldBindingsFiles, isGeneratedBindingFile);
-
-    // Get a list of the Doxygen XML files that specify a namespace.
-    // Note: we must do this before adding the normal files so that
-    // when we process the files sequentially, we process the namespaces
-    // before the normal files (so that namespaces can be removed
-    // properly from class/struct names, etc.)
-    vector<string> files;
-    getFileList(inDir, files, isNamespaceFile);
-
-    // Add all of the normal Doxygen XML files we want to use to generate Lua bindings.
-    if (!getFileList(inDir, files, isWantedFileNormal) || files.empty())
-    {
-        GP_ERROR("Failed to get a valid list of files to generate bindings from using directory '%s'.", inDir.c_str());
-        return;
-    }
-
-    // Go through each file and build the data needed to generate the bindings.
-    for (vector<string>::iterator iter = files.begin(); iter != files.end(); iter++)
-    {
-        tinyxml2::XMLDocument doc;
-        _file = iter->c_str();
-        doc.LoadFile(iter->c_str());
-
-        int ret = doc.ErrorID();
-        if (ret != 0)
-        {
-            GP_ERROR("Failed to load XML document '%s' properly with error ID %d.", iter->c_str(), ret);
-            continue;
-        }
-
-        XMLElement* rootNode = doc.FirstChildElement("doxygen");
-        if (!rootNode)
-        {
-            GP_ERROR("Missing root 'doxygen' node for XML document '%s'.", iter->c_str());
-            continue;
-        }
-        XMLElement* node = rootNode->FirstChildElement("compounddef");
-        if (!node)
-        {
-            GP_ERROR("Missing 'compounddef' node for XML document '%s'.", iter->c_str());
-            continue;
-        }
-
-        const char* kind = node->Attribute("kind");
-        if (kind && strcmp(kind, "namespace") == 0)
-        {
-            string name = getCompoundName(node);
-            cout << "Parsing namespace " << name << "...\n";
-            getNamespace(node, name);
-        }
-        else if ( (kind && (strcmp(kind, "class") == 0 || strcmp(kind, "struct") == 0) ) && strcmp(node->Attribute("prot"), "public") == 0)
-        {
-            string name = getCompoundName(node);
-            cout << "Parsing class/struct " << name << "...\n";
-            getClass(node, name);
-        }
-        else if (kind && strcmp(kind, "file") == 0)
-        {
-            string name = getCompoundName(node);
-            cout << "Parsing file " << name << "...\n";
-            if (name.find(".h") != name.npos)
-            {
-                getFunctions(node);
-                getEnums(node, name);
-            }
-            else if (name.find(".cpp") != name.npos)
-            {
-                getIncludes(node, name);
-            }
-        }
-    }
-
-    // Resolve all inheritance.
-    resolveInheritance();
-
-    // Resolve all unrecognized parameter and return value types.
-    resolveTypes();
-
-    // Resolve all inherited include files.
-    resolveInheritedIncludes();
-
-    // Generate the script bindings.
-    generateBindings(bindingNS);
-
-    // Print out all warnings (unsupported types, function name-Lua keyword clashes, etc.)
-    if (__warnings.size() > 0)
-    {
-        cout << "\nWarnings:\n";
-        for (set<string>::iterator iter = __warnings.begin(); iter!= __warnings.end(); iter++)
-        {
-            GP_WARN("%s", iter->c_str());
-        }
-    }
-
-    // Print warnings for the use of unsupported C++ features.
-    if (__printTemplateWarning)
-        GP_WARN("Detected the use of template parameters; this feature of C++ is not supported.");
-    if (__printVarargWarning)
-        GP_WARN("Detected the use of variable argument lists; this feature of C++ is not supported.");
-    if (__printOperatorWarning)
-        GP_WARN("Detected the use of operator overloading; this feature of C++ is not supported.");
-
-    // Delete files that are no longer needed and print warnings for them
-    for (unsigned int i = 0; i < oldBindingsFiles.size(); i++)
-    {
-        if (std::find(generatedFiles.begin(), generatedFiles.end(), oldBindingsFiles[i]) == generatedFiles.end())
-        {
-            GP_WARN("Deleting unused file: %s", oldBindingsFiles[i].c_str());
-            remove(oldBindingsFiles[i].c_str());
-        }
-    }
-}
-
-Generator::Generator()
-{
-}
-
-Generator::~Generator()
-{
-}
-
-void Generator::getFunctions(XMLElement* fileNode, string ns)
-{
-    // Process all public, non-static functions and variables that are defined in this file.
-    XMLElement* node = NULL;
-    const char* kind = NULL;
-    const char* isStatic = NULL;
-    for (node = fileNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
-    {
-        kind = node->Attribute("kind");
-        if (kind && strcmp(kind, "func") == 0)
-        {
-            XMLElement* e = node->FirstChildElement("memberdef");
-            while (e)
-            {
-                isStatic = e->Attribute("static");
-                if (e->FirstChildElement("templateparamlist"))
-                {
-                    __printTemplateWarning = true;
-                }
-                else if (getScriptFlag(e) != "ignore" &&
-                    (!isStatic || strcmp(isStatic, "yes") != 0))
-                {
-                    FunctionBinding b;
-                    b.type = FunctionBinding::GLOBAL_FUNCTION;
-                    b.name = getName(e);
-
-                    if (!isReservedKeyword(b.name))
-                    {
-                        // Ignore operators.
-                        if (b.name.find("operator") != 0)
-                        {
-                            b.returnParam = getParam(e);
-
-                            getParams(e, b);
-                            getCreateFlag(e, b);
-                            _functions[b.getFunctionName()].push_back(b);
-
-                            // Add the function to the set of namespace members if it is part of a namespace.
-                            if (ns.size() > 0)
-                                _namespaces[ns].insert(b.name);
-                        }
-                        else
-                        {
-                            __printOperatorWarning = true;
-                        }
-                    }
-                    else
-                    {
-                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
-                    }
-                }
-                e = e->NextSiblingElement("memberdef");
-            }
-        }
-        else if (kind && strcmp(kind, "var") == 0)
-        {
-            XMLElement* e = node->FirstChildElement("memberdef");
-            while (e)
-            {
-                isStatic = e->Attribute("static");
-                if (getScriptFlag(e) != "ignore" &&
-                    (!isStatic || strcmp(isStatic, "yes") != 0))
-                {
-                    FunctionBinding b;
-                    if (getIsConstType(e))
-                        b.type = FunctionBinding::GLOBAL_CONSTANT;
-                    else
-                        b.type = FunctionBinding::GLOBAL_VARIABLE;
-
-                    b.name = getName(e);
-                    if (!isReservedKeyword(b.name))
-                    {
-                        b.returnParam = getParam(e, true);
-                        _functions[b.getFunctionName()].push_back(b);
-                        
-                        // Add the variable to the set of namespace members if it is part of a namespace.
-                        if (ns.size() > 0)
-                            _namespaces[ns].insert(b.name);
-                    }
-                    else
-                    {
-                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
-                    }
-                }
-                e = e->NextSiblingElement("memberdef");
-            }
-        }
-    }
-}
-
-void Generator::getNamespace(XMLElement* nsNode, const string& name)
-{
-    // Skip the 'std' namespace.
-    if (name == "std")
-        return;
-
-    // Create the set of all classes that are a part of this namespace.
-    XMLElement* e = nsNode->FirstChildElement("innerclass");
-    while (e)
-    {
-        string classname = e->GetText();
-        size_t i = classname.find("::");
-        if (i != classname.npos)
-            classname = classname.substr(i + 2);
-        _namespaces[name].insert(classname);
-        e = e->NextSiblingElement("innerclass");
-    }
-
-    // Parse all functions that are directly in this namespace.
-    getFunctions(nsNode, name);
-
-    // Parse all enums that are directly in this namespace.
-    getEnums(nsNode, name);
-
-    // Parse all typedefs.
-    getTypedefs(nsNode, name);
-}
-
-void Generator::getClass(XMLElement* classNode, const string& name)
-{
-    // Get the ref id for the class.
-    string refId = classNode->Attribute("id");
-
-    // Create the class binding object that we will store the function bindings in (name -> binding).
-    ClassBinding classBinding(name, refId);
-
-    // Store the mapping between the ref id and the class's fully qualified name.
-    Generator::getInstance()->setIdentifier(refId, classBinding.classname);
-
-    // Check if we should ignore this class.
-    if (getScriptFlag(classNode) == "ignore")
-        return;
-
-    // Get the include header for the original class declaration.
-    XMLElement* includeElement = classNode->FirstChildElement("includes");
-    if (includeElement)
-    {
-        const char* text = includeElement->GetText();
-        if (!text)
-        {
-            GP_ERROR("The 'includes' node is empty (a class must have an include file) for XML document '%s'.", _file);
-            return;
-        }
-        classBinding.include = text;
-    }
-    else
-    {
-        // See if we are an inner class. If so, attempt to get the include from the root parent class.
-        size_t index = classBinding.classname.find("::");
-        if (index != classBinding.classname.npos)
-        {
-            string parentClassName = classBinding.classname.substr(0, index);
-            if (_classes.find(parentClassName) != _classes.end())
-                classBinding.include = _classes[parentClassName].include;
-        }
-        else
-        {
-            // Attempt to guess the name of the header.
-            classBinding.include = classBinding.classname + ".h";
-        }
-    }
-
-    // Track whether the class has any pure virtual functions.
-    bool hasPureVirtual = false;
-
-    // Process all public members that are defined in this class.
-    XMLElement* node = NULL;
-    const char* kind = NULL;
-    for (node = classNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
-    {
-        kind = node->Attribute("kind");
-        if (!kind)
-        {
-            GP_ERROR("Section definition is missing required 'kind' attribute in XML document  '%s'.", _file);
-            return;
-        }
-
-        // Process public static functions.
-        if (strcmp(kind, "public-static-func") == 0)
-        {
-            XMLElement* e = node->FirstChildElement("memberdef");
-            while (e)
-            {
-                if (e->FirstChildElement("templateparamlist"))
-                {
-                    __printTemplateWarning = true;
-                }
-                else if (getScriptFlag(e) != "ignore")
-                {
-                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
-                    b.type = FunctionBinding::STATIC_FUNCTION;
-
-                    b.name = getName(e);
-                    if (!isReservedKeyword(b.name))
-                    {
-                        b.returnParam = getParam(e, false, b.classname);
-                        
-                        getParams(e, b);
-                        getCreateFlag(e, b);
-                        classBinding.bindings[b.getFunctionName()].push_back(b);
-                    }
-                    else
-                    {
-                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
-                    }
-                }
-                e = e->NextSiblingElement("memberdef");
-            }
-        }
-        // Process public member functions.
-        else if (strcmp(kind, "public-func") == 0)
-        {
-            XMLElement* e = node->FirstChildElement("memberdef");
-            while (e)
-            {
-                if (e->FirstChildElement("templateparamlist"))
-                {
-                    __printTemplateWarning = true;
-                }
-                else if (getScriptFlag(e) != "ignore")
-                {
-                    if (strcmp(e->Attribute("virt"), "pure-virtual") == 0)
-                        hasPureVirtual = true;
-
-                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
-                    b.type = FunctionBinding::MEMBER_FUNCTION;
-
-                    b.name = getName(e);
-
-                    if (!isReservedKeyword(b.name))
-                    {
-                        // Ignore operators.
-                        if (b.name.find("operator") != 0)
-                        {
-                            b.returnParam = getParam(e, false, b.classname);
-                            if (b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
-                            {
-                                b.returnParam.info = refId;
-                                b.own = true;
-                            }
-
-                            getParams(e, b);
-                            getCreateFlag(e, b);
-                            classBinding.bindings[b.getFunctionName()].push_back(b);
-                        }
-                        else
-                        {
-                            __printOperatorWarning = true;
-                        }
-                    }
-                    else
-                    {
-                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
-                    }
-                }
-                e = e->NextSiblingElement("memberdef");
-            }
-        }
-        // Process public static variables.
-        else if (strcmp(kind, "public-static-attrib") == 0)
-        {
-            XMLElement* e = node->FirstChildElement("memberdef");
-            while (e)
-            {
-                if (getScriptFlag(e) != "ignore")
-                {
-                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
-                    if (getIsConstType(e))
-                        b.type = FunctionBinding::STATIC_CONSTANT;
-                    else
-                        b.type = FunctionBinding::STATIC_VARIABLE;
-
-                    b.name = getName(e);
-                    if (!isReservedKeyword(b.name))
-                    {
-                        b.returnParam = getParam(e, true, b.classname);
-                        classBinding.bindings[b.getFunctionName()].push_back(b);
-                    }
-                    else
-                    {
-                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
-                    }
-                }
-                e = e->NextSiblingElement("memberdef");
-            }
-        }
-        // Process public member variables.
-        else if (strcmp(kind, "public-attrib") == 0)
-        {
-            XMLElement* e = node->FirstChildElement("memberdef");
-            while (e)
-            {
-                if (e->FirstChildElement("templateparamlist"))
-                {
-                    __printTemplateWarning = true;
-                }
-                else if (getScriptFlag(e) != "ignore")
-                {
-                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
-                    if (getIsConstType(e))
-                        b.type = FunctionBinding::MEMBER_CONSTANT;
-                    else
-                        b.type = FunctionBinding::MEMBER_VARIABLE;
-
-                    b.name = getName(e);
-                    if (!isReservedKeyword(b.name))
-                    {
-                        b.returnParam = getParam(e, true, b.classname);
-                        classBinding.bindings[b.getFunctionName()].push_back(b);
-                    }
-                    else
-                    {
-                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
-                    }
-                }
-                e = e->NextSiblingElement("memberdef");
-            }
-        }
-        else if (strcmp(kind, "protected-func") == 0 ||
-                 strcmp(kind, "private-func") == 0)
-        {
-            // Check for inaccessible constructor/destructor
-            // and create a list of all other inaccessible functions
-            // (we do this so that classes that override a public function
-            // and change its scope to protected or private work properly
-            // from Lua-i.e. no binding is generated for such functions).
-            XMLElement* e = node->FirstChildElement("memberdef");
-            while (e)
-            {
-                if (strcmp(e->Attribute("virt"), "pure-virtual") == 0)
-                    hasPureVirtual = true;
-
-                FunctionBinding::Param t = getParam(e);
-                if (t.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
-                {
-                    classBinding.inaccessibleConstructor = true;
-                }
-                else if (t.type == FunctionBinding::Param::TYPE_DESTRUCTOR)
-                {
-                    classBinding.inaccessibleDestructor = true;
-                }
-                else
-                {
-                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
-                    b.type = FunctionBinding::MEMBER_FUNCTION;
-
-                    b.name = getName(e);
-                
-                    if (!isReservedKeyword(b.name))
-                    {
-                        // Ignore operators.
-                        if (b.name.find("operator") != 0)
-                        {
-                            b.returnParam = getParam(e, false, b.classname);
-                            if (b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
-                            {
-                                b.returnParam.info = refId;
-                                b.own = true;
-                            }
-
-                            getParams(e, b);
-                            getCreateFlag(e, b);
-                            classBinding.hidden[b.getFunctionName()].push_back(b);
-                        }
-                        else
-                        {
-                            __printOperatorWarning = true;
-                        }
-                    }
-                }
-                e = e->NextSiblingElement("memberdef");
-            }
-        }
-        else if (strcmp(kind, "protected-static-func") == 0 ||
-                 strcmp(kind, "private-static-func") == 0)
-        {
-            // Create a list of all other inaccessible functions
-            // (we do this so that classes that override a public function
-            // and change its scope to protected or private work properly
-            // from Lua-i.e. no binding is generated for such functions).
-
-            XMLElement* e = node->FirstChildElement("memberdef");
-            while (e)
-            {
-                if (e->FirstChildElement("templateparamlist"))
-                {
-                    __printTemplateWarning = true;
-                }
-                else if (getScriptFlag(e) != "ignore")
-                {
-                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
-                    b.type = FunctionBinding::STATIC_FUNCTION;
-
-                    b.name = getName(e);
-                    if (!isReservedKeyword(b.name))
-                    {
-                        b.returnParam = getParam(e, false, b.classname);
-                        
-                        getParams(e, b);
-                        getCreateFlag(e, b);
-                        classBinding.hidden[b.getFunctionName()].push_back(b);
-                    }
-                }
-                e = e->NextSiblingElement("memberdef");
-            }
-        }
-        // Process public enums and typedefs.
-        else if (strcmp(kind, "public-type") == 0)
-        {
-            XMLElement* e = node->FirstChildElement("memberdef");
-            while (e)
-            {
-                if (getScriptFlag(e) != "ignore")
-                {
-                    if (strcmp(e->Attribute("kind"), "enum") == 0)
-                    {
-                        getEnum(e, classBinding.classname, classBinding.ns, classBinding.include);
-                    }
-                    else if (strcmp(e->Attribute("kind"), "typedef") == 0)
-                    {
-                        getTypedef(e, classBinding.classname, classBinding.ns);
-                    }
-                }
-                e = e->NextSiblingElement("memberdef");
-            }
-        }
-        else
-        {
-            // Ignore other section definitions.
-        }
-    }
-
-    // If the class has a pure-virtual method, we mark the constructor as inaccessible
-    // and remove any constructor bindings that are in the list.
-    if (hasPureVirtual)
-    {
-        classBinding.inaccessibleConstructor = true;
-        map<string, vector<FunctionBinding> >::iterator iter = classBinding.bindings.begin();
-        for (; iter != classBinding.bindings.end(); iter++)
-        {
-            if (iter->second[0].returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
-            {
-                classBinding.bindings.erase(iter);
-                break;
-            }
-        }
-    }
-
-    // Store the class's derived class(es)' ref id(s) if it has any.
-    node = classNode->FirstChildElement("derivedcompoundref");
-    while (node)
-    {
-        classBinding.derived.push_back(node->Attribute("refid"));
-        node = node->NextSiblingElement("derivedcompoundref");
-    }
-
-    // If the class has no base classes and it has derived classes, add it to the list of top-level classes.
-    if (!classNode->FirstChildElement("basecompoundref") && classBinding.derived.size() > 0)
-        _topLevelBaseClasses.push_back(classBinding.classname);
-
-    // Insert the class binding into the global table.
-    _classes[classBinding.classname] = classBinding;
-}
-
-void Generator::getEnums(XMLElement* fileNode, string ns)
-{
-    XMLElement* node = NULL;
-    const char* kind = NULL;
-    for (node = fileNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
-    {
-        kind = node->Attribute("kind");
-        if (!kind)
-        {
-            GP_ERROR("Section definition is missing required 'kind' attribute in XML document  '%s'.", _file);
-            return;
-        }
-
-        // Process the enums.
-        if (strcmp(kind, "enum") == 0)
-        {
-            XMLElement* e = node->FirstChildElement("memberdef");
-            while (e)
-            {
-                if (getScriptFlag(e) != "ignore" && strcmp(e->Attribute("kind"), "enum") == 0)
-                {
-                    getEnum(e, "", ns);
-                }
-                e = e->NextSiblingElement("memberdef");
-            }
-        }
-    }
-}
-
-void Generator::getEnum(XMLElement* e, string classname, string ns, string include)
-{
-    // Get the enumeration's name.
-    string enumname = classname;
-    if (enumname.size() > 0)
-        enumname += string("::");
-    enumname += getName(e);
-
-    // Get the ref id for the enum.
-    string refId = e->Attribute("id");
-
-    // Store the ref id to name mapping.
-    Generator::getInstance()->setIdentifier(refId, enumname);
-    
-    // Add the enum to the enum list if it's not there 
-    // (we implicitly create it when we set its scope path).
-    if (_enums.find(enumname) == _enums.end())
-        _enums[enumname].scopePath = Generator::getScopePath(enumname, ns);
-
-    // Set the include file for the enum.
-    if (include.size() > 0)
-        _enums[enumname].include = include;
-    else
-    {
-        XMLElement* location = e->FirstChildElement("location");
-        if (location)
-            _enums[enumname].include = location->Attribute("file");
-    }
-
-    for (e = e->FirstChildElement("enumvalue"); e; e = e->NextSiblingElement("enumvalue"))
-    {
-        _enums[enumname].values.push_back(getName(e));
-    }
-
-    // Add the enum to the set of namespace members if it is part of a namespace.
-    if (ns.size() > 0)
-        _namespaces[ns].insert(enumname);
-}
-
-void Generator::getTypedefs(XMLElement* fileNode, string ns)
-{
-    XMLElement* node = NULL;
-    const char* kind = NULL;
-    for (node = fileNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
-    {
-        kind = node->Attribute("kind");
-        if (!kind)
-        {
-            GP_ERROR("Section definition is missing required 'kind' attribute in XML document  '%s'.", _file);
-            return;
-        }
-
-        // Process the enums.
-        if (strcmp(kind, "typedef") == 0)
-        {
-            XMLElement* e = node->FirstChildElement("memberdef");
-            while (e)
-            {
-                if (getScriptFlag(e) != "ignore" && strcmp(e->Attribute("kind"), "typedef") == 0)
-                {
-                    getTypedef(e, "", ns);
-                }
-                e = e->NextSiblingElement("memberdef");
-            }
-        }
-    }
-}
-
-void Generator::getTypedef(XMLElement* e, string classname, string ns)
-{
-    TypedefBinding t;
-
-    // Get the typedef's name.
-    string tname = classname;
-    if (tname.size() > 0)
-        tname += string("::");
-    tname += getName(e);
-
-    // Get the typedef's id and store the mapping from ref id to name.
-    string refId = e->Attribute("id");
-    setIdentifier(refId, tname);
-
-    FunctionBinding::Param p = getParam(e);
-    if (p.info.size() > 0)
-        t.refId = p.info;
-
-    _typedefs[tname] = t;
-
-    // Add the typedef to the set of namespace members if it is part of a namespace.
-    if (ns.size() > 0)
-        _namespaces[ns].insert(tname);
-}
-
-static inline bool getScriptFlagHelper(XMLElement* e, string& flag)
-{
-    XMLElement* x = e->FirstChildElement("xmlonly");
-    if (x)
-    {
-        flag = x->GetText();
-        return true;
-    }
-
-    x = e->FirstChild() ? e->FirstChild()->ToElement() : NULL;
-    while (x)
-    {
-        if (getScriptFlagHelper(x, flag))
-            return true;
-
-        x = x->NextSibling() ? x->NextSibling()->ToElement() : NULL;
-    }
-    return false;
-}
-
-string Generator::getScriptFlag(XMLElement* e)
-{
-    string flag;
-
-    XMLElement* n = e->FirstChildElement("detaileddescription");
-    if (n)
-        getScriptFlagHelper(n, flag);
-    
-    return flag;
-}
-
-void Generator::getCreateFlag(XMLElement* e, FunctionBinding& b)
-{
-    if (getScriptFlag(e) == "create")
-        b.own = true;
-}
-
-string Generator::getName(XMLElement* e)
-{
-    // Get the name for the binding.
-    XMLElement* nameElement = e->FirstChildElement("name");
-    if (!nameElement)
-    {
-        GP_ERROR("Missing 'name' child node in XML document '%s'.", _file);
-        return string();
-    }
-    return nameElement->GetText();
-}
-
-bool Generator::getIsConstType(XMLElement* e)
-{
-    XMLElement* typeElement = e->FirstChildElement("type");
-    if (!typeElement)
-    {
-        GP_ERROR("Missing 'type' node in XML document '%s'.", _file);
-        return false;
-    }
-
-    XMLNode* textNode = typeElement->FirstChild();
-    if (textNode)
-    {
-        XMLText* text = textNode->ToText();
-        if (text)
-        {
-            string type = text->Value();
-            return type.find("const") != type.npos;
-        }
-    }
-    return false;
-}
-
-FunctionBinding::Param Generator::getParam(XMLElement* e, bool isVariable, string classname)
-{
-    // Get the type for the current element (either the return type or a parameter type).
-    XMLElement* typeElement = e->FirstChildElement("type");
-    if (!typeElement)
-    {
-        GP_ERROR("Missing 'type' node in XML document '%s'.", _file);
-    }
-
-    FunctionBinding::Param p;
-    XMLNode* textNode = typeElement->FirstChild();
-    if (!textNode)
-    {
-        // Get the name of the current element to see if it is a destructor.
-        string name = getName(e);
-        if (name.find("~") == 0)
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_DESTRUCTOR);
-        }
-        else
-        {
-            // Assume it's a constructor.
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_CONSTRUCTOR, FunctionBinding::Param::KIND_POINTER, name);
-        }
-    }
-    else
-    {
-        // Get the type string without const or reference qualifiers (and trim whitespace).
-        string refId = "";
-        string typeStr = "";
-        int levelsOfIndirection = 0;
-        FunctionBinding::Param::Kind kind;
-        {
-            // Attempt to process the type as reference (i.e. class, struct, enum, typedef, etc.) type.
-            XMLNode* node = textNode;
-            while (node)
-            {
-                if (strcmp(node->Value(), "ref") == 0)
-                {
-                    refId = node->ToElement()->Attribute("refid");
-                    typeStr += node->ToElement()->GetText();
-                }
-                else if (node->ToText())
-                {
-                    typeStr += node->ToText()->Value();
-                }
-
-                node = node->NextSibling();
-            }
-
-            typeStr = stripTypeQualifiers(typeStr, kind, levelsOfIndirection);
-        }
-
-        if (typeStr == "void")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_VOID, kind);
-        }
-        else if (typeStr == "bool")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_BOOL, kind);
-        }
-        else if (typeStr == "char" && kind != FunctionBinding::Param::KIND_POINTER)
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_CHAR, kind);
-        }
-        else if (typeStr == "short")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_SHORT, kind);
-        }
-        else if (typeStr == "int")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_INT, kind);
-        }
-        else if (typeStr == "long")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_LONG, kind);
-        }
-        else if (typeStr == "unsigned char")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_UCHAR, kind);
-        }
-        else if (typeStr == "unsigned short")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_USHORT, kind);
-        }
-        else if (typeStr == "unsigned int")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_UINT, kind);
-        }
-        else if (typeStr == "unsigned long")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_ULONG, kind);
-        }
-        else if (typeStr == "float")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_FLOAT, kind);
-        }
-        else if (typeStr == "double")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_DOUBLE, kind);
-        }
-        else if (typeStr == "string" || typeStr == "std::string")
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_STRING, kind, "string");
-        }
-        else if (typeStr == "char" && kind == FunctionBinding::Param::KIND_POINTER)
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_STRING, kind, "char*");
-        }
-        else if (_enums.find(typeStr) != _enums.end() ||
-            (classname.size() > 0 && _enums.find(classname + string("::") + typeStr) != _enums.end()))
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_ENUM, kind, refId);
-        }
-        else if (typeStr == "...")
-        {
-            __printVarargWarning = true;
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_VARARGS);
-        }
-        else
-        {
-            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_UNRECOGNIZED, kind, (refId.size() > 0) ? refId : typeStr);
-        }
-        p.levelsOfIndirection = levelsOfIndirection;
-
-        // Check if the type is a pointer declared with square brackets (i.e. float x[4]).
-        XMLElement* arrayElement = NULL;
-        if ((arrayElement = e->FirstChildElement("array")) != NULL ||
-            (isVariable && (arrayElement = e->FirstChildElement("argsstring")) != NULL))
-        {
-            const char* text = arrayElement->GetText();
-            string arrayString = (text ? text : "");
-            string::size_type i = arrayString.find("[");
-            string::size_type k = arrayString.find("]");
-            if (i != arrayString.npos && k != arrayString.npos)
-            {
-                p.kind = FunctionBinding::Param::KIND_POINTER;
-                p.levelsOfIndirection = 1;
-                if (i != k - 1)
-                    p.info = arrayString.substr(i + 1, k - (i + 1));
-            }
-        }
-    }
-
-    // Get the default value for the parameter if it has one.
-    XMLElement* defaultValueElement = e->FirstChildElement("defval");
-    if (defaultValueElement)
-    {
-        p.hasDefaultValue = true;
-    }
-
-    return p;
-}
-
-void Generator::getParams(XMLElement* e, FunctionBinding& b)
-{
-    XMLElement* param = e->FirstChildElement("param");
-    while (param)
-    {
-        FunctionBinding::Param p = getParam(param, false, b.classname);
-        if (p.type != FunctionBinding::Param::TYPE_VARARGS)
-            b.paramTypes.push_back(p);
-        param = param->NextSiblingElement("param");
-    }
-}
-
-void Generator::resolveMembers(const ClassBinding& c)
-{
-    vector<ClassBinding*> derived;
-
-    // Go through the derived classes' bindings and update them.
-    ClassBinding* cb = NULL;
-    map<string, vector<FunctionBinding> >::const_iterator iter;
-    for (unsigned int i = 0; i < c.derived.size(); i++)
-    {
-        // If the class is not in the map of classes, then
-        // it was marked to be ignored, so skip over it.
-        string derivedClassName = getIdentifier(c.derived[i]);
-        if (_classes.find(derivedClassName) == _classes.end())
-            continue;
-
-        cb = &_classes[derivedClassName];
-
-        // Go through this class' bindings and add them to the current
-        // derived class if they are not already there (excluding constructors and destructors).
-        for (iter = c.bindings.begin(); iter != c.bindings.end(); iter++)
-        {
-            FunctionBinding b(cb->classname, cb->uniquename);
-            b.type = iter->second[0].type;
-            b.name = iter->second[0].name;
-
-            map<string, vector<FunctionBinding> >::iterator findIter = cb->bindings.find(b.getFunctionName());
-            map<string, vector<FunctionBinding> >::iterator hiddenIter = cb->hidden.find(b.getFunctionName());
-            if (findIter == cb->bindings.end() && hiddenIter == cb->hidden.end())
-            {
-                for (unsigned int i = 0, iCount = iter->second.size(); i < iCount; i++)
-                {
-                    if (iter->second[i].returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR &&
-                        iter->second[i].returnParam.type != FunctionBinding::Param::TYPE_DESTRUCTOR)
-                    {
-                        // Copy the binding, but set its function name to 
-                        // empty so that it is regenerated correctly.
-                        b = iter->second[i];
-                        b.functionName = "";
-                        b.classname = cb->classname;
-                        b.uniquename = cb->uniquename;
-
-                        cb->bindings[b.getFunctionName()].push_back(b);
-                    }
-                }
-            }
-            else
-            {
-                bool addBinding;
-                for (unsigned int i = 0, iCount = iter->second.size(); i < iCount; i++)
-                {
-                    string name = iter->second[i].name;
-
-                    addBinding = true;
-                    if (findIter != cb->bindings.end())
-                    {
-                        for (unsigned int j = 0, jCount = findIter->second.size(); j < jCount; j++)
-                        {
-                            if (FunctionBinding::signaturesMatch(iter->second[i], findIter->second[j]))
-                            {
-                                addBinding = false;
-                                break;
-                            }
-                        }
-
-                        // To call the base function, we have to qualify the call since
-                        // the derived class has a function with the same name and different parameters.
-                        if (addBinding)
-                            name = iter->second[i].classname + string("::") + iter->second[i].name;
-                    }
-                    if (hiddenIter != cb->hidden.end())
-                    {
-                        for (unsigned int j = 0, jCount = hiddenIter->second.size(); j < jCount; j++)
-                        {
-                            if (FunctionBinding::signaturesMatch(iter->second[i], hiddenIter->second[j]))
-                            {
-                                addBinding = false;
-                                break;
-                            }
-                        }
-                    }
-
-                    if (addBinding)
-                    {
-                        FunctionBinding b = iter->second[i];
-                        b.name = name;
-                        b.functionName = findIter->first;
-                        b.classname = cb->classname;
-                        b.uniquename = getUniqueName(cb->classname);
-
-                        if (findIter != cb->bindings.end())
-                            findIter->second.push_back(b);
-                        else
-                            cb->bindings[b.getFunctionName()].push_back(b);
-                    }
-                }
-            }
-        }
-
-        derived.push_back(cb);
-    }
-
-    // Go through the derived classes' bindings and resolve the members for their derived classes.
-    for (unsigned int i = 0; i < derived.size(); i++)
-    {
-        resolveMembers(*derived[i]);
-    }
-}
-
-void Generator::resolveInheritance()
-{
-    // Go through the class inheritance tree and update each class's bindings list 
-    // to include the bindings from the base class that haven't been overridden.
-    for (unsigned int i = 0; i < _topLevelBaseClasses.size(); i++)
-    {
-        resolveMembers(_classes[_topLevelBaseClasses[i]]);
-    }
-}
-
-void Generator::resolveIncludes(const ClassBinding& c)
-{
-    vector<ClassBinding*> derived;
-
-    // Go through the derived classes' bindings and update them.
-    ClassBinding* cb = NULL;
-    map<string, vector<FunctionBinding> >::const_iterator iter;
-    for (unsigned int i = 0; i < c.derived.size(); i++)
-    {
-        // If the class is not in the map of classes, then
-        // it was marked to be ignored, so skip over it.
-        string derivedClassName = getIdentifier(c.derived[i]);
-        if (_classes.find(derivedClassName) == _classes.end())
-            continue;
-
-        cb = &_classes[derivedClassName];
-
-        // Add all include files (uniquely) from the base class to the derived class.
-        map<string, set<string> >::iterator baseIncludes = _includes.find(c.include);
-        if (baseIncludes != _includes.end() && baseIncludes->second.size() > 0)
-        {
-            set<string>::iterator iter = baseIncludes->second.begin();
-            set<string>& derivedIncludes = _includes[cb->include];
-            for (; iter != baseIncludes->second.end(); iter++)
-            {
-                derivedIncludes.insert(*iter);
-            }
-        }
-        
-        derived.push_back(cb);
-    }
-
-    // Go through the derived classes' bindings and resolve the members for their derived classes.
-    for (unsigned int i = 0; i < derived.size(); i++)
-    {
-        resolveIncludes(*derived[i]);
-    }
-}
-
-void Generator::resolveInheritedIncludes()
-{
-    // Go through the class inheritance tree and update each class's 
-    // list of includes to include the includes from the base class
-    for (unsigned int i = 0; i < _topLevelBaseClasses.size(); i++)
-    {
-        resolveIncludes(_classes[_topLevelBaseClasses[i]]);
-    }
-}
-
-void Generator::resolveType(FunctionBinding::Param* param, string functionName, string header)
-{
-    string name = getIdentifier(param->info);
-
-    if (param->type == FunctionBinding::Param::TYPE_UNRECOGNIZED)
-    {
-        map<string, TypedefBinding>::iterator typedefIter = _typedefs.find(name);
-        if (typedefIter != _typedefs.end() && typedefIter->second.refId.size() > 0)
-        {
-            param->type = FunctionBinding::Param::TYPE_OBJECT;
-            param->info = typedefIter->second.refId;
-        }
-        else
-        {
-            map<string, ClassBinding>::iterator classIter = _classes.find(name);
-            if (classIter != _classes.end())
-            {
-                param->type = FunctionBinding::Param::TYPE_OBJECT;
-            }
-            else
-            {
-                map<string, EnumBinding>::iterator enumIter = _enums.find(name);
-                if (enumIter != _enums.end())
-                {
-                    param->type = FunctionBinding::Param::TYPE_ENUM;
-                }
-                else
-                {
-                    __warnings.insert(string("Unrecognized C++ type: ") + functionName + string(" -- ") + (name.size() > 0 ? name : param->info));
-                }
-            }
-        }
-    }
-
-    // Ensure that the header for the Lua enum conversion 
-    // functions is included in the file containing the
-    // generated binding that this param/return value is part of.
-    if (param->type == FunctionBinding::Param::TYPE_ENUM)
-    {
-        string enumHeader = string("lua_") + getUniqueName(name) + string(".h");
-        if (_includes.find(header) != _includes.end())
-        {
-            set<string>& includes = _includes[header];
-            if (includes.find(enumHeader) == includes.end())
-                includes.insert(enumHeader);
-        }
-        else
-        {
-            _includes[header].insert(enumHeader);
-        }
-    }
-}
-
-void Generator::resolveTypes()
-{
-    // Go through all member functions and attempt to resolve unrecognized types.
-    for (map<string, ClassBinding>::iterator iter = _classes.begin(); iter != _classes.end(); iter++)
-    {
-        map<string, vector<FunctionBinding> >::iterator functionNameIter = iter->second.bindings.begin();
-        for (; functionNameIter != iter->second.bindings.end(); functionNameIter++)
-        {
-            vector<FunctionBinding>::iterator functionIter = functionNameIter->second.begin();
-            for (; functionIter != functionNameIter->second.end(); functionIter++)
-            {
-                resolveType(&functionIter->returnParam, iter->first + string("::") + functionIter->name, iter->second.include);
-
-                vector<FunctionBinding::Param>::iterator paramIter = functionIter->paramTypes.begin();
-                for (; paramIter != functionIter->paramTypes.end(); paramIter++)
-                {
-                    resolveType(&(*paramIter), iter->first + string("::") + functionIter->name, iter->second.include);
-                }
-            }
-        }
-    }
-
-    // Go through all non-member functions and attempt to resolve unrecognized types.
-    string globalHeader = string("lua_") + string(LUA_GLOBAL_FILENAME) + string(".h");
-    for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
-    {
-        vector<FunctionBinding>::iterator functionIter = iter->second.begin();
-        for (; functionIter != iter->second.end(); functionIter++)
-        {
-            resolveType(&functionIter->returnParam, functionIter->name, globalHeader);
-
-            vector<FunctionBinding::Param>::iterator paramIter = functionIter->paramTypes.begin();
-            for (; paramIter != functionIter->paramTypes.end(); paramIter++)
-            {
-                resolveType(&(*paramIter), functionIter->name, globalHeader);
-            }
-        }
-    }
-}
-
-void Generator::generateBindings(string* bindingNS)
-{
-    bool generatingGameplay = false;
-    if (bindingNS && (*bindingNS == "gameplay"))
-        generatingGameplay = true;
-
-    string luaAllHStr = _outDir + string(LUA_ALL_BINDINGS_FILENAME) + string(".h");
-    ostringstream luaAllH;
-    string includeGuard = string(LUA_ALL_BINDINGS_FILENAME) + string("_H_");
-    transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
-    luaAllH << "#ifndef " << includeGuard << "\n";
-    luaAllH << "#define " << includeGuard << "\n\n";
-    
-    string luaAllCppStr = _outDir + string(LUA_ALL_BINDINGS_FILENAME) + string(".cpp");
-    ostringstream luaAllCpp;
-    luaAllCpp << "#include \"Base.h\"\n";
-    luaAllCpp << "#include \"" << string(LUA_ALL_BINDINGS_FILENAME) << ".h\"\n\n";
-    if (bindingNS)
-    {
-        luaAllCpp << "namespace " << *bindingNS << "\n";
-        luaAllCpp << "{\n\n";
-    }
-    luaAllCpp << "void lua_RegisterAllBindings()\n";
-    luaAllCpp << "{\n";
-
-    // Write out all the class bindings.
-    if (_classes.size() > 0)
-    {
-        map<string, ClassBinding>::iterator iter = _classes.begin();
-        for (; iter != _classes.end(); iter++)
-        {
-            if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->second.classname) == _namespaces["gameplay"].end()))
-            {
-                cout << "Generating bindings for '" << iter->first << "'...\n";
-                iter->second.write(_outDir, _includes[iter->second.include], bindingNS);
-
-                luaAllH << "#include \"lua_" << iter->second.uniquename << ".h\"\n";
-                luaAllCpp << "    luaRegister_" << iter->second.uniquename << "();\n";
-            }
-        }
-    }
-
-    // Go through all the classes and if they have any derived classes, add them to the list of base classes.
-    vector<string> baseClasses;
-    for (map<string, ClassBinding>::iterator iter = _classes.begin(); iter != _classes.end(); iter++)
-    {
-        if (iter->second.derived.size() > 0)
-            baseClasses.push_back(iter->first);
-    }
-
-    // Write out all the enum files.
-    if (_enums.size() > 0)
-    {
-        // Write out the enum conversion function declarations.
-        for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
-        {
-            if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
-            {
-                cout << "Generating bindings for '" << iter->first << "'...\n";
-
-                // Header.
-                string enumHStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".h");
-                ostringstream enumH;
-                includeGuard = string("lua_") + getUniqueName(iter->first) + string("_H_");
-                transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
-                enumH << "#ifndef " << includeGuard << "\n";
-                enumH << "#define " << includeGuard << "\n\n";
-                enumH << "#include \"" << iter->second.include << "\"\n\n";
-
-                if (bindingNS)
-                {
-                    enumH << "namespace " << *bindingNS << "\n";
-                    enumH << "{\n\n";
-                }
-
-                enumH << "// Lua bindings for enum conversion functions for " << iter->first << ".\n";
-                enumH << iter->first << " lua_enumFromString_" << getUniqueName(iter->first) << "(const char* s);\n";
-                enumH << "const char* lua_stringFromEnum_" << getUniqueName(iter->first) << "(" << iter->first << " e);\n\n";
-
-                if (bindingNS)
-                {
-                    enumH << "}\n\n";
-                }
-
-                enumH << "#endif\n";
-
-                writeFile(enumHStr, enumH.str());
-
-                // Implementation.
-                string enumCppStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".cpp"); 
-                ostringstream enumCpp(enumCppStr.c_str());
-                enumCpp << "#include \"Base.h\"\n";
-                enumCpp << "#include \"lua_" << getUniqueName(iter->first) << ".h\"\n\n";
-
-                if (bindingNS)
-                {
-                    enumCpp << "namespace " << *bindingNS << "\n";
-                    enumCpp << "{\n\n";
-                }
-
-                enumCpp << "static const char* enumStringEmpty = \"\";\n\n";
-
-                // Build the scope string if applicable.
-                string scope;
-                if (iter->second.scopePath.size() > 0)
-                {
-                    for (unsigned int i = 0; i < iter->second.scopePath.size(); i++)
-                    {
-                        scope += iter->second.scopePath[i] + string("::");
-                    }
-                }
-
-                // Write out the string constants that correspond to the enumeration values.
-                for (unsigned int i = 0; i < iter->second.values.size(); i++)
-                {
-                    enumCpp << "static const char* luaEnumString_" << getUniqueName(iter->first) << "_";
-                    enumCpp << iter->second.values[i] << " = \"" << iter->second.values[i] << "\";\n";
-                }
-                enumCpp << "\n";
-
-                enumCpp << iter->first << " lua_enumFromString_" << getUniqueName(iter->first) << "(const char* s)\n";
-                enumCpp << "{\n";
-                
-                for (unsigned int i = 0; i < iter->second.values.size(); i++)
-                {
-                    enumCpp << "    ";
-                        
-                    enumCpp << "if (strcmp(s, luaEnumString_" << getUniqueName(iter->first) << "_" << iter->second.values[i] << ") == 0)\n";
-                    enumCpp << "        return ";
-                    if (scope.size() > 0)
-                        enumCpp << scope;
-                    enumCpp << iter->second.values[i] << ";\n";
-
-                    if (i == iter->second.values.size() - 1)
-                    {
-                        //enumCpp << "    GP_ERROR(\"Invalid enumeration value '%s' for enumeration " << iter->first << ".\", s);\n";
-                        enumCpp << "    return ";
-                        if (scope.size() > 0)
-                            enumCpp << scope;
-                        enumCpp << iter->second.values[0] << ";\n";
-                    }
-                }
-
-                enumCpp << "}\n\n";
-
-                enumCpp << "const char* lua_stringFromEnum_" << getUniqueName(iter->first) << "(" << iter->first << " e)\n";
-                enumCpp << "{\n";
-
-                // Write out the enum-to-string conversion code.
-                for (unsigned int i = 0; i < iter->second.values.size(); i++)
-                {
-                    enumCpp << "    ";
-                        
-                    enumCpp << "if (e == ";
-                    if (scope.size() > 0)
-                        enumCpp << scope;
-                    enumCpp << iter->second.values[i] << ")\n";
-                    enumCpp << "        return luaEnumString_" << getUniqueName(iter->first) << "_" << iter->second.values[i] << ";\n";
-
-                    if (i == iter->second.values.size() - 1)
-                    {
-                        //enumCpp << "    GP_ERROR(\"Invalid enumeration value '%d' for enumeration " << iter->first << ".\", e);\n";
-                        enumCpp << "    return enumStringEmpty;\n";
-                    }
-                }
-
-                enumCpp << "}\n\n";
-
-                if (bindingNS)
-                {
-                    enumCpp << "}\n\n";
-                }
-
-                writeFile(enumCppStr, enumCpp.str());
-            }
-        }
-    }
-
-    // Write out the global bindings file.
-    cout << "Generating global bindings...\n";
-    if (baseClasses.size() > 0 || _functions.size() > 0 || _enums.size() > 0)
-    {
-        // Calculate if there are global function bindings to write out.
-        bool generateGlobalFunctionBindings = false;
-        if (_functions.size() > 0)
-        {
-            for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
-            {
-                if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
-                {
-                    generateGlobalFunctionBindings = true;
-                    break;
-                }
-            }
-        }
-
-        // Calculate if there are enum bindings to write out.
-        bool generateEnumBindings = false;
-        if (_enums.size() > 0)
-        {
-            for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
-            {
-                if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
-                {
-                    generateEnumBindings = true;
-                    break;
-                }
-            }
-        }
-
-        // Write out the header file.
-        {
-            string path = _outDir + string(LUA_GLOBAL_FILENAME) + string(".h");
-            ostringstream global;
-            includeGuard = string(LUA_GLOBAL_FILENAME) + string("_H_");
-            transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
-            global << "#ifndef " << includeGuard << "\n";
-            global << "#define " << includeGuard << "\n\n";
-
-            // Write out the needed includes for the global enumeration function.
-            for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
-            {
-                if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
-                    global << "#include \"lua_" << getUniqueName(iter->first) << ".h\"\n";
-            }
-            global << "\n";
-            luaAllH << "#include \"" << string(LUA_GLOBAL_FILENAME) << ".h\"\n";
-            luaAllCpp << "    luaRegister_" << LUA_GLOBAL_FILENAME << "();\n";
-
-            if (bindingNS)
-            {
-                global << "namespace " << *bindingNS << "\n";
-                global << "{\n\n";
-            }
-
-            if (generateGlobalFunctionBindings)
-            {
-                global << "// Lua bindings for global functions.\n";
-
-                // Write out the binding function declarations.
-                for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
-                {
-                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
-                        global << "int " << iter->second[0].getFunctionName() << "(lua_State* state);\n";
-                }
-                global << "\n";
-            }
-
-            if (generateEnumBindings)
-            {
-                global << "// Global enum to string conversion function (used to pass enums to Lua from C++).\n";
-                global << "const char* lua_stringFromEnumGlobal(std::string& enumname, unsigned int value);\n\n";
-            }
-            
-            // Write out the signature of the function used to register the global functions with Lua.
-            global << "void luaRegister_" << LUA_GLOBAL_FILENAME << "();\n\n";
-
-            if (bindingNS)
-                global << "}\n\n";
-            global << "#endif\n";
-
-            writeFile(path, global.str());
-        }
-
-        // Write out the implementation.
-        {
-            string path = _outDir + string(LUA_GLOBAL_FILENAME) + string(".cpp");
-            ostringstream global;
-            global << "#include \"ScriptController.h\"\n";
-            global << "#include \"" << LUA_GLOBAL_FILENAME << ".h\"\n";
-            map<string, set<string> >::iterator iter = _includes.find(string(LUA_GLOBAL_FILENAME) + string(".h"));
-            if (iter != _includes.end())
-            {
-                set<string>::iterator includeIter = iter->second.begin();
-                for (; includeIter != iter->second.end(); includeIter++)
-                {
-                    global << "#include \"" << *includeIter << "\"\n";
-                }
-            }
-            global << "\n";
-
-            if (bindingNS)
-            {
-                global << "namespace " << *bindingNS << "\n";
-                global << "{\n\n";
-            }
-
-            // Write out the function used to register all global bindings with Lua.
-            global << "void luaRegister_" << LUA_GLOBAL_FILENAME << "()\n";
-            global << "{\n";
-        
-            if (generateGlobalFunctionBindings)
-            {
-                // Bind the non-member functions.
-                for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
-                {
-                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
-                        global << "    gameplay::ScriptUtil::registerFunction(\"" << iter->second[0].name << "\", " << iter->second[0].getFunctionName() << ");\n";
-                }
-            }
-
-            // Generate the hierarchy map.
-            if (baseClasses.size() > 0)
-            {
-                for (unsigned int i = 0, count = baseClasses.size(); i < count; i++)
-                {
-                    set<string> derived;
-                    getAllDerived(derived, baseClasses[i]);
-                    for (set<string>::iterator iter = derived.begin(); iter != derived.end(); iter++)
-                    {
-                        if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(*iter) == _namespaces["gameplay"].end()))
-                            global << "    gameplay::ScriptUtil::setGlobalHierarchyPair(\"" << baseClasses[i] << "\", \"" << *iter << "\");\n";
-                    }
-                }
-            }
-
-            // Register all enums.
-            if (generateEnumBindings)
-            {
-                global << "    gameplay::ScriptUtil::addStringFromEnumConversionFunction(&";
-                if (bindingNS)
-                    global << *bindingNS << "::";
-                global << "lua_stringFromEnumGlobal);\n";
-
-                for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
-                {
-                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
-                    {
-                        global << "\n    // Register enumeration " << iter->first << ".\n";
-                        global << "    {\n";
-
-                        global << "        std::vector<std::string> scopePath;\n";
-                        for (unsigned int i = 0; i < iter->second.scopePath.size(); i++)
-                        {
-                            global << "        scopePath.push_back(\"" << iter->second.scopePath[i] << "\");\n";
-                        }
-
-                        vector<string>::iterator enumIter = iter->second.values.begin();
-                        for (; enumIter != iter->second.values.end(); enumIter++)
-                        {
-                            global << "        gameplay::ScriptUtil::registerConstantString(\"" << *enumIter << "\", \"" << *enumIter << "\", scopePath);\n";
-                        }
-
-                        global << "    }\n";
-                    }
-                }
-            }
-            global << "}\n\n";
-            
-            // Write out the binding functions.
-            if (generateGlobalFunctionBindings)
-            {
-                for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
-                {
-                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
-                        FunctionBinding::write(global, iter->second);
-                }
-            }
-
-            // Write out the global enum conversion function (used to pass enums from C++ to Lua).
-            if (generateEnumBindings)
-            {
-                global << "static const char* enumStringEmpty = \"\";\n\n";
-                global << "const char* lua_stringFromEnumGlobal(std::string& enumname, unsigned int value)\n";
-                global << "{\n";
-                for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
-                {
-                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
-                    {
-                        global << "    if (enumname == \"";
-                        global << iter->first << "\")\n";
-                        global << "        return lua_stringFromEnum_" << getUniqueName(iter->first) << "((" << iter->first << ")value);\n";
-                    }
-                }
-                global << "\n";
-                global << "    GP_ERROR(\"Unrecognized enumeration type '%s'.\", enumname.c_str());\n";
-                global << "    return enumStringEmpty;\n";
-                global << "}\n\n";
-            }
-
-            if (bindingNS)
-                global << "}\n";
-
-            writeFile(path, global.str());
-        }
-    }
-
-    luaAllCpp << "}\n\n";
-    if (bindingNS)
-        luaAllCpp << "}\n\n";
-
-    writeFile(luaAllCppStr, luaAllCpp.str());
-
-    if (bindingNS)
-    {
-        luaAllH << "\nnamespace " << *bindingNS << "\n";
-        luaAllH << "{\n\n";
-    }
-    luaAllH << "void lua_RegisterAllBindings();\n\n";
-    if (bindingNS)
-        luaAllH<< "}\n\n";
-    luaAllH << "#endif\n";
-
-    writeFile(luaAllHStr, luaAllH.str());
-}
-
-void Generator::getAllDerived(set<string>& derived, string classname)
-{
-    for (unsigned int i = 0, count = _classes[classname].derived.size(); i < count; i++)
-    {
-        // If the derived class is not in the ref ID table, then it
-        // is a hidden (protected, private, etc.) class, so don't include it.
-        if (_refIds.find(_classes[classname].derived[i]) != _refIds.end())
-        {
-            string derivedClassName = getIdentifier(_classes[classname].derived[i]);
-            derived.insert(derivedClassName);
-            getAllDerived(derived, derivedClassName);
-        }
-    }
-}
-
-void Generator::getIncludes(XMLElement* e, string filename)
-{
-    filename.replace(filename.find(".cpp"), 4, ".h");
-    for (e = e->FirstChildElement("includes"); e; e = e->NextSiblingElement("includes"))
-    {
-        if (e->Attribute("refid"))
-            _includes[filename].insert(e->GetText());
-    }
-}
-
-// ----------------------------------------------------------------------------
-// Utility functions
-
-static string trim(const string& str)
-{
-    string s = str;
-    while (isspace(s[0]))
-    {
-        s.erase(s.begin());
-    }
-    while (isspace(s[s.size() - 1]))
-    {
-        s.erase(s.begin() + s.size() - 1);
-    }
-    return s;
-}
-
-static string stripTypeQualifiers(const string& typeStr, FunctionBinding::Param::Kind& kind, int& levelsOfIndirection)
-{
-    levelsOfIndirection = 0;
-
-    string type = typeStr;
-    kind = FunctionBinding::Param::KIND_VALUE;
-
-    // Check if the type is a reference.
-    string::size_type i = type.find("&");
-    if (i != type.npos)
-    {
-        kind = FunctionBinding::Param::KIND_REFERENCE;
-        type.erase(type.begin() + i);
-    }
-
-    // Check if the type is a pointer.
-    while ((i = type.find("*")) != std::string::npos)
-    {
-        kind = FunctionBinding::Param::KIND_POINTER;
-        type.erase(type.begin() + i);
-        ++levelsOfIndirection;
-        int j = 0;
-    }
-
-    // Ignore const qualifiers.
-    i = type.find("const ");
-    if (i != type.npos)
-    {
-        type.erase(type.begin() + i, type.begin() + i + 6);
-    }
-
-    return trim(type);
-}
-
-static inline bool isWantedFileNormal(const string& s)
-{
-    if (s.find(".xml") == s.size() - 4)
-    {
-        if (s.find("class") == 0 || s.find("struct") == 0 || 
-            (s.find("_") == 0 && (s.find("h.xml") != s.npos || s.find("cpp.xml") != s.npos)))
-            return true;
-    }
-    return false;
-}
-
-static inline bool isNamespaceFile(const string& s)
-{
-    if (s.find(".xml") == s.size() - 4)
-    {
-        if (s.find("namespace") == 0)
-            return true;
-    }
-    return false;
-}
-
-static inline bool isGeneratedBindingFile(const string& s)
-{
-    return ( (s.find(".cpp") == s.size() - 4) || (s.find(".h") == s.size() - 2) );
-}
-
-static bool getFileList(string directory, vector<string>& files, bool (*isWantedFile)(const string& s))
-{
-#ifdef WIN32
-    string path = directory + string("/*");
-
-    // Convert char to wchar.
-    basic_string<TCHAR> wPath;
-    wPath.assign(path.begin(), path.end());
-
-    WIN32_FIND_DATA FindFileData;
-    HANDLE hFind = FindFirstFile(wPath.c_str(), &FindFileData);
-    if (hFind == INVALID_HANDLE_VALUE) 
-    {
-        return false;
-    }
-    do
-    {
-        // Add to the list if this is not a directory and it passes the test function.
-        if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
-        {
-            // Convert wchar to char.
-            basic_string<TCHAR> wfilename(FindFileData.cFileName);
-            string filename;
-            filename.assign(wfilename.begin(), wfilename.end());
-
-            if (isWantedFile(filename))
-            {
-                filename = string(directory) + filename;
-                files.push_back(filename);
-            }
-        }
-    } while (FindNextFile(hFind, &FindFileData) != 0);
-
-    FindClose(hFind);
-    return true;
-#else
-    string path = directory + string("/.");
-    struct dirent* dp;
-    DIR* dir = opendir(path.c_str());
-    if (!dir)
-    {
-        return false;
-    }
-    while ((dp = readdir(dir)) != NULL)
-    {
-        string filepath(path);
-        filepath.append("/");
-        filepath.append(dp->d_name);
-
-        struct stat buf;
-        if (!stat(filepath.c_str(), &buf))
-        {
-            // Add to the list if this is not a directory and it passes the test function.
-            if (!S_ISDIR(buf.st_mode))
-            {
-                string filename = dp->d_name;
-                if (isWantedFile(filename))
-                {
-                    filename = string(directory) + filename;
-                    files.push_back(filename);
-                }
-            }
-        }
-    }
-    closedir(dir);
-    return true;
-#endif
-}
-
-bool isReservedKeyword(string name)
-{
-    static set<string> keywords;
-    if (keywords.size() == 0)
-    {
-        keywords.insert("and");
-        keywords.insert("break");
-        keywords.insert("do");
-        keywords.insert("else");
-        keywords.insert("elseif");
-        keywords.insert("end");
-        keywords.insert("false");
-        keywords.insert("for");
-        keywords.insert("function");
-        keywords.insert("if");
-        keywords.insert("in");
-        keywords.insert("local");
-        keywords.insert("nil");
-        keywords.insert("not");
-        keywords.insert("or");
-        keywords.insert("repeat");
-        keywords.insert("return");
-        keywords.insert("then");
-        keywords.insert("true");
-        keywords.insert("until");
-        keywords.insert("while");
-    };
-
-    return keywords.find(name) != keywords.end();
-}
-
-// ----------------------------------------------------------------------------
+#include "Generator.h"
+
+Generator* Generator::__instance = NULL;
+
+// Warning flags.
+static bool __printTemplateWarning = false;
+static bool __printVarargWarning = false;
+static bool __printOperatorWarning = false;
+
+// Utility functions (local to this file).
+static string trim(const string& str);
+static string stripTypeQualifiers(const string& typeStr, FunctionBinding::Param::Kind& kind, int& levelsOfIndirection);
+static inline bool isWantedFileNormal(const string& s);
+static inline bool isNamespaceFile(const string& s);
+static inline bool isGeneratedBindingFile(const string& s);
+static bool getFileList(string directory, vector<string>& files, bool (*isWantedFile)(const string& s));
+static bool isReservedKeyword(string name);
+
+Generator* Generator::getInstance()
+{
+    if (!__instance)
+        __instance = new Generator();
+
+    return __instance;
+}
+
+void Generator::releaseInstance()
+{
+    SAFE_DELETE(__instance);
+}
+
+string Generator::getUniqueName(string name)
+{
+    // Calculate the unique name for the given identifier (class, struct, enum, etc).
+    string uniquename = name;
+    size_t i = uniquename.find("::");
+    while (i != uniquename.npos)
+    {
+        uniquename.replace(i, 2, SCOPE_REPLACEMENT);
+        i = uniquename.find("::");
+    }
+
+    return uniquename;
+}
+
+string Generator::getUniqueNameFromRef(string refId)
+{
+    return getUniqueName(getIdentifier(refId));
+}
+
+vector<string> Generator::getScopePath(string classname, string ns)
+{
+    size_t i = classname.find("::");
+    vector<string> scopePath;
+    while (i != classname.npos)
+    {
+        string scope = classname.substr(0, i);
+        if (scope != ns)
+            scopePath.push_back(scope);
+        classname = classname.substr(i + 2);
+        i = classname.find("::");
+    }
+
+    return scopePath;
+}
+
+string Generator::getIdentifier(string refId)
+{
+    if (_refIds.find(refId) != _refIds.end())
+        return _refIds[refId];
+    return refId;
+}
+
+string Generator::getClassNameAndNamespace(string classname, string* ns)
+{
+    size_t index = classname.find("::");
+    if (index != classname.npos)
+    {
+        string classNS = classname.substr(0, index);
+        if (_namespaces.find(classNS) != _namespaces.end())
+        {
+            if (ns)
+                *ns = classNS;
+
+            string tmp = classname.substr(index + 2);
+            if (_namespaces[classNS].find(tmp) != _namespaces[classNS].end())
+                return classname.substr(index + 2);
+            else
+            {
+                size_t tmpIndex = tmp.find("::");
+                if (tmpIndex != tmp.npos)
+                {
+                    tmp = tmp.substr(0, tmpIndex);
+                    if (_namespaces[classNS].find(tmp) != _namespaces[classNS].end())
+                    {
+                        _namespaces[classNS].insert(classname.substr(index + 2));
+                        return classname.substr(index + 2);
+                    }
+                }
+            }
+        }
+    }
+
+    return classname;
+}
+
+void Generator::setIdentifier(string refId, string id)
+{
+    _refIds[refId] = id;
+}
+
+bool Generator::isDerived(const ClassBinding& c, string classname)
+{
+    for (unsigned int i = 0; i < c.derived.size(); i++)
+    {
+        // If the derived class is not in the ref ID table, then it
+        // is a hidden (protected, private, etc.) class, so don't consider it.
+        if (_refIds.find(c.derived[i]) != _refIds.end())
+        {
+            const string& derivedClassName = getIdentifier(c.derived[i]);
+            if (derivedClassName == classname || 
+                (_classes.find(derivedClassName) != _classes.end() &&
+                isDerived(_classes[derivedClassName], classname)))
+            {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool Generator::isRef(string classname)
+{
+    // Check if the class is derived from Ref.
+    for (unsigned int i = 0; i < _topLevelBaseClasses.size(); i++)
+    {
+        if (_topLevelBaseClasses[i] == REF_CLASS_NAME)
+        {
+            return isDerived(_classes[_topLevelBaseClasses[i]], classname);
+        }
+    }
+    return classname == REF_CLASS_NAME;
+}
+
+string Generator::getCompoundName(XMLElement* node)
+{
+    // Get the name of the namespace, class, struct, or file that we are processing.
+    XMLElement* nameElement = node->FirstChildElement("compoundname");
+    if (!nameElement)
+    {
+        GP_ERROR("Missing 'compoundname' child node of 'compounddef' node for XML document '%s'.", _file);
+        return "";
+    }
+    const char* text = nameElement->GetText();
+    if (!text)
+    {
+        GP_ERROR("The 'compoundname' node is empty for XML document '%s'.", _file);
+        return "";
+    }
+
+    return string(text);
+}
+
+void Generator::run(string inDir, string outDir, string* bindingNS)
+{
+    // Set the output directory.
+    _outDir = outDir;
+
+    // Get a list of all .cpp and .h files in the output directory so
+    // we can delete them before generating new bindings.
+    vector<string> oldBindingsFiles;
+    getFileList(outDir, oldBindingsFiles, isGeneratedBindingFile);
+
+    // Get a list of the Doxygen XML files that specify a namespace.
+    // Note: we must do this before adding the normal files so that
+    // when we process the files sequentially, we process the namespaces
+    // before the normal files (so that namespaces can be removed
+    // properly from class/struct names, etc.)
+    vector<string> files;
+    getFileList(inDir, files, isNamespaceFile);
+
+    // Add all of the normal Doxygen XML files we want to use to generate Lua bindings.
+    if (!getFileList(inDir, files, isWantedFileNormal) || files.empty())
+    {
+        GP_ERROR("Failed to get a valid list of files to generate bindings from using directory '%s'.", inDir.c_str());
+        return;
+    }
+
+    // Go through each file and build the data needed to generate the bindings.
+    for (vector<string>::iterator iter = files.begin(); iter != files.end(); iter++)
+    {
+        tinyxml2::XMLDocument doc;
+        _file = iter->c_str();
+        doc.LoadFile(iter->c_str());
+
+        int ret = doc.ErrorID();
+        if (ret != 0)
+        {
+            GP_ERROR("Failed to load XML document '%s' properly with error ID %d.", iter->c_str(), ret);
+            continue;
+        }
+
+        XMLElement* rootNode = doc.FirstChildElement("doxygen");
+        if (!rootNode)
+        {
+            GP_ERROR("Missing root 'doxygen' node for XML document '%s'.", iter->c_str());
+            continue;
+        }
+        XMLElement* node = rootNode->FirstChildElement("compounddef");
+        if (!node)
+        {
+            GP_ERROR("Missing 'compounddef' node for XML document '%s'.", iter->c_str());
+            continue;
+        }
+
+        const char* kind = node->Attribute("kind");
+        if (kind && strcmp(kind, "namespace") == 0)
+        {
+            string name = getCompoundName(node);
+            cout << "Parsing namespace " << name << "...\n";
+            getNamespace(node, name);
+        }
+        else if ( (kind && (strcmp(kind, "class") == 0 || strcmp(kind, "struct") == 0) ) && strcmp(node->Attribute("prot"), "public") == 0)
+        {
+            string name = getCompoundName(node);
+            cout << "Parsing class/struct " << name << "...\n";
+            getClass(node, name);
+        }
+        else if (kind && strcmp(kind, "file") == 0)
+        {
+            string name = getCompoundName(node);
+            cout << "Parsing file " << name << "...\n";
+            if (name.find(".h") != name.npos)
+            {
+                getFunctions(node);
+                getEnums(node, name);
+            }
+            else if (name.find(".cpp") != name.npos)
+            {
+                getIncludes(node, name);
+            }
+        }
+    }
+
+    // Resolve all inheritance.
+    resolveInheritance();
+
+    // Resolve all unrecognized parameter and return value types.
+    resolveTypes();
+
+    // Resolve all inherited include files.
+    resolveInheritedIncludes();
+
+    // Generate the script bindings.
+    generateBindings(bindingNS);
+
+    // Print out all warnings (unsupported types, function name-Lua keyword clashes, etc.)
+    if (__warnings.size() > 0)
+    {
+        cout << "\nWarnings:\n";
+        for (set<string>::iterator iter = __warnings.begin(); iter!= __warnings.end(); iter++)
+        {
+            GP_WARN("%s", iter->c_str());
+        }
+    }
+
+    // Print warnings for the use of unsupported C++ features.
+    if (__printTemplateWarning)
+        GP_WARN("Detected the use of template parameters; this feature of C++ is not supported.");
+    if (__printVarargWarning)
+        GP_WARN("Detected the use of variable argument lists; this feature of C++ is not supported.");
+    if (__printOperatorWarning)
+        GP_WARN("Detected the use of operator overloading; this feature of C++ is not supported.");
+
+    // Delete files that are no longer needed and print warnings for them
+    for (unsigned int i = 0; i < oldBindingsFiles.size(); i++)
+    {
+        if (std::find(generatedFiles.begin(), generatedFiles.end(), oldBindingsFiles[i]) == generatedFiles.end())
+        {
+            GP_WARN("Deleting unused file: %s", oldBindingsFiles[i].c_str());
+            remove(oldBindingsFiles[i].c_str());
+        }
+    }
+}
+
+Generator::Generator()
+{
+}
+
+Generator::~Generator()
+{
+}
+
+void Generator::getFunctions(XMLElement* fileNode, string ns)
+{
+    // Process all public, non-static functions and variables that are defined in this file.
+    XMLElement* node = NULL;
+    const char* kind = NULL;
+    const char* isStatic = NULL;
+    for (node = fileNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
+    {
+        kind = node->Attribute("kind");
+        if (kind && strcmp(kind, "func") == 0)
+        {
+            XMLElement* e = node->FirstChildElement("memberdef");
+            while (e)
+            {
+                isStatic = e->Attribute("static");
+                if (e->FirstChildElement("templateparamlist"))
+                {
+                    __printTemplateWarning = true;
+                }
+                else if (getScriptFlag(e) != "ignore" &&
+                    (!isStatic || strcmp(isStatic, "yes") != 0))
+                {
+                    FunctionBinding b;
+                    b.type = FunctionBinding::GLOBAL_FUNCTION;
+                    b.name = getName(e);
+
+                    if (!isReservedKeyword(b.name))
+                    {
+                        // Ignore operators.
+                        if (b.name.find("operator") != 0)
+                        {
+                            b.returnParam = getParam(e);
+
+                            getParams(e, b);
+                            getCreateFlag(e, b);
+                            _functions[b.getFunctionName()].push_back(b);
+
+                            // Add the function to the set of namespace members if it is part of a namespace.
+                            if (ns.size() > 0)
+                                _namespaces[ns].insert(b.name);
+                        }
+                        else
+                        {
+                            __printOperatorWarning = true;
+                        }
+                    }
+                    else
+                    {
+                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
+                    }
+                }
+                e = e->NextSiblingElement("memberdef");
+            }
+        }
+        else if (kind && strcmp(kind, "var") == 0)
+        {
+            XMLElement* e = node->FirstChildElement("memberdef");
+            while (e)
+            {
+                isStatic = e->Attribute("static");
+                if (getScriptFlag(e) != "ignore" &&
+                    (!isStatic || strcmp(isStatic, "yes") != 0))
+                {
+                    FunctionBinding b;
+                    if (getIsConstType(e))
+                        b.type = FunctionBinding::GLOBAL_CONSTANT;
+                    else
+                        b.type = FunctionBinding::GLOBAL_VARIABLE;
+
+                    b.name = getName(e);
+                    if (!isReservedKeyword(b.name))
+                    {
+                        b.returnParam = getParam(e, true);
+                        _functions[b.getFunctionName()].push_back(b);
+                        
+                        // Add the variable to the set of namespace members if it is part of a namespace.
+                        if (ns.size() > 0)
+                            _namespaces[ns].insert(b.name);
+                    }
+                    else
+                    {
+                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
+                    }
+                }
+                e = e->NextSiblingElement("memberdef");
+            }
+        }
+    }
+}
+
+void Generator::getNamespace(XMLElement* nsNode, const string& name)
+{
+    // Skip the 'std' namespace.
+    if (name == "std")
+        return;
+
+    // Create the set of all classes that are a part of this namespace.
+    XMLElement* e = nsNode->FirstChildElement("innerclass");
+    while (e)
+    {
+        string classname = e->GetText();
+        size_t i = classname.find("::");
+        if (i != classname.npos)
+            classname = classname.substr(i + 2);
+        _namespaces[name].insert(classname);
+        e = e->NextSiblingElement("innerclass");
+    }
+
+    // Parse all functions that are directly in this namespace.
+    getFunctions(nsNode, name);
+
+    // Parse all enums that are directly in this namespace.
+    getEnums(nsNode, name);
+
+    // Parse all typedefs.
+    getTypedefs(nsNode, name);
+}
+
+void Generator::getClass(XMLElement* classNode, const string& name)
+{
+    // Get the ref id for the class.
+    string refId = classNode->Attribute("id");
+
+    // Create the class binding object that we will store the function bindings in (name -> binding).
+    ClassBinding classBinding(name, refId);
+
+    // Store the mapping between the ref id and the class's fully qualified name.
+    Generator::getInstance()->setIdentifier(refId, classBinding.classname);
+
+    // Check if we should ignore this class.
+    if (getScriptFlag(classNode) == "ignore")
+        return;
+
+    // Get the include header for the original class declaration.
+    XMLElement* includeElement = classNode->FirstChildElement("includes");
+    if (includeElement)
+    {
+        const char* text = includeElement->GetText();
+        if (!text)
+        {
+            GP_ERROR("The 'includes' node is empty (a class must have an include file) for XML document '%s'.", _file);
+            return;
+        }
+        classBinding.include = text;
+    }
+    else
+    {
+        // See if we are an inner class. If so, attempt to get the include from the root parent class.
+        size_t index = classBinding.classname.find("::");
+        if (index != classBinding.classname.npos)
+        {
+            string parentClassName = classBinding.classname.substr(0, index);
+            if (_classes.find(parentClassName) != _classes.end())
+                classBinding.include = _classes[parentClassName].include;
+        }
+        else
+        {
+            // Attempt to guess the name of the header.
+            classBinding.include = classBinding.classname + ".h";
+        }
+    }
+
+    // Track whether the class has any pure virtual functions.
+    bool hasPureVirtual = false;
+
+    // Process all public members that are defined in this class.
+    XMLElement* node = NULL;
+    const char* kind = NULL;
+    for (node = classNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
+    {
+        kind = node->Attribute("kind");
+        if (!kind)
+        {
+            GP_ERROR("Section definition is missing required 'kind' attribute in XML document  '%s'.", _file);
+            return;
+        }
+
+        // Process public static functions.
+        if (strcmp(kind, "public-static-func") == 0)
+        {
+            XMLElement* e = node->FirstChildElement("memberdef");
+            while (e)
+            {
+                if (e->FirstChildElement("templateparamlist"))
+                {
+                    __printTemplateWarning = true;
+                }
+                else if (getScriptFlag(e) != "ignore")
+                {
+                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
+                    b.type = FunctionBinding::STATIC_FUNCTION;
+
+                    b.name = getName(e);
+                    if (!isReservedKeyword(b.name))
+                    {
+                        b.returnParam = getParam(e, false, b.classname);
+                        
+                        getParams(e, b);
+                        getCreateFlag(e, b);
+                        classBinding.bindings[b.getFunctionName()].push_back(b);
+                    }
+                    else
+                    {
+                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
+                    }
+                }
+                e = e->NextSiblingElement("memberdef");
+            }
+        }
+        // Process public member functions.
+        else if (strcmp(kind, "public-func") == 0)
+        {
+            XMLElement* e = node->FirstChildElement("memberdef");
+            while (e)
+            {
+                if (e->FirstChildElement("templateparamlist"))
+                {
+                    __printTemplateWarning = true;
+                }
+                else if (getScriptFlag(e) != "ignore")
+                {
+                    if (strcmp(e->Attribute("virt"), "pure-virtual") == 0)
+                        hasPureVirtual = true;
+
+                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
+                    b.type = FunctionBinding::MEMBER_FUNCTION;
+
+                    b.name = getName(e);
+
+                    if (!isReservedKeyword(b.name))
+                    {
+                        // Ignore operators.
+                        if (b.name.find("operator") != 0)
+                        {
+                            b.returnParam = getParam(e, false, b.classname);
+                            if (b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
+                            {
+                                b.returnParam.info = refId;
+                                b.own = true;
+                            }
+
+                            getParams(e, b);
+                            getCreateFlag(e, b);
+                            classBinding.bindings[b.getFunctionName()].push_back(b);
+                        }
+                        else
+                        {
+                            __printOperatorWarning = true;
+                        }
+                    }
+                    else
+                    {
+                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
+                    }
+                }
+                e = e->NextSiblingElement("memberdef");
+            }
+        }
+        // Process public static variables.
+        else if (strcmp(kind, "public-static-attrib") == 0)
+        {
+            XMLElement* e = node->FirstChildElement("memberdef");
+            while (e)
+            {
+                if (getScriptFlag(e) != "ignore")
+                {
+                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
+                    if (getIsConstType(e))
+                        b.type = FunctionBinding::STATIC_CONSTANT;
+                    else
+                        b.type = FunctionBinding::STATIC_VARIABLE;
+
+                    b.name = getName(e);
+                    if (!isReservedKeyword(b.name))
+                    {
+                        b.returnParam = getParam(e, true, b.classname);
+                        classBinding.bindings[b.getFunctionName()].push_back(b);
+                    }
+                    else
+                    {
+                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
+                    }
+                }
+                e = e->NextSiblingElement("memberdef");
+            }
+        }
+        // Process public member variables.
+        else if (strcmp(kind, "public-attrib") == 0)
+        {
+            XMLElement* e = node->FirstChildElement("memberdef");
+            while (e)
+            {
+                if (e->FirstChildElement("templateparamlist"))
+                {
+                    __printTemplateWarning = true;
+                }
+                else if (getScriptFlag(e) != "ignore")
+                {
+                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
+                    if (getIsConstType(e))
+                        b.type = FunctionBinding::MEMBER_CONSTANT;
+                    else
+                        b.type = FunctionBinding::MEMBER_VARIABLE;
+
+                    b.name = getName(e);
+                    if (!isReservedKeyword(b.name))
+                    {
+                        b.returnParam = getParam(e, true, b.classname);
+                        classBinding.bindings[b.getFunctionName()].push_back(b);
+                    }
+                    else
+                    {
+                        __warnings.insert(string("Function name '") + b.name + string("' is a reserved Lua keyword; binding '") + b.getFunctionName() + string("' was not generated."));
+                    }
+                }
+                e = e->NextSiblingElement("memberdef");
+            }
+        }
+        else if (strcmp(kind, "protected-func") == 0 ||
+                 strcmp(kind, "private-func") == 0)
+        {
+            // Check for inaccessible constructor/destructor
+            // and create a list of all other inaccessible functions
+            // (we do this so that classes that override a public function
+            // and change its scope to protected or private work properly
+            // from Lua-i.e. no binding is generated for such functions).
+            XMLElement* e = node->FirstChildElement("memberdef");
+            while (e)
+            {
+                if (strcmp(e->Attribute("virt"), "pure-virtual") == 0)
+                    hasPureVirtual = true;
+
+                FunctionBinding::Param t = getParam(e);
+                if (t.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
+                {
+                    classBinding.inaccessibleConstructor = true;
+                }
+                else if (t.type == FunctionBinding::Param::TYPE_DESTRUCTOR)
+                {
+                    classBinding.inaccessibleDestructor = true;
+                }
+                else
+                {
+                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
+                    b.type = FunctionBinding::MEMBER_FUNCTION;
+
+                    b.name = getName(e);
+                
+                    if (!isReservedKeyword(b.name))
+                    {
+                        // Ignore operators.
+                        if (b.name.find("operator") != 0)
+                        {
+                            b.returnParam = getParam(e, false, b.classname);
+                            if (b.returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
+                            {
+                                b.returnParam.info = refId;
+                                b.own = true;
+                            }
+
+                            getParams(e, b);
+                            getCreateFlag(e, b);
+                            classBinding.hidden[b.getFunctionName()].push_back(b);
+                        }
+                        else
+                        {
+                            __printOperatorWarning = true;
+                        }
+                    }
+                }
+                e = e->NextSiblingElement("memberdef");
+            }
+        }
+        else if (strcmp(kind, "protected-static-func") == 0 ||
+                 strcmp(kind, "private-static-func") == 0)
+        {
+            // Create a list of all other inaccessible functions
+            // (we do this so that classes that override a public function
+            // and change its scope to protected or private work properly
+            // from Lua-i.e. no binding is generated for such functions).
+
+            XMLElement* e = node->FirstChildElement("memberdef");
+            while (e)
+            {
+                if (e->FirstChildElement("templateparamlist"))
+                {
+                    __printTemplateWarning = true;
+                }
+                else if (getScriptFlag(e) != "ignore")
+                {
+                    FunctionBinding b(classBinding.classname, classBinding.uniquename);
+                    b.type = FunctionBinding::STATIC_FUNCTION;
+
+                    b.name = getName(e);
+                    if (!isReservedKeyword(b.name))
+                    {
+                        b.returnParam = getParam(e, false, b.classname);
+                        
+                        getParams(e, b);
+                        getCreateFlag(e, b);
+                        classBinding.hidden[b.getFunctionName()].push_back(b);
+                    }
+                }
+                e = e->NextSiblingElement("memberdef");
+            }
+        }
+        // Process public enums and typedefs.
+        else if (strcmp(kind, "public-type") == 0)
+        {
+            XMLElement* e = node->FirstChildElement("memberdef");
+            while (e)
+            {
+                if (getScriptFlag(e) != "ignore")
+                {
+                    if (strcmp(e->Attribute("kind"), "enum") == 0)
+                    {
+                        getEnum(e, classBinding.classname, classBinding.ns, classBinding.include);
+                    }
+                    else if (strcmp(e->Attribute("kind"), "typedef") == 0)
+                    {
+                        getTypedef(e, classBinding.classname, classBinding.ns);
+                    }
+                }
+                e = e->NextSiblingElement("memberdef");
+            }
+        }
+        else
+        {
+            // Ignore other section definitions.
+        }
+    }
+
+    // If the class has a pure-virtual method, we mark the constructor as inaccessible
+    // and remove any constructor bindings that are in the list.
+    if (hasPureVirtual)
+    {
+        classBinding.inaccessibleConstructor = true;
+        map<string, vector<FunctionBinding> >::iterator iter = classBinding.bindings.begin();
+        for (; iter != classBinding.bindings.end(); iter++)
+        {
+            if (iter->second[0].returnParam.type == FunctionBinding::Param::TYPE_CONSTRUCTOR)
+            {
+                classBinding.bindings.erase(iter);
+                break;
+            }
+        }
+    }
+
+    // Store the class's derived class(es)' ref id(s) if it has any.
+    node = classNode->FirstChildElement("derivedcompoundref");
+    while (node)
+    {
+        classBinding.derived.push_back(node->Attribute("refid"));
+        node = node->NextSiblingElement("derivedcompoundref");
+    }
+
+    // If the class has no base classes and it has derived classes, add it to the list of top-level classes.
+    if (!classNode->FirstChildElement("basecompoundref") && classBinding.derived.size() > 0)
+        _topLevelBaseClasses.push_back(classBinding.classname);
+
+    // Insert the class binding into the global table.
+    _classes[classBinding.classname] = classBinding;
+}
+
+void Generator::getEnums(XMLElement* fileNode, string ns)
+{
+    XMLElement* node = NULL;
+    const char* kind = NULL;
+    for (node = fileNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
+    {
+        kind = node->Attribute("kind");
+        if (!kind)
+        {
+            GP_ERROR("Section definition is missing required 'kind' attribute in XML document  '%s'.", _file);
+            return;
+        }
+
+        // Process the enums.
+        if (strcmp(kind, "enum") == 0)
+        {
+            XMLElement* e = node->FirstChildElement("memberdef");
+            while (e)
+            {
+                if (getScriptFlag(e) != "ignore" && strcmp(e->Attribute("kind"), "enum") == 0)
+                {
+                    getEnum(e, "", ns);
+                }
+                e = e->NextSiblingElement("memberdef");
+            }
+        }
+    }
+}
+
+void Generator::getEnum(XMLElement* e, string classname, string ns, string include)
+{
+    // Get the enumeration's name.
+    string enumname = classname;
+    if (enumname.size() > 0)
+        enumname += string("::");
+    enumname += getName(e);
+
+    // Get the ref id for the enum.
+    string refId = e->Attribute("id");
+
+    // Store the ref id to name mapping.
+    Generator::getInstance()->setIdentifier(refId, enumname);
+    
+    // Add the enum to the enum list if it's not there 
+    // (we implicitly create it when we set its scope path).
+    if (_enums.find(enumname) == _enums.end())
+        _enums[enumname].scopePath = Generator::getScopePath(enumname, ns);
+
+    // Set the include file for the enum.
+    if (include.size() > 0)
+        _enums[enumname].include = include;
+    else
+    {
+        XMLElement* location = e->FirstChildElement("location");
+        if (location)
+            _enums[enumname].include = location->Attribute("file");
+    }
+
+    for (e = e->FirstChildElement("enumvalue"); e; e = e->NextSiblingElement("enumvalue"))
+    {
+        _enums[enumname].values.push_back(getName(e));
+    }
+
+    // Add the enum to the set of namespace members if it is part of a namespace.
+    if (ns.size() > 0)
+        _namespaces[ns].insert(enumname);
+}
+
+void Generator::getTypedefs(XMLElement* fileNode, string ns)
+{
+    XMLElement* node = NULL;
+    const char* kind = NULL;
+    for (node = fileNode->FirstChildElement("sectiondef"); node != NULL; node = node->NextSiblingElement("sectiondef"))
+    {
+        kind = node->Attribute("kind");
+        if (!kind)
+        {
+            GP_ERROR("Section definition is missing required 'kind' attribute in XML document  '%s'.", _file);
+            return;
+        }
+
+        // Process the enums.
+        if (strcmp(kind, "typedef") == 0)
+        {
+            XMLElement* e = node->FirstChildElement("memberdef");
+            while (e)
+            {
+                if (getScriptFlag(e) != "ignore" && strcmp(e->Attribute("kind"), "typedef") == 0)
+                {
+                    getTypedef(e, "", ns);
+                }
+                e = e->NextSiblingElement("memberdef");
+            }
+        }
+    }
+}
+
+void Generator::getTypedef(XMLElement* e, string classname, string ns)
+{
+    TypedefBinding t;
+
+    // Get the typedef's name.
+    string tname = classname;
+    if (tname.size() > 0)
+        tname += string("::");
+    tname += getName(e);
+
+    // Get the typedef's id and store the mapping from ref id to name.
+    string refId = e->Attribute("id");
+    setIdentifier(refId, tname);
+
+    FunctionBinding::Param p = getParam(e);
+    if (p.info.size() > 0)
+        t.refId = p.info;
+
+    _typedefs[tname] = t;
+
+    // Add the typedef to the set of namespace members if it is part of a namespace.
+    if (ns.size() > 0)
+        _namespaces[ns].insert(tname);
+}
+
+static inline bool getScriptFlagHelper(XMLElement* e, string& flag)
+{
+    XMLElement* x = e->FirstChildElement("xmlonly");
+    if (x)
+    {
+        flag = x->GetText();
+        return true;
+    }
+
+    x = e->FirstChild() ? e->FirstChild()->ToElement() : NULL;
+    while (x)
+    {
+        if (getScriptFlagHelper(x, flag))
+            return true;
+
+        x = x->NextSibling() ? x->NextSibling()->ToElement() : NULL;
+    }
+    return false;
+}
+
+string Generator::getScriptFlag(XMLElement* e)
+{
+    string flag;
+
+    XMLElement* n = e->FirstChildElement("detaileddescription");
+    if (n)
+        getScriptFlagHelper(n, flag);
+    
+    return flag;
+}
+
+void Generator::getCreateFlag(XMLElement* e, FunctionBinding& b)
+{
+    if (getScriptFlag(e) == "create")
+        b.own = true;
+}
+
+string Generator::getName(XMLElement* e)
+{
+    // Get the name for the binding.
+    XMLElement* nameElement = e->FirstChildElement("name");
+    if (!nameElement)
+    {
+        GP_ERROR("Missing 'name' child node in XML document '%s'.", _file);
+        return string();
+    }
+    return nameElement->GetText();
+}
+
+bool Generator::getIsConstType(XMLElement* e)
+{
+    XMLElement* typeElement = e->FirstChildElement("type");
+    if (!typeElement)
+    {
+        GP_ERROR("Missing 'type' node in XML document '%s'.", _file);
+        return false;
+    }
+
+    XMLNode* textNode = typeElement->FirstChild();
+    if (textNode)
+    {
+        XMLText* text = textNode->ToText();
+        if (text)
+        {
+            string type = text->Value();
+            return type.find("const") != type.npos;
+        }
+    }
+    return false;
+}
+
+FunctionBinding::Param Generator::getParam(XMLElement* e, bool isVariable, string classname)
+{
+    // Get the type for the current element (either the return type or a parameter type).
+    XMLElement* typeElement = e->FirstChildElement("type");
+    if (!typeElement)
+    {
+        GP_ERROR("Missing 'type' node in XML document '%s'.", _file);
+    }
+
+    FunctionBinding::Param p;
+    XMLNode* textNode = typeElement->FirstChild();
+    if (!textNode)
+    {
+        // Get the name of the current element to see if it is a destructor.
+        string name = getName(e);
+        if (name.find("~") == 0)
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_DESTRUCTOR);
+        }
+        else
+        {
+            // Assume it's a constructor.
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_CONSTRUCTOR, FunctionBinding::Param::KIND_POINTER, name);
+        }
+    }
+    else
+    {
+        // Get the type string without const or reference qualifiers (and trim whitespace).
+        string refId = "";
+        string typeStr = "";
+        int levelsOfIndirection = 0;
+        FunctionBinding::Param::Kind kind;
+        {
+            // Attempt to process the type as reference (i.e. class, struct, enum, typedef, etc.) type.
+            XMLNode* node = textNode;
+            while (node)
+            {
+                if (strcmp(node->Value(), "ref") == 0)
+                {
+                    refId = node->ToElement()->Attribute("refid");
+                    typeStr += node->ToElement()->GetText();
+                }
+                else if (node->ToText())
+                {
+                    typeStr += node->ToText()->Value();
+                }
+
+                node = node->NextSibling();
+            }
+
+            typeStr = stripTypeQualifiers(typeStr, kind, levelsOfIndirection);
+        }
+
+        if (typeStr == "void")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_VOID, kind);
+        }
+        else if (typeStr == "bool")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_BOOL, kind);
+        }
+        else if (typeStr == "char" && kind != FunctionBinding::Param::KIND_POINTER)
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_CHAR, kind);
+        }
+        else if (typeStr == "short")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_SHORT, kind);
+        }
+        else if (typeStr == "int")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_INT, kind);
+        }
+        else if (typeStr == "long")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_LONG, kind);
+        }
+        else if (typeStr == "unsigned char")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_UCHAR, kind);
+        }
+        else if (typeStr == "unsigned short")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_USHORT, kind);
+        }
+        else if (typeStr == "unsigned int")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_UINT, kind);
+        }
+        else if (typeStr == "unsigned long")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_ULONG, kind);
+        }
+        else if (typeStr == "float")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_FLOAT, kind);
+        }
+        else if (typeStr == "double")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_DOUBLE, kind);
+        }
+        else if (typeStr == "string" || typeStr == "std::string")
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_STRING, kind, "string");
+        }
+        else if (typeStr == "char" && kind == FunctionBinding::Param::KIND_POINTER)
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_STRING, kind, "char*");
+        }
+        else if (_enums.find(typeStr) != _enums.end() ||
+            (classname.size() > 0 && _enums.find(classname + string("::") + typeStr) != _enums.end()))
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_ENUM, kind, refId);
+        }
+        else if (typeStr == "...")
+        {
+            __printVarargWarning = true;
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_VARARGS);
+        }
+        else
+        {
+            p = FunctionBinding::Param(FunctionBinding::Param::TYPE_UNRECOGNIZED, kind, (refId.size() > 0) ? refId : typeStr);
+        }
+        p.levelsOfIndirection = levelsOfIndirection;
+
+        // Check if the type is a pointer declared with square brackets (i.e. float x[4]).
+        XMLElement* arrayElement = NULL;
+        if ((arrayElement = e->FirstChildElement("array")) != NULL ||
+            (isVariable && (arrayElement = e->FirstChildElement("argsstring")) != NULL))
+        {
+            const char* text = arrayElement->GetText();
+            string arrayString = (text ? text : "");
+            string::size_type i = arrayString.find("[");
+            string::size_type k = arrayString.find("]");
+            if (i != arrayString.npos && k != arrayString.npos)
+            {
+                p.kind = FunctionBinding::Param::KIND_POINTER;
+                p.levelsOfIndirection = 1;
+                if (i != k - 1)
+                    p.info = arrayString.substr(i + 1, k - (i + 1));
+            }
+        }
+    }
+
+    // Get the default value for the parameter if it has one.
+    XMLElement* defaultValueElement = e->FirstChildElement("defval");
+    if (defaultValueElement)
+    {
+        p.hasDefaultValue = true;
+    }
+
+    return p;
+}
+
+void Generator::getParams(XMLElement* e, FunctionBinding& b)
+{
+    XMLElement* param = e->FirstChildElement("param");
+    while (param)
+    {
+        FunctionBinding::Param p = getParam(param, false, b.classname);
+        if (p.type != FunctionBinding::Param::TYPE_VARARGS)
+            b.paramTypes.push_back(p);
+        param = param->NextSiblingElement("param");
+    }
+}
+
+void Generator::resolveMembers(const ClassBinding& c)
+{
+    vector<ClassBinding*> derived;
+
+    // Go through the derived classes' bindings and update them.
+    ClassBinding* cb = NULL;
+    map<string, vector<FunctionBinding> >::const_iterator iter;
+    for (unsigned int i = 0; i < c.derived.size(); i++)
+    {
+        // If the class is not in the map of classes, then
+        // it was marked to be ignored, so skip over it.
+        string derivedClassName = getIdentifier(c.derived[i]);
+        if (_classes.find(derivedClassName) == _classes.end())
+            continue;
+
+        cb = &_classes[derivedClassName];
+
+        // Go through this class' bindings and add them to the current
+        // derived class if they are not already there (excluding constructors and destructors).
+        for (iter = c.bindings.begin(); iter != c.bindings.end(); iter++)
+        {
+            FunctionBinding b(cb->classname, cb->uniquename);
+            b.type = iter->second[0].type;
+            b.name = iter->second[0].name;
+
+            map<string, vector<FunctionBinding> >::iterator findIter = cb->bindings.find(b.getFunctionName());
+            map<string, vector<FunctionBinding> >::iterator hiddenIter = cb->hidden.find(b.getFunctionName());
+            if (findIter == cb->bindings.end() && hiddenIter == cb->hidden.end())
+            {
+                for (unsigned int i = 0, iCount = iter->second.size(); i < iCount; i++)
+                {
+                    if (iter->second[i].returnParam.type != FunctionBinding::Param::TYPE_CONSTRUCTOR &&
+                        iter->second[i].returnParam.type != FunctionBinding::Param::TYPE_DESTRUCTOR)
+                    {
+                        // Copy the binding, but set its function name to 
+                        // empty so that it is regenerated correctly.
+                        b = iter->second[i];
+                        b.functionName = "";
+                        b.classname = cb->classname;
+                        b.uniquename = cb->uniquename;
+
+                        cb->bindings[b.getFunctionName()].push_back(b);
+                    }
+                }
+            }
+            else
+            {
+                bool addBinding;
+                for (unsigned int i = 0, iCount = iter->second.size(); i < iCount; i++)
+                {
+                    string name = iter->second[i].name;
+
+                    addBinding = true;
+                    if (findIter != cb->bindings.end())
+                    {
+                        for (unsigned int j = 0, jCount = findIter->second.size(); j < jCount; j++)
+                        {
+                            if (FunctionBinding::signaturesMatch(iter->second[i], findIter->second[j]))
+                            {
+                                addBinding = false;
+                                break;
+                            }
+                        }
+
+                        // To call the base function, we have to qualify the call since
+                        // the derived class has a function with the same name and different parameters.
+                        if (addBinding)
+                            name = iter->second[i].classname + string("::") + iter->second[i].name;
+                    }
+                    if (hiddenIter != cb->hidden.end())
+                    {
+                        for (unsigned int j = 0, jCount = hiddenIter->second.size(); j < jCount; j++)
+                        {
+                            if (FunctionBinding::signaturesMatch(iter->second[i], hiddenIter->second[j]))
+                            {
+                                addBinding = false;
+                                break;
+                            }
+                        }
+                    }
+
+                    if (addBinding)
+                    {
+                        FunctionBinding b = iter->second[i];
+                        b.name = name;
+                        b.functionName = findIter->first;
+                        b.classname = cb->classname;
+                        b.uniquename = getUniqueName(cb->classname);
+
+                        if (findIter != cb->bindings.end())
+                            findIter->second.push_back(b);
+                        else
+                            cb->bindings[b.getFunctionName()].push_back(b);
+                    }
+                }
+            }
+        }
+
+        derived.push_back(cb);
+    }
+
+    // Go through the derived classes' bindings and resolve the members for their derived classes.
+    for (unsigned int i = 0; i < derived.size(); i++)
+    {
+        resolveMembers(*derived[i]);
+    }
+}
+
+void Generator::resolveInheritance()
+{
+    // Go through the class inheritance tree and update each class's bindings list 
+    // to include the bindings from the base class that haven't been overridden.
+    for (unsigned int i = 0; i < _topLevelBaseClasses.size(); i++)
+    {
+        resolveMembers(_classes[_topLevelBaseClasses[i]]);
+    }
+}
+
+void Generator::resolveIncludes(const ClassBinding& c)
+{
+    vector<ClassBinding*> derived;
+
+    // Go through the derived classes' bindings and update them.
+    ClassBinding* cb = NULL;
+    map<string, vector<FunctionBinding> >::const_iterator iter;
+    for (unsigned int i = 0; i < c.derived.size(); i++)
+    {
+        // If the class is not in the map of classes, then
+        // it was marked to be ignored, so skip over it.
+        string derivedClassName = getIdentifier(c.derived[i]);
+        if (_classes.find(derivedClassName) == _classes.end())
+            continue;
+
+        cb = &_classes[derivedClassName];
+
+        // Add all include files (uniquely) from the base class to the derived class.
+        map<string, set<string> >::iterator baseIncludes = _includes.find(c.include);
+        if (baseIncludes != _includes.end() && baseIncludes->second.size() > 0)
+        {
+            set<string>::iterator iter = baseIncludes->second.begin();
+            set<string>& derivedIncludes = _includes[cb->include];
+            for (; iter != baseIncludes->second.end(); iter++)
+            {
+                derivedIncludes.insert(*iter);
+            }
+        }
+        
+        derived.push_back(cb);
+    }
+
+    // Go through the derived classes' bindings and resolve the members for their derived classes.
+    for (unsigned int i = 0; i < derived.size(); i++)
+    {
+        resolveIncludes(*derived[i]);
+    }
+}
+
+void Generator::resolveInheritedIncludes()
+{
+    // Go through the class inheritance tree and update each class's 
+    // list of includes to include the includes from the base class
+    for (unsigned int i = 0; i < _topLevelBaseClasses.size(); i++)
+    {
+        resolveIncludes(_classes[_topLevelBaseClasses[i]]);
+    }
+}
+
+void Generator::resolveType(FunctionBinding::Param* param, string functionName, string header)
+{
+    string name = getIdentifier(param->info);
+
+    if (param->type == FunctionBinding::Param::TYPE_UNRECOGNIZED)
+    {
+        map<string, TypedefBinding>::iterator typedefIter = _typedefs.find(name);
+        if (typedefIter != _typedefs.end() && typedefIter->second.refId.size() > 0)
+        {
+            param->type = FunctionBinding::Param::TYPE_OBJECT;
+            param->info = typedefIter->second.refId;
+        }
+        else
+        {
+            map<string, ClassBinding>::iterator classIter = _classes.find(name);
+            if (classIter != _classes.end())
+            {
+                param->type = FunctionBinding::Param::TYPE_OBJECT;
+            }
+            else
+            {
+                map<string, EnumBinding>::iterator enumIter = _enums.find(name);
+                if (enumIter != _enums.end())
+                {
+                    param->type = FunctionBinding::Param::TYPE_ENUM;
+                }
+                else
+                {
+                    __warnings.insert(string("Unrecognized C++ type: ") + functionName + string(" -- ") + (name.size() > 0 ? name : param->info));
+                }
+            }
+        }
+    }
+
+    // Ensure that the header for the Lua enum conversion 
+    // functions is included in the file containing the
+    // generated binding that this param/return value is part of.
+    if (param->type == FunctionBinding::Param::TYPE_ENUM)
+    {
+        string enumHeader = string("lua_") + getUniqueName(name) + string(".h");
+        if (_includes.find(header) != _includes.end())
+        {
+            set<string>& includes = _includes[header];
+            if (includes.find(enumHeader) == includes.end())
+                includes.insert(enumHeader);
+        }
+        else
+        {
+            _includes[header].insert(enumHeader);
+        }
+    }
+}
+
+void Generator::resolveTypes()
+{
+    // Go through all member functions and attempt to resolve unrecognized types.
+    for (map<string, ClassBinding>::iterator iter = _classes.begin(); iter != _classes.end(); iter++)
+    {
+        map<string, vector<FunctionBinding> >::iterator functionNameIter = iter->second.bindings.begin();
+        for (; functionNameIter != iter->second.bindings.end(); functionNameIter++)
+        {
+            vector<FunctionBinding>::iterator functionIter = functionNameIter->second.begin();
+            for (; functionIter != functionNameIter->second.end(); functionIter++)
+            {
+                resolveType(&functionIter->returnParam, iter->first + string("::") + functionIter->name, iter->second.include);
+
+                vector<FunctionBinding::Param>::iterator paramIter = functionIter->paramTypes.begin();
+                for (; paramIter != functionIter->paramTypes.end(); paramIter++)
+                {
+                    resolveType(&(*paramIter), iter->first + string("::") + functionIter->name, iter->second.include);
+                }
+            }
+        }
+    }
+
+    // Go through all non-member functions and attempt to resolve unrecognized types.
+    string globalHeader = string("lua_") + string(LUA_GLOBAL_FILENAME) + string(".h");
+    for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
+    {
+        vector<FunctionBinding>::iterator functionIter = iter->second.begin();
+        for (; functionIter != iter->second.end(); functionIter++)
+        {
+            resolveType(&functionIter->returnParam, functionIter->name, globalHeader);
+
+            vector<FunctionBinding::Param>::iterator paramIter = functionIter->paramTypes.begin();
+            for (; paramIter != functionIter->paramTypes.end(); paramIter++)
+            {
+                resolveType(&(*paramIter), functionIter->name, globalHeader);
+            }
+        }
+    }
+}
+
+void Generator::generateBindings(string* bindingNS)
+{
+    bool generatingGameplay = false;
+    if (bindingNS && (*bindingNS == "gameplay"))
+        generatingGameplay = true;
+
+    string luaAllHStr = _outDir + string(LUA_ALL_BINDINGS_FILENAME) + string(".h");
+    ostringstream luaAllH;
+    string includeGuard = string(LUA_ALL_BINDINGS_FILENAME) + string("_H_");
+    transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
+    luaAllH << "#ifndef " << includeGuard << "\n";
+    luaAllH << "#define " << includeGuard << "\n\n";
+    
+    string luaAllCppStr = _outDir + string(LUA_ALL_BINDINGS_FILENAME) + string(".cpp");
+    ostringstream luaAllCpp;
+    luaAllCpp << "#include \"Base.h\"\n";
+    luaAllCpp << "#include \"" << string(LUA_ALL_BINDINGS_FILENAME) << ".h\"\n\n";
+    if (bindingNS)
+    {
+        luaAllCpp << "namespace " << *bindingNS << "\n";
+        luaAllCpp << "{\n\n";
+    }
+    luaAllCpp << "void lua_RegisterAllBindings()\n";
+    luaAllCpp << "{\n";
+
+    // Write out all the class bindings.
+    if (_classes.size() > 0)
+    {
+        map<string, ClassBinding>::iterator iter = _classes.begin();
+        for (; iter != _classes.end(); iter++)
+        {
+            if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->second.classname) == _namespaces["gameplay"].end()))
+            {
+                cout << "Generating bindings for '" << iter->first << "'...\n";
+                iter->second.write(_outDir, _includes[iter->second.include], bindingNS);
+
+                luaAllH << "#include \"lua_" << iter->second.uniquename << ".h\"\n";
+                luaAllCpp << "    luaRegister_" << iter->second.uniquename << "();\n";
+            }
+        }
+    }
+
+    // Go through all the classes and if they have any derived classes, add them to the list of base classes.
+    vector<string> baseClasses;
+    for (map<string, ClassBinding>::iterator iter = _classes.begin(); iter != _classes.end(); iter++)
+    {
+        if (iter->second.derived.size() > 0)
+            baseClasses.push_back(iter->first);
+    }
+
+    // Write out all the enum files.
+    if (_enums.size() > 0)
+    {
+        // Write out the enum conversion function declarations.
+        for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
+        {
+            if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
+            {
+                cout << "Generating bindings for '" << iter->first << "'...\n";
+
+                // Header.
+                string enumHStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".h");
+                ostringstream enumH;
+                includeGuard = string("lua_") + getUniqueName(iter->first) + string("_H_");
+                transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
+                enumH << "#ifndef " << includeGuard << "\n";
+                enumH << "#define " << includeGuard << "\n\n";
+                enumH << "#include \"" << iter->second.include << "\"\n\n";
+
+                if (bindingNS)
+                {
+                    enumH << "namespace " << *bindingNS << "\n";
+                    enumH << "{\n\n";
+                }
+
+                enumH << "// Lua bindings for enum conversion functions for " << iter->first << ".\n";
+                enumH << iter->first << " lua_enumFromString_" << getUniqueName(iter->first) << "(const char* s);\n";
+                enumH << "const char* lua_stringFromEnum_" << getUniqueName(iter->first) << "(" << iter->first << " e);\n\n";
+
+                if (bindingNS)
+                {
+                    enumH << "}\n\n";
+                }
+
+                enumH << "#endif\n";
+
+                writeFile(enumHStr, enumH.str());
+
+                // Implementation.
+                string enumCppStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".cpp"); 
+                ostringstream enumCpp(enumCppStr.c_str());
+                enumCpp << "#include \"Base.h\"\n";
+                enumCpp << "#include \"lua_" << getUniqueName(iter->first) << ".h\"\n\n";
+
+                if (bindingNS)
+                {
+                    enumCpp << "namespace " << *bindingNS << "\n";
+                    enumCpp << "{\n\n";
+                }
+
+                enumCpp << "static const char* enumStringEmpty = \"\";\n\n";
+
+                // Build the scope string if applicable.
+                string scope;
+                if (iter->second.scopePath.size() > 0)
+                {
+                    for (unsigned int i = 0; i < iter->second.scopePath.size(); i++)
+                    {
+                        scope += iter->second.scopePath[i] + string("::");
+                    }
+                }
+
+                // Write out the string constants that correspond to the enumeration values.
+                for (unsigned int i = 0; i < iter->second.values.size(); i++)
+                {
+                    enumCpp << "static const char* luaEnumString_" << getUniqueName(iter->first) << "_";
+                    enumCpp << iter->second.values[i] << " = \"" << iter->second.values[i] << "\";\n";
+                }
+                enumCpp << "\n";
+
+                enumCpp << iter->first << " lua_enumFromString_" << getUniqueName(iter->first) << "(const char* s)\n";
+                enumCpp << "{\n";
+                
+                for (unsigned int i = 0; i < iter->second.values.size(); i++)
+                {
+                    enumCpp << "    ";
+                        
+                    enumCpp << "if (strcmp(s, luaEnumString_" << getUniqueName(iter->first) << "_" << iter->second.values[i] << ") == 0)\n";
+                    enumCpp << "        return ";
+                    if (scope.size() > 0)
+                        enumCpp << scope;
+                    enumCpp << iter->second.values[i] << ";\n";
+
+                    if (i == iter->second.values.size() - 1)
+                    {
+                        //enumCpp << "    GP_ERROR(\"Invalid enumeration value '%s' for enumeration " << iter->first << ".\", s);\n";
+                        enumCpp << "    return ";
+                        if (scope.size() > 0)
+                            enumCpp << scope;
+                        enumCpp << iter->second.values[0] << ";\n";
+                    }
+                }
+
+                enumCpp << "}\n\n";
+
+                enumCpp << "const char* lua_stringFromEnum_" << getUniqueName(iter->first) << "(" << iter->first << " e)\n";
+                enumCpp << "{\n";
+
+                // Write out the enum-to-string conversion code.
+                for (unsigned int i = 0; i < iter->second.values.size(); i++)
+                {
+                    enumCpp << "    ";
+                        
+                    enumCpp << "if (e == ";
+                    if (scope.size() > 0)
+                        enumCpp << scope;
+                    enumCpp << iter->second.values[i] << ")\n";
+                    enumCpp << "        return luaEnumString_" << getUniqueName(iter->first) << "_" << iter->second.values[i] << ";\n";
+
+                    if (i == iter->second.values.size() - 1)
+                    {
+                        //enumCpp << "    GP_ERROR(\"Invalid enumeration value '%d' for enumeration " << iter->first << ".\", e);\n";
+                        enumCpp << "    return enumStringEmpty;\n";
+                    }
+                }
+
+                enumCpp << "}\n\n";
+
+                if (bindingNS)
+                {
+                    enumCpp << "}\n\n";
+                }
+
+                writeFile(enumCppStr, enumCpp.str());
+            }
+        }
+    }
+
+    // Write out the global bindings file.
+    cout << "Generating global bindings...\n";
+    if (baseClasses.size() > 0 || _functions.size() > 0 || _enums.size() > 0)
+    {
+        // Calculate if there are global function bindings to write out.
+        bool generateGlobalFunctionBindings = false;
+        if (_functions.size() > 0)
+        {
+            for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
+            {
+                if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
+                {
+                    generateGlobalFunctionBindings = true;
+                    break;
+                }
+            }
+        }
+
+        // Calculate if there are enum bindings to write out.
+        bool generateEnumBindings = false;
+        if (_enums.size() > 0)
+        {
+            for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
+            {
+                if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
+                {
+                    generateEnumBindings = true;
+                    break;
+                }
+            }
+        }
+
+        // Write out the header file.
+        {
+            string path = _outDir + string(LUA_GLOBAL_FILENAME) + string(".h");
+            ostringstream global;
+            includeGuard = string(LUA_GLOBAL_FILENAME) + string("_H_");
+            transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
+            global << "#ifndef " << includeGuard << "\n";
+            global << "#define " << includeGuard << "\n\n";
+
+            // Write out the needed includes for the global enumeration function.
+            for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
+            {
+                if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
+                    global << "#include \"lua_" << getUniqueName(iter->first) << ".h\"\n";
+            }
+            global << "\n";
+            luaAllH << "#include \"" << string(LUA_GLOBAL_FILENAME) << ".h\"\n";
+            luaAllCpp << "    luaRegister_" << LUA_GLOBAL_FILENAME << "();\n";
+
+            if (bindingNS)
+            {
+                global << "namespace " << *bindingNS << "\n";
+                global << "{\n\n";
+            }
+
+            if (generateGlobalFunctionBindings)
+            {
+                global << "// Lua bindings for global functions.\n";
+
+                // Write out the binding function declarations.
+                for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
+                {
+                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
+                        global << "int " << iter->second[0].getFunctionName() << "(lua_State* state);\n";
+                }
+                global << "\n";
+            }
+
+            if (generateEnumBindings)
+            {
+                global << "// Global enum to string conversion function (used to pass enums to Lua from C++).\n";
+                global << "const char* lua_stringFromEnumGlobal(std::string& enumname, unsigned int value);\n\n";
+            }
+            
+            // Write out the signature of the function used to register the global functions with Lua.
+            global << "void luaRegister_" << LUA_GLOBAL_FILENAME << "();\n\n";
+
+            if (bindingNS)
+                global << "}\n\n";
+            global << "#endif\n";
+
+            writeFile(path, global.str());
+        }
+
+        // Write out the implementation.
+        {
+            string path = _outDir + string(LUA_GLOBAL_FILENAME) + string(".cpp");
+            ostringstream global;
+            global << "#include \"ScriptController.h\"\n";
+            global << "#include \"" << LUA_GLOBAL_FILENAME << ".h\"\n";
+            map<string, set<string> >::iterator iter = _includes.find(string(LUA_GLOBAL_FILENAME) + string(".h"));
+            if (iter != _includes.end())
+            {
+                set<string>::iterator includeIter = iter->second.begin();
+                for (; includeIter != iter->second.end(); includeIter++)
+                {
+                    global << "#include \"" << *includeIter << "\"\n";
+                }
+            }
+            global << "\n";
+
+            if (bindingNS)
+            {
+                global << "namespace " << *bindingNS << "\n";
+                global << "{\n\n";
+            }
+
+            // Write out the function used to register all global bindings with Lua.
+            global << "void luaRegister_" << LUA_GLOBAL_FILENAME << "()\n";
+            global << "{\n";
+        
+            if (generateGlobalFunctionBindings)
+            {
+                // Bind the non-member functions.
+                for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
+                {
+                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
+                        global << "    gameplay::ScriptUtil::registerFunction(\"" << iter->second[0].name << "\", " << iter->second[0].getFunctionName() << ");\n";
+                }
+            }
+
+            // Generate the hierarchy map.
+            if (baseClasses.size() > 0)
+            {
+                for (unsigned int i = 0, count = baseClasses.size(); i < count; i++)
+                {
+                    set<string> derived;
+                    getAllDerived(derived, baseClasses[i]);
+                    for (set<string>::iterator iter = derived.begin(); iter != derived.end(); iter++)
+                    {
+                        if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(*iter) == _namespaces["gameplay"].end()))
+                            global << "    gameplay::ScriptUtil::setGlobalHierarchyPair(\"" << baseClasses[i] << "\", \"" << *iter << "\");\n";
+                    }
+                }
+            }
+
+            // Register all enums.
+            if (generateEnumBindings)
+            {
+                global << "    gameplay::ScriptUtil::addStringFromEnumConversionFunction(&";
+                if (bindingNS)
+                    global << *bindingNS << "::";
+                global << "lua_stringFromEnumGlobal);\n";
+
+                for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
+                {
+                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
+                    {
+                        global << "\n    // Register enumeration " << iter->first << ".\n";
+                        global << "    {\n";
+
+                        global << "        std::vector<std::string> scopePath;\n";
+                        for (unsigned int i = 0; i < iter->second.scopePath.size(); i++)
+                        {
+                            global << "        scopePath.push_back(\"" << iter->second.scopePath[i] << "\");\n";
+                        }
+
+                        vector<string>::iterator enumIter = iter->second.values.begin();
+                        for (; enumIter != iter->second.values.end(); enumIter++)
+                        {
+                            global << "        gameplay::ScriptUtil::registerConstantString(\"" << *enumIter << "\", \"" << *enumIter << "\", scopePath);\n";
+                        }
+
+                        global << "    }\n";
+                    }
+                }
+            }
+            global << "}\n\n";
+            
+            // Write out the binding functions.
+            if (generateGlobalFunctionBindings)
+            {
+                for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
+                {
+                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
+                        FunctionBinding::write(global, iter->second);
+                }
+            }
+
+            // Write out the global enum conversion function (used to pass enums from C++ to Lua).
+            if (generateEnumBindings)
+            {
+                global << "static const char* enumStringEmpty = \"\";\n\n";
+                global << "const char* lua_stringFromEnumGlobal(std::string& enumname, unsigned int value)\n";
+                global << "{\n";
+                for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
+                {
+                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
+                    {
+                        global << "    if (enumname == \"";
+                        global << iter->first << "\")\n";
+                        global << "        return lua_stringFromEnum_" << getUniqueName(iter->first) << "((" << iter->first << ")value);\n";
+                    }
+                }
+                global << "\n";
+                global << "    GP_ERROR(\"Unrecognized enumeration type '%s'.\", enumname.c_str());\n";
+                global << "    return enumStringEmpty;\n";
+                global << "}\n\n";
+            }
+
+            if (bindingNS)
+                global << "}\n";
+
+            writeFile(path, global.str());
+        }
+    }
+
+    luaAllCpp << "}\n\n";
+    if (bindingNS)
+        luaAllCpp << "}\n\n";
+
+    writeFile(luaAllCppStr, luaAllCpp.str());
+
+    if (bindingNS)
+    {
+        luaAllH << "\nnamespace " << *bindingNS << "\n";
+        luaAllH << "{\n\n";
+    }
+    luaAllH << "void lua_RegisterAllBindings();\n\n";
+    if (bindingNS)
+        luaAllH<< "}\n\n";
+    luaAllH << "#endif\n";
+
+    writeFile(luaAllHStr, luaAllH.str());
+}
+
+void Generator::getAllDerived(set<string>& derived, string classname)
+{
+    for (unsigned int i = 0, count = _classes[classname].derived.size(); i < count; i++)
+    {
+        // If the derived class is not in the ref ID table, then it
+        // is a hidden (protected, private, etc.) class, so don't include it.
+        if (_refIds.find(_classes[classname].derived[i]) != _refIds.end())
+        {
+            string derivedClassName = getIdentifier(_classes[classname].derived[i]);
+            derived.insert(derivedClassName);
+            getAllDerived(derived, derivedClassName);
+        }
+    }
+}
+
+void Generator::getIncludes(XMLElement* e, string filename)
+{
+    filename.replace(filename.find(".cpp"), 4, ".h");
+    for (e = e->FirstChildElement("includes"); e; e = e->NextSiblingElement("includes"))
+    {
+        if (e->Attribute("refid"))
+            _includes[filename].insert(e->GetText());
+    }
+}
+
+// ----------------------------------------------------------------------------
+// Utility functions
+
+static string trim(const string& str)
+{
+    string s = str;
+    while (isspace(s[0]))
+    {
+        s.erase(s.begin());
+    }
+    while (isspace(s[s.size() - 1]))
+    {
+        s.erase(s.begin() + s.size() - 1);
+    }
+    return s;
+}
+
+static string stripTypeQualifiers(const string& typeStr, FunctionBinding::Param::Kind& kind, int& levelsOfIndirection)
+{
+    levelsOfIndirection = 0;
+
+    string type = typeStr;
+    kind = FunctionBinding::Param::KIND_VALUE;
+
+    // Check if the type is a reference.
+    string::size_type i = type.find("&");
+    if (i != type.npos)
+    {
+        kind = FunctionBinding::Param::KIND_REFERENCE;
+        type.erase(type.begin() + i);
+    }
+
+    // Check if the type is a pointer.
+    while ((i = type.find("*")) != std::string::npos)
+    {
+        kind = FunctionBinding::Param::KIND_POINTER;
+        type.erase(type.begin() + i);
+        ++levelsOfIndirection;
+        int j = 0;
+    }
+
+    // Ignore const qualifiers.
+    i = type.find("const ");
+    if (i != type.npos)
+    {
+        type.erase(type.begin() + i, type.begin() + i + 6);
+    }
+
+    return trim(type);
+}
+
+static inline bool isWantedFileNormal(const string& s)
+{
+    if (s.find(".xml") == s.size() - 4)
+    {
+        if (s.find("class") == 0 || s.find("struct") == 0 || 
+            (s.find("_") == 0 && (s.find("h.xml") != s.npos || s.find("cpp.xml") != s.npos)))
+            return true;
+    }
+    return false;
+}
+
+static inline bool isNamespaceFile(const string& s)
+{
+    if (s.find(".xml") == s.size() - 4)
+    {
+        if (s.find("namespace") == 0)
+            return true;
+    }
+    return false;
+}
+
+static inline bool isGeneratedBindingFile(const string& s)
+{
+    return ( (s.find(".cpp") == s.size() - 4) || (s.find(".h") == s.size() - 2) );
+}
+
+static bool getFileList(string directory, vector<string>& files, bool (*isWantedFile)(const string& s))
+{
+#ifdef WIN32
+    string path = directory + string("/*");
+
+    // Convert char to wchar.
+    basic_string<TCHAR> wPath;
+    wPath.assign(path.begin(), path.end());
+
+    WIN32_FIND_DATA FindFileData;
+    HANDLE hFind = FindFirstFile(wPath.c_str(), &FindFileData);
+    if (hFind == INVALID_HANDLE_VALUE) 
+    {
+        return false;
+    }
+    do
+    {
+        // Add to the list if this is not a directory and it passes the test function.
+        if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
+        {
+            // Convert wchar to char.
+            basic_string<TCHAR> wfilename(FindFileData.cFileName);
+            string filename;
+            filename.assign(wfilename.begin(), wfilename.end());
+
+            if (isWantedFile(filename))
+            {
+                filename = string(directory) + filename;
+                files.push_back(filename);
+            }
+        }
+    } while (FindNextFile(hFind, &FindFileData) != 0);
+
+    FindClose(hFind);
+    return true;
+#else
+    string path = directory + string("/.");
+    struct dirent* dp;
+    DIR* dir = opendir(path.c_str());
+    if (!dir)
+    {
+        return false;
+    }
+    while ((dp = readdir(dir)) != NULL)
+    {
+        string filepath(path);
+        filepath.append("/");
+        filepath.append(dp->d_name);
+
+        struct stat buf;
+        if (!stat(filepath.c_str(), &buf))
+        {
+            // Add to the list if this is not a directory and it passes the test function.
+            if (!S_ISDIR(buf.st_mode))
+            {
+                string filename = dp->d_name;
+                if (isWantedFile(filename))
+                {
+                    filename = string(directory) + filename;
+                    files.push_back(filename);
+                }
+            }
+        }
+    }
+    closedir(dir);
+    return true;
+#endif
+}
+
+bool isReservedKeyword(string name)
+{
+    static set<string> keywords;
+    if (keywords.size() == 0)
+    {
+        keywords.insert("and");
+        keywords.insert("break");
+        keywords.insert("do");
+        keywords.insert("else");
+        keywords.insert("elseif");
+        keywords.insert("end");
+        keywords.insert("false");
+        keywords.insert("for");
+        keywords.insert("function");
+        keywords.insert("if");
+        keywords.insert("in");
+        keywords.insert("local");
+        keywords.insert("nil");
+        keywords.insert("not");
+        keywords.insert("or");
+        keywords.insert("repeat");
+        keywords.insert("return");
+        keywords.insert("then");
+        keywords.insert("true");
+        keywords.insert("until");
+        keywords.insert("while");
+    };
+
+    return keywords.find(name) != keywords.end();
+}
+
+// ----------------------------------------------------------------------------

+ 207 - 207
tools/luagen/src/Generator.h

@@ -1,207 +1,207 @@
-#ifndef GENERATOR_H_
-#define GENERATOR_H_
-
-#include "Base.h"
-#include "ClassBinding.h"
-#include "EnumBinding.h"
-#include "FunctionBinding.h"
-#include "Generator.h"
-#include "TypedefBinding.h"
-
-#include <tinyxml2.h>
-using namespace tinyxml2;
-
-/**
- * Generates script bindings.
- */
-class Generator
-{
-public:
-
-    /**
-     * Retrieves the global instance of the generator.
-     * 
-     * @return The global instance of the generator.
-     */
-    static Generator* getInstance();
-
-    /**
-     * Releases the global instance of the generator.
-     */
-    static void releaseInstance();
-
-    /**
-     * Retrieves the unique name for the given identifier (class, struct, enum, etc.).
-     * 
-     * @param name The identifier's name.
-     * @return The unique name.
-     */
-    static string getUniqueName(string name);
-
-    /**
-     * Retrieves the unique name for the given ref id.
-     * 
-     * @param refId The ref id.
-     * @return The unique name.
-     */
-    string getUniqueNameFromRef(string refId);
-
-    /**
-     * Gets the scope path for a given fully resolved classname.
-     * 
-     * @param classname The class name.
-     * @param ns The namespace of the class if it has one.
-     * @return The scope path.
-     */
-    static vector<string> getScopePath(string classname, string ns = string());
-
-    /**
-     * Retrieves the class/struct/enum name for the given ref id.
-     * 
-     * @param refId The ref id.
-     * @return The class/struct/enum name.
-     */
-    string getIdentifier(string refId);
-
-    /**
-     * Gets the given class name (without the namespace) and stores the class's namespace in the given string pointer (if non-null).
-     * 
-     * @param classname The fully qualified name of the class.
-     * @param ns Output variable for the namespace of the class.
-     * @return The class name without the namespace.
-     */
-    string getClassNameAndNamespace(string classname, string* ns);
-
-    /**
-     * Sets the given ref id and class/struct/enum name pair.
-     * 
-     * @param refId The ref id.
-     * @param classname The class/struct/enum name.
-     */
-    void setIdentifier(string refId, string classname);
-
-    /**
-     * Generates Lua bindings for all classes defined within the given input directory
-     * and places the generated class bindings in the given output directory.
-     * Note that the input directory must point to a folder containing the Doxygen XML 
-     * output files for the classes that the user wants to generate bindings for.
-     * 
-     * @param inDir The input directory (must contain Doxygen XML output files).
-     * @param outDir The output directory.
-     * @param bindingNS The namespace to generate the bindings within.
-     */
-    void run(string inDir, string outDir, string* bindingNS = NULL);
-
-    /**
-     * Retrieves whether the given class is derived from Ref.
-     * 
-     * @param classname The name of the class.
-     * @return True if the class is derived from Ref; false otherwise.
-     */
-    bool isRef(string classname);
-
-protected:
-    /**
-     * Constructor.
-     */
-    Generator();
-
-    /**
-     * Destructor.
-     */
-    ~Generator();
-
-    // Checks if the given class name specifies a class derived from the class represented by the given class binding.
-    bool isDerived(const ClassBinding& c, string classname);
-
-    // Gets the name of the namespace, file, class, or struct.
-    string getCompoundName(XMLElement* node);
-
-    // Parses the non-member functions and adds them to the list (optionally within the given namespace).
-    void getFunctions(XMLElement* classNode, string ns = "");
-
-    // Parses the namespace (with the given name).
-    void getNamespace(XMLElement* nsNode, const string& name);
-
-    // Parses the class (with the given name) and adds it to the list.
-    void getClass(XMLElement* classNode, const string& name);
-
-    // Parses all enumerations within a file (optionally within a namespace).
-    void getEnums(XMLElement* fileNode, string ns = "");
-    
-    // Parses the enumeration type and adds it to the global list.
-    void getEnum(XMLElement* e, string classname = "", string ns = "", string include = "");
-
-    // Parses all typedefs within a file (optionall within a namespace).
-    void getTypedefs(XMLElement* fileNode, string ns = "");
-
-    // Parses the typedef and adds it to the global list.
-    void getTypedef(XMLElement* e, string classname = "", string ns = "");
-
-    // Gets the script flag if it is specified.
-    string getScriptFlag(XMLElement* e);
-
-    // Gets whether the current function has been marked as a creation function
-    // (indicating that the return value is owned by the script runtime and not C++).
-    void getCreateFlag(XMLElement* e, FunctionBinding& b);
-
-    // Gets the name of the binding.
-    string getName(XMLElement* e);
-
-    // Gets whether the type is const or not.
-    bool getIsConstType(XMLElement* e);
-
-    // Gets the parameter or return value, optionally within the scope of the given class.
-    FunctionBinding::Param getParam(XMLElement* e, bool isVariable = false,  string classname = "");
-
-    // Gets all of the parameters for a function.
-    void getParams(XMLElement* e, FunctionBinding& b);
-
-    // Resolves members for all classes' derived from class 'c'.
-    void resolveMembers(const ClassBinding& c);
-
-    // Resolves the inheritance.
-    void resolveInheritance();
-
-    // Resolves includes for all classes' derived from class 'c'.
-    void resolveIncludes(const ClassBinding& c);
-
-    // Resolves inherited include files.
-    void resolveInheritedIncludes();
-
-    // Resolves the type for a single parameter/return value 
-    // (also takes the function that the parameter/return value is for along
-    // with the header file that the parameter/return value belongs to-the original
-    // class header file for class bindings or the global Lua bindings header file
-    // for global bindings).
-    void resolveType(FunctionBinding::Param* param, string functionName, string header);
-
-    // Resolves all unrecognized types.
-    void resolveTypes();
-
-    // Generates the bindings to C++ header and source files.
-    void generateBindings(string* bindingNS);
-    
-    // Gets the set off all classes that derives from the given class.
-    void getAllDerived(set<string>& derived, string classname);
-
-    // Gets the included files for a cpp file.
-    void getIncludes(XMLElement* e, string filename);
-
-private:
-    static Generator* __instance;
-
-    const char* _file;
-    map<string, string> _refIds;
-    string _outDir;
-    map<string, ClassBinding> _classes;
-    vector<string> _topLevelBaseClasses;
-    map<string, set<string> > _includes;
-    map<string, vector<FunctionBinding> > _functions;
-    map<string, EnumBinding> _enums;
-    map<string, set<string> > _namespaces;
-    map<string, TypedefBinding> _typedefs;
-    set<string> __warnings;
-};
-
-#endif
+#ifndef GENERATOR_H_
+#define GENERATOR_H_
+
+#include "Base.h"
+#include "ClassBinding.h"
+#include "EnumBinding.h"
+#include "FunctionBinding.h"
+#include "Generator.h"
+#include "TypedefBinding.h"
+
+#include <tinyxml2.h>
+using namespace tinyxml2;
+
+/**
+ * Generates script bindings.
+ */
+class Generator
+{
+public:
+
+    /**
+     * Retrieves the global instance of the generator.
+     * 
+     * @return The global instance of the generator.
+     */
+    static Generator* getInstance();
+
+    /**
+     * Releases the global instance of the generator.
+     */
+    static void releaseInstance();
+
+    /**
+     * Retrieves the unique name for the given identifier (class, struct, enum, etc.).
+     * 
+     * @param name The identifier's name.
+     * @return The unique name.
+     */
+    static string getUniqueName(string name);
+
+    /**
+     * Retrieves the unique name for the given ref id.
+     * 
+     * @param refId The ref id.
+     * @return The unique name.
+     */
+    string getUniqueNameFromRef(string refId);
+
+    /**
+     * Gets the scope path for a given fully resolved classname.
+     * 
+     * @param classname The class name.
+     * @param ns The namespace of the class if it has one.
+     * @return The scope path.
+     */
+    static vector<string> getScopePath(string classname, string ns = string());
+
+    /**
+     * Retrieves the class/struct/enum name for the given ref id.
+     * 
+     * @param refId The ref id.
+     * @return The class/struct/enum name.
+     */
+    string getIdentifier(string refId);
+
+    /**
+     * Gets the given class name (without the namespace) and stores the class's namespace in the given string pointer (if non-null).
+     * 
+     * @param classname The fully qualified name of the class.
+     * @param ns Output variable for the namespace of the class.
+     * @return The class name without the namespace.
+     */
+    string getClassNameAndNamespace(string classname, string* ns);
+
+    /**
+     * Sets the given ref id and class/struct/enum name pair.
+     * 
+     * @param refId The ref id.
+     * @param classname The class/struct/enum name.
+     */
+    void setIdentifier(string refId, string classname);
+
+    /**
+     * Generates Lua bindings for all classes defined within the given input directory
+     * and places the generated class bindings in the given output directory.
+     * Note that the input directory must point to a folder containing the Doxygen XML 
+     * output files for the classes that the user wants to generate bindings for.
+     * 
+     * @param inDir The input directory (must contain Doxygen XML output files).
+     * @param outDir The output directory.
+     * @param bindingNS The namespace to generate the bindings within.
+     */
+    void run(string inDir, string outDir, string* bindingNS = NULL);
+
+    /**
+     * Retrieves whether the given class is derived from Ref.
+     * 
+     * @param classname The name of the class.
+     * @return True if the class is derived from Ref; false otherwise.
+     */
+    bool isRef(string classname);
+
+protected:
+    /**
+     * Constructor.
+     */
+    Generator();
+
+    /**
+     * Destructor.
+     */
+    ~Generator();
+
+    // Checks if the given class name specifies a class derived from the class represented by the given class binding.
+    bool isDerived(const ClassBinding& c, string classname);
+
+    // Gets the name of the namespace, file, class, or struct.
+    string getCompoundName(XMLElement* node);
+
+    // Parses the non-member functions and adds them to the list (optionally within the given namespace).
+    void getFunctions(XMLElement* classNode, string ns = "");
+
+    // Parses the namespace (with the given name).
+    void getNamespace(XMLElement* nsNode, const string& name);
+
+    // Parses the class (with the given name) and adds it to the list.
+    void getClass(XMLElement* classNode, const string& name);
+
+    // Parses all enumerations within a file (optionally within a namespace).
+    void getEnums(XMLElement* fileNode, string ns = "");
+    
+    // Parses the enumeration type and adds it to the global list.
+    void getEnum(XMLElement* e, string classname = "", string ns = "", string include = "");
+
+    // Parses all typedefs within a file (optionall within a namespace).
+    void getTypedefs(XMLElement* fileNode, string ns = "");
+
+    // Parses the typedef and adds it to the global list.
+    void getTypedef(XMLElement* e, string classname = "", string ns = "");
+
+    // Gets the script flag if it is specified.
+    string getScriptFlag(XMLElement* e);
+
+    // Gets whether the current function has been marked as a creation function
+    // (indicating that the return value is owned by the script runtime and not C++).
+    void getCreateFlag(XMLElement* e, FunctionBinding& b);
+
+    // Gets the name of the binding.
+    string getName(XMLElement* e);
+
+    // Gets whether the type is const or not.
+    bool getIsConstType(XMLElement* e);
+
+    // Gets the parameter or return value, optionally within the scope of the given class.
+    FunctionBinding::Param getParam(XMLElement* e, bool isVariable = false,  string classname = "");
+
+    // Gets all of the parameters for a function.
+    void getParams(XMLElement* e, FunctionBinding& b);
+
+    // Resolves members for all classes' derived from class 'c'.
+    void resolveMembers(const ClassBinding& c);
+
+    // Resolves the inheritance.
+    void resolveInheritance();
+
+    // Resolves includes for all classes' derived from class 'c'.
+    void resolveIncludes(const ClassBinding& c);
+
+    // Resolves inherited include files.
+    void resolveInheritedIncludes();
+
+    // Resolves the type for a single parameter/return value 
+    // (also takes the function that the parameter/return value is for along
+    // with the header file that the parameter/return value belongs to-the original
+    // class header file for class bindings or the global Lua bindings header file
+    // for global bindings).
+    void resolveType(FunctionBinding::Param* param, string functionName, string header);
+
+    // Resolves all unrecognized types.
+    void resolveTypes();
+
+    // Generates the bindings to C++ header and source files.
+    void generateBindings(string* bindingNS);
+    
+    // Gets the set off all classes that derives from the given class.
+    void getAllDerived(set<string>& derived, string classname);
+
+    // Gets the included files for a cpp file.
+    void getIncludes(XMLElement* e, string filename);
+
+private:
+    static Generator* __instance;
+
+    const char* _file;
+    map<string, string> _refIds;
+    string _outDir;
+    map<string, ClassBinding> _classes;
+    vector<string> _topLevelBaseClasses;
+    map<string, set<string> > _includes;
+    map<string, vector<FunctionBinding> > _functions;
+    map<string, EnumBinding> _enums;
+    map<string, set<string> > _namespaces;
+    map<string, TypedefBinding> _typedefs;
+    set<string> __warnings;
+};
+
+#endif

+ 16 - 16
tools/luagen/src/TypedefBinding.h

@@ -1,16 +1,16 @@
-#ifndef TYPEDEFBINDING_H_
-#define TYPEDEFBINDING_H_
-
-/**
- * Represents a typedef.
- * 
- * Note: the name of the typedef is stored as the key in the 
- * map containing all typedefs. The refId member is set if
- * the typedef is a class, struct, or enumerated type.
- */
-struct TypedefBinding
-{
-    string refId;
-};
-
-#endif
+#ifndef TYPEDEFBINDING_H_
+#define TYPEDEFBINDING_H_
+
+/**
+ * Represents a typedef.
+ * 
+ * Note: the name of the typedef is stored as the key in the 
+ * map containing all typedefs. The refId member is set if
+ * the typedef is a class, struct, or enumerated type.
+ */
+struct TypedefBinding
+{
+    string refId;
+};
+
+#endif

+ 83 - 83
tools/luagen/src/main.cpp

@@ -1,83 +1,83 @@
-#include "Base.h"
-#include "Generator.h"
-
-//TRACK_MEMORY();
-
-// Generated file list (extern from Base.h)
-std::vector<string> generatedFiles;
-
-void printError(const char* format, ...)
-{
-    va_list argptr;
-    va_start(argptr, format);
-#ifdef WIN32
-    int sz = vfprintf(stderr, format, argptr);
-    if (sz > 0)
-    {
-        char* buf = new char[sz + 1];
-        vsprintf(buf, format, argptr);
-        buf[sz] = 0;
-        OutputDebugStringA(buf);
-        SAFE_DELETE_ARRAY(buf);
-    }
-#else
-    vfprintf(stderr, format, argptr);
-#endif
-    va_end(argptr);
-}
-
-void writeFile(const std::string& path, const std::string& text)
-{
-    generatedFiles.push_back(path);
-
-    // Read in content of path to compare before writing
-    bool changed = true;
-    ifstream in(path.c_str());
-    if (in.is_open())
-    {
-        changed = false;
-        istringstream textStream(text, istringstream::in);
-        string line1, line2;
-        while (in.good() && textStream.good())
-        {
-            getline(in, line1);
-            getline(textStream, line2);
-            if (line1 != line2 || in.good() != textStream.good())
-            {
-                // Files differ
-                changed = true;
-                break;
-            }
-        }
-        in.close();
-    }
-
-    if (changed)
-    {
-        ofstream o(path.c_str());
-        o << text;
-        o.close();
-    }
-}
-
-int main(int argc, char** argv)
-{
-    // Ensure the user is calling the program correctly.
-    if (argc < 2 || argc > 4)
-    {
-        printf("Usage: gameplay-luagen <doxygen-xml-input-directory> [output-directory] [binding-namespace]\n");
-        exit(0);
-    }
-
-    // Generate the bindings.
-    string* bindingNS = (argc >= 4) ? new string(argv[3]) : NULL;
-    Generator::getInstance()->run(argv[1], (argc >= 3) ? argv[2] : argv[1], bindingNS);
-    Generator::releaseInstance();
-    SAFE_DELETE(bindingNS);
-
-#ifdef WIN32
-    system("pause");
-#endif
-    
-    return 0;
-}
+#include "Base.h"
+#include "Generator.h"
+
+//TRACK_MEMORY();
+
+// Generated file list (extern from Base.h)
+std::vector<string> generatedFiles;
+
+void printError(const char* format, ...)
+{
+    va_list argptr;
+    va_start(argptr, format);
+#ifdef WIN32
+    int sz = vfprintf(stderr, format, argptr);
+    if (sz > 0)
+    {
+        char* buf = new char[sz + 1];
+        vsprintf(buf, format, argptr);
+        buf[sz] = 0;
+        OutputDebugStringA(buf);
+        SAFE_DELETE_ARRAY(buf);
+    }
+#else
+    vfprintf(stderr, format, argptr);
+#endif
+    va_end(argptr);
+}
+
+void writeFile(const std::string& path, const std::string& text)
+{
+    generatedFiles.push_back(path);
+
+    // Read in content of path to compare before writing
+    bool changed = true;
+    ifstream in(path.c_str());
+    if (in.is_open())
+    {
+        changed = false;
+        istringstream textStream(text, istringstream::in);
+        string line1, line2;
+        while (in.good() && textStream.good())
+        {
+            getline(in, line1);
+            getline(textStream, line2);
+            if (line1 != line2 || in.good() != textStream.good())
+            {
+                // Files differ
+                changed = true;
+                break;
+            }
+        }
+        in.close();
+    }
+
+    if (changed)
+    {
+        ofstream o(path.c_str());
+        o << text;
+        o.close();
+    }
+}
+
+int main(int argc, char** argv)
+{
+    // Ensure the user is calling the program correctly.
+    if (argc < 2 || argc > 4)
+    {
+        printf("Usage: gameplay-luagen <doxygen-xml-input-directory> [output-directory] [binding-namespace]\n");
+        exit(0);
+    }
+
+    // Generate the bindings.
+    string* bindingNS = (argc >= 4) ? new string(argv[3]) : NULL;
+    Generator::getInstance()->run(argv[1], (argc >= 3) ? argv[2] : argv[1], bindingNS);
+    Generator::releaseInstance();
+    SAFE_DELETE(bindingNS);
+
+#ifdef WIN32
+    system("pause");
+#endif
+    
+    return 0;
+}