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);