]>
Dogcows Code - chaz/yoink/blob - src/Moof/Animation.cc
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 "Animation.hh"
33 #include "Mippleton.hh"
34 #include "Serializable.hh"
41 * The collection of nested animation classes. The animation implementation
42 * consists of an Impl class which is allocated and initialized with the
43 * interface object. This class contains the specific fields which are required
44 * to run a single instance of an animation. The sequence data is loaded in a
45 * different class which can be shared amongst multiple animation implementation
51 friend class Animation
;
54 * Contains "global" animation data for the various animations which get
55 * loaded. This is a mippleton, so it will be shared amongst any animation
56 * which wants to use these loaded sequences.
59 class Data
: public Mippleton
<Data
>
62 friend class Mippleton
<Data
>;
65 * A frame of an animation sequence. A frame is merely an index which
66 * presumably represents a "slide" or tile which should be displayed,
67 * and the duration that is how long the slide will be shown.
72 unsigned index
; ///< Frame index.
73 Scalar duration
; ///< 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(SerializableP root
) :
84 Serializable::Map rootObj
;
86 if (root
->get(rootObj
))
88 Serializable::Map::iterator it
;
90 for (it
= rootObj
.begin(); it
!= rootObj
.end(); ++it
)
92 std::string key
= (*it
).first
;
96 (*it
).second
->get(value
);
97 index
= unsigned(value
);
99 else if (key
== "duration")
102 (*it
).second
->getNumber(value
);
103 duration
= Scalar(value
);
112 * A sequence is just a few attributes and a list of frames in the order
113 * that they should be played.
118 std::vector
<Frame
> frames
; ///< List of frames.
119 Scalar delay
; ///< Scale frame durations.
120 bool loop
; ///< Does the sequence repeat?
121 std::string next
; ///< Next sequence name.
124 * Construction is initialization. The constructor loads sequence
125 * data from the sequence map, presumably loaded from an animation
126 * file. The rest of the loading takes place in the frame's
127 * constructor which loads each individual frame.
130 Sequence(SerializableP root
) :
134 Serializable::Map rootObj
;
136 if (root
->get(rootObj
))
138 Serializable::Map::iterator it
;
139 for (it
= rootObj
.begin(); it
!= rootObj
.end(); ++it
)
141 std::string key
= (*it
).first
;
145 Serializable::Array framesObj
;
147 if ((*it
).second
->get(framesObj
))
149 Serializable::Array::iterator jt
;
151 for (jt
= framesObj
.begin();
152 jt
!= framesObj
.end(); ++jt
)
156 frames
.push_back(Frame(*jt
));
161 else if (key
== "delay")
164 (*it
).second
->getNumber(value
);
165 delay
= Scalar(value
);
167 else if (key
== "loop")
169 (*it
).second
->get(loop
);
171 else if (key
== "next")
173 (*it
).second
->get(next
);
182 * Starts loading a file with animation data. Such a file is formatted
183 * as a map of named sequences. The sequence constructor loads each
184 * individual sequence.
189 std::string filePath
= Animation::getPath(getName());
191 Deserializer
deserializer(filePath
);
193 SerializableP root
= deserializer
.deserialize();
197 Serializable::Map rootObj
;
199 if (root
->get(rootObj
))
201 Serializable::Map::iterator it
;
203 for (it
= rootObj
.begin(); it
!= rootObj
.end(); ++it
)
205 sequences
.insert(std::pair
<std::string
,Sequence
>((*it
).first
,
206 Sequence((*it
).second
)));
213 * Construction is initialization. The animation class data container
214 * registers itself as a mippleton and then loads the animation data.
217 explicit Data(const std::string
& name
) :
218 Mippleton
<Data
>(name
)
223 std::map
<std::string
,Sequence
> sequences
; ///< List of sequences.
228 * Construction is intialization.
231 Impl(const std::string
& name
) :
232 data(Data::getInstance(name
)),
241 * Sets up the animation classes to "play" a named sequence. If another
242 * sequence was active, it will be replaced as the current sequence. Future
243 * updates will progress the new sequence.
246 void startSequence(const std::string
& name
)
248 std::map
<std::string
,Data::Sequence
>::iterator it
;
250 it
= data
->sequences
.find(name
);
252 if (it
!= data
->sequences
.end())
254 currentSequence
= &(*it
).second
;
256 frameIndex
= currentSequence
->frames
[0].index
;
258 frameDuration
= currentSequence
->delay
*
259 currentSequence
->frames
[0].duration
;
264 * Updates or progresses the animation sequence. If the time interval
265 * surpasses the duration of the current frame, a new frame becomes the
266 * current frame. If the last frame of a sequence expires, the active
267 * sequence will switch automatically to the designated "next" sequence, or
268 * if none is specified but the sequence is set to loop, the first frame of
269 * the sequence will become the current frame, and the animation essentially
273 void update(Scalar t
, Scalar dt
)
279 if (timeAccum
>= frameDuration
)
281 if (++frameCounter
>= currentSequence
->frames
.size())
283 if (!currentSequence
->next
.empty())
285 startSequence(currentSequence
->next
);
287 else if (currentSequence
->loop
)
298 frameIndex
= currentSequence
->frames
[frameCounter
].index
;
299 timeAccum
= frameDuration
- timeAccum
;
300 frameDuration
= currentSequence
->delay
*
301 currentSequence
->frames
[frameCounter
].duration
;
306 boost::shared_ptr
<Data
> data
; ///< Internal data.
308 Data::Sequence
* currentSequence
; ///< Active sequence.
309 unsigned frameCounter
; ///< Current frame.
310 unsigned frameIndex
; ///< Index of current frame.
311 Scalar timeAccum
; ///< Time accumulation.
312 Scalar frameDuration
; ///< Scaled frame duration.
316 Animation::Animation(const std::string
& name
) :
318 impl_(new Animation::Impl(name
)) {}
321 void Animation::startSequence(const std::string
& name
)
324 impl_
->startSequence(name
);
327 void Animation::update(Scalar t
, Scalar dt
)
330 impl_
->update(t
, dt
);
335 * Gets the index for the current frame. This is presumably called by some
336 * drawing code which will draw the correct current frame.
339 unsigned Animation::getFrame() const
341 return impl_
->frameIndex
;
346 * Specialized search location for animation files. They can be found in the
347 * "animations" subdirectory of any of the searched directories.
350 std::string
Animation::getPath(const std::string
& name
)
352 return Resource::getPath("animations/" + name
+ ".json");
358 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.050068 seconds and 4 git commands to generate.