]>
Dogcows Code - chaz/yoink/blob - src/Moof/Animation.cc
39dcb5a40a8b643a7e98958e293ecdcfc7b30ac4
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
49 struct Animation::Impl
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 struct GlobalData
: public Mippleton
<GlobalData
>
61 * A frame of an animation sequence. A frame is merely an index which
62 * presumably represents a "slide" or tile which should be displayed,
63 * and the duration that is how long the slide will be shown.
68 unsigned index
; ///< Frame index.
69 Scalar duration
; ///< Frame duration.
72 * Construction is initialization. The frame data is loaded from a
73 * frame map which is probably loaded within an animation file.
76 Frame(SerializablePtr root
) :
80 std::map
<std::string
,SerializablePtr
> rootObj
;
82 if (root
->get(rootObj
))
84 std::map
<std::string
,SerializablePtr
>::iterator it
;
86 for (it
= rootObj
.begin(); it
!= rootObj
.end(); ++it
)
88 std::string key
= (*it
).first
;
92 (*it
).second
->get(value
);
93 index
= unsigned(value
);
95 else if (key
== "duration")
98 (*it
).second
->getNumber(value
);
99 duration
= Scalar(value
);
108 * A sequence is just a few attributes and a list of frames in the order
109 * that they should be played.
114 std::vector
<Frame
> frames
; ///< List of frames.
115 Scalar delay
; ///< Scale frame durations.
116 bool loop
; ///< Does the sequence repeat?
117 std::string next
; ///< Next sequence name.
120 * Construction is initialization. The constructor loads sequence
121 * data from the sequence map, presumably loaded from an animation
122 * file. The rest of the loading takes place in the frame's
123 * constructor which loads each individual frame.
126 Sequence(SerializablePtr root
) :
130 std::map
<std::string
,SerializablePtr
> rootObj
;
132 if (root
->get(rootObj
))
134 std::map
<std::string
,SerializablePtr
>::iterator it
;
135 for (it
= rootObj
.begin(); it
!= rootObj
.end(); ++it
)
137 std::string key
= (*it
).first
;
141 std::vector
<SerializablePtr
> framesObj
;
143 if ((*it
).second
->get(framesObj
))
145 std::vector
<SerializablePtr
>::iterator jt
;
147 for (jt
= framesObj
.begin();
148 jt
!= framesObj
.end(); ++jt
)
152 frames
.push_back(Frame(*jt
));
157 else if (key
== "delay")
160 (*it
).second
->getNumber(value
);
161 delay
= Scalar(value
);
163 else if (key
== "loop")
165 (*it
).second
->get(loop
);
167 else if (key
== "next")
169 (*it
).second
->get(next
);
178 * Starts loading a file with animation data. Such a file is formatted
179 * as a map of named sequences. The sequence constructor loads each
180 * individual sequence.
185 std::string filePath
= Animation::getPath(getName());
187 Deserializer
deserializer(filePath
);
189 SerializablePtr root
= deserializer
.deserialize();
193 std::map
<std::string
,SerializablePtr
> rootObj
;
195 if (root
->get(rootObj
))
197 std::map
<std::string
,SerializablePtr
>::iterator it
;
199 for (it
= rootObj
.begin(); it
!= rootObj
.end(); ++it
)
201 sequences
.insert(std::pair
<std::string
,Sequence
>((*it
).first
,
202 Sequence((*it
).second
)));
209 * Construction is initialization. The animation class data container
210 * registers itself as a mippleton and then loads the animation data.
213 explicit GlobalData(const std::string
& name
) :
214 Mippleton
<GlobalData
>(name
)
219 std::map
<std::string
,Sequence
> sequences
; ///< List of sequences.
224 * Construction is intialization.
227 Impl(const std::string
& name
) :
228 data(GlobalData::getInstance(name
)),
237 * Sets up the animation classes to "play" a named sequence. If another
238 * sequence was active, it will be replaced as the current sequence. Future
239 * updates will progress the new sequence.
242 void startSequence(const std::string
& name
)
244 std::map
<std::string
,GlobalData::Sequence
>::iterator it
;
246 it
= data
->sequences
.find(name
);
248 if (it
!= data
->sequences
.end())
250 currentSequence
= &(*it
).second
;
252 frameIndex
= currentSequence
->frames
[0].index
;
254 frameDuration
= currentSequence
->delay
*
255 currentSequence
->frames
[0].duration
;
260 * Updates or progresses the animation sequence. If the time interval
261 * surpasses the duration of the current frame, a new frame becomes the
262 * current frame. If the last frame of a sequence expires, the active
263 * sequence will switch automatically to the designated "next" sequence, or
264 * if none is specified but the sequence is set to loop, the first frame of
265 * the sequence will become the current frame, and the animation essentially
269 void update(Scalar t
, Scalar dt
)
275 if (timeAccum
>= frameDuration
)
277 if (++frameCounter
>= currentSequence
->frames
.size())
279 if (!currentSequence
->next
.empty())
281 startSequence(currentSequence
->next
);
283 else if (currentSequence
->loop
)
294 frameIndex
= currentSequence
->frames
[frameCounter
].index
;
295 timeAccum
= frameDuration
- timeAccum
;
296 frameDuration
= currentSequence
->delay
*
297 currentSequence
->frames
[frameCounter
].duration
;
302 boost::shared_ptr
<GlobalData
> data
; ///< Internal data.
304 GlobalData::Sequence
* currentSequence
; ///< Active sequence.
305 unsigned frameCounter
; ///< Current frame.
306 unsigned frameIndex
; ///< Index of current frame.
307 Scalar timeAccum
; ///< Time accumulation.
308 Scalar frameDuration
; ///< Scaled frame duration.
312 Animation::Animation(const std::string
& name
) :
314 impl_(new Animation::Impl(name
)) {}
317 void Animation::startSequence(const std::string
& name
)
320 impl_
->startSequence(name
);
323 void Animation::update(Scalar t
, Scalar dt
)
326 impl_
->update(t
, dt
);
331 * Gets the index for the current frame. This is presumably called by some
332 * drawing code which will draw the correct current frame.
335 unsigned Animation::getFrame() const
337 return impl_
->frameIndex
;
342 * Specialized search location for animation files. They can be found in the
343 * "animations" subdirectory of any of the searched directories.
346 std::string
Animation::getPath(const std::string
& name
)
348 return Resource::getPath("animations/" + name
+ ".json");
354 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.051924 seconds and 4 git commands to generate.