AnimationState.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057
  1. /******************************************************************************
  2. * Spine Runtimes License Agreement
  3. * Last updated January 1, 2020. Replaces all prior versions.
  4. *
  5. * Copyright (c) 2013-2020, Esoteric Software LLC
  6. *
  7. * Integration of the Spine Runtimes into software or otherwise creating
  8. * derivative works of the Spine Runtimes is permitted under the terms and
  9. * conditions of Section 2 of the Spine Editor License Agreement:
  10. * http://esotericsoftware.com/spine-editor-license
  11. *
  12. * Otherwise, it is permitted to integrate the Spine Runtimes into software
  13. * or otherwise create derivative works of the Spine Runtimes (collectively,
  14. * "Products"), provided that each user of the Products must obtain their own
  15. * Spine Editor license and redistribution of the Products in any form must
  16. * include this license and copyright notice.
  17. *
  18. * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
  19. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
  24. * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *****************************************************************************/
  29. #include <spine/AnimationState.h>
  30. #include <spine/extension.h>
  31. #include <limits.h>
  32. #define SUBSEQUENT 0
  33. #define FIRST 1
  34. #define HOLD 2
  35. #define HOLD_MIX 3
  36. #define SETUP 1
  37. #define CURRENT 2
  38. _SP_ARRAY_IMPLEMENT_TYPE(spTrackEntryArray, spTrackEntry*)
  39. static spAnimation* SP_EMPTY_ANIMATION = 0;
  40. void spAnimationState_disposeStatics () {
  41. if (SP_EMPTY_ANIMATION) spAnimation_dispose(SP_EMPTY_ANIMATION);
  42. SP_EMPTY_ANIMATION = 0;
  43. }
  44. /* Forward declaration of some "private" functions so we can keep
  45. the same function order in C as we have method order in Java. */
  46. void _spAnimationState_disposeTrackEntry (spTrackEntry* entry);
  47. void _spAnimationState_disposeTrackEntries (spAnimationState* state, spTrackEntry* entry);
  48. int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* entry, float delta);
  49. float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* entry, spSkeleton* skeleton, spMixBlend currentBlend);
  50. void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, spMixBlend blend, float* timelinesRotation, int i, int /*boolean*/ firstFrame);
  51. void _spAnimationState_applyAttachmentTimeline(spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float animationTime, spMixBlend blend, int /*bool*/ firstFrame);
  52. void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry, float animationTime);
  53. void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEntry* current, int /*boolean*/ interrupt);
  54. spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index);
  55. spTrackEntry* _spAnimationState_trackEntry (spAnimationState* self, int trackIndex, spAnimation* animation, int /*boolean*/ loop, spTrackEntry* last);
  56. void _spAnimationState_disposeNext (spAnimationState* self, spTrackEntry* entry);
  57. void _spAnimationState_animationsChanged (spAnimationState* self);
  58. float* _spAnimationState_resizeTimelinesRotation(spTrackEntry* entry, int newSize);
  59. int* _spAnimationState_resizeTimelinesFirst(spTrackEntry* entry, int newSize);
  60. void _spAnimationState_ensureCapacityPropertyIDs(spAnimationState* self, int capacity);
  61. int _spAnimationState_addPropertyID(spAnimationState* self, int id);
  62. void _spTrackEntry_computeHold(spTrackEntry* self, spAnimationState* state);
  63. _spEventQueue* _spEventQueue_create (_spAnimationState* state) {
  64. _spEventQueue *self = CALLOC(_spEventQueue, 1);
  65. self->state = state;
  66. self->objectsCount = 0;
  67. self->objectsCapacity = 16;
  68. self->objects = CALLOC(_spEventQueueItem, self->objectsCapacity);
  69. self->drainDisabled = 0;
  70. return self;
  71. }
  72. void _spEventQueue_free (_spEventQueue* self) {
  73. FREE(self->objects);
  74. FREE(self);
  75. }
  76. void _spEventQueue_ensureCapacity (_spEventQueue* self, int newElements) {
  77. if (self->objectsCount + newElements > self->objectsCapacity) {
  78. _spEventQueueItem* newObjects;
  79. self->objectsCapacity <<= 1;
  80. newObjects = CALLOC(_spEventQueueItem, self->objectsCapacity);
  81. memcpy(newObjects, self->objects, sizeof(_spEventQueueItem) * self->objectsCount);
  82. FREE(self->objects);
  83. self->objects = newObjects;
  84. }
  85. }
  86. void _spEventQueue_addType (_spEventQueue* self, spEventType type) {
  87. _spEventQueue_ensureCapacity(self, 1);
  88. self->objects[self->objectsCount++].type = type;
  89. }
  90. void _spEventQueue_addEntry (_spEventQueue* self, spTrackEntry* entry) {
  91. _spEventQueue_ensureCapacity(self, 1);
  92. self->objects[self->objectsCount++].entry = entry;
  93. }
  94. void _spEventQueue_addEvent (_spEventQueue* self, spEvent* event) {
  95. _spEventQueue_ensureCapacity(self, 1);
  96. self->objects[self->objectsCount++].event = event;
  97. }
  98. void _spEventQueue_start (_spEventQueue* self, spTrackEntry* entry) {
  99. _spEventQueue_addType(self, SP_ANIMATION_START);
  100. _spEventQueue_addEntry(self, entry);
  101. self->state->animationsChanged = 1;
  102. }
  103. void _spEventQueue_interrupt (_spEventQueue* self, spTrackEntry* entry) {
  104. _spEventQueue_addType(self, SP_ANIMATION_INTERRUPT);
  105. _spEventQueue_addEntry(self, entry);
  106. }
  107. void _spEventQueue_end (_spEventQueue* self, spTrackEntry* entry) {
  108. _spEventQueue_addType(self, SP_ANIMATION_END);
  109. _spEventQueue_addEntry(self, entry);
  110. self->state->animationsChanged = 1;
  111. }
  112. void _spEventQueue_dispose (_spEventQueue* self, spTrackEntry* entry) {
  113. _spEventQueue_addType(self, SP_ANIMATION_DISPOSE);
  114. _spEventQueue_addEntry(self, entry);
  115. }
  116. void _spEventQueue_complete (_spEventQueue* self, spTrackEntry* entry) {
  117. _spEventQueue_addType(self, SP_ANIMATION_COMPLETE);
  118. _spEventQueue_addEntry(self, entry);
  119. }
  120. void _spEventQueue_event (_spEventQueue* self, spTrackEntry* entry, spEvent* event) {
  121. _spEventQueue_addType(self, SP_ANIMATION_EVENT);
  122. _spEventQueue_addEntry(self, entry);
  123. _spEventQueue_addEvent(self, event);
  124. }
  125. void _spEventQueue_clear (_spEventQueue* self) {
  126. self->objectsCount = 0;
  127. }
  128. void _spEventQueue_drain (_spEventQueue* self) {
  129. int i;
  130. if (self->drainDisabled) return;
  131. self->drainDisabled = 1;
  132. for (i = 0; i < self->objectsCount; i += 2) {
  133. spEventType type = (spEventType)self->objects[i].type;
  134. spTrackEntry* entry = self->objects[i+1].entry;
  135. spEvent* event;
  136. switch (type) {
  137. case SP_ANIMATION_START:
  138. case SP_ANIMATION_INTERRUPT:
  139. case SP_ANIMATION_COMPLETE:
  140. if (entry->listener) entry->listener(SUPER(self->state), type, entry, 0);
  141. if (self->state->super.listener) self->state->super.listener(SUPER(self->state), type, entry, 0);
  142. break;
  143. case SP_ANIMATION_END:
  144. if (entry->listener) entry->listener(SUPER(self->state), type, entry, 0);
  145. if (self->state->super.listener) self->state->super.listener(SUPER(self->state), type, entry, 0);
  146. /* Fall through. */
  147. case SP_ANIMATION_DISPOSE:
  148. if (entry->listener) entry->listener(SUPER(self->state), SP_ANIMATION_DISPOSE, entry, 0);
  149. if (self->state->super.listener) self->state->super.listener(SUPER(self->state), SP_ANIMATION_DISPOSE, entry, 0);
  150. _spAnimationState_disposeTrackEntry(entry);
  151. break;
  152. case SP_ANIMATION_EVENT:
  153. event = self->objects[i+2].event;
  154. if (entry->listener) entry->listener(SUPER(self->state), type, entry, event);
  155. if (self->state->super.listener) self->state->super.listener(SUPER(self->state), type, entry, event);
  156. i++;
  157. break;
  158. }
  159. }
  160. _spEventQueue_clear(self);
  161. self->drainDisabled = 0;
  162. }
  163. /* These two functions are needed in the UE4 runtime, see #1037 */
  164. void _spAnimationState_enableQueue(spAnimationState* self) {
  165. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  166. internal->queue->drainDisabled = 0;
  167. }
  168. void _spAnimationState_disableQueue(spAnimationState* self) {
  169. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  170. internal->queue->drainDisabled = 1;
  171. }
  172. void _spAnimationState_disposeTrackEntry (spTrackEntry* entry) {
  173. spIntArray_dispose(entry->timelineMode);
  174. spTrackEntryArray_dispose(entry->timelineHoldMix);
  175. FREE(entry->timelinesRotation);
  176. FREE(entry);
  177. }
  178. void _spAnimationState_disposeTrackEntries (spAnimationState* state, spTrackEntry* entry) {
  179. while (entry) {
  180. spTrackEntry* next = entry->next;
  181. spTrackEntry* from = entry->mixingFrom;
  182. while (from) {
  183. spTrackEntry* nextFrom = from->mixingFrom;
  184. if (entry->listener) entry->listener(state, SP_ANIMATION_DISPOSE, from, 0);
  185. if (state->listener) state->listener(state, SP_ANIMATION_DISPOSE, from, 0);
  186. _spAnimationState_disposeTrackEntry(from);
  187. from = nextFrom;
  188. }
  189. if (entry->listener) entry->listener(state, SP_ANIMATION_DISPOSE, entry, 0);
  190. if (state->listener) state->listener(state, SP_ANIMATION_DISPOSE, entry, 0);
  191. _spAnimationState_disposeTrackEntry(entry);
  192. entry = next;
  193. }
  194. }
  195. spAnimationState* spAnimationState_create (spAnimationStateData* data) {
  196. _spAnimationState* internal;
  197. spAnimationState* self;
  198. if (!SP_EMPTY_ANIMATION) {
  199. SP_EMPTY_ANIMATION = (spAnimation*)1; /* dirty trick so we can recursively call spAnimation_create */
  200. SP_EMPTY_ANIMATION = spAnimation_create("<empty>", 0);
  201. }
  202. internal = NEW(_spAnimationState);
  203. self = SUPER(internal);
  204. CONST_CAST(spAnimationStateData*, self->data) = data;
  205. self->timeScale = 1;
  206. internal->queue = _spEventQueue_create(internal);
  207. internal->events = CALLOC(spEvent*, 128);
  208. internal->propertyIDs = CALLOC(int, 128);
  209. internal->propertyIDsCapacity = 128;
  210. return self;
  211. }
  212. void spAnimationState_dispose (spAnimationState* self) {
  213. int i;
  214. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  215. for (i = 0; i < self->tracksCount; i++)
  216. _spAnimationState_disposeTrackEntries(self, self->tracks[i]);
  217. FREE(self->tracks);
  218. _spEventQueue_free(internal->queue);
  219. FREE(internal->events);
  220. FREE(internal->propertyIDs);
  221. FREE(internal);
  222. }
  223. void spAnimationState_update (spAnimationState* self, float delta) {
  224. int i, n;
  225. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  226. delta *= self->timeScale;
  227. for (i = 0, n = self->tracksCount; i < n; i++) {
  228. float currentDelta;
  229. spTrackEntry* current = self->tracks[i];
  230. spTrackEntry* next;
  231. if (!current) continue;
  232. current->animationLast = current->nextAnimationLast;
  233. current->trackLast = current->nextTrackLast;
  234. currentDelta = delta * current->timeScale;
  235. if (current->delay > 0) {
  236. current->delay -= currentDelta;
  237. if (current->delay > 0) continue;
  238. currentDelta = -current->delay;
  239. current->delay = 0;
  240. }
  241. next = current->next;
  242. if (next) {
  243. /* When the next entry's delay is passed, change to the next entry, preserving leftover time. */
  244. float nextTime = current->trackLast - next->delay;
  245. if (nextTime >= 0) {
  246. next->delay = 0;
  247. next->trackTime += current->timeScale == 0 ? 0 : (nextTime / current->timeScale + delta) * next->timeScale;
  248. current->trackTime += currentDelta;
  249. _spAnimationState_setCurrent(self, i, next, 1);
  250. while (next->mixingFrom) {
  251. next->mixTime += delta;
  252. next = next->mixingFrom;
  253. }
  254. continue;
  255. }
  256. } else {
  257. /* Clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. */
  258. if (current->trackLast >= current->trackEnd && current->mixingFrom == 0) {
  259. self->tracks[i] = 0;
  260. _spEventQueue_end(internal->queue, current);
  261. _spAnimationState_disposeNext(self, current);
  262. continue;
  263. }
  264. }
  265. if (current->mixingFrom != 0 && _spAnimationState_updateMixingFrom(self, current, delta)) {
  266. /* End mixing from entries once all have completed. */
  267. spTrackEntry* from = current->mixingFrom;
  268. current->mixingFrom = 0;
  269. if (from != 0) from->mixingTo = 0;
  270. while (from != 0) {
  271. _spEventQueue_end(internal->queue, from);
  272. from = from->mixingFrom;
  273. }
  274. }
  275. current->trackTime += currentDelta;
  276. }
  277. _spEventQueue_drain(internal->queue);
  278. }
  279. int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* to, float delta) {
  280. spTrackEntry* from = to->mixingFrom;
  281. int finished;
  282. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  283. if (!from) return -1;
  284. finished = _spAnimationState_updateMixingFrom(self, from, delta);
  285. from->animationLast = from->nextAnimationLast;
  286. from->trackLast = from->nextTrackLast;
  287. /* Require mixTime > 0 to ensure the mixing from entry was applied at least once. */
  288. if (to->mixTime > 0 && to->mixTime >= to->mixDuration) {
  289. /* Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). */
  290. if (from->totalAlpha == 0 || to->mixDuration == 0) {
  291. to->mixingFrom = from->mixingFrom;
  292. if (from->mixingFrom != 0) from->mixingFrom->mixingTo = to;
  293. to->interruptAlpha = from->interruptAlpha;
  294. _spEventQueue_end(internal->queue, from);
  295. }
  296. return finished;
  297. }
  298. from->trackTime += delta * from->timeScale;
  299. to->mixTime += delta;
  300. return 0;
  301. }
  302. int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
  303. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  304. spTrackEntry* current;
  305. int i, ii, n;
  306. float animationLast, animationTime;
  307. int timelineCount;
  308. spTimeline** timelines;
  309. int /*boolean*/ firstFrame;
  310. float* timelinesRotation;
  311. spTimeline* timeline;
  312. int applied = 0;
  313. spMixBlend blend;
  314. spMixBlend timelineBlend;
  315. int setupState = 0;
  316. spSlot** slots = NULL;
  317. spSlot* slot = NULL;
  318. const char* attachmentName = NULL;
  319. if (internal->animationsChanged) _spAnimationState_animationsChanged(self);
  320. for (i = 0, n = self->tracksCount; i < n; i++) {
  321. float mix;
  322. current = self->tracks[i];
  323. if (!current || current->delay > 0) continue;
  324. applied = -1;
  325. blend = i == 0 ? SP_MIX_BLEND_FIRST : current->mixBlend;
  326. /* Apply mixing from entries first. */
  327. mix = current->alpha;
  328. if (current->mixingFrom)
  329. mix *= _spAnimationState_applyMixingFrom(self, current, skeleton, blend);
  330. else if (current->trackTime >= current->trackEnd && current->next == 0)
  331. mix = 0;
  332. /* Apply current entry. */
  333. animationLast = current->animationLast; animationTime = spTrackEntry_getAnimationTime(current);
  334. timelineCount = current->animation->timelinesCount;
  335. timelines = current->animation->timelines;
  336. if ((i == 0 && mix == 1) || blend == SP_MIX_BLEND_ADD) {
  337. for (ii = 0; ii < timelineCount; ii++) {
  338. timeline = timelines[ii];
  339. if (timeline->type == SP_TIMELINE_ATTACHMENT) {
  340. _spAnimationState_applyAttachmentTimeline(self, timeline, skeleton, animationTime, blend, -1);
  341. } else {
  342. spTimeline_apply(timelines[ii], skeleton, animationLast, animationTime, internal->events,
  343. &internal->eventsCount, mix, blend, SP_MIX_DIRECTION_IN);
  344. }
  345. }
  346. } else {
  347. spIntArray* timelineMode = current->timelineMode;
  348. firstFrame = current->timelinesRotationCount == 0;
  349. if (firstFrame) _spAnimationState_resizeTimelinesRotation(current, timelineCount << 1);
  350. timelinesRotation = current->timelinesRotation;
  351. for (ii = 0; ii < timelineCount; ii++) {
  352. timeline = timelines[ii];
  353. timelineBlend = timelineMode->items[ii] == SUBSEQUENT ? blend : SP_MIX_BLEND_SETUP;
  354. if (timeline->type == SP_TIMELINE_ROTATE)
  355. _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame);
  356. else if (timeline->type == SP_TIMELINE_ATTACHMENT)
  357. _spAnimationState_applyAttachmentTimeline(self, timeline, skeleton, animationTime, timelineBlend, -1);
  358. else
  359. spTimeline_apply(timeline, skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, mix, timelineBlend, SP_MIX_DIRECTION_IN);
  360. }
  361. }
  362. _spAnimationState_queueEvents(self, current, animationTime);
  363. internal->eventsCount = 0;
  364. current->nextAnimationLast = animationTime;
  365. current->nextTrackLast = current->trackTime;
  366. }
  367. setupState = self->unkeyedState + SETUP;
  368. slots = skeleton->slots;
  369. for (i = 0, n = skeleton->slotsCount; i < n; i++) {
  370. slot = slots[i];
  371. if (slot->attachmentState == setupState) {
  372. attachmentName = slot->data->attachmentName;
  373. slot->attachment = attachmentName == NULL ? NULL : spSkeleton_getAttachmentForSlotIndex(skeleton, slot->data->index, attachmentName);
  374. }
  375. }
  376. self->unkeyedState += 2;
  377. _spEventQueue_drain(internal->queue);
  378. return applied;
  379. }
  380. float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* to, spSkeleton* skeleton, spMixBlend blend) {
  381. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  382. float mix;
  383. spEvent** events;
  384. int /*boolean*/ attachments;
  385. int /*boolean*/ drawOrder;
  386. float animationLast;
  387. float animationTime;
  388. int timelineCount;
  389. spTimeline** timelines;
  390. spIntArray* timelineMode;
  391. spTrackEntryArray* timelineHoldMix;
  392. spMixBlend timelineBlend;
  393. float alphaHold;
  394. float alphaMix;
  395. float alpha;
  396. int /*boolean*/ firstFrame;
  397. float* timelinesRotation;
  398. int i;
  399. spTrackEntry* holdMix;
  400. spTrackEntry* from = to->mixingFrom;
  401. if (from->mixingFrom) _spAnimationState_applyMixingFrom(self, from, skeleton, blend);
  402. if (to->mixDuration == 0) { /* Single frame mix to undo mixingFrom changes. */
  403. mix = 1;
  404. if (blend == SP_MIX_BLEND_FIRST) blend = SP_MIX_BLEND_SETUP;
  405. } else {
  406. mix = to->mixTime / to->mixDuration;
  407. if (mix > 1) mix = 1;
  408. if (blend != SP_MIX_BLEND_FIRST) blend = from->mixBlend;
  409. }
  410. events = mix < from->eventThreshold ? internal->events : 0;
  411. attachments = mix < from->attachmentThreshold;
  412. drawOrder = mix < from->drawOrderThreshold;
  413. animationLast = from->animationLast;
  414. animationTime = spTrackEntry_getAnimationTime(from);
  415. timelineCount = from->animation->timelinesCount;
  416. timelines = from->animation->timelines;
  417. alphaHold = from->alpha * to->interruptAlpha; alphaMix = alphaHold * (1 - mix);
  418. if (blend == SP_MIX_BLEND_ADD) {
  419. for (i = 0; i < timelineCount; i++) {
  420. spTimeline *timeline = timelines[i];
  421. spTimeline_apply(timeline, skeleton, animationLast, animationTime, events, &internal->eventsCount, alphaMix, blend, SP_MIX_DIRECTION_OUT);
  422. }
  423. } else {
  424. timelineMode = from->timelineMode;
  425. timelineHoldMix = from->timelineHoldMix;
  426. firstFrame = from->timelinesRotationCount == 0;
  427. if (firstFrame) _spAnimationState_resizeTimelinesRotation(from, timelineCount << 1);
  428. timelinesRotation = from->timelinesRotation;
  429. from->totalAlpha = 0;
  430. for (i = 0; i < timelineCount; i++) {
  431. spMixDirection direction = SP_MIX_DIRECTION_OUT;
  432. spTimeline *timeline = timelines[i];
  433. switch (timelineMode->items[i]) {
  434. case SUBSEQUENT:
  435. if (!drawOrder && timeline->type == SP_TIMELINE_DRAWORDER) continue;
  436. timelineBlend = blend;
  437. alpha = alphaMix;
  438. break;
  439. case FIRST:
  440. timelineBlend = SP_MIX_BLEND_SETUP;
  441. alpha = alphaMix;
  442. break;
  443. case HOLD:
  444. timelineBlend = SP_MIX_BLEND_SETUP;
  445. alpha = alphaHold;
  446. break;
  447. default:
  448. timelineBlend = SP_MIX_BLEND_SETUP;
  449. holdMix = timelineHoldMix->items[i];
  450. alpha = alphaHold * MAX(0, 1 - holdMix->mixTime / holdMix->mixDuration);
  451. break;
  452. }
  453. from->totalAlpha += alpha;
  454. if (timeline->type == SP_TIMELINE_ROTATE)
  455. _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, alpha, timelineBlend,
  456. timelinesRotation, i << 1, firstFrame);
  457. else if (timeline->type == SP_TIMELINE_ATTACHMENT)
  458. _spAnimationState_applyAttachmentTimeline(self, timeline, skeleton, animationTime, timelineBlend, attachments);
  459. else {
  460. if (drawOrder && timeline->type == SP_TIMELINE_DRAWORDER && timelineBlend == SP_MIX_BLEND_SETUP)
  461. direction = SP_MIX_DIRECTION_IN;
  462. spTimeline_apply(timeline, skeleton, animationLast, animationTime, events, &internal->eventsCount,
  463. alpha, timelineBlend, direction);
  464. }
  465. }
  466. }
  467. if (to->mixDuration > 0) _spAnimationState_queueEvents(self, from, animationTime);
  468. internal->eventsCount = 0;
  469. from->nextAnimationLast = animationTime;
  470. from->nextTrackLast = from->trackTime;
  471. return mix;
  472. }
  473. static void _spAnimationState_setAttachment(spAnimationState* self, spSkeleton* skeleton, spSlot* slot, const char* attachmentName, int /*bool*/ attachments) {
  474. slot->attachment = attachmentName == NULL ? NULL : spSkeleton_getAttachmentForSlotIndex(skeleton, slot->data->index, attachmentName);
  475. if (attachments) slot->attachmentState = self->unkeyedState + CURRENT;
  476. }
  477. /* @param target After the first and before the last entry. */
  478. static int binarySearch1 (float *values, int valuesLength, float target) {
  479. int low = 0, current;
  480. int high = valuesLength - 2;
  481. if (high == 0) return 1;
  482. current = high >> 1;
  483. while (1) {
  484. if (values[(current + 1)] <= target)
  485. low = current + 1;
  486. else
  487. high = current;
  488. if (low == high) return low + 1;
  489. current = (low + high) >> 1;
  490. }
  491. return 0;
  492. }
  493. void _spAnimationState_applyAttachmentTimeline(spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, spMixBlend blend, int /*bool*/ attachments) {
  494. spAttachmentTimeline* attachmentTimeline;
  495. spSlot* slot;
  496. int frameIndex;
  497. float* frames;
  498. attachmentTimeline = SUB_CAST(spAttachmentTimeline, timeline);
  499. slot = skeleton->slots[attachmentTimeline->slotIndex];
  500. if (!slot->bone->active) return;
  501. frames = attachmentTimeline->frames;
  502. if (time < frames[0]) {
  503. if (blend == SP_MIX_BLEND_SETUP || blend == SP_MIX_BLEND_FIRST)
  504. _spAnimationState_setAttachment(self, skeleton, slot, slot->data->attachmentName, attachments);
  505. }
  506. else {
  507. if (time >= frames[attachmentTimeline->framesCount - 1])
  508. frameIndex = attachmentTimeline->framesCount - 1;
  509. else
  510. frameIndex = binarySearch1(frames, attachmentTimeline->framesCount, time) - 1;
  511. _spAnimationState_setAttachment(self, skeleton, slot, attachmentTimeline->attachmentNames[frameIndex], attachments);
  512. }
  513. /* If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.*/
  514. if (slot->attachmentState <= self->unkeyedState) slot->attachmentState = self->unkeyedState + SETUP;
  515. }
  516. void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time,
  517. float alpha, spMixBlend blend, float* timelinesRotation, int i, int /*boolean*/ firstFrame
  518. ) {
  519. spRotateTimeline *rotateTimeline;
  520. float *frames;
  521. spBone* bone;
  522. float r1, r2;
  523. int frame;
  524. float prevRotation;
  525. float frameTime;
  526. float percent;
  527. float total, diff;
  528. int /*boolean*/ current, dir;
  529. UNUSED(self);
  530. if (firstFrame) timelinesRotation[i] = 0;
  531. if (alpha == 1) {
  532. spTimeline_apply(timeline, skeleton, 0, time, 0, 0, 1, blend, SP_MIX_DIRECTION_IN);
  533. return;
  534. }
  535. rotateTimeline = SUB_CAST(spRotateTimeline, timeline);
  536. frames = rotateTimeline->frames;
  537. bone = skeleton->bones[rotateTimeline->boneIndex];
  538. if (!bone->active) return;
  539. if (time < frames[0]) {
  540. switch (blend) {
  541. case SP_MIX_BLEND_SETUP:
  542. bone->rotation = bone->data->rotation;
  543. default:
  544. return;
  545. case SP_MIX_BLEND_FIRST:
  546. r1 = bone->rotation;
  547. r2 = bone->data->rotation;
  548. }
  549. } else {
  550. r1 = blend == SP_MIX_BLEND_SETUP ? bone->data->rotation : bone->rotation;
  551. if (time >= frames[rotateTimeline->framesCount - ROTATE_ENTRIES]) /* Time is after last frame. */
  552. r2 = bone->data->rotation + frames[rotateTimeline->framesCount + ROTATE_PREV_ROTATION];
  553. else {
  554. /* Interpolate between the previous frame and the current frame. */
  555. frame = _spCurveTimeline_binarySearch(frames, rotateTimeline->framesCount, time, ROTATE_ENTRIES);
  556. prevRotation = frames[frame + ROTATE_PREV_ROTATION];
  557. frameTime = frames[frame];
  558. percent = spCurveTimeline_getCurvePercent(SUPER(rotateTimeline), (frame >> 1) - 1,
  559. 1 - (time - frameTime) / (frames[frame + ROTATE_PREV_TIME] - frameTime));
  560. r2 = frames[frame + ROTATE_ROTATION] - prevRotation;
  561. r2 -= (16384 - (int) (16384.499999999996 - r2 / 360)) * 360;
  562. r2 = prevRotation + r2 * percent + bone->data->rotation;
  563. r2 -= (16384 - (int) (16384.499999999996 - r2 / 360)) * 360;
  564. }
  565. }
  566. /* Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. */
  567. diff = r2 - r1;
  568. diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360;
  569. if (diff == 0) {
  570. total = timelinesRotation[i];
  571. } else {
  572. float lastTotal, lastDiff;
  573. if (firstFrame) {
  574. lastTotal = 0;
  575. lastDiff = diff;
  576. } else {
  577. lastTotal = timelinesRotation[i]; /* Angle and direction of mix, including loops. */
  578. lastDiff = timelinesRotation[i + 1]; /* Difference between bones. */
  579. }
  580. current = diff > 0;
  581. dir = lastTotal >= 0;
  582. /* Detect cross at 0 (not 180). */
  583. if (SIGNUM(lastDiff) != SIGNUM(diff) && ABS(lastDiff) <= 90) {
  584. /* A cross after a 360 rotation is a loop. */
  585. if (ABS(lastTotal) > 180) lastTotal += 360 * SIGNUM(lastTotal);
  586. dir = current;
  587. }
  588. total = diff + lastTotal - FMOD(lastTotal, 360); /* Store loops as part of lastTotal. */
  589. if (dir != current) total += 360 * SIGNUM(lastTotal);
  590. timelinesRotation[i] = total;
  591. }
  592. timelinesRotation[i + 1] = diff;
  593. r1 += total * alpha;
  594. bone->rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360;
  595. }
  596. void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry, float animationTime) {
  597. spEvent** events;
  598. spEvent* event;
  599. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  600. int i, n, complete;
  601. float animationStart = entry->animationStart, animationEnd = entry->animationEnd;
  602. float duration = animationEnd - animationStart;
  603. float trackLastWrapped = FMOD(entry->trackLast, duration);
  604. /* Queue events before complete. */
  605. events = internal->events;
  606. for (i = 0, n = internal->eventsCount; i < n; i++) {
  607. event = events[i];
  608. if (event->time < trackLastWrapped) break;
  609. if (event->time > animationEnd) continue; /* Discard events outside animation start/end. */
  610. _spEventQueue_event(internal->queue, entry, event);
  611. }
  612. /* Queue complete if completed a loop iteration or the animation. */
  613. if (entry->loop)
  614. complete = duration == 0 || (trackLastWrapped > FMOD(entry->trackTime, duration));
  615. else
  616. complete = (animationTime >= animationEnd && entry->animationLast < animationEnd);
  617. if (complete) _spEventQueue_complete(internal->queue, entry);
  618. /* Queue events after complete. */
  619. for (; i < n; i++) {
  620. event = events[i];
  621. if (event->time < animationStart) continue; /* Discard events outside animation start/end. */
  622. _spEventQueue_event(internal->queue, entry, event);
  623. }
  624. }
  625. void spAnimationState_clearTracks (spAnimationState* self) {
  626. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  627. int i, n, oldDrainDisabled;
  628. oldDrainDisabled = internal->queue->drainDisabled;
  629. internal->queue->drainDisabled = 1;
  630. for (i = 0, n = self->tracksCount; i < n; i++)
  631. spAnimationState_clearTrack(self, i);
  632. self->tracksCount = 0;
  633. internal->queue->drainDisabled = oldDrainDisabled;
  634. _spEventQueue_drain(internal->queue);
  635. }
  636. void spAnimationState_clearTrack (spAnimationState* self, int trackIndex) {
  637. spTrackEntry* current;
  638. spTrackEntry* entry;
  639. spTrackEntry* from;
  640. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  641. if (trackIndex >= self->tracksCount) return;
  642. current = self->tracks[trackIndex];
  643. if (!current) return;
  644. _spEventQueue_end(internal->queue, current);
  645. _spAnimationState_disposeNext(self, current);
  646. entry = current;
  647. while (1) {
  648. from = entry->mixingFrom;
  649. if (!from) break;
  650. _spEventQueue_end(internal->queue, from);
  651. entry->mixingFrom = 0;
  652. entry->mixingTo = 0;
  653. entry = from;
  654. }
  655. self->tracks[current->trackIndex] = 0;
  656. _spEventQueue_drain(internal->queue);
  657. }
  658. void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEntry* current, int /*boolean*/ interrupt) {
  659. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  660. spTrackEntry* from = _spAnimationState_expandToIndex(self, index);
  661. self->tracks[index] = current;
  662. if (from) {
  663. if (interrupt) _spEventQueue_interrupt(internal->queue, from);
  664. current->mixingFrom = from;
  665. from->mixingTo = current;
  666. current->mixTime = 0;
  667. /* Store the interrupted mix percentage. */
  668. if (from->mixingFrom != 0 && from->mixDuration > 0)
  669. current->interruptAlpha *= MIN(1, from->mixTime / from->mixDuration);
  670. from->timelinesRotationCount = 0;
  671. }
  672. _spEventQueue_start(internal->queue, current);
  673. }
  674. /** Set the current animation. Any queued animations are cleared. */
  675. spTrackEntry* spAnimationState_setAnimationByName (spAnimationState* self, int trackIndex, const char* animationName, int/*bool*/loop) {
  676. spAnimation* animation = spSkeletonData_findAnimation(self->data->skeletonData, animationName);
  677. return spAnimationState_setAnimation(self, trackIndex, animation, loop);
  678. }
  679. spTrackEntry* spAnimationState_setAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop) {
  680. spTrackEntry* entry;
  681. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  682. int interrupt = 1;
  683. spTrackEntry* current = _spAnimationState_expandToIndex(self, trackIndex);
  684. if (current) {
  685. if (current->nextTrackLast == -1) {
  686. /* Don't mix from an entry that was never applied. */
  687. self->tracks[trackIndex] = current->mixingFrom;
  688. _spEventQueue_interrupt(internal->queue, current);
  689. _spEventQueue_end(internal->queue, current);
  690. _spAnimationState_disposeNext(self, current);
  691. current = current->mixingFrom;
  692. interrupt = 0;
  693. } else
  694. _spAnimationState_disposeNext(self, current);
  695. }
  696. entry = _spAnimationState_trackEntry(self, trackIndex, animation, loop, current);
  697. _spAnimationState_setCurrent(self, trackIndex, entry, interrupt);
  698. _spEventQueue_drain(internal->queue);
  699. return entry;
  700. }
  701. /** Adds an animation to be played delay seconds after the current or last queued animation, taking into account any mix
  702. * duration. */
  703. spTrackEntry* spAnimationState_addAnimationByName (spAnimationState* self, int trackIndex, const char* animationName,
  704. int/*bool*/loop, float delay
  705. ) {
  706. spAnimation* animation = spSkeletonData_findAnimation(self->data->skeletonData, animationName);
  707. return spAnimationState_addAnimation(self, trackIndex, animation, loop, delay);
  708. }
  709. spTrackEntry* spAnimationState_addAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop, float delay) {
  710. spTrackEntry* entry;
  711. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  712. spTrackEntry* last = _spAnimationState_expandToIndex(self, trackIndex);
  713. if (last) {
  714. while (last->next)
  715. last = last->next;
  716. }
  717. entry = _spAnimationState_trackEntry(self, trackIndex, animation, loop, last);
  718. if (!last) {
  719. _spAnimationState_setCurrent(self, trackIndex, entry, 1);
  720. _spEventQueue_drain(internal->queue);
  721. } else {
  722. last->next = entry;
  723. if (delay <= 0) {
  724. float duration = last->animationEnd - last->animationStart;
  725. if (duration != 0) {
  726. if (last->loop) {
  727. delay += duration * (1 + (int) (last->trackTime / duration));
  728. } else {
  729. delay += MAX(duration, last->trackTime);
  730. }
  731. delay -= spAnimationStateData_getMix(self->data, last->animation, animation);
  732. } else
  733. delay = last->trackTime;
  734. }
  735. }
  736. entry->delay = delay;
  737. return entry;
  738. }
  739. spTrackEntry* spAnimationState_setEmptyAnimation(spAnimationState* self, int trackIndex, float mixDuration) {
  740. spTrackEntry* entry = spAnimationState_setAnimation(self, trackIndex, SP_EMPTY_ANIMATION, 0);
  741. entry->mixDuration = mixDuration;
  742. entry->trackEnd = mixDuration;
  743. return entry;
  744. }
  745. spTrackEntry* spAnimationState_addEmptyAnimation(spAnimationState* self, int trackIndex, float mixDuration, float delay) {
  746. spTrackEntry* entry;
  747. if (delay <= 0) delay -= mixDuration;
  748. entry = spAnimationState_addAnimation(self, trackIndex, SP_EMPTY_ANIMATION, 0, delay);
  749. entry->mixDuration = mixDuration;
  750. entry->trackEnd = mixDuration;
  751. return entry;
  752. }
  753. void spAnimationState_setEmptyAnimations(spAnimationState* self, float mixDuration) {
  754. int i, n, oldDrainDisabled;
  755. spTrackEntry* current;
  756. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  757. oldDrainDisabled = internal->queue->drainDisabled;
  758. internal->queue->drainDisabled = 1;
  759. for (i = 0, n = self->tracksCount; i < n; i++) {
  760. current = self->tracks[i];
  761. if (current) spAnimationState_setEmptyAnimation(self, current->trackIndex, mixDuration);
  762. }
  763. internal->queue->drainDisabled = oldDrainDisabled;
  764. _spEventQueue_drain(internal->queue);
  765. }
  766. spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index) {
  767. spTrackEntry** newTracks;
  768. if (index < self->tracksCount) return self->tracks[index];
  769. newTracks = CALLOC(spTrackEntry*, index + 1);
  770. memcpy(newTracks, self->tracks, self->tracksCount * sizeof(spTrackEntry*));
  771. FREE(self->tracks);
  772. self->tracks = newTracks;
  773. self->tracksCount = index + 1;
  774. return 0;
  775. }
  776. spTrackEntry* _spAnimationState_trackEntry (spAnimationState* self, int trackIndex, spAnimation* animation, int /*boolean*/ loop, spTrackEntry* last) {
  777. spTrackEntry* entry = NEW(spTrackEntry);
  778. entry->trackIndex = trackIndex;
  779. entry->animation = animation;
  780. entry->loop = loop;
  781. entry->holdPrevious = 0;
  782. entry->eventThreshold = 0;
  783. entry->attachmentThreshold = 0;
  784. entry->drawOrderThreshold = 0;
  785. entry->animationStart = 0;
  786. entry->animationEnd = animation->duration;
  787. entry->animationLast = -1;
  788. entry->nextAnimationLast = -1;
  789. entry->delay = 0;
  790. entry->trackTime = 0;
  791. entry->trackLast = -1;
  792. entry->nextTrackLast = -1;
  793. entry->trackEnd = (float)INT_MAX;
  794. entry->timeScale = 1;
  795. entry->alpha = 1;
  796. entry->interruptAlpha = 1;
  797. entry->mixTime = 0;
  798. entry->mixDuration = !last ? 0 : spAnimationStateData_getMix(self->data, last->animation, animation);
  799. entry->mixBlend = SP_MIX_BLEND_REPLACE;
  800. entry->timelineMode = spIntArray_create(16);
  801. entry->timelineHoldMix = spTrackEntryArray_create(16);
  802. return entry;
  803. }
  804. void _spAnimationState_disposeNext (spAnimationState* self, spTrackEntry* entry) {
  805. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  806. spTrackEntry* next = entry->next;
  807. while (next) {
  808. _spEventQueue_dispose(internal->queue, next);
  809. next = next->next;
  810. }
  811. entry->next = 0;
  812. }
  813. void _spAnimationState_animationsChanged (spAnimationState* self) {
  814. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  815. int i, n;
  816. spTrackEntry* entry;
  817. internal->animationsChanged = 0;
  818. internal->propertyIDsCount = 0;
  819. i = 0; n = self->tracksCount;
  820. for (;i < n; i++) {
  821. entry = self->tracks[i];
  822. if (!entry) continue;
  823. while (entry->mixingFrom != 0)
  824. entry = entry->mixingFrom;
  825. do {
  826. if (entry->mixingTo == 0 || entry->mixBlend != SP_MIX_BLEND_ADD) _spTrackEntry_computeHold(entry, self);
  827. entry = entry->mixingTo;
  828. } while (entry != 0);
  829. }
  830. }
  831. float* _spAnimationState_resizeTimelinesRotation(spTrackEntry* entry, int newSize) {
  832. if (entry->timelinesRotationCount != newSize) {
  833. float* newTimelinesRotation = CALLOC(float, newSize);
  834. FREE(entry->timelinesRotation);
  835. entry->timelinesRotation = newTimelinesRotation;
  836. entry->timelinesRotationCount = newSize;
  837. }
  838. return entry->timelinesRotation;
  839. }
  840. void _spAnimationState_ensureCapacityPropertyIDs(spAnimationState* self, int capacity) {
  841. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  842. if (internal->propertyIDsCapacity < capacity) {
  843. int *newPropertyIDs = CALLOC(int, capacity << 1);
  844. memcpy(newPropertyIDs, internal->propertyIDs, sizeof(int) * internal->propertyIDsCount);
  845. FREE(internal->propertyIDs);
  846. internal->propertyIDs = newPropertyIDs;
  847. internal->propertyIDsCapacity = capacity << 1;
  848. }
  849. }
  850. int _spAnimationState_addPropertyID(spAnimationState* self, int id) {
  851. int i, n;
  852. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  853. for (i = 0, n = internal->propertyIDsCount; i < n; i++) {
  854. if (internal->propertyIDs[i] == id) return 0;
  855. }
  856. _spAnimationState_ensureCapacityPropertyIDs(self, internal->propertyIDsCount + 1);
  857. internal->propertyIDs[internal->propertyIDsCount] = id;
  858. internal->propertyIDsCount++;
  859. return 1;
  860. }
  861. spTrackEntry* spAnimationState_getCurrent (spAnimationState* self, int trackIndex) {
  862. if (trackIndex >= self->tracksCount) return 0;
  863. return self->tracks[trackIndex];
  864. }
  865. void spAnimationState_clearListenerNotifications(spAnimationState* self) {
  866. _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
  867. _spEventQueue_clear(internal->queue);
  868. }
  869. float spTrackEntry_getAnimationTime (spTrackEntry* entry) {
  870. if (entry->loop) {
  871. float duration = entry->animationEnd - entry->animationStart;
  872. if (duration == 0) return entry->animationStart;
  873. return FMOD(entry->trackTime, duration) + entry->animationStart;
  874. }
  875. return MIN(entry->trackTime + entry->animationStart, entry->animationEnd);
  876. }
  877. int /*boolean*/ _spTrackEntry_hasTimeline(spTrackEntry* self, int id) {
  878. spTimeline** timelines = self->animation->timelines;
  879. int i, n;
  880. for (i = 0, n = self->animation->timelinesCount; i < n; i++)
  881. if (spTimeline_getPropertyId(timelines[i]) == id) return 1;
  882. return 0;
  883. }
  884. void _spTrackEntry_computeHold(spTrackEntry* entry, spAnimationState* state) {
  885. spTrackEntry* to;
  886. spTimeline** timelines;
  887. int timelinesCount;
  888. int* timelineMode;
  889. spTrackEntry** timelineHoldMix;
  890. spTrackEntry* next;
  891. int i;
  892. to = entry->mixingTo;
  893. timelines = entry->animation->timelines;
  894. timelinesCount = entry->animation->timelinesCount;
  895. timelineMode = spIntArray_setSize(entry->timelineMode, timelinesCount)->items;
  896. spTrackEntryArray_clear(entry->timelineHoldMix);
  897. timelineHoldMix = spTrackEntryArray_setSize(entry->timelineHoldMix, timelinesCount)->items;
  898. if (to != 0 && to->holdPrevious) {
  899. for (i = 0; i < timelinesCount; i++) {
  900. int id = spTimeline_getPropertyId(timelines[i]);
  901. _spAnimationState_addPropertyID(state, id);
  902. timelineMode[i] = HOLD;
  903. }
  904. return;
  905. }
  906. i = 0;
  907. continue_outer:
  908. for (; i < timelinesCount; i++) {
  909. spTimeline* timeline = timelines[i];
  910. int id = spTimeline_getPropertyId(timeline);
  911. if (!_spAnimationState_addPropertyID(state, id))
  912. timelineMode[i] = SUBSEQUENT;
  913. else if (to == 0 || timeline->type == SP_TIMELINE_ATTACHMENT || timeline->type == SP_TIMELINE_DRAWORDER ||
  914. timeline->type == SP_TIMELINE_EVENT || !_spTrackEntry_hasTimeline(to, id)) {
  915. timelineMode[i] = FIRST;
  916. } else {
  917. for (next = to->mixingTo; next != 0; next = next->mixingTo) {
  918. if (_spTrackEntry_hasTimeline(next, id)) continue;
  919. if (next->mixDuration > 0) {
  920. timelineMode[i] = HOLD_MIX;
  921. timelineHoldMix[i] = next;
  922. i++;
  923. goto continue_outer;
  924. }
  925. break;
  926. }
  927. timelineMode[i] = HOLD;
  928. }
  929. }
  930. }