1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _SD_CUSTOMANIMATIONEFFECT_HXX
25 #define _SD_CUSTOMANIMATIONEFFECT_HXX
26 
27 #include <com/sun/star/animations/XAnimationNode.hpp>
28 #include <com/sun/star/animations/XTimeContainer.hpp>
29 #include <com/sun/star/animations/XAudio.hpp>
30 #include <com/sun/star/drawing/XShape.hpp>
31 #include <com/sun/star/util/XChangesListener.hpp>
32 #include <tools/string.hxx>
33 
34 #include <boost/shared_ptr.hpp>
35 
36 #include <comphelper/stl_types.hxx>
37 #include <vcl/timer.hxx>
38 
39 #include <sddllapi.h>
40 
41 #include <list>
42 #include <map>
43 
44 class SdrPathObj;
45 
46 namespace sd {
47 
48 // --------------------------------------------------------------------
49 
50 enum EValue { VALUE_FROM, VALUE_TO, VALUE_BY, VALUE_FIRST, VALUE_LAST };
51 
52 class CustomAnimationEffect;
53 class AnimationTrigger;
54 
55 class CustomAnimationPreset;
56 typedef boost::shared_ptr< CustomAnimationPreset > CustomAnimationPresetPtr;
57 
58 typedef boost::shared_ptr< CustomAnimationEffect > CustomAnimationEffectPtr;
59 
60 typedef std::list< CustomAnimationEffectPtr > EffectSequence;
61 
62 class EffectSequenceHelper;
63 
64 class CustomAnimationEffect
65 {
66 	friend class MainSequence;
67 	friend class EffectSequenceHelper;
68 
69 public:
70 	SD_DLLPUBLIC CustomAnimationEffect( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode );
71 	SD_DLLPUBLIC virtual ~CustomAnimationEffect();
72 
getNode() const73 	const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& getNode() const { return mxNode; }
74 	void setNode( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode );
75 	void replaceNode( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode );
76 
77 	CustomAnimationEffectPtr clone() const;
78 
79 	// attributes
getPresetId() const80 	const rtl::OUString&	getPresetId() const { return maPresetId; }
getPresetSubType() const81 	const rtl::OUString&	getPresetSubType() const { return maPresetSubType; }
getProperty() const82 	const rtl::OUString&	getProperty() const { return maProperty; }
83 
getPresetClass() const84 	sal_Int16				getPresetClass() const { return mnPresetClass; }
85 	void					setPresetClass( sal_Int16 nPresetClass );
86 
getNodeType() const87 	sal_Int16		getNodeType() const { return mnNodeType; }
88 	SD_DLLPUBLIC void			setNodeType( sal_Int16 nNodeType );
89 
90 	::com::sun::star::uno::Any				getRepeatCount() const;
91 	void			setRepeatCount( const ::com::sun::star::uno::Any& rRepeatCount );
92 
93 	::com::sun::star::uno::Any				getEnd() const;
94 	void			setEnd( const ::com::sun::star::uno::Any& rEnd );
95 
96 	sal_Int16		getFill() const;
97 	void			setFill( sal_Int16 nFill );
98 
getBegin() const99 	double			getBegin() const { return mfBegin; }
100 	SD_DLLPUBLIC void			setBegin( double fBegin );
101 
getDuration() const102 	double			getDuration() const { return mfDuration; }
103 	SD_DLLPUBLIC void			setDuration( double fDuration );
104 
getAbsoluteDuration() const105 	double			getAbsoluteDuration() const { return mfAbsoluteDuration; }
106 
getName() const107 	const String&	getName() const { return maName; }
setName(const String & rName)108 	void			setName( const String& rName ) { maName = rName; }
109 
getIterateType() const110 	sal_Int16		getIterateType() const { return mnIterateType; }
111 	SD_DLLPUBLIC void			setIterateType( sal_Int16 nIterateType );
112 
getIterateInterval() const113 	double			getIterateInterval() const { return mfIterateInterval; }
114 	SD_DLLPUBLIC void			setIterateInterval( double fIterateInterval );
115 
getTarget() const116 	::com::sun::star::uno::Any	getTarget() const { return maTarget; }
117 	SD_DLLPUBLIC void						setTarget( const ::com::sun::star::uno::Any& rTarget );
118 
hasAfterEffect() const119 	sal_Bool		hasAfterEffect() const { return mbHasAfterEffect; }
setHasAfterEffect(sal_Bool bHasAfterEffect)120 	void			setHasAfterEffect( sal_Bool bHasAfterEffect ) { mbHasAfterEffect = bHasAfterEffect; }
121 
getDimColor() const122 	::com::sun::star::uno::Any	getDimColor() const { return maDimColor; }
setDimColor(::com::sun::star::uno::Any aDimColor)123 	void						setDimColor( ::com::sun::star::uno::Any aDimColor ) { maDimColor = aDimColor; }
124 
IsAfterEffectOnNext() const125 	bool			IsAfterEffectOnNext() const { return mbAfterEffectOnNextEffect; }
setAfterEffectOnNext(bool bOnNextEffect)126 	void			setAfterEffectOnNext( bool bOnNextEffect ) { mbAfterEffectOnNextEffect = bOnNextEffect; }
127 
getParaDepth() const128 	sal_Int32		getParaDepth() const { return mnParaDepth; }
129 
hasText() const130 	sal_Bool		hasText() const { return mbHasText; }
131 
getCommand() const132 	sal_Int16		getCommand() const { return mnCommand; }
133 
getAcceleration() const134 	double			getAcceleration() const { return mfAcceleration; }
135 	void			setAcceleration( double fAcceleration );
136 
getDecelerate() const137 	double			getDecelerate() const { return mfDecelerate; }
138 	void			setDecelerate( double fDecelerate );
139 
getAutoReverse() const140 	sal_Bool		getAutoReverse() const { return mbAutoReverse; }
141 	void			setAutoReverse( sal_Bool bAutoReverse );
142 
143 	::com::sun::star::uno::Any	getProperty( sal_Int32 nNodeType, const rtl::OUString& rAttributeName, EValue eValue );
144 	bool						setProperty( sal_Int32 nNodeType, const rtl::OUString& rAttributeName, EValue eValue, const ::com::sun::star::uno::Any& rValue );
145 
146 	::com::sun::star::uno::Any	getTransformationProperty( sal_Int32 nTransformType, EValue eValue );
147 	bool						setTransformationProperty( sal_Int32 nTransformType, EValue eValue, const ::com::sun::star::uno::Any& rValue );
148 
149 	::com::sun::star::uno::Any	getColor( sal_Int32 nIndex );
150 	void						setColor( sal_Int32 nIndex, const ::com::sun::star::uno::Any& rColor );
151 
152 	::com::sun::star::uno::Any	getRotation();
153 	void						setRotation( const ::com::sun::star::uno::Any& rRotation );
154 
getGroupId() const155 	sal_Int32		getGroupId() const { return mnGroupId; }
156 	void			setGroupId( sal_Int32 nGroupId );
157 
getTargetSubItem() const158 	sal_Int16		getTargetSubItem() const { return mnTargetSubItem; }
159 	SD_DLLPUBLIC void			setTargetSubItem( sal_Int16 nSubItem );
160 
161 	::rtl::OUString	getPath() const;
162 	void setPath( const ::rtl::OUString& rPath );
163 
164 	bool checkForText();
165 	bool calculateIterateDuration();
166 
167 	void setAudio( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAudio >& xAudio );
168 	bool getStopAudio() const;
169 	SD_DLLPUBLIC void setStopAudio();
170 	SD_DLLPUBLIC void createAudio( const ::com::sun::star::uno::Any& rSource, double fVolume = 1.0 );
171 	void removeAudio();
getAudio() const172 	const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAudio >& getAudio() const { return mxAudio; }
173 
getEffectSequence() const174 	EffectSequenceHelper*	getEffectSequence() const { return mpEffectSequence; }
175 
176 	// helper
177 	::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode > createAfterEffectNode() const throw (com::sun::star::uno::Exception);
178 	::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > getTargetShape() const;
179 
180 	// static helpers
181 	static sal_Int32 get_node_type( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode );
182 	static sal_Int32 getNumberOfSubitems( const ::com::sun::star::uno::Any& aTarget, sal_Int16 nIterateType );
183 
184 	SdrPathObj* createSdrPathObjFromPath();
185 	void updateSdrPathObjFromPath( SdrPathObj& rPathObj );
186 	void updatePathFromSdrPathObj( const SdrPathObj& rPathObj );
187 
188 protected:
setEffectSequence(EffectSequenceHelper * pSequence)189 	void setEffectSequence( EffectSequenceHelper* pSequence ) { mpEffectSequence = pSequence; }
190 
191 private:
192 	sal_Int16		mnNodeType;
193 	rtl::OUString	maPresetId;
194 	rtl::OUString	maPresetSubType;
195 	rtl::OUString	maProperty;
196 	sal_Int16		mnPresetClass;
197 	double			mfBegin;
198 	double			mfDuration;					// this is the maximum duration of the subeffects
199 	double			mfAbsoluteDuration;			// this is the maximum duration of the subeffects including possible iterations
200 	sal_Int32		mnGroupId;
201 	sal_Int16		mnIterateType;
202 	double			mfIterateInterval;
203 	sal_Int32		mnParaDepth;
204 	sal_Bool		mbHasText;
205 	double			mfAcceleration;
206 	double			mfDecelerate;
207 	sal_Bool		mbAutoReverse;
208 	sal_Int16		mnTargetSubItem;
209 	sal_Int16		mnCommand;
210 
211 	EffectSequenceHelper* mpEffectSequence;
212 
213 	String			maName;
214 
215 	::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode > mxNode;
216 	::com::sun::star::uno::Reference< ::com::sun::star::animations::XAudio > mxAudio;
217 	::com::sun::star::uno::Any maTarget;
218 
219 	sal_Bool		mbHasAfterEffect;
220 	::com::sun::star::uno::Any maDimColor;
221 	bool		mbAfterEffectOnNextEffect;
222 };
223 
224 struct stl_CustomAnimationEffect_search_node_predict
225 {
226 	stl_CustomAnimationEffect_search_node_predict( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xSearchNode );
227 	bool operator()( CustomAnimationEffectPtr pEffect ) const;
228 	const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& mxSearchNode;
229 };
230 
231 enum ESequenceHint { EFFECT_EDITED, EFFECT_REMOVED, EFFECT_ADDED };
232 
233 /** this listener is implemented by UI components to track changes in the animation core */
234 class ISequenceListener
235 {
236 public:
237 	virtual void notify_change() = 0;
238 };
239 
240 /** this class keeps track of a group of animations that build up
241 	a text animation for a single shape */
242 class CustomAnimationTextGroup
243 {
244 	friend class EffectSequenceHelper;
245 
246 public:
247 	CustomAnimationTextGroup( const ::com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& rTarget, sal_Int32 nGroupId );
248 
249 	void reset();
250 	void addEffect( CustomAnimationEffectPtr& pEffect );
251 
getTarget() const252 	const ::com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& getTarget() const { return maTarget; }
getEffects() const253 	const EffectSequence& getEffects() const { return maEffects; }
254 
255 	/* -1: as single object, 0: all at once, n > 0: by n Th paragraph */
getTextGrouping() const256 	sal_Int32 getTextGrouping() const { return mnTextGrouping; }
257 
getAnimateForm() const258 	sal_Bool getAnimateForm() const { return mbAnimateForm; }
getTextReverse() const259 	sal_Bool getTextReverse() const { return mbTextReverse; }
getTextGroupingAuto() const260 	double getTextGroupingAuto() const { return mfGroupingAuto; }
261 
262 private:
263 	EffectSequence maEffects;
264 	::com::sun::star::uno::Reference< com::sun::star::drawing::XShape > maTarget;
265 
266 	sal_Int32 mnTextGrouping;
267 	sal_Bool mbAnimateForm;
268 	sal_Bool mbTextReverse;
269 	double mfGroupingAuto;
270 	sal_Int32 mnLastPara;
271 	sal_Int8 mnDepthFlags[5];
272 	sal_Int32 mnGroupId;
273 };
274 
275 typedef boost::shared_ptr< CustomAnimationTextGroup > CustomAnimationTextGroupPtr;
276 typedef std::map< sal_Int32, CustomAnimationTextGroupPtr > CustomAnimationTextGroupMap;
277 
278 class EffectSequenceHelper
279 {
280 friend class MainSequence;
281 
282 public:
283 	EffectSequenceHelper();
284 	EffectSequenceHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XTimeContainer >& xSequenceRoot );
285 	virtual ~EffectSequenceHelper();
286 
287 	virtual ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode > getRootNode();
288 
289 	CustomAnimationEffectPtr append( const CustomAnimationPresetPtr& pDescriptor, const ::com::sun::star::uno::Any& rTarget, double fDuration = -1.0 );
290 	CustomAnimationEffectPtr append( const SdrPathObj& rPathObj, const ::com::sun::star::uno::Any& rTarget, double fDuration = -1.0 );
291 	SD_DLLPUBLIC void append( const CustomAnimationEffectPtr& pEffect );
292 	void insert( EffectSequence::iterator& rPos, const CustomAnimationEffectPtr& pEffect );
293 	void replace( const CustomAnimationEffectPtr& pEffect, const CustomAnimationPresetPtr& pDescriptor, double fDuration = -1.0 );
294 	void replace( const CustomAnimationEffectPtr& pEffect, const CustomAnimationPresetPtr& pDescriptor, const rtl::OUString& rPresetSubType, double fDuration = -1.0 );
295 	void remove( const CustomAnimationEffectPtr& pEffect );
296 
297 	void create( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode );
298 	void createEffectsequence( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode );
299 	void processAfterEffect( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode );
300 	void createEffects( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode );
301 
getCount() const302 	sal_Int32 getCount() const { return sal::static_int_cast< sal_Int32 >( maEffects.size() ); }
303 
304 	virtual CustomAnimationEffectPtr findEffect( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) const;
305 
306 	virtual bool disposeShape( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape );
307 	virtual void insertTextRange( const com::sun::star::uno::Any& aTarget );
308 	virtual void disposeTextRange( const com::sun::star::uno::Any& aTarget );
309 	virtual bool hasEffect( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape );
310 	virtual void onTextChanged( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape );
311 
312 	/** this must be called if effects from this sequence are changed.
313 		the method will call the registered listeners */
314 	void update( const CustomAnimationEffectPtr& pEffect );
315 
316 	/** this method rebuilds the animation nodes */
317 	virtual void rebuild();
318 
getBegin()319 	EffectSequence::iterator getBegin() { return maEffects.begin(); }
getEnd()320 	EffectSequence::iterator getEnd() { return maEffects.end(); }
321 	EffectSequence::iterator find( const CustomAnimationEffectPtr& pEffect );
322 
getSequence()323 	EffectSequence& getSequence() { return maEffects; }
324 
325 	void addListener( ISequenceListener* pListener );
326 	void removeListener( ISequenceListener* pListener );
327 
328 	// text group methods
329 
330 	CustomAnimationTextGroupPtr findGroup( sal_Int32 nGroupId );
331 	SD_DLLPUBLIC CustomAnimationTextGroupPtr	createTextGroup( CustomAnimationEffectPtr pEffect, sal_Int32 nTextGrouping, double fTextGroupingAuto, sal_Bool bAnimateForm, sal_Bool bTextReverse );
332 	void setTextGrouping( CustomAnimationTextGroupPtr pTextGroup, sal_Int32 nTextGrouping );
333 	void setAnimateForm( CustomAnimationTextGroupPtr pTextGroup, sal_Bool bAnimateForm );
334 	void setTextGroupingAuto( CustomAnimationTextGroupPtr pTextGroup, double fTextGroupingAuto );
335 	void setTextReverse( CustomAnimationTextGroupPtr pTextGroup, sal_Bool bAnimateForm );
336 
getSequenceType() const337 	sal_Int32 getSequenceType() const { return mnSequenceType; }
338 
getTriggerShape() const339 	::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > getTriggerShape() const { return mxEventSource; }
setTriggerShape(const::com::sun::star::uno::Reference<::com::sun::star::drawing::XShape> & xTrigger)340 	void setTriggerShape( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xTrigger ) { mxEventSource = xTrigger; }
341 
342 	virtual sal_Int32 getOffsetFromEffect( const CustomAnimationEffectPtr& xEffect ) const;
343 	virtual CustomAnimationEffectPtr getEffectFromOffset( sal_Int32 nOffset ) const;
344 
345 protected:
346 	virtual void implRebuild();
347 	virtual void reset();
348 
349 	void createTextGroupParagraphEffects( CustomAnimationTextGroupPtr pTextGroup, CustomAnimationEffectPtr pEffect, bool bUsed );
350 
351 	void notify_listeners();
352 
353 	::com::sun::star::uno::Reference< ::com::sun::star::animations::XTimeContainer > createParallelTimeContainer() const;
354 
355 	void updateTextGroups();
356 
357 protected:
358 	::com::sun::star::uno::Reference< ::com::sun::star::animations::XTimeContainer > mxSequenceRoot;
359 	EffectSequence maEffects;
360 	std::list< ISequenceListener* > maListeners;
361 	CustomAnimationTextGroupMap maGroupMap;
362 	sal_Int32 mnSequenceType;
363 	::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > mxEventSource;
364 };
365 
366 class MainSequence;
367 
368 class InteractiveSequence : public EffectSequenceHelper
369 {
370 friend class MainSequence;
371 friend class MainSequenceChangeGuard;
372 
373 public:
374 	InteractiveSequence( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XTimeContainer >& xSequenceRoot, MainSequence* pMainSequence );
375 
376 	/** this method rebuilds the animation nodes */
377 	virtual void rebuild();
378 
379 private:
380 	virtual void implRebuild();
381 
382 	MainSequence*	mpMainSequence;
383 };
384 
385 typedef boost::shared_ptr< InteractiveSequence > InteractiveSequencePtr;
386 typedef std::list< InteractiveSequencePtr > InteractiveSequenceList;
387 
388 class MainSequence : public EffectSequenceHelper, public ISequenceListener
389 {
390 	friend class UndoAnimation;
391 	friend class MainSequenceRebuildGuard;
392 	friend class MainSequenceChangeGuard;
393 
394 public:
395 	MainSequence();
396 	MainSequence( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xTimingRootNode );
397 	~MainSequence();
398 
399 	virtual ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode > getRootNode();
400 	void reset( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xTimingRootNode );
401 
402 	/** this method rebuilds the animation nodes */
403 	virtual void rebuild();
404 
405 	virtual CustomAnimationEffectPtr findEffect( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) const;
406 
407 	virtual bool disposeShape( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape );
408 	virtual void insertTextRange( const com::sun::star::uno::Any& aTarget );
409 	virtual void disposeTextRange( const com::sun::star::uno::Any& aTarget );
410 	virtual bool hasEffect( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape );
411 	virtual void onTextChanged( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape );
412 
getInteractiveSequenceList() const413 	const InteractiveSequenceList& getInteractiveSequenceList() const { return maInteractiveSequenceList; }
414 
415 	virtual void notify_change();
416 
417 	bool setTrigger( const CustomAnimationEffectPtr& pEffect, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xTriggerShape );
418 
419 	/** starts a timer that recreates the internal structure from the API core after 1 second */
420 	void startRecreateTimer();
421 
422 	/** starts a timer that rebuilds the API core from the internal structure after 1 second */
423 	void startRebuildTimer();
424 
425 	virtual sal_Int32 getOffsetFromEffect( const CustomAnimationEffectPtr& xEffect ) const;
426 	virtual CustomAnimationEffectPtr getEffectFromOffset( sal_Int32 nOffset ) const;
427 
428 protected:
429 	/** permits rebuilds until unlockRebuilds() is called. All rebuild calls during a locked sequence are
430 		process after unlockRebuilds() call. lockRebuilds() and unlockRebuilds() calls can be nested. */
431 	void lockRebuilds();
432 	void unlockRebuilds();
433 
434 	DECL_LINK( onTimerHdl, Timer * );
435 
436 	virtual void implRebuild();
437 
438 	void init();
439 
440 	void createMainSequence();
441 	virtual void reset();
442 
443 	InteractiveSequencePtr createInteractiveSequence( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape );
444 
445 	InteractiveSequenceList maInteractiveSequenceList;
446 
447 	::com::sun::star::uno::Reference< ::com::sun::star::util::XChangesListener > mxChangesListener;
448 	::com::sun::star::uno::Reference< ::com::sun::star::animations::XTimeContainer > mxTimingRootNode;
449 	Timer maTimer;
450 	bool mbTimerMode;
451 	bool mbRebuilding;
452 
453 	long mnRebuildLockGuard;
454 	bool mbPendingRebuildRequest;
455 	sal_Int32 mbIgnoreChanges;
456 };
457 
458 typedef boost::shared_ptr< MainSequence > MainSequencePtr;
459 
460 class MainSequenceRebuildGuard
461 {
462 public:
463 	MainSequenceRebuildGuard( const MainSequencePtr& pMainSequence );
464 	~MainSequenceRebuildGuard();
465 
466 private:
467 	MainSequencePtr mpMainSequence;
468 };
469 
470 }
471 
472 #endif // _SD_CUSTOMANIMATIONEFFECT_HXX
473