]> Dogcows Code - chaz/yoink/blobdiff - src/Animation.cc
fixed some resource management bugs
[chaz/yoink] / src / Animation.cc
index b449a0fbd97a500e36cd10e987831117fee4bf08..fead5cab1697f67682d5df9546f14f7308356779 100644 (file)
 
-/*******************************************************************************
-
- Copyright (c) 2009, Charles McGarvey
- All rights reserved.
- Redistribution   and   use  in  source  and  binary  forms,  with  or  without
- modification, are permitted provided that the following conditions are met:
-   * Redistributions  of  source  code  must retain the above copyright notice,
-     this list of conditions and the following disclaimer.
-   * Redistributions  in binary form must reproduce the above copyright notice,
-     this  list of conditions and the following disclaimer in the documentation
-     and/or other materials provided with the distribution.
- THIS  SOFTWARE  IS  PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND  ANY  EXPRESS  OR  IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED.  IN  NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- FOR  ANY  DIRECT,  INDIRECT,  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES  (INCLUDING,  BUT  NOT  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES;  LOSS  OF  USE,  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*******************************************************************************/
+/*]  Copyright (c) 2009-2010, Charles McGarvey  [**************************
+**]  All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
 
 #include <map>
+#include <stdexcept>
 #include <vector>
 
-#include <Moof/Log.hh>
-#include <Moof/Mippleton.hh>
-#include <Moof/Script.hh>
+#include <moof/manager.hh>
+#include <moof/log.hh>
+#include <moof/script.hh>
 
 #include "Animation.hh"
 
 
 /**
- * The collection of nested animation classes.  The animation implementation
- * consists of an Impl class which is allocated and initialized with the
- * interface object.  This class contains the specific fields which are required
- * to run a single instance of an animation.  The sequence data is loaded in a
- * different class which can be shared amongst multiple animation implementation
- * instances.
+ * The collection of nested animation classes.  The animation
+ * implementation consists of an impl class which is allocated and
+ * initialized with the interface object.  This class contains the specific
+ * fields which are required to run a single instance of an animation.  The
+ * sequence data is loaded in a different class which can be shared amongst
+ * multiple animation implementation instances.
  */
 
