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