-/*******************************************************************************
-
- 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 <vector>
+#include <Moof/Error.hh>
+#include <Moof/Manager.hh>
#include <Moof/Log.hh>
-#include <Moof/Mippleton.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
{
- 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 Mf::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.
*/
class Frame
{
- friend class Impl;
+ public:
unsigned mIndex; ///< Frame index.
Mf::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) :
+ Frame(const Mf::Script::Slot& table) :
mIndex(0),
mDuration(1.0)
{
- table.pushField("index");
- script[-1].get(mIndex);
- script.pop();
-
- table.pushField("duration");
- script[-1].get(mDuration);
- 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
{
- friend class Impl;
+ public:
- std::vector<Frame> mFrames; ///< List of frames.
- Mf::Scalar mDelay; ///< Scale frame durations.
- bool mLoop; ///< Does the sequence repeat?
- std::string mNext; ///< Next sequence name.
+ std::vector<Frame> mFrames; ///< List of frames.
+ Mf::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) :
+ Sequence(const Mf::Script::Slot& table) :
mDelay(0.0),
mLoop(true)
{
- table.pushField("delay");
- script[-1].get(mDelay);
- script.pop();
-
- table.pushField("loop");
- script[-1].get(mLoop);
- script.pop();
-
- table.pushField("next");
- script[-1].get(mNext);
- 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();
+ Mf::Script::Slot frameTable = table.pushField("frames");
if (frameTable.isTable())
{
- 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()) mFrames.push_back(Frame(script, top));
- else break;
-
- ++index;
+ Mf::Script::Slot top = frameTable.pushField(index);
+
+ if (top.isTable())
+ {
+ mFrames.push_back(Frame(top));
+ }
+ else
+ {
+ Mf::logWarning << "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());
+ std::string path(name);
+
+ if (!Animation::getPath(path))
+ {
+ Mf::Error(Mf::Error::RESOURCE_NOT_FOUND).raise();
+ }
- script.importStandardLibraries();
- importLogScript(script);
+ script.importBaseLibrary();
+ importLogFunctions(script);
importAnimationBindings(script);
- if (script.doFile(filePath) != Mf::Script::SUCCESS)
+ if (script.doFile(path) != Mf::Script::SUCCESS)
{
std::string str;
script[-1].get(str);
- Mf::logScript("%s", str.c_str());
+ Mf::logWarning(str);
}
}
int defineSequence(Mf::Script& script)
{
- Mf::Script::Value name = script[1].requireString();
- Mf::Script::Value table = script[2].requireTable();
+ Mf::Script::Slot name = script[1].requireString();
+ Mf::Script::Slot table = script[2].requireTable();
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)
{
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");
+ boost::bind(&Data::defineSequence,
+ this, _1));
+
+ script.globals().setField("ATTACK", 1);
+ script.globals().setField("CHARGE", 2);
+ script.globals().setField("FLY", 3);
+ script.globals().setField("HIT", 4);
+ script.globals().setField("JUMP", 5);
+ script.globals().setField("RUN", 6);
+ script.globals().setField("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.
};
/**
- * 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 = mData->sequences.find(name);
+ it = mData->mSequences.find(name);
- if (it != mData->sequences.end())
+ if (it != mData->mSequences.end())
{
mCurrentSequence = &(*it).second;
mFrameCounter = 0;
mFrameIndex = mCurrentSequence->mFrames[0].mIndex;
mTimeAccum = 0.0;
mFrameDuration = mCurrentSequence->mDelay *
- mCurrentSequence->mFrames[0].mDuration;
+ mCurrentSequence->mFrames[0].mDuration;
}
}
* 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)
{
- if (mCurrentSequence)
- {
- mTimeAccum += dt;
+ if (!mCurrentSequence) return;
+
+ mTimeAccum += dt;
- if (mTimeAccum >= mFrameDuration)
+ if (mTimeAccum >= mFrameDuration)
+ {
+ if (++mFrameCounter >= mCurrentSequence->mFrames.size())
{
- if (++mFrameCounter >= mCurrentSequence->mFrames.size())
+ if (!mCurrentSequence->mNext.empty())
{
- if (!mCurrentSequence->mNext.empty())
- {
- startSequence(mCurrentSequence->mNext);
- }
- else if (mCurrentSequence->mLoop)
- {
- mFrameCounter = 0;
- }
- else
- {
- mFrameCounter--;
- mCurrentSequence = 0;
- }
+ startSequence(mCurrentSequence->mNext);
+ }
+ else if (mCurrentSequence->mLoop)
+ {
+ mFrameCounter = 0;
+ }
+ else
+ {
+ mFrameCounter--;
+ mCurrentSequence = 0;
}
-
- mFrameIndex = mCurrentSequence->mFrames[mFrameCounter].mIndex;
- mTimeAccum = mFrameDuration - mTimeAccum;
- mFrameDuration = mCurrentSequence->mDelay *
- mCurrentSequence->mFrames[mFrameCounter].mDuration;
}
+
+ mFrameIndex = mCurrentSequence->mFrames[mFrameCounter].mIndex;
+ mTimeAccum = mFrameDuration - mTimeAccum;
+ mFrameDuration = mCurrentSequence->mDelay *
+ mCurrentSequence->mFrames[mFrameCounter].mDuration;
}
}
/**
- * Specialized search location for animation files. They can be found in the
- * "animations" subdirectory of any of the searched directories.
+ * Specialized search location for animation files. They can be found in
+ * the "animations" subdirectory of any of the search directories.
*/
-std::string Animation::getPath(const std::string& name)
+bool Animation::getPath(std::string& name)
{
- return Mf::Resource::getPath("animations/" + name + ".lua");
+ return Mf::Resource::getPath(name, "animations/", "lua");
}
-
-/** vim: set ts=4 sw=4 tw=80: *************************************************/
-