-class Animation::Impl
+class Animation::impl
 {
-       friend class Animation;
+public:
 
        /**
-        * Contains "global" animation data for the various animations which get
-        * loaded.  This is a mippleton, so it will be shared amongst any animation
-        * which wants to use these loaded sequences.
+        * Contains "global" animation data for the various animations which
+        * get loaded.  This is a mippleton, so it will be shared amongst any
+        * animation which wants to use these loaded sequences.
         */
 
-       class Data : public Mf::Mippleton<Data>
+       class Data : public moof::manager<Data>
        {
-               friend class Impl;
-               friend class Mf::Mippleton<Data>;
+       public:
 
                /**
-                * A frame of an animation sequence.  A frame is merely an index which
-                * presumably represents a "slide" or tile which should be displayed,
-                * and the duration that is how long the slide will be shown.
+                * A frame of an animation sequence.  A frame is merely an index
+                * which presumably represents a "slide" or tile which should be
+                * displayed, and the duration that is how long the slide will be
+                * shown.
                 */
 
-               struct Frame
+               class Frame
                {
-                       unsigned        index;                                  ///< Frame index.
-                       Mf::Scalar      duration;                               ///< Frame duration.
+               public:
+
+                       unsigned        mIndex;                                 ///< Frame index.
+                       moof::scalar    mDuration;                              ///< Frame duration.
 
                        /**
-                        * Construction is initialization.  The frame data is loaded from a
-                        * frame map which is probably loaded within an animation file.
+                        * Construction is initialization.  The frame data is loaded
+                        * from a frame map which is probably loaded within an
+                        * animation file.
                         */
                
-                       Frame(Mf::Script& script, Mf::Script::Value table) :
-                               index(0),
-                               duration(1.0)
+                       Frame(const moof::script::slot& table) :
+                               mIndex(0),
+                               mDuration(1.0)
                        {
-                               table.pushField("index");
-                               script[-1].get(index);
-                               script.pop();
-
-                               table.pushField("duration");
-                               script[-1].get(duration);
-                               script.pop();
+                               table.get(mIndex,    "index");
+                               table.get(mDuration, "duration");
                        }
                };
 
 
                /**
-                * A sequence is just a few attributes and a list of frames in the order
-                * that they should be played.
+                * A sequence is just a few attributes and a list of frames in the
+                * order that they should be played.
                 */
 
-               struct Sequence
+               class Sequence
                {
-                       std::vector<Frame>      frames;                 ///< List of frames.
-                       Mf::Scalar                      delay;                  ///< Scale frame durations.
-                       bool                            loop;                   ///< Does the sequence repeat?
-                       std::string                     next;                   ///< Next sequence name.
+               public:
+
+                       std::vector<Frame>      mFrames;        ///< List of frames.
+                       moof::scalar                    mDelay;         ///< Scale frame durations.
+                       bool                            mLoop;          ///< Does the sequence repeat?
+                       std::string                     mNext;          ///< Next sequence name.
 
                        /**
-                        * Construction is initialization.  The constructor loads sequence
-                        * data from the sequence map, presumably loaded from an animation
-                        * file.  The rest of the loading takes place in the frame's
-                        * constructor which loads each individual frame.
+                        * Construction is initialization.  The constructor loads
+                        * sequence data from the sequence map, presumably loaded from
+                        * an animation file.  The rest of the loading takes place in
+                        * the frame's constructor which loads each individual frame.
                         */
 
-                       Sequence(Mf::Script& script, Mf::Script::Value table) :
-                               delay(0.0),
-                               loop(true)
+                       Sequence(const moof::script::slot& table) :
+                               mDelay(0.0),
+                               mLoop(true)
                        {
-                               table.pushField("delay");
-                               script[-1].get(delay);
-                               script.pop();
-
-                               table.pushField("loop");
-                               script[-1].get(loop);
-                               script.pop();
-
-                               table.pushField("next");
-                               script[-1].get(next);
-                               script.pop();
+                               table.get(mDelay, "delay");
+                               table.get(mLoop,  "loop");
+                               table.get(mNext,  "next");
 
                                // TODO - sequence class/type not yet implemented
 
-                               table.pushField("frames");
-                               Mf::Script::Value frameTable = script.getTop();
-                               if (frameTable.isTable())
+                               moof::script::slot frameTable = table.push_field("frames");
+                               if (frameTable.is_table())
                                {
-                                       Mf::Script::Value top = script[-1];
-                                       int index = 1;
-
-                                       for (;;)
+                                       int max = frameTable.length();
+                                       for (int index = 1; index <= max; ++index)
                                        {
-                                               script.push(index);
-                                               frameTable.pushField();
-
-                                               if (top.isTable()) frames.push_back(Frame(script, top));
-                                               else               break;
-
-                                               ++index;
+                                               moof::script::slot top = frameTable.push_field(index);
+
+                                               if (top.is_table())
+                                               {
+                                                       mFrames.push_back(Frame(top));
+                                               }
+                                               else
+                                               {
+                                                       moof::log_warning << "invalid frame at index "
+                                                                                  << index << std::endl;
+                                               }
                                        }
                                }
-                               script.pop();
+                               frameTable.remove();
                        }
                };
 
 
                /**
-                * Starts loading a file with animation data.  Such a file is formatted
-                * as a map of named sequences.   The sequence constructor loads each
-                * individual sequence.
+                * Starts loading a file with animation data.  Such a file is
+                * formatted as a map of named sequences.   The sequence
+                * constructor loads each individual sequence.
                 */
 
-               void loadFromFile()
+               void init(const std::string& name)
                {
-                       Mf::Script script;
-                       std::string filePath = Animation::getPath(getName());
-
-                       script.importStandardLibraries();
-                       importLogScript(script);
+                       moof::script script;
+                       std::string path = moof::resource::find_file("animations/"+name, "lua");
+                       
+                       //if (!resource::find(path))
+                       //{
+                               //throw std::runtime_error("cannot find resource " + name);
+                       //}
+
+                       script.import_base_library();
+                       moof::log::import(script);
                        importAnimationBindings(script);
 
-                       if (script.doFile(filePath) != Mf::Script::SUCCESS)
+                       if (script.do_file(path) != moof::script::success)
                        {
                                std::string str;
                                script[-1].get(str);
-                               Mf::logScript("%s", str.c_str());
+                               moof::log_warning(str);
                        }
                }
 
-               int defineSequence(Mf::Script& script)
+               int defineSequence(moof::script& script)
                {
-                       Mf::Script::Value name = script[1].requireString();
-                       Mf::Script::Value table = script[2].requireTable();
+                       moof::script::slot name = script[1].require_string();
+                       moof::script::slot table = script[2].require_table();
 
                        std::string nameStr;
                        name.get(nameStr);
 
-                       sequences.insert(std::pair<std::string,Sequence>(nameStr,
-                                               Sequence(script, table)));
+                       mSequences.insert(std::make_pair(nameStr, Sequence(table)));
 
                        return 0;
                }
 
 
-               void importAnimationBindings(Mf::Script& script)
+               void importAnimationBindings(moof::script& script)
                {
-                       script.importFunction("DefineSequence",
-                                       boost::bind(&Data::defineSequence, this, _1));
-
-                       script.push(1); script.set("ATTACK");
-                       script.push(2); script.set("CHARGE");
-                       script.push(3); script.set("FLY");
-                       script.push(4); script.set("HIT");
-                       script.push(5); script.set("JUMP");
-                       script.push(6); script.set("RUN");
-                       script.push(7); script.set("STAND");
+                       script.import_function("DefineSequence",
+                                                                 boost::bind(&Data::defineSequence,
+                                                                                         this, _1));
+
+                       script.globals().set_field("ATTACK",    1);
+                       script.globals().set_field("CHARGE",    2);
+                       script.globals().set_field("FLY",       3);
+                       script.globals().set_field("HIT",       4);
+                       script.globals().set_field("JUMP",      5);
+                       script.globals().set_field("RUN",       6);
+                       script.globals().set_field("STAND",     7);
                }
 
 
-               /**
-                * Construction is initialization.  The animation class data container
-                * registers itself as a mippleton and then loads the animation data.
-                */
-
-               explicit Data(const std::string& name) :
-                       Mf::Mippleton<Data>(name)
-               {
-                       loadFromFile();
-               }
-
-               std::map<std::string,Sequence> sequences;               ///< List of sequences.
+               std::map<std::string,Sequence> mSequences;      ///< List of sequences.
        };
 
 
@@ -223,35 +194,34 @@ class Animation::Impl
         * Construction is intialization.
         */
 
-       Impl(const std::string& name) :
-               data(Data::getInstance(name)),
-               currentSequence(0),
-               frameCounter(0),
-               frameIndex(0),
-               timeAccum(0),
-               frameDuration(0) {}
+       impl(const std::string& name) :
+               mData(Data::instance(name)),
+               mCurrentSequence(0),
+               mFrameCounter(0),
+               mFrameIndex(0),
+               mTimeAccum(0),
+               mFrameDuration(0) {}
 
 
        /**
-        * Sets up the animation classes to "play" a named sequence.  If another
-        * sequence was active, it will be replaced.  Future updates will progress
-        * the new sequence.
+        * Sets up the animation classes to "play" a named sequence.  If
+        * another sequence was active, it will be replaced.  Future updates
+        * will progress the new sequence.
         */
 
        void startSequence(const std::string& name)
        {
                std::map<std::string,Data::Sequence>::iterator it;
 
-               it = data->sequences.find(name);
-
-               if (it != data->sequences.end())
+               it = mData->mSequences.find(name);
+               if (it != mData->mSequences.end())
                {
-                       currentSequence = &(*it).second;
-                       frameCounter = 0;
-                       frameIndex = currentSequence->frames[0].index;
-                       timeAccum = 0.0;
-                       frameDuration = currentSequence->delay *
-                               currentSequence->frames[0].duration;
+                       mCurrentSequence = &(*it).second;
+                       mFrameCounter = 0;
+                       mFrameIndex = mCurrentSequence->mFrames[0].mIndex;
+                       mTimeAccum = 0.0;
+                       mFrameDuration = mCurrentSequence->mDelay *
+                                                        mCurrentSequence->mFrames[0].mDuration;
                }
        }
 
@@ -259,58 +229,57 @@ class Animation::Impl
         * Updates or progresses the animation sequence.  If the time interval
         * surpasses the duration of the current frame, a new frame becomes the
         * current frame.  If the last frame of a sequence expires, the active
-        * sequence will switch automatically to the designated "next" sequence, or
-        * if none is specified but the sequence is set to loop, the first frame of
-        * the sequence will become the current frame, and the animation essentially
-        * starts over again.
+        * sequence will switch automatically to the designated "next"
+        * sequence, or if none is specified but the sequence is set to loop,
+        * the first frame of the sequence will become the current frame, and
+        * the animation essentially starts over again.
         */
 
-       void update(Mf::Scalar t, Mf::Scalar dt)
+       void update(moof::scalar t, moof::scalar dt)
        {
-               if (currentSequence)
-               {
-                       timeAccum += dt;
+               if (!mCurrentSequence) return;
+
+               mTimeAccum += dt;
 
-                       if (timeAccum >= frameDuration)
+               if (mTimeAccum >= mFrameDuration)
+               {
+                       if (++mFrameCounter >= mCurrentSequence->mFrames.size())
                        {
-                               if (++frameCounter >= currentSequence->frames.size())
+                               if (!mCurrentSequence->mNext.empty())
                                {
-                                       if (!currentSequence->next.empty())
-                                       {
-                                               startSequence(currentSequence->next);
-                                       }
-                                       else if (currentSequence->loop)
-                                       {
-                                               frameCounter = 0;
-                                       }
-                                       else
-                                       {
-                                               frameCounter--;
-                                               currentSequence = 0;
-                                       }
+                                       startSequence(mCurrentSequence->mNext);
+                               }
+                               else if (mCurrentSequence->mLoop)
+                               {
+                                       mFrameCounter = 0;
+                               }
+                               else
+                               {
+                                       mFrameCounter--;
+                                       mCurrentSequence = 0;
                                }
-
-                               frameIndex = currentSequence->frames[frameCounter].index;
-                               timeAccum = frameDuration - timeAccum;
-                               frameDuration = currentSequence->delay *
-                                       currentSequence->frames[frameCounter].duration;
                        }
+
+                       mFrameIndex = mCurrentSequence->mFrames[mFrameCounter].mIndex;
+                       mTimeAccum = mFrameDuration - mTimeAccum;
+                       mFrameDuration = mCurrentSequence->mDelay *
+                               mCurrentSequence->mFrames[mFrameCounter].mDuration;
                }
        }
 
-       boost::shared_ptr<Data> data;                           ///< Internal data.
+       boost::shared_ptr<Data> mData;                          ///< Internal data.
 
-       Data::Sequence*                 currentSequence;        ///< Active sequence.
-       unsigned                                frameCounter;           ///< Current frame.
-       unsigned                                frameIndex;                     ///< Index of current frame.
-       Mf::Scalar                              timeAccum;                      ///< Time accumulation.
-       Mf::Scalar                              frameDuration;          ///< Scaled frame duration.
+       Data::Sequence*                 mCurrentSequence;       ///< Active sequence.
+       unsigned                                mFrameCounter;          ///< Current frame.
+       unsigned                                mFrameIndex;            ///< Index of current frame.
+       moof::scalar                            mTimeAccum;                     ///< Time accumulation.
+       moof::scalar                            mFrameDuration;         ///< Scaled frame duration.
 };
 
 
 Animation::Animation(const std::string& name) :
        // pass through
-       impl_(new Animation::Impl(name)) {}
+       impl_(new Animation::impl(name)) {}
 
 
 void Animation::startSequence(const std::string& name)
@@ -319,7 +288,7 @@ void Animation::startSequence(const std::string& name)
        impl_->startSequence(name);
 }
 
-void Animation::update(Mf::Scalar t, Mf::Scalar dt)
+void Animation::update(moof::scalar t, moof::scalar dt)
 {
        // pass through
        impl_->update(t, dt);
@@ -333,20 +302,6 @@ void Animation::update(Mf::Scalar t, Mf::Scalar dt)
 
 unsigned Animation::getFrame() const
 {
-       return impl_->frameIndex;
-}
-
-
-/**
- * Specialized search location for animation files.  They can be found in the
- * "animations" subdirectory of any of the searched directories.
- */
-
-std::string Animation::getPath(const std::string& name)
-{
-       return Mf::Resource::getPath("animations/" + name + ".lua");
+       return impl_->mFrameIndex;
 }
 
-
-/** vim: set ts=4 sw=4 tw=80: *************************************************/
-
This page took 0.035076 seconds and 4 git commands to generate.