1 /***********************************************************************
2 created: 7/8/2010
3 author: Martin Preisler
4
5 purpose: Implements the KeyFrame class
6 *************************************************************************/
7 /***************************************************************************
8 * Copyright (C) 2004 - 2010 Paul D Turner & The CEGUI Development Team
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining
11 * a copy of this software and associated documentation files (the
12 * "Software"), to deal in the Software without restriction, including
13 * without limitation the rights to use, copy, modify, merge, publish,
14 * distribute, sublicense, and/or sell copies of the Software, and to
15 * permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 ***************************************************************************/
29 #include "CEGUI/KeyFrame.h"
30 #include "CEGUI/AnimationInstance.h"
31 #include "CEGUI/Affector.h"
32 #include "CEGUI/Animation_xmlHandler.h"
33 #include "CEGUI/XMLSerializer.h"
34 #include "CEGUI/PropertyHelper.h"
35 #include "CEGUI/Exceptions.h"
36 #include <cmath>
37
38 // Start of CEGUI namespace section
39 namespace CEGUI
40 {
41
42 //----------------------------------------------------------------------------//
KeyFrame(Affector * parent,float position)43 KeyFrame::KeyFrame(Affector* parent, float position):
44 d_parent(parent),
45 d_position(position),
46
47 d_progression(P_Linear)
48 {}
49
50 //----------------------------------------------------------------------------//
~KeyFrame(void)51 KeyFrame::~KeyFrame(void)
52 {}
53
54 //----------------------------------------------------------------------------//
getParent() const55 Affector* KeyFrame::getParent() const
56 {
57 return d_parent;
58 }
59
60 //----------------------------------------------------------------------------//
getIdxInParent() const61 size_t KeyFrame::getIdxInParent() const
62 {
63 const Affector* parent = getParent();
64 assert(getParent() && "No parent, no index in parent!");
65
66 size_t i = 0;
67 while (i < parent->getNumKeyFrames())
68 {
69 if (parent->getKeyFrameAtIdx(i) == this)
70 {
71 return i;
72 }
73
74 ++i;
75 }
76
77 CEGUI_THROW(UnknownObjectException(
78 "KeyFrame wasn't found in parent, therefore its index is unknown!"));
79 }
80
81 //----------------------------------------------------------------------------//
moveToPosition(float newPosition)82 void KeyFrame::moveToPosition(float newPosition)
83 {
84 assert(d_parent);
85
86 d_parent->moveKeyFrameToPosition(this, newPosition);
87 }
88
89 //----------------------------------------------------------------------------//
getPosition() const90 float KeyFrame::getPosition() const
91 {
92 return d_position;
93 }
94
95 //----------------------------------------------------------------------------//
setValue(const String & value)96 void KeyFrame::setValue(const String& value)
97 {
98 d_value = value;
99 }
100
101 //----------------------------------------------------------------------------//
getValue() const102 const String& KeyFrame::getValue() const
103 {
104 return d_value;
105 }
106
107 //----------------------------------------------------------------------------//
setSourceProperty(const String & sourceProperty)108 void KeyFrame::setSourceProperty(const String& sourceProperty)
109 {
110 d_sourceProperty = sourceProperty;
111 }
112
113 //----------------------------------------------------------------------------//
getSourceProperty() const114 const String& KeyFrame::getSourceProperty() const
115 {
116 return d_sourceProperty;
117 }
118
119 //----------------------------------------------------------------------------//
getValueForAnimation(AnimationInstance * instance) const120 const String& KeyFrame::getValueForAnimation(AnimationInstance* instance) const
121 {
122 if (!d_sourceProperty.empty())
123 {
124 return instance->getSavedPropertyValue(d_sourceProperty);
125 }
126 else
127 {
128 return d_value;
129 }
130 }
131
132 //----------------------------------------------------------------------------//
setProgression(Progression p)133 void KeyFrame::setProgression(Progression p)
134 {
135 d_progression = p;
136 }
137
138 //----------------------------------------------------------------------------//
getProgression() const139 KeyFrame::Progression KeyFrame::getProgression() const
140 {
141 return d_progression;
142 }
143
144 //----------------------------------------------------------------------------//
alterInterpolationPosition(float position)145 float KeyFrame::alterInterpolationPosition(float position)
146 {
147 switch (d_progression)
148 {
149 case P_Linear:
150 return position;
151
152 case P_QuadraticAccelerating:
153 return position * position;
154
155 case P_QuadraticDecelerating:
156 return sqrtf(position);
157
158 case P_Discrete:
159 return position < 1.0f ? 0.0f : 1.0f;
160 }
161
162 // todo: more progression methods?
163 assert(0);
164 return position;
165 }
166
167 //----------------------------------------------------------------------------//
savePropertyValue(AnimationInstance * instance)168 void KeyFrame::savePropertyValue(AnimationInstance* instance)
169 {
170 if (!d_sourceProperty.empty())
171 {
172 instance->savePropertyValue(d_sourceProperty);
173 }
174 }
175
176 //----------------------------------------------------------------------------//
notifyPositionChanged(float newPosition)177 void KeyFrame::notifyPositionChanged(float newPosition)
178 {
179 d_position = newPosition;
180 }
181
writeXMLToStream(XMLSerializer & xml_stream) const182 void KeyFrame::writeXMLToStream(XMLSerializer& xml_stream) const
183 {
184 xml_stream.openTag(AnimationKeyFrameHandler::ElementName);
185
186 xml_stream.attribute(AnimationKeyFrameHandler::PositionAttribute, PropertyHelper<float>::toString(getPosition()));
187
188 if (!d_sourceProperty.empty())
189 {
190 xml_stream.attribute(AnimationKeyFrameHandler::SourcePropertyAttribute, getSourceProperty());
191 }
192 else
193 {
194 xml_stream.attribute(AnimationKeyFrameHandler::ValueAttribute, getValue());
195 }
196
197 String progression;
198 switch(getProgression())
199 {
200 case P_Linear:
201 progression = AnimationKeyFrameHandler::ProgressionLinear;
202 break;
203 case P_Discrete:
204 progression = AnimationKeyFrameHandler::ProgressionDiscrete;
205 break;
206 case P_QuadraticAccelerating:
207 progression = AnimationKeyFrameHandler::ProgressionQuadraticAccelerating;
208 break;
209 case P_QuadraticDecelerating:
210 progression = AnimationKeyFrameHandler::ProgressionQuadraticDecelerating;
211 break;
212
213 default:
214 assert(0 && "How did we get here?");
215 break;
216 }
217 xml_stream.attribute(AnimationKeyFrameHandler::ProgressionAttribute, progression);
218
219 xml_stream.closeTag();
220 }
221
222 //----------------------------------------------------------------------------//
223
224 } // End of CEGUI namespace section
225