1 module spine.animation;
2 
3 import spine.skeleton;
4 import std.string: toStringz;
5 import std.conv: to;
6 
7 class AnimationStateData
8 {
9     private SkeletonData skeletonData;
10     package spAnimationStateData* sp_animationStateData;
11 
12     this(SkeletonData sd)
13     {
14         skeletonData = sd;
15         sp_animationStateData = spAnimationStateData_create(skeletonData.sp_skeletonData);
16 
17         assert(sp_animationStateData);
18     }
19 
20     ~this()
21     {
22         spAnimationStateData_dispose(sp_animationStateData);
23     }
24 
25     void setMixByName(string fromName, string toName, float duration)
26     {
27         spAnimationStateData_setMixByName(
28                 sp_animationStateData,
29                 fromName.toStringz,
30                 toName.toStringz,
31                 duration
32             );
33     }
34 
35     void setMix(Animation from, Animation to, float duration)
36     {
37         spAnimationStateData_setMix(
38                 sp_animationStateData,
39                 from.sp_animation,
40                 to.sp_animation,
41                 duration
42             );
43     }
44 }
45 
46 class AnimationStateInstance
47 {
48     private AnimationStateData stateData;
49     package spAnimationState* sp_animationState;
50 
51     this(AnimationStateData asd)
52     {
53         stateData = asd;
54         sp_animationState = spAnimationState_create(stateData.sp_animationStateData);
55 
56         assert(sp_animationState);
57     }
58 
59     ~this()
60     {
61         spAnimationState_dispose(sp_animationState);
62     }
63 
64     void update(float deltaTime)
65     {
66         spAnimationState_update(sp_animationState, deltaTime);
67     }
68 
69     void apply(Skeleton skeleton)
70     {
71         spAnimationState_apply(sp_animationState, skeleton.sp_skeleton);
72     }
73 
74     void setAnimationByName(int trackIndex, string animationName, bool loop)
75     {
76         spAnimationState_setAnimationByName(sp_animationState, trackIndex, animationName.toStringz, loop);
77     }
78 
79     void setAnimation(int trackIndex, Animation animation, bool loop)
80     {
81         spAnimationState_setAnimation(sp_animationState, trackIndex, animation.sp_animation, loop);
82     }
83 
84     void addAnimationByName(int trackIndex, string animationName, bool loop, float delay)
85     {
86         spAnimationState_addAnimationByName(sp_animationState, trackIndex, animationName.toStringz, loop, delay);
87     }
88 
89     void addAnimation(int trackIndex, Animation animation, bool loop, float delay)
90     {
91         spAnimationState_addAnimation(sp_animationState, trackIndex, animation.sp_animation, loop, delay);
92     }
93 
94     void timeScale(float t)
95     {
96         sp_animationState.timeScale = t;
97     }
98 
99     void addListener(spAnimationStateListener listener)
100     {
101         sp_animationState.listener = listener;
102     }
103 }
104 
105 struct Animation
106 {
107     private spAnimation* sp_animation;
108 }
109 
110 Animation findAnimation(SkeletonData sd, string animationName)
111 {
112     Animation ret;
113     ret.sp_animation = spSkeletonData_findAnimation(sd.sp_skeletonData, animationName.toStringz);
114 
115     return ret;
116 }
117 
118 extern(C):
119 
120 enum spEventType
121 {
122     SP_ANIMATION_START,
123     SP_ANIMATION_INTERRUPT,
124     SP_ANIMATION_END,
125     SP_ANIMATION_COMPLETE,
126     SP_ANIMATION_DISPOSE,
127     SP_ANIMATION_EVENT
128 }
129 
130 private:
131 
132 struct spEventData
133 {
134 	const char* name;
135 	int intValue;
136 	float floatValue;
137 	const(char)* stringValue;
138 
139     string toString() const
140     {
141         return
142             "name="~name.to!string~
143             " intValue="~intValue.to!string~
144             " floatValue="~floatValue.to!string~
145             " stringValue="~stringValue.to!string;
146     }
147 }
148 
149 struct spEvent
150 {
151 	const(spEventData)* data;
152 	const float time;
153 	int intValue;
154 	float floatValue;
155 	const(char)* stringValue;
156 
157     string toString() const
158     {
159         return
160             "data=(ptr="~data.to!string~
161             " "~data.toString~
162             ") time="~time.to!string~
163             " intValue="~intValue.to!string~
164             " floatValue="~floatValue.to!string~
165             " stringValue="~stringValue.to!string;
166     }
167 }
168 
169 void spAnimation_dispose (spAnimation* self);
170 
171 void spAnimation_apply (const(spAnimation)* self, spSkeleton* skeleton, float lastTime, float time, int loop,
172 		spEvent** events, int* eventsCount, float alpha, int /*boolean*/ setupPose, int /*boolean*/ mixingOut);
173 
174 spAnimation* spSkeletonData_findAnimation (const(spSkeletonData)* self, const(char)* animationName);
175 
176 alias spAnimationStateListener = void function(spAnimationState* state, spEventType type, spTrackEntry* entry, spEvent* event);
177 
178 struct spAnimationState
179 {
180 	const(spAnimationStateData)* data;
181 
182 	int tracksCount;
183 	spTrackEntry** tracks;
184 
185 	spAnimationStateListener listener;
186 
187 	float timeScale = 0;
188 
189 	void* rendererObject;
190 }
191 
192 struct spAnimationStateData;
193 
194 spAnimationStateData* spAnimationStateData_create (spSkeletonData* skeletonData);
195 void spAnimationStateData_dispose (spAnimationStateData* self);
196 
197 void spAnimationStateData_setMixByName (spAnimationStateData* self, const(char)* fromName, const(char)* toName, float duration);
198 
199 void spAnimationStateData_setMix (spAnimationStateData* self, spAnimation* from, spAnimation* to, float duration);
200 
201 /* @param data May be 0 for no mixing. */
202 spAnimationState* spAnimationState_create (spAnimationStateData* data);
203 void spAnimationState_dispose (spAnimationState* self);
204 
205 struct spTrackEntry;
206 
207 /** Set the current animation. Any queued animations are cleared. */
208 spTrackEntry* spAnimationState_setAnimationByName (spAnimationState* self, int trackIndex, const(char)* animationName, int/*bool*/loop);
209 
210 /// ditto
211 spTrackEntry* spAnimationState_setAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop);
212 
213 /** Adds an animation to be played delay seconds after the current or last queued animation, taking into account any mix duration. */
214 spTrackEntry* spAnimationState_addAnimationByName (spAnimationState* self, int trackIndex, const(char)* animationName, int/*bool*/loop, float delay);
215 
216 /// ditto
217 spTrackEntry* spAnimationState_addAnimation(spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop, float delay);
218 
219 void spAnimationState_update (spAnimationState* self, float delta);
220 
221 void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton);