]>
Dogcows Code - chaz/yoink/blob - Animation.cc
477997037230b125635f28cf4980d8ffa3d3cc3a
2 /*******************************************************************************
4 Copyright (c) 2009, Charles McGarvey
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *******************************************************************************/
32 #include <Moof/Manager.hh>
33 #include <Moof/Log.hh>
34 #include <Moof/Script.hh>
36 #include "Animation.hh"
40 * The collection of nested animation classes. The animation implementation
41 * consists of an Impl class which is allocated and initialized with the
42 * interface object. This class contains the specific fields which are required
43 * to run a single instance of an animation. The sequence data is loaded in a
44 * different class which can be shared amongst multiple animation implementation
53 * Contains "global" animation data for the various animations which get
54 * loaded. This is a mippleton, so it will be shared amongst any animation
55 * which wants to use these loaded sequences.
58 class Data
: public Mf::Manager
<Data
>
63 * A frame of an animation sequence. A frame is merely an index which
64 * presumably represents a "slide" or tile which should be displayed,
65 * and the duration that is how long the slide will be shown.
72 unsigned mIndex
; ///< Frame index.
73 Mf::Scalar mDuration
; ///< Frame duration.
76 * Construction is initialization. The frame data is loaded from a
77 * frame map which is probably loaded within an animation file.
80 Frame(Mf::Script
& script
, Mf::Script::Slot table
) :
84 table
.pushField("index");
85 script
[-1].get(mIndex
);
88 table
.pushField("duration");
89 script
[-1].get(mDuration
);
96 * A sequence is just a few attributes and a list of frames in the order
97 * that they should be played.
104 std::vector
<Frame
> mFrames
; ///< List of frames.
105 Mf::Scalar mDelay
; ///< Scale frame durations.
106 bool mLoop
; ///< Does the sequence repeat?
107 std::string mNext
; ///< Next sequence name.
110 * Construction is initialization. The constructor loads sequence
111 * data from the sequence map, presumably loaded from an animation
112 * file. The rest of the loading takes place in the frame's
113 * constructor which loads each individual frame.
116 Sequence(Mf::Script
& script
, Mf::Script::Slot table
) :
120 table
.pushField("delay");
121 script
[-1].get(mDelay
);
124 table
.pushField("loop");
125 script
[-1].get(mLoop
);
128 table
.pushField("next");
129 script
[-1].get(mNext
);
132 // TODO - sequence class/type not yet implemented
134 table
.pushField("frames");
135 Mf::Script::Slot frameTable
= script
.getTop();
136 if (frameTable
.isTable())
138 Mf::Script::Slot top
= script
[-1];
144 frameTable
.pushField();
146 if (top
.isTable()) mFrames
.push_back(Frame(script
, top
));
158 * Starts loading a file with animation data. Such a file is formatted
159 * as a map of named sequences. The sequence constructor loads each
160 * individual sequence.
163 void init(const std::string
& name
)
166 std::string filePath
= Animation::getPath(name
);
168 script
.importBaseLibrary();
169 importLogFunctions(script
);
170 importAnimationBindings(script
);
172 if (script
.doFile(filePath
) != Mf::Script::SUCCESS
)
180 int defineSequence(Mf::Script
& script
)
182 Mf::Script::Slot name
= script
[1].requireString();
183 Mf::Script::Slot table
= script
[2].requireTable();
188 mSequences
.insert(std::pair
<std::string
,Sequence
>(nameStr
,
189 Sequence(script
, table
)));
195 void importAnimationBindings(Mf::Script
& script
)
197 script
.importFunction("DefineSequence",
198 boost::bind(&Data::defineSequence
, this, _1
));
200 script
.push(1); script
.set("ATTACK");
201 script
.push(2); script
.set("CHARGE");
202 script
.push(3); script
.set("FLY");
203 script
.push(4); script
.set("HIT");
204 script
.push(5); script
.set("JUMP");
205 script
.push(6); script
.set("RUN");
206 script
.push(7); script
.set("STAND");
210 std::map
<std::string
,Sequence
> mSequences
; ///< List of sequences.
215 * Construction is intialization.
218 Impl(const std::string
& name
) :
219 mData(Data::getInstance(name
)),
228 * Sets up the animation classes to "play" a named sequence. If another
229 * sequence was active, it will be replaced. Future updates will progress
233 void startSequence(const std::string
& name
)
235 std::map
<std::string
,Data::Sequence
>::iterator it
;
237 it
= mData
->mSequences
.find(name
);
239 if (it
!= mData
->mSequences
.end())
241 mCurrentSequence
= &(*it
).second
;
243 mFrameIndex
= mCurrentSequence
->mFrames
[0].mIndex
;
245 mFrameDuration
= mCurrentSequence
->mDelay
*
246 mCurrentSequence
->mFrames
[0].mDuration
;
251 * Updates or progresses the animation sequence. If the time interval
252 * surpasses the duration of the current frame, a new frame becomes the
253 * current frame. If the last frame of a sequence expires, the active
254 * sequence will switch automatically to the designated "next" sequence, or
255 * if none is specified but the sequence is set to loop, the first frame of
256 * the sequence will become the current frame, and the animation essentially
260 void update(Mf::Scalar t
, Mf::Scalar dt
)
262 if (mCurrentSequence
)
266 if (mTimeAccum
>= mFrameDuration
)
268 if (++mFrameCounter
>= mCurrentSequence
->mFrames
.size())
270 if (!mCurrentSequence
->mNext
.empty())
272 startSequence(mCurrentSequence
->mNext
);
274 else if (mCurrentSequence
->mLoop
)
281 mCurrentSequence
= 0;
285 mFrameIndex
= mCurrentSequence
->mFrames
[mFrameCounter
].mIndex
;
286 mTimeAccum
= mFrameDuration
- mTimeAccum
;
287 mFrameDuration
= mCurrentSequence
->mDelay
*
288 mCurrentSequence
->mFrames
[mFrameCounter
].mDuration
;
293 boost::shared_ptr
<Data
> mData
; ///< Internal data.
295 Data::Sequence
* mCurrentSequence
; ///< Active sequence.
296 unsigned mFrameCounter
; ///< Current frame.
297 unsigned mFrameIndex
; ///< Index of current frame.
298 Mf::Scalar mTimeAccum
; ///< Time accumulation.
299 Mf::Scalar mFrameDuration
; ///< Scaled frame duration.
303 Animation::Animation(const std::string
& name
) :
305 mImpl(new Animation::Impl(name
)) {}
308 void Animation::startSequence(const std::string
& name
)
311 mImpl
->startSequence(name
);
314 void Animation::update(Mf::Scalar t
, Mf::Scalar dt
)
317 mImpl
->update(t
, dt
);
322 * Gets the index for the current frame. This is presumably called by some
323 * drawing code which will draw the correct current frame.
326 unsigned Animation::getFrame() const
328 return mImpl
->mFrameIndex
;
333 * Specialized search location for animation files. They can be found in the
334 * "animations" subdirectory of any of the searched directories.
337 std::string
Animation::getPath(const std::string
& name
)
339 return Mf::Resource::getPath("animations/" + name
+ ".lua");
343 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.043968 seconds and 3 git commands to generate.