1 /*
2 Copyright (C) 2007, 2010 - Bit-Blot
3 
4 This file is part of Aquaria.
5 
6 Aquaria is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 
15 See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */
21 #include "SkeletalSprite.h"
22 #include "Core.h"
23 #include "Particles.h"
24 #include "MathFunctions.h"
25 #include "SimpleIStringStream.h"
26 
27 #include "tinyxml2.h"
28 using namespace tinyxml2;
29 
30 std::string SkeletalSprite::animationPath				= "data/animations/";
31 std::string SkeletalSprite::skinPath					= "skins/";
32 
33 std::string SkeletalSprite::secondaryAnimationPath		= "";
34 
35 static std::map<std::string, XMLDocument*> skelCache;
36 
_retrieveSkeletalXML(const std::string & name,bool keepEmpty)37 static XMLDocument *_retrieveSkeletalXML(const std::string& name, bool keepEmpty)
38 {
39 	std::map<std::string, XMLDocument*>::iterator it = skelCache.find(name);
40 	if(it != skelCache.end())
41 		return it->second;
42 
43 	XMLDocument *doc = readXML(name, NULL, keepEmpty);
44 	if(doc)
45 		skelCache[name] = doc;
46 
47 	return doc;
48 }
49 
clearCache()50 void SkeletalSprite::clearCache()
51 {
52 	for(std::map<std::string, XMLDocument*>::iterator it = skelCache.begin(); it != skelCache.end(); ++it)
53 		delete it->second;
54 	skelCache.clear();
55 }
56 
57 
copyAllButTime(SkeletalKeyframe * copy)58 void SkeletalKeyframe::copyAllButTime(SkeletalKeyframe *copy)
59 {
60 	if (!copy) return;
61 
62 	float t = this->t;
63 	(*this) = (*copy);
64 	this->t = t;
65 }
66 
Bone()67 Bone::Bone() : Quad()
68 {
69 	addType(SCO_BONE);
70 	fileRenderQuad = true;
71 	skeleton = 0;
72 	generateCollisionMask = true;
73 	animated = ANIM_ALL;
74 	originalScale = Vector(1,1);
75 	boneIdx = pidx = -1;
76 	rbp = 0;
77 	segmentChain = 0;
78 
79 	minDist = maxDist = 128;
80 	reverse = false;
81 }
82 /*
83 void Bone::createStrip(bool vert, int num)
84 {
85 	Quad::createStrip(vert, num);
86 	changeStrip.resize(num);
87 }
88 */
89 
destroy()90 void Bone::destroy()
91 {
92 	Quad::destroy();
93 
94 	for (int i = 0; i < segments.size(); i++)
95 	{
96 		segments[i]->setLife(1.0);
97 		segments[i]->setDecayRate(10);
98 		segments[i]->alpha = 0;
99 	}
100 	segments.clear();
101 }
102 
addSegment(Bone * b)103 void Bone::addSegment(Bone *b)
104 {
105 	segments.push_back(b);
106 
107 	b->segmentChain = 2;
108 
109 	skeleton->removeChild(b);
110 
111 	core->getTopStateData()->addRenderObject(b, skeleton->getTopLayer());
112 	b->position = this->getWorldPosition();
113 }
114 
createStrip(bool vert,int num)115 void Bone::createStrip(bool vert, int num)
116 {
117 	if (!vert)
118 	{
119 		createGrid(num, 2);
120 	}
121 	else
122 	{
123 		createGrid(2, num);
124 	}
125 	stripVert = vert;
126 	gridType = GRID_SET;
127 	changeStrip.resize(num);
128 	setGridPoints(vert, strip);
129 }
130 
131 
addFrame(const std::string & gfx)132 Quad* Bone::addFrame(const std::string &gfx)
133 {
134 	renderQuad = false;
135 	Quad *q = new Quad();
136 	q->setTexture(gfx);
137 	q->renderBeforeParent = 1;
138 	addChild(q, PM_POINTER);
139 	return q;
140 }
141 
showFrame(int idx)142 void Bone::showFrame(int idx)
143 {
144 	//float t = 0.1;
145 	int c = 0;
146 	for (Children::iterator i = children.begin(); i != children.end(); i++)
147 	{
148 		RenderObject *r = (*i);
149 		if (idx == c)
150 		{
151 			if (r->alpha == 0)
152 			{
153 				r->alpha = 1;
154 
155 				// add option to turn on alpha fading
156 				//r->alpha.interpolateTo(1, t);
157 			}
158 			else
159 			{
160 				r->alpha = 1;
161 			}
162 		}
163 		else
164 		{
165 			if (r->alpha == 1)
166 			{
167 				r->alpha = 0;
168 				//r->alpha.interpolateTo(0, t*2);
169 			}
170 			else
171 			{
172 				r->alpha = 0;
173 			}
174 		}
175 		c++;
176 	}
177 }
178 
179 
setAnimated(int b)180 void Bone::setAnimated(int b)
181 {
182 	/*
183 	std::ostringstream os;
184 	os << "setting animated: " << b;
185 	debugLog(os.str());
186 	*/
187 
188 	animated = b;
189 }
190 
191 
setSegmentProps(int minDist,int maxDist,bool reverse)192 void Bone::setSegmentProps(int minDist, int maxDist, bool reverse)
193 {
194 	this->minDist = minDist;
195 	this->maxDist = maxDist;
196 	this->reverse = reverse;
197 }
198 
updateSegment(Bone * b,const Vector & diff)199 void Bone::updateSegment(Bone *b, const Vector &diff)
200 {
201 	/*
202 	int maxDist, minDist;
203 	maxDist = minDist = 128;
204 	*/
205 
206 	float angle = -1;
207 	if (diff.getSquaredLength2D() > sqr(maxDist))
208 	{
209 		Vector useDiff = diff;
210 		useDiff.setLength2D(maxDist);
211 		Vector reallyUseDiff = diff - useDiff;
212 		b->position += reallyUseDiff;
213 
214 		MathFunctions::calculateAngleBetweenVectorsInDegrees(Vector(0,0,0), diff, angle);
215 	}
216 	else if (diff.getSquaredLength2D() > sqr(minDist)) // 6.3
217 	{
218 		b->position += diff*0.05f;
219 
220 		MathFunctions::calculateAngleBetweenVectorsInDegrees(Vector(0,0,0), diff, angle);
221 
222 		//b->rotation.interpolateTo(Vector(0,0,angle),0.2);
223 	}
224 	if (angle != -1)
225 	{
226 		/*
227 		std::ostringstream os;
228 		os << "rotz: " << b->rotation.z << " angle: " << angle;
229 		debugLog(os.str());
230 		*/
231 
232 		if (b->rotation.z >= 270 && angle < 90)
233 		{
234 			b->rotation.stop();
235 			b->rotation.z -= 360;
236 		}
237 
238 		if (b->rotation.z <= 90 && angle > 270)
239 		{
240 			b->rotation.stop();
241 			b->rotation.z += 360;
242 		}
243 
244 
245 		b->rotation.interpolateTo(Vector(0,0,angle),0.2);
246 	}
247 	/*
248 	else
249 	{
250 		float angle;
251 		MathFunctions::calculateAngleBetweenVectorsInDegrees(Vector(0,0,0), diff, angle);
252 		b->rotation.interpolateTo(Vector(0,0,angle),0);
253 	}
254 	*/
255 }
256 
updateSegments()257 void Bone::updateSegments()
258 {
259 	if (segmentChain>0 && !segments.empty())
260 	{
261 		//bool reverse = true;
262 
263 		/*
264 		std::vector<Bone*> segments;
265 		Bone *child = (Bone*)(this->children.front());
266 		while (child)
267 		{
268 			segments.push_back(child);
269 
270 			if (child->children.empty())
271 				child = 0;
272 			else
273 				child = (Bone*)(child->children.front());
274 		}
275 		*/
276 
277 		if (!reverse)
278 		{
279 			for (int i = 0; i < segments.size(); i++)
280 			{
281 				Vector diff;
282 				if (i == 0)
283 				{
284 					Vector world = getWorldCollidePosition(segmentOffset);
285 					diff = world - segments[i]->getWorldPosition();
286 				}
287 				else
288 					diff = segments[i-1]->getWorldPosition() - segments[i]->getWorldPosition();
289 
290 				updateSegment(segments[i], diff);
291 			}
292 		}
293 		else
294 		{
295 			int top = segments.size()-1;
296 			for (int i = top; i >= 0; i--)
297 			{
298 				Vector diff;
299 				if (i == top)
300 				{
301 					Vector world = getWorldCollidePosition(segmentOffset);
302 					diff = world - segments[i]->getWorldPosition();
303 				}
304 				else
305 					diff = segments[i+1]->getWorldPosition() - segments[i]->getWorldPosition();
306 
307 				updateSegment(segments[i], diff);
308 			}
309 		}
310 	}
311 }
312 
parse(Bone * b,SimpleIStringStream & is)313 void BoneCommand::parse(Bone *b, SimpleIStringStream &is)
314 {
315 	std::string type;
316 	is >> type;
317 	this->b = b;
318 	if (type=="AC_PRT_LOAD")
319 	{
320 		command = AC_PRT_LOAD;
321 		is >> slot >> file;
322 	}
323 	else if (type=="AC_SND_PLAY")
324 	{
325 		command = AC_SND_PLAY;
326 		is >> file;
327 	}
328 	else if (type=="AC_FRM_SHOW")
329 	{
330 		command = AC_FRM_SHOW;
331 		is >> slot;
332 	}
333 	else if (type=="AC_PRT_START")
334 	{
335 		command = AC_PRT_START;
336 		is >> slot;
337 		/*
338 		Emitter *e = b->emitters[slot];
339 		if (e)
340 		{
341 			e->start();
342 		}
343 		*/
344 	}
345 	else if (type=="AC_PRT_STOP")
346 	{
347 		command = AC_PRT_STOP;
348 		is >> slot;
349 		/*
350 		Emitter *e = b->emitters[slot];
351 		if (e)
352 		{
353 			e->stop();
354 		}
355 		*/
356 	}
357 	else if (type=="AC_SEGS_START")
358 		command = AC_SEGS_START;
359 	else if (type=="AC_SEGS_STOP")
360 		command = AC_SEGS_STOP;
361 }
362 
run()363 void BoneCommand::run()
364 {
365 	//debugLog("running CMD");
366 	switch(command)
367 	{
368 	case AC_SND_PLAY:
369 	{
370 		core->sound->playSfx(file);
371 	}
372 	break;
373 	case AC_FRM_SHOW:
374 	{
375 		b->showFrame(slot);
376 	}
377 	break;
378 	case AC_PRT_LOAD:
379 	{
380 		ParticleEffect *e = b->emitters[slot];
381 		if (e)
382 		{
383 			e->load(file);
384 		}
385 	}
386 	break;
387 	case AC_PRT_START:
388 	{
389 		ParticleEffect *e = b->emitters[slot];
390 		if (e)
391 			e->start();
392 	}
393 	break;
394 	case AC_PRT_STOP:
395 	{
396 		ParticleEffect *e = b->emitters[slot];
397 		if (e)
398 			e->stop();
399 	}
400 	break;
401 	}
402 }
403 
404 
AnimationLayer()405 AnimationLayer::AnimationLayer()
406 {
407 	lastNewKey = 0;
408 	fallThru= 0;
409 	//index = -1;
410 	timer = 0;
411 	loop = 0;
412 	enqueuedAnimationLoop = 0;
413 	timeMultiplier = 1;
414 	animationLength = 0;
415 	currentAnimation = 0;
416 	animating = false;
417 	fallThruSpeed = 0;
418 	s = 0;
419 }
420 
setTimeMultiplier(float t)421 void AnimationLayer::setTimeMultiplier(float t)
422 {
423 	timeMultiplier = t;
424 }
425 
playCurrentAnimation(int loop)426 void AnimationLayer::playCurrentAnimation(int loop)
427 {
428 	playAnimation(currentAnimation, loop);
429 }
430 
animate(const std::string & a,int loop)431 void AnimationLayer::animate(const std::string &a, int loop)
432 {
433     std::string animation = a;
434     stringToLower(animation);
435 
436 	bool played = false;
437 	for (int i = 0; i < s->animations.size(); i++)
438 	{
439 		if (s->animations[i].name == animation)
440 		{
441 			playAnimation(i, loop);
442 			played = true;
443 			break;
444 		}
445 	}
446 	if (!played)
447 	{
448 		std::ostringstream os;
449 		os << "Could not find animation: " << animation;
450 		debugLog(os.str());
451 	}
452 }
453 
playAnimation(int idx,int loop)454 void AnimationLayer::playAnimation(int idx, int loop)
455 {
456 	if (!(&s->animLayers[0] == this))
457 	{
458 		fallThru = 1;
459 		fallThruSpeed = 10;
460 	}
461 	timeMultiplier = 1;
462 	//currentKeyframe = 0;
463 	currentAnimation = idx;
464 	timer = 0;
465 	animating = true;
466 
467 	this->loop = loop;
468 
469 	animationLength = getCurrentAnimation()->getAnimationLength();
470 	//doNextKeyframe();
471 }
472 
enqueueAnimation(const std::string & anim,int loop)473 void AnimationLayer::enqueueAnimation(const std::string& anim, int loop)
474 {
475 	enqueuedAnimation = anim;
476 	enqueuedAnimationLoop = loop;
477 	stringToLower(enqueuedAnimation);
478 }
479 
transitionAnimate(std::string anim,float time,int loop)480 float AnimationLayer::transitionAnimate(std::string anim, float time, int loop)
481 {
482     stringToLower(anim);
483 	float totalTime =0;
484 	if (createTransitionAnimation(anim, time))
485 	{
486 		timeMultiplier = 1;
487 
488 		currentAnimation = -1;
489 		this->loop = 0;
490 		timer = 0;
491 		animating = 1;
492 		animationLength = getCurrentAnimation()->getAnimationLength();
493 		enqueueAnimation(anim, loop);
494 		Animation *a = this->s->getAnimation(anim);
495 		if (a)
496 		{
497 			if (loop > -1)
498 				totalTime = a->getAnimationLength()*(loop+1) + time;
499 			else
500 				totalTime = a->getAnimationLength() + time;
501 		}
502 	}
503 	return totalTime;
504 }
505 
setSkeletalSprite(SkeletalSprite * s)506 void AnimationLayer::setSkeletalSprite(SkeletalSprite *s)
507 {
508 	this->s = s;
509 }
510 
getCurrentAnimation()511 Animation* AnimationLayer::getCurrentAnimation()
512 {
513 	if (currentAnimation == -1)
514 		return &blendAnimation;
515 	if (currentAnimation < 0 || currentAnimation >= s->animations.size())
516 	{
517 		std::ostringstream os;
518 		os << "skel: " << s->filenameLoaded << " currentAnimation: " << currentAnimation << " is out of range\n error in anim file?";
519 		exit_error(os.str());
520 		return 0;
521 	}
522 	return &s->animations[currentAnimation];
523 }
524 
createTransitionAnimation(const std::string & anim,float time)525 bool AnimationLayer::createTransitionAnimation(const std::string& anim, float time)
526 {
527 	//Animation *a = getCurrentAnimation();
528 	Animation *to = s->getAnimation(anim);
529 	if (!to) return false;
530 	blendAnimation.keyframes.clear();
531 	SkeletalKeyframe k;
532 	k.t = 0;
533 	for (int i = 0; i < s->bones.size(); i++)
534 	{
535 		BoneKeyframe b;
536 		b.idx = s->bones[i]->boneIdx;
537 		b.x = s->bones[i]->position.x;
538 		b.y = s->bones[i]->position.y;
539 		b.rot = s->bones[i]->rotation.z;
540 		b.strip = s->bones[i]->strip;
541 		b.sx = s->bones[i]->scale.x;
542 		b.sy = s->bones[i]->scale.y;
543 		k.keyframes.push_back(b);
544 	}
545 	blendAnimation.keyframes.push_back(k);
546 
547 	SkeletalKeyframe k2;
548 	SkeletalKeyframe *rk = to->getKeyframe(0);
549 	if (!rk) return false;
550 	k2 = *rk;
551 	k2.t = time;
552 	blendAnimation.keyframes.push_back(k2);
553 
554 	blendAnimation.name = anim;
555 	return true;
556 }
557 
558 
stopAnimation()559 void AnimationLayer::stopAnimation()
560 {
561 	animating = false;
562 	if (!enqueuedAnimation.empty())
563 	{
564 		animate(enqueuedAnimation, enqueuedAnimationLoop);
565 		enqueuedAnimation = "";
566 		enqueuedAnimationLoop = 0;
567 	}
568 }
569 
isAnimating()570 bool AnimationLayer::isAnimating()
571 {
572 	return animating;
573 }
574 
getAnimationLength()575 float AnimationLayer::getAnimationLength()
576 {
577 	return animationLength;
578 }
579 
getNumKeyframes()580 int Animation::getNumKeyframes()
581 {
582 	return keyframes.size();
583 }
584 
getKeyframe(int key)585 SkeletalKeyframe *Animation::getKeyframe(int key)
586 {
587 	if (key < 0 || key >= keyframes.size()) return 0;
588 	return &keyframes[key];
589 }
590 
reverse()591 void Animation::reverse()
592 {
593 	Keyframes copy = keyframes;
594 	Keyframes copy2 = keyframes;
595 	keyframes.clear();
596 	int sz = copy.size()-1;
597 	for (int i = sz; i >= 0; i--)
598 	{
599 		keyframes.push_back(copy[i]);
600 		keyframes[keyframes.size()-1].t = copy2[sz-i].t;
601 	}
602 	reorderKeyframes();
603 }
604 
getAnimationLength()605 float Animation::getAnimationLength()
606 {
607 	return getLastKeyframe()->t;
608 }
609 
getLastKeyframe()610 SkeletalKeyframe *Animation::getLastKeyframe()
611 {
612 	if (!keyframes.empty())
613 		return &keyframes[keyframes.size()-1];
614 	return 0;
615 }
616 
getFirstKeyframe()617 SkeletalKeyframe *Animation::getFirstKeyframe()
618 {
619 	if (!keyframes.empty())
620 		return &keyframes[0];
621 	return 0;
622 }
623 
reorderKeyframes()624 void Animation::reorderKeyframes()
625 {
626 	/*
627 	std::vector<SkeletalKeyframe> copy = this->keyframes;
628 	keyframes.clear();
629 	*/
630 	for (int i = 0; i < keyframes.size(); i++)
631 	{
632 		for (int j = 0; j < keyframes.size()-1; j++)
633 		{
634 			if (keyframes[j].t > keyframes[j+1].t)
635 			{
636 				SkeletalKeyframe temp = keyframes[j+1];
637 				keyframes[j+1] = keyframes[j];
638 				keyframes[j] = temp;
639 			}
640 		}
641 	}
642 }
643 
cloneKey(int key,float toffset)644 void Animation::cloneKey(int key, float toffset)
645 {
646 	std::vector<SkeletalKeyframe> copy = this->keyframes;
647 	keyframes.clear();
648 	int i = 0;
649 	for (i = 0; i <= key; i++)
650 		keyframes.push_back(copy[i]);
651 	for (i = key; i < copy.size(); i++)
652 		keyframes.push_back(copy[i]);
653 	keyframes[key+1].t += toffset;
654 }
655 
deleteKey(int key)656 void Animation::deleteKey(int key)
657 {
658 	std::vector<SkeletalKeyframe> copy = this->keyframes;
659 	keyframes.clear();
660 	int i = 0;
661 	for (i = 0; i < key; i++)
662 		keyframes.push_back(copy[i]);
663 	for (i = key+1; i < copy.size(); i++)
664 		keyframes.push_back(copy[i]);
665 }
666 
getSkeletalKeyframeIndex(SkeletalKeyframe * skey)667 int Animation::getSkeletalKeyframeIndex(SkeletalKeyframe *skey)
668 {
669 	for (int i = 0; i < keyframes.size(); i++)
670 	{
671 		if (&keyframes[i] == skey)
672 			return i;
673 	}
674 	return -1;
675 }
676 
getBoneKeyframe(int idx)677 BoneKeyframe *SkeletalKeyframe::getBoneKeyframe(int idx)
678 {
679 	for (int i = 0; i < keyframes.size(); i++)
680 	{
681 		if (keyframes[i].idx == idx)
682 		{
683 			return &keyframes[i];
684 		}
685 	}
686 	return 0;
687 }
688 
getPrevKeyframe(float t)689 SkeletalKeyframe *Animation::getPrevKeyframe(float t)
690 {
691 	int kf = -1;
692 	for (int i = keyframes.size()-1; i >= 0; i--)
693 	{
694 		if (t >= keyframes[i].t)
695 		{
696 			kf = i;
697 			break;
698 		}
699 	}
700 	if (kf == -1)
701 		return 0;
702 	if (kf >= keyframes.size())
703 		kf = keyframes.size()-1;
704 	if (kf < 0)
705 		kf = 0;
706 	return &keyframes[kf];
707 }
708 
getNextKeyframe(float t)709 SkeletalKeyframe *Animation::getNextKeyframe(float t)
710 {
711 	int kf = -1;
712 	for (int i = 0; i < keyframes.size(); i++)
713 	{
714 		if (t <= keyframes[i].t)
715 		{
716 			kf = i;
717 			break;
718 		}
719 	}
720 //	kf++;
721 	if (kf == -1)
722 		return 0;
723 	if (kf >= keyframes.size())
724 		kf = keyframes.size()-1;
725 	if (kf < 0)
726 		kf = 0;
727 	return &keyframes[kf];
728 }
729 
SkeletalSprite()730 SkeletalSprite::SkeletalSprite() : RenderObject()
731 {
732 	frozen = false;
733 	animKeyNotify = 0;
734 	loaded = false;
735 	animLayers.resize(10);
736 	for (int i = 0; i < animLayers.size(); i++)
737 		animLayers[i].setSkeletalSprite(this);
738 	selectedBone = -1;
739 }
740 
741 
setAnimationKeyNotify(RenderObject * r)742 void SkeletalSprite::setAnimationKeyNotify(RenderObject *r)
743 {
744 	animKeyNotify = r;
745 }
746 
animate(const std::string & animation,int loop,int layer)747 void SkeletalSprite::animate(const std::string &animation, int loop, int layer)
748 {
749 	animLayers[layer].animate(animation, loop);
750 }
751 
transitionAnimate(const std::string & anim,float time,int loop,int layer)752 float SkeletalSprite::transitionAnimate(const std::string& anim, float time, int loop, int layer)
753 {
754 	AnimationLayer *animLayer = getAnimationLayer(layer);
755 	if (animLayer)
756 		return animLayer->transitionAnimate(anim, time, loop);
757 
758 	std::ostringstream os;
759 	os << "playing animation on invalid layer: " << layer;
760 	errorLog(os.str());
761 	return 0;
762 }
763 
getAnimationLayer(int l)764 AnimationLayer* SkeletalSprite::getAnimationLayer(int l)
765 {
766 	if (l >= 0 && l < animLayers.size())
767 	{
768 		return &animLayers[l];
769 	}
770 	std::ostringstream os;
771 	os << "couldn't get animLayer: " << l;
772 	debugLog(os.str());
773 	return 0;
774 }
775 
isLoaded()776 bool SkeletalSprite::isLoaded()
777 {
778 	return loaded;
779 }
780 
onUpdate(float dt)781 void SkeletalSprite::onUpdate(float dt)
782 {
783 	if (frozen) return;
784 	RenderObject::onUpdate(dt);
785 
786 	int i = 0;
787 
788 	for (i = 0; i < bones.size(); i++)
789 	{
790 		Bone *b = bones[i];
791 		if (b && !b->collisionMask.empty())
792 		{
793 			if (b->collisionMask.size() != b->transformedCollisionMask.size())
794 			{
795 				b->transformedCollisionMask.resize(b->collisionMask.size());
796 			}
797 			for (int i = 0; i < b->collisionMask.size(); i++)
798 			{
799 				b->transformedCollisionMask[i] = b->getWorldCollidePosition(b->collisionMask[i]);
800 			}
801 		}
802 	}
803 
804 	/*
805 	for (int i = 0; i < bones.size(); i++)
806 	{
807 		bones[i]->update(dt);
808 	}
809 	*/
810 	for (i = 0; i < animLayers.size(); i++)
811 	{
812 		animLayers[i].update(dt);
813 	}
814 	//updateBones();
815 }
816 
update(float dt)817 void AnimationLayer::update(float dt)
818 {
819 	timeMultiplier.update(dt);
820 	if (animating)
821 	{
822 		timer += dt*timeMultiplier.x;
823 
824 		if (timer > animationLength)
825 		{
826 			float leftover;
827 			if (animationLength > 0)
828 				leftover = fmodf(timer, animationLength);
829 			else
830 				leftover = 0;
831 			timer = animationLength;
832 			if (loop==-1 || loop > 0)
833 			{
834 				playAnimation(this->currentAnimation, loop);
835 				if (loop > 0)
836 					loop --;
837 				timer = leftover;
838 			}
839 			else
840 			{
841 				stopAnimation();
842 			}
843 		}
844 		updateBones();
845 	}
846 	else if (!animating)
847 	{
848 		if (fallThru > 0)
849 		{
850 			fallThru -= dt * fallThruSpeed;
851 			if (fallThru < 0)
852 				fallThru = 0;
853 			updateBones();
854 		}
855 	}
856 }
857 
saveSkeletal(const std::string & fn)858 bool SkeletalSprite::saveSkeletal(const std::string &fn)
859 {
860 	std::string file, filename=fn;
861 	stringToLower(filename);
862 
863 	if (!secondaryAnimationPath.empty())
864 	{
865 		createDir(secondaryAnimationPath);
866 		file = secondaryAnimationPath + filename + ".xml";
867 	}
868 	else
869 	{
870 		file = animationPath + filename + ".xml";
871 	}
872 
873 	int i = 0;
874 	XMLDocument *xml = _retrieveSkeletalXML(file, true);
875 	xml->Clear();
876 
877 	XMLElement *animationLayers = xml->NewElement("AnimationLayers");
878 	for (i = 0; i < animLayers.size(); i++)
879 	{
880 		XMLElement *animationLayer = xml->NewElement("AnimationLayer");
881 		if (animLayers[i].ignoreBones.size() > 0)
882 		{
883 			std::ostringstream os;
884 			for (int j = 0; j < animLayers[i].ignoreBones.size(); j++)
885 			{
886 				os << animLayers[i].ignoreBones[j] << " ";
887 			}
888 			animationLayer->SetAttribute("ignore", os.str().c_str());
889 		}
890 		if (animLayers[i].includeBones.size() > 0)
891 		{
892 			std::ostringstream os;
893 			for (int j = 0; j < animLayers[i].includeBones.size(); j++)
894 			{
895 				os << animLayers[i].includeBones[j] << " ";
896 			}
897 			animationLayer->SetAttribute("include", os.str().c_str());
898 		}
899 		if (!animLayers[i].name.empty())
900 		{
901 			animationLayer->SetAttribute("name", animLayers[i].name.c_str());
902 		}
903 
904 		animationLayers->InsertEndChild(animationLayer);
905 	}
906 	xml->InsertEndChild(animationLayers);
907 
908 
909 	XMLElement *bones = xml->NewElement("Bones");
910 	for (i = 0; i < this->bones.size(); i++)
911 	{
912 		XMLElement *bone = xml->NewElement("Bone");
913 		bone->SetAttribute("idx", this->bones[i]->boneIdx);
914 		bone->SetAttribute("gfx", this->bones[i]->gfx.c_str());
915 		bone->SetAttribute("pidx", this->bones[i]->pidx);
916 		bone->SetAttribute("name", this->bones[i]->name.c_str());
917 		bone->SetAttribute("fh", this->bones[i]->isfh());
918 		bone->SetAttribute("fv", this->bones[i]->isfv());
919 		bone->SetAttribute("gc", this->bones[i]->generateCollisionMask);
920 		bone->SetAttribute("cr", this->bones[i]->collideRadius);
921 		if (!this->bones[i]->renderQuad)
922 		{
923 			bone->SetAttribute("rq", this->bones[i]->fileRenderQuad);
924 		}
925 		if (!this->bones[i]->collisionRects.empty())
926 		{
927 			std::ostringstream os;
928 			os << this->bones[i]->collisionRects.size() << " ";
929 			for (int j = 0; j < this->bones[i]->collisionRects.size(); j++)
930 			{
931 				RectShape *r = &this->bones[i]->collisionRects[j];
932 				int x, y, w, h;
933 				r->getCWH(&x, &y, &w, &h);
934 				os << x << " " << y << " " << w << " " << h << " ";
935 			}
936 			bone->SetAttribute("crects", os.str().c_str());
937 		}
938 		std::ostringstream os;
939 		os << this->bones[i]->collidePosition.x << " " << this->bones[i]->collidePosition.y;
940 		bone->SetAttribute("cp", os.str().c_str());
941 		if (this->bones[i]->rbp)
942 			bone->SetAttribute("rbp", this->bones[i]->rbp);
943 		if (this->bones[i]->getRenderPass())
944 			bone->SetAttribute("pass", this->bones[i]->getRenderPass());
945 		if (this->bones[i]->offset.x)
946 			bone->SetAttribute("offx", this->bones[i]->offset.x);
947 		if (this->bones[i]->offset.y)
948 			bone->SetAttribute("offy", this->bones[i]->offset.y);
949 		if (!this->bones[i]->prt.empty())
950 			bone->SetAttribute("prt", this->bones[i]->prt.c_str());
951 		if (!this->bones[i]->changeStrip.empty())
952 		{
953 			std::ostringstream os;
954 			os << this->bones[i]->stripVert << " " << this->bones[i]->changeStrip.size();
955 			bone->SetAttribute("strip", os.str().c_str());
956 		}
957 		if (!this->bones[i]->internalOffset.isZero())
958 		{
959 			std::ostringstream os;
960 			os << this->bones[i]->internalOffset.x << " " << this->bones[i]->internalOffset.y;
961 			bone->SetAttribute("io", os.str().c_str());
962 		}
963 		if (this->bones[i]->isRepeatingTextureToFill())
964 		{
965 			bone->SetAttribute("rt", 1);
966 		}
967 		if (this->bones[i]->originalScale.x != 1 || this->bones[i]->originalScale.y != 1)
968 		{
969 			std::ostringstream os;
970 			os << this->bones[i]->originalScale.x << " " << this->bones[i]->originalScale.y;
971 			bone->SetAttribute("sz", os.str().c_str());
972 		}
973 		/*
974 		if (this->bones[i]->color.x != 1 || this->bones[i]->color.y != 1 || this->bones[i]->color.z != 1)
975 		{
976 			std::ostringstream os;
977 			os << this->bones[i]->color.x << " " << this->bones[i]->color.y << " " << this->bones[i]->color.z;
978 			bone->SetAttribute("color", os.str().c_str());
979 		}
980 		*/
981 
982 		for (Children::iterator j = this->bones[i]->children.begin(); j != this->bones[i]->children.end(); j++)
983 		{
984 			Bone *b = dynamic_cast<Bone*>(*j);
985 			Quad *q = dynamic_cast<Quad*>(*j);
986 			Particle *p = dynamic_cast<Particle*>(*j);
987 			if (q && !b && !p)
988 			{
989 				XMLElement *frame = xml->NewElement("Frame");
990 				frame->SetAttribute("gfx", q->texture->name.c_str());
991 				if (q->getRenderPass() != 0)
992 				{
993 					frame->SetAttribute("pass", q->getRenderPass());
994 				}
995 				bone->InsertEndChild(frame);
996 			}
997 		}
998 		bones->InsertEndChild(bone);
999 	}
1000 	xml->InsertEndChild(bones);
1001 
1002 	XMLElement *animations = xml->NewElement("Animations");
1003 	for (i = 0; i < this->animations.size(); i++)
1004 	{
1005 		Animation *a = &this->animations[i];
1006 		XMLElement *animation = xml->NewElement("Animation");
1007 		animation->SetAttribute("name", a->name.c_str());
1008 		for (int j = 0; j < a->keyframes.size(); j++)
1009 		{
1010 			XMLElement *key = xml->NewElement("Key");
1011 			if (!a->keyframes[j].sound.empty())
1012 				key->SetAttribute("sound", a->keyframes[j].sound.c_str());
1013 			if (!a->keyframes[j].cmd.empty())
1014 			{
1015 				key->SetAttribute("cmd", a->keyframes[j].cmd.c_str());
1016 			}
1017 			if (a->keyframes[j].lerpType != 0)
1018 			{
1019 				key->SetAttribute("lerp", a->keyframes[j].lerpType);
1020 			}
1021 			std::ostringstream os;
1022 			os << a->keyframes[j].t << " ";
1023 			std::ostringstream szos;
1024 			for (int k = 0; k < a->keyframes[j].keyframes.size(); k++)
1025 			{
1026 				BoneKeyframe *b = &a->keyframes[j].keyframes[k];
1027 				os << b->idx << " " << b->x << " " << b->y << " " << b->rot << " ";
1028 				os << b->strip.size() << " ";
1029 				for (int i = 0; i < b->strip.size(); i++)
1030 				{
1031 					os << b->strip[i].x << " " << b->strip[i].y << " ";
1032 				}
1033 				if (b->doScale)
1034 				{
1035 					szos << b->idx << " " << b->sx << " " << b->sy << " ";
1036 				}
1037 			}
1038 			std::string szoss = szos.str();
1039 			if (!szoss.empty())
1040 				key->SetAttribute("sz", szoss.c_str());
1041 
1042 			key->SetAttribute("e", os.str().c_str());
1043 
1044 			animation->InsertEndChild(key);
1045 		}
1046 		animations->InsertEndChild(animation);
1047 	}
1048 	xml->InsertEndChild(animations);
1049 	return xml->SaveFile(file.c_str()) == XML_SUCCESS;
1050 }
1051 
getBoneIdx(Bone * b)1052 int SkeletalSprite::getBoneIdx(Bone *b)
1053 {
1054 	for (int i = 0; i < bones.size(); i++)
1055 	{
1056 		if (bones[i] == b)
1057 			return i;
1058 	}
1059 	return -1;
1060 }
1061 
toggleBone(int idx,int v)1062 void SkeletalSprite::toggleBone(int idx, int v)
1063 {
1064 	if (idx >= 0 && idx < bones.size())
1065 	{
1066 		bones[idx]->alpha.x = v;
1067 	}
1068 }
1069 
getBoneByName(const std::string & name)1070 Bone *SkeletalSprite::getBoneByName(const std::string &name)
1071 {
1072 	for (int i = 0; i < bones.size(); i++)
1073 	{
1074 		if (bones[i]->name == name)
1075 			return bones[i];
1076 	}
1077 	std::ostringstream os;
1078 	os << "Could not find bone with name[" << name << "]";
1079 	debugLog(os.str());
1080 	return 0;
1081 }
1082 
getBoneByIdx(int idx)1083 Bone *SkeletalSprite::getBoneByIdx(int idx)
1084 {
1085 	for (int i = 0; i < bones.size(); i++)
1086 	{
1087 		if (bones[i]->boneIdx == idx)
1088 			return bones[i];
1089 	}
1090 	std::ostringstream os;
1091 	os << "Could not find bone with idx[" << idx << "]";
1092 	debugLog(os.str());
1093 	return 0;
1094 }
1095 
initBone(int idx,std::string gfx,int pidx,int rbp,std::string name,float cr,bool fh,bool fv,const Vector & cp)1096 Bone *SkeletalSprite::initBone(int idx, std::string gfx, int pidx, int rbp, std::string name, float cr, bool fh, bool fv, const Vector &cp)
1097 {
1098 	Bone *b = new Bone;
1099 	b->boneIdx = idx;
1100 	b->setTexture(gfx);
1101 	b->skeleton = this;
1102 	b->gfx = gfx;
1103 	b->rbp = rbp;
1104 	b->renderBeforeParent = rbp;
1105 	b->pidx = pidx;
1106 	b->collideRadius = cr;
1107 	b->collidePosition = cp;
1108 	b->name = name;
1109 	//core->generateCollisionMask(b);
1110 	if (fh)
1111 		b->flipHorizontal();
1112 	if (fv)
1113 		b->flipVertical();
1114 	bones.push_back(b);
1115 	return b;
1116 }
1117 
firstAnimation()1118 void SkeletalSprite::firstAnimation()
1119 {
1120 	stopAnimation();
1121 	animLayers[0].currentAnimation = 0;
1122 }
1123 
lastAnimation()1124 void SkeletalSprite::lastAnimation()
1125 {
1126 	stopAnimation();
1127 	animLayers[0].currentAnimation = animations.size()-1;
1128 }
1129 
nextAnimation()1130 void SkeletalSprite::nextAnimation()
1131 {
1132 	stopAnimation();
1133 	animLayers[0].currentAnimation++;
1134 	if (animLayers[0].currentAnimation >= animations.size())
1135 		animLayers[0].currentAnimation = 0;
1136 }
1137 
prevAnimation()1138 void SkeletalSprite::prevAnimation()
1139 {
1140 	stopAnimation();
1141 	animLayers[0].currentAnimation--;
1142 	if (animLayers[0].currentAnimation < 0)
1143 		animLayers[0].currentAnimation = animations.size()-1;
1144 }
1145 
deleteBones()1146 void SkeletalSprite::deleteBones()
1147 {
1148 	bones.clear();
1149 	for(Children::iterator it = children.begin(); it != children.end(); ++it)
1150 	{
1151 		(*it)->safeKill();
1152 	}
1153 	bones.clear();
1154 }
1155 
getAnimation(const std::string & anim)1156 Animation *SkeletalSprite::getAnimation(const std::string& anim)
1157 {
1158 	for (int i = 0; i < animations.size(); i++)
1159 	{
1160 		if (animations[i].name == anim)
1161 			return &animations[i];
1162 	}
1163 	return 0;
1164 }
1165 
loadSkin(const std::string & fn)1166 void SkeletalSprite::loadSkin(const std::string &fn)
1167 {
1168 	std::string file;
1169 
1170 	if (!secondaryAnimationPath.empty())
1171 	{
1172 		file = secondaryAnimationPath + skinPath + fn + ".xml";
1173 	}
1174 
1175 	if (file.empty() || !exists(file, false))
1176 	{
1177 		file = animationPath + skinPath + fn + ".xml";
1178 	}
1179 
1180 	file = core->adjustFilenameCase(file);
1181 
1182 	if (!exists(file))
1183 	{
1184 		errorLog("Could not load skin[" + file + "] - File not found.");
1185 		return;
1186 	}
1187 	XMLDocument *d = _retrieveSkeletalXML(file, false);
1188 	if(!d)
1189 	{
1190 		errorLog("Could not load skin[" + file + "] - Malformed XML.");
1191 		return;
1192 	}
1193 
1194 	XMLElement *bonesXml = d->FirstChildElement("Bones");
1195 	if (bonesXml)
1196 	{
1197 		XMLElement *boneXml = bonesXml->FirstChildElement("Bone");
1198 		while (boneXml)
1199 		{
1200 			int idx = atoi(boneXml->Attribute("idx"));
1201 			Bone *b = getBoneByIdx(idx);
1202 			if (b)
1203 			{
1204 				if (boneXml->Attribute("rq"))
1205 				{
1206 					int rq = atoi(boneXml->Attribute("rq"));
1207 					b->renderQuad = rq;
1208 				}
1209 
1210 				std::string gfx;
1211 				if (boneXml->Attribute("gfx"))
1212 				{
1213 					gfx = boneXml->Attribute("gfx");
1214 					if (!gfx.empty())
1215 					{
1216 						b->gfx = gfx;
1217 						b->setTexture(b->gfx);
1218 						b->renderQuad = true;
1219 					}
1220 				}
1221 
1222 				if (gfx.empty())
1223 				{
1224 					b->renderQuad = false;
1225 				}
1226 
1227 				if (boneXml->Attribute("fh"))
1228 				{
1229 					int fh = atoi(boneXml->Attribute("fh"));
1230 					if (fh)
1231 						b->flipHorizontal();
1232 				}
1233 				if (boneXml->Attribute("fv"))
1234 				{
1235 					int fv = atoi(boneXml->Attribute("fv"));
1236 					if (fv)
1237 						b->flipVertical();
1238 				}
1239 
1240 				/*
1241 				if (boneXml->Attribute("a"))
1242 				{
1243 					float alpha = 0;
1244 					boneXml->Attribute("a", &alpha);
1245 					b->alpha = alpha;
1246 				}
1247 				*/
1248 				/*
1249 				// this is for SKINS
1250 				if (boneXml->Attribute("sz"))
1251 				{
1252 					float v1, v2;
1253 					SimpleIStringStream is(boneXml->Attribute("sz"));
1254 					is >> v1 >> v2;
1255 					b->scale = Vector(v1,v2);
1256 					b->originalScale = b->scale;
1257 				}
1258 				*/
1259 			}
1260 			else
1261 			{
1262 				std::ostringstream os;
1263 				os << "SkinLoad: Could not find idx[" << idx << "]";
1264 				debugLog(os.str());
1265 			}
1266 			boneXml = boneXml->NextSiblingElement("Bone");
1267 		}
1268 	}
1269 }
1270 
stopAnimation(int layer)1271 void SkeletalSprite::stopAnimation(int layer)
1272 {
1273 	animLayers[layer].stopAnimation();
1274 }
1275 
stopAllAnimations()1276 void SkeletalSprite::stopAllAnimations()
1277 {
1278 	for (int i = 0; i < animLayers.size(); i++)
1279 	{
1280 		animLayers[i].stopAnimation();
1281 	}
1282 }
1283 
playCurrentAnimation(int loop,int layer)1284 void SkeletalSprite::playCurrentAnimation(int loop, int layer)
1285 {
1286 	animLayers[layer].playCurrentAnimation(loop);
1287 }
1288 
loadSkeletal(const std::string & fn)1289 void SkeletalSprite::loadSkeletal(const std::string &fn)
1290 {
1291 	filenameLoaded = "";
1292 	loaded = false;
1293 	stopAnimation();
1294 	animLayers.clear();
1295 	deleteBones();
1296 
1297 
1298 	filenameLoaded = fn;
1299 	stringToLower(filenameLoaded);
1300 
1301 	std::string file;
1302 
1303 	if (!secondaryAnimationPath.empty())
1304 	{
1305 		file = secondaryAnimationPath + filenameLoaded + ".xml";
1306 	}
1307 
1308 	if (file.empty() || !exists(file, false))
1309 	{
1310 		file = animationPath + filenameLoaded + ".xml";
1311 	}
1312 
1313 	if (!exists(file))
1314 	{
1315 		filenameLoaded = "";
1316 		errorLog("Could not load skeletal[" + file + "] - File not found.");
1317 		return;
1318 	}
1319 
1320 	file = core->adjustFilenameCase(file);
1321 
1322 	XMLDocument *xml = _retrieveSkeletalXML(file, false);
1323 	if(!xml)
1324 	{
1325 		filenameLoaded = "";
1326 		errorLog("Could not load skeletal[" + file + "] - Malformed XML.");
1327 		return;
1328 	}
1329 
1330 	loaded = true;
1331 
1332 	XMLElement *bones = xml->FirstChildElement("Bones");
1333 	if (bones)
1334 	{
1335 		if (bones->Attribute("scale"))
1336 		{
1337 			SimpleIStringStream is(bones->Attribute("scale"));
1338 			is >> scale.x >> scale.y;
1339 		}
1340 
1341 		XMLElement *bone = bones->FirstChildElement("Bone");
1342 		while(bone)
1343 		{
1344 			int idx = atoi(bone->Attribute("idx"));
1345 			int pidx = -1, rbp=0, cr=0, fh=0, fv=0;
1346 
1347 			std::string name;
1348 			Vector cp;
1349 			if (bone->Attribute("pidx"))
1350 				pidx = atoi(bone->Attribute("pidx"));
1351 			if (bone->Attribute("rbp"))
1352 				rbp = atoi(bone->Attribute("rbp"));
1353 
1354 			if (bone->Attribute("name"))
1355 				name = bone->Attribute("name");
1356 			if (bone->Attribute("cr"))
1357 				cr = atoi(bone->Attribute("cr"));
1358 			if (bone->Attribute("fh"))
1359 				fh = atoi(bone->Attribute("fh"));
1360 			if (bone->Attribute("fv"))
1361 				fv = atoi(bone->Attribute("fv"));
1362 			if (bone->Attribute("cp"))
1363 			{
1364 				SimpleIStringStream is(bone->Attribute("cp"));
1365 				is >> cp.x >> cp.y;
1366 			}
1367 
1368 
1369 
1370 
1371 
1372 			std::string gfx = bone->Attribute("gfx");
1373 			Bone *newb = initBone(idx, gfx, pidx, rbp, name, cr, fh, fv, cp);
1374 			if (bone->Attribute("offx"))
1375 				newb->offset.x = atoi(bone->Attribute("offx"));
1376 			if (bone->Attribute("offy"))
1377 				newb->offset.y = atoi(bone->Attribute("offy"));
1378 
1379 			if (bone->Attribute("crects"))
1380 			{
1381 				SimpleIStringStream is(bone->Attribute("crects"));
1382 				int num = 0;
1383 				is >> num;
1384 				for (int i = 0; i < num; i++)
1385 				{
1386 					RectShape r;
1387 					int x, y, w, h;
1388 					is >> x >> y >> w >> h;
1389 					r.setCWH(x, y, w, h);
1390 
1391 					newb->collisionRects.push_back(r);
1392 				}
1393 			}
1394 
1395 			if (bone->Attribute("prt"))
1396 			{
1397 				newb->prt = bone->Attribute("prt");
1398 				SimpleIStringStream is(newb->prt);
1399 				int slot;
1400 				while (is >> slot)
1401 				{
1402 					std::string pfile;
1403 					is >> pfile;
1404 					// add particle system + load
1405 					newb->emitters[slot] = new ParticleEffect;
1406 					ParticleEffect *e = newb->emitters[slot];
1407 					newb->addChild(e, PM_POINTER);
1408 					e->load(pfile);
1409 					// hack for now:
1410 					//e->start();
1411 				}
1412 			}
1413 			XMLElement *fr=0;
1414 			fr = bone->FirstChildElement("Frame");
1415 			int frc=0;
1416 			while(fr)
1417 			{
1418 				Quad *q=0;
1419 				std::string gfx;
1420 				if (fr->Attribute("gfx"))
1421 				{
1422 					gfx = fr->Attribute("gfx");
1423 					q = newb->addFrame(gfx);
1424 				}
1425 				if (fr->Attribute("pass"))
1426 				{
1427 					if (q)
1428 					{
1429 						q->setRenderPass(atoi(fr->Attribute("pass")));
1430 					}
1431 				}
1432 				fr = fr->NextSiblingElement("Frame");
1433 				frc++;
1434 			}
1435 			if (frc)
1436 			{
1437 				newb->showFrame(0);
1438 			}
1439 			if (bone->Attribute("pass"))
1440 			{
1441 				newb->setRenderPass(atoi(bone->Attribute("pass")));
1442 			}
1443 			if (bone->Attribute("gc"))
1444 			{
1445 				newb->generateCollisionMask = atoi(bone->Attribute("gc"));
1446 			}
1447 			if (bone->Attribute("rq"))
1448 			{
1449 				newb->renderQuad = newb->fileRenderQuad = atoi(bone->Attribute("rq"));
1450 			}
1451 			if (bone->Attribute("io"))
1452 			{
1453 				SimpleIStringStream is(bone->Attribute("io"));
1454 				is >> newb->internalOffset.x >> newb->internalOffset.y;
1455 			}
1456 
1457 			if (bone->Attribute("strip"))
1458 			{
1459 				SimpleIStringStream is(bone->Attribute("strip"));
1460 				bool vert;
1461 				int num;
1462 				is >> vert >> num;
1463 				newb->createStrip(vert, num);
1464 			}
1465 			if (bone->Attribute("sz"))
1466 			{
1467 				float sx, sy;
1468 				SimpleIStringStream is(bone->Attribute("sz"));
1469 				is >> sx >> sy;
1470 
1471 				newb->scale = newb->originalScale = Vector(sx,sy);
1472 			}
1473 			if (bone->Attribute("rt"))
1474 			{
1475 				newb->repeatTextureToFill(true);
1476 			}
1477 
1478 			if (bone->Attribute("blend"))
1479 			{
1480 				//if (bone->Attribute("blend")=="add")
1481 				newb->blendType = blendType = BLEND_ADD;
1482 			}
1483 
1484 			if (bone->Attribute("alpha"))
1485 			{
1486 				float a=1.0;
1487 				SimpleIStringStream is(bone->Attribute("alpha"));
1488 				is >> a;
1489 				newb->alpha = a;
1490 			}
1491 
1492 			if (bone->Attribute("alphaMod"))
1493 			{
1494 				float a=1.0;
1495 				SimpleIStringStream is(bone->Attribute("alphaMod"));
1496 				is >> a;
1497 				newb->alphaMod = a;
1498 			}
1499 
1500 			if (bone->Attribute("segs"))
1501 			{
1502 				int x, y;
1503 				float dgox, dgoy, dgmx, dgmy, dgtm;
1504 				bool dgo;
1505 				SimpleIStringStream is(bone->Attribute("segs"));
1506 				is >> x >> y >> dgox >> dgoy >> dgmx >> dgmy >> dgtm >> dgo;
1507 				newb->setSegs(x, y, dgox, dgoy, dgmx, dgmy, dgtm, dgo);
1508 			}
1509 
1510 			if (bone->Attribute("color"))
1511 			{
1512 				SimpleIStringStream in(bone->Attribute("color"));
1513 				in >> newb->color.x >> newb->color.y >> newb->color.z;
1514 			}
1515 			bone = bone->NextSiblingElement("Bone");
1516 		}
1517 		// attach bones
1518 		for (int i = 0; i < this->bones.size(); i++)
1519 		{
1520 			Bone *b = this->bones[i];
1521 			if (b->pidx != -1)
1522 			{
1523 				Bone *pb = getBoneByIdx(b->pidx);
1524 				if (!pb)
1525 				{
1526 					std::ostringstream os;
1527 					os << "Parent bone not found, index: " << b->pidx << " from bone idx: " << b->getIdx();
1528 					debugLog(os.str());
1529 				}
1530 				else
1531 				{
1532 					pb->addChild(b, PM_POINTER);
1533 				}
1534 			}
1535 			else
1536 				addChild(b, PM_POINTER);
1537 		}
1538 	}
1539 
1540 	animLayers.clear();
1541 	XMLElement *animationLayers = xml->FirstChildElement("AnimationLayers");
1542 	if (animationLayers)
1543 	{
1544 		XMLElement *animationLayer = animationLayers->FirstChildElement("AnimationLayer");
1545 		while (animationLayer)
1546 		{
1547 			AnimationLayer newAnimationLayer;
1548 			if (animationLayer->Attribute("ignore"))
1549 			{
1550 				SimpleIStringStream is(animationLayer->Attribute("ignore"));
1551 				int t;
1552 				while (is >> t)
1553 				{
1554 					newAnimationLayer.ignoreBones.push_back(t);
1555 				}
1556 			}
1557 			if (animationLayer->Attribute("include"))
1558 			{
1559 				SimpleIStringStream is(animationLayer->Attribute("include"));
1560 				int t;
1561 				while (is >> t)
1562 				{
1563 					newAnimationLayer.includeBones.push_back(t);
1564 				}
1565 			}
1566 			if (animationLayer->Attribute("name"))
1567 			{
1568 				newAnimationLayer.name = animationLayer->Attribute("name");
1569 			}
1570 			newAnimationLayer.setSkeletalSprite(this);
1571 			animLayers.push_back(newAnimationLayer);
1572 			animationLayer = animationLayer->NextSiblingElement("AnimationLayer");
1573 		}
1574 	}
1575 
1576 	animations.clear();
1577 	XMLElement *animations = xml->FirstChildElement("Animations");
1578 	if (animations)
1579 	{
1580 		XMLElement *animation = animations->FirstChildElement("Animation");
1581 		while(animation)
1582 		{
1583 			Animation newAnimation;
1584 			newAnimation.name = animation->Attribute("name");
1585 			stringToLower(newAnimation.name);
1586 
1587 			XMLElement *key = animation->FirstChildElement("Key");
1588 			while (key)
1589 			{
1590 				SkeletalKeyframe newSkeletalKeyframe;
1591 				if (key->Attribute("e"))
1592 				{
1593 					float time;
1594 					SimpleIStringStream is(key->Attribute("e"));
1595 					is >> time;
1596 					int idx, x, y, rot, strip;
1597 					newSkeletalKeyframe.t = time;
1598 					if (key->Attribute("sound"))
1599 					{
1600 						newSkeletalKeyframe.sound = key->Attribute("sound");
1601 					}
1602 					if (key->Attribute("lerp"))
1603 					{
1604 						newSkeletalKeyframe.lerpType = atoi(key->Attribute("lerp"));
1605 					}
1606 					while (is >> idx)
1607 					{
1608 						BoneKeyframe b;
1609 						is >> x >> y >> rot >> strip;
1610 						b.idx = idx;
1611 						b.x = x;
1612 						b.y = y;
1613 						b.rot = rot;
1614 						if (strip>0)
1615 						{
1616 							b.strip.resize(strip);
1617 							for (int i = 0; i < b.strip.size(); i++)
1618 							{
1619 								is >> b.strip[i].x >> b.strip[i].y;
1620 								//b.strip[i].y *= 10;
1621 							}
1622 						}
1623 						if (key->Attribute("sz"))
1624 						{
1625 							SimpleIStringStream is2(key->Attribute("sz"));
1626 							int midx;
1627 							float bsx, bsy;
1628 							while (is2 >> midx)
1629 							{
1630 								is2 >> bsx >> bsy;
1631 								if (midx == idx)
1632 								{
1633 									b.doScale = true;
1634 									b.sx = bsx;
1635 									b.sy = bsy;
1636 									break;
1637 								}
1638 							}
1639 						}
1640 						newSkeletalKeyframe.keyframes.push_back(b);
1641 					}
1642 
1643 				}
1644 				if (key->Attribute("d"))
1645 				{
1646 					float time;
1647 					SimpleIStringStream is(key->Attribute("d"));
1648 					is >> time;
1649 					int idx, x, y, rot;
1650 
1651 					newSkeletalKeyframe.t = time;
1652 					if (key->Attribute("sound"))
1653 					{
1654 						newSkeletalKeyframe.sound = key->Attribute("sound");
1655 					}
1656 					while (is >> idx)
1657 					{
1658 						is >> x >> y >> rot;
1659 						BoneKeyframe b;
1660 						b.idx = idx;
1661 						b.x = x;
1662 						b.y = y;
1663 						b.rot = rot;
1664 						newSkeletalKeyframe.keyframes.push_back(b);
1665 					}
1666 				}
1667 				if (key->Attribute("cmd"))
1668 				{
1669 					newSkeletalKeyframe.cmd = key->Attribute("cmd");
1670 					SimpleIStringStream is(newSkeletalKeyframe.cmd);
1671 					int bidx;
1672 					while (is >> bidx)
1673 					{
1674 						Bone *b = this->getBoneByIdx(bidx);
1675 						if (b)
1676 						{
1677 							BoneCommand bcmd;
1678 							bcmd.parse(b, is);
1679 							newSkeletalKeyframe.commands.push_back(bcmd);
1680 						}
1681 					}
1682 				}
1683 				// generate empty bone keys
1684 				for (int i = 0; i < this->bones.size(); i++)
1685 				{
1686 					if (newSkeletalKeyframe.getBoneKeyframe(this->bones[i]->boneIdx))
1687 					{
1688 					}
1689 					else
1690 					{
1691 						BoneKeyframe b;
1692 						b.idx = this->bones[i]->boneIdx;
1693 						newSkeletalKeyframe.keyframes.push_back(b);
1694 					}
1695 				}
1696 				newAnimation.keyframes.push_back(newSkeletalKeyframe);
1697 				key = key->NextSiblingElement("Key");
1698 			}
1699 			animation = animation->NextSiblingElement("Animation");
1700 			this->animations.push_back(newAnimation);
1701 		}
1702 	}
1703 }
1704 
getCurrentAnimation(int layer)1705 Animation *SkeletalSprite::getCurrentAnimation(int layer)
1706 {
1707 	return layer < animLayers.size() ? animLayers[layer].getCurrentAnimation() : NULL;
1708 }
1709 
setTime(float time,int layer)1710 void SkeletalSprite::setTime(float time, int layer)
1711 {
1712 	if(layer < animLayers.size())
1713 		animLayers[layer].timer = time;
1714 }
1715 
updateBones()1716 void AnimationLayer::updateBones()
1717 {
1718 	if (!animating && !(&s->animLayers[0] == this) && fallThru == 0) return;
1719 
1720 	SkeletalKeyframe *key1 = getCurrentAnimation()->getPrevKeyframe(timer);
1721 	SkeletalKeyframe *key2 = getCurrentAnimation()->getNextKeyframe(timer);
1722 	if (!key1 || !key2) return;
1723 	float t1 = key1->t;
1724 	float t2 = key2->t;
1725 
1726 	/*
1727 	if (key1 == key2)
1728 		stopAnimation();
1729 	*/
1730 
1731 	float diff = t2-t1;
1732 	float dt;
1733 	if (diff != 0)
1734 		dt = (timer - t1)/(t2-t1);
1735 	else
1736 		dt = 0;
1737 
1738 	if (lastNewKey != key2)
1739 	{
1740 		if (!key2->sound.empty())
1741 		{
1742 			core->sound->playSfx(key2->sound);
1743 		}
1744 		if (!key2->commands.empty())
1745 		{
1746 			for (int i = 0; i < key2->commands.size(); i++)
1747 			{
1748 				key2->commands[i].run();
1749 			}
1750 		}
1751 		if (s->animKeyNotify)
1752 		{
1753 			s->animKeyNotify->onAnimationKeyPassed(getCurrentAnimation()->getSkeletalKeyframeIndex(lastNewKey));
1754 		}
1755 	}
1756 	lastNewKey = key2;
1757 
1758 	bool c = 0;
1759 	for (int i = 0; i < s->bones.size(); i++)
1760 	{
1761 		int idx = s->bones[i]->boneIdx;
1762 		Bone *b = s->bones[i];
1763 
1764 		if (b->segmentChain == 1)
1765 		{
1766 			b->updateSegments();
1767 		}
1768 		if (b->segmentChain < 2)
1769 		{
1770 			c=0;
1771 			if (!ignoreBones.empty())
1772 			{
1773 				for (int j = 0; j < ignoreBones.size(); j++)
1774 				{
1775 					if (idx == ignoreBones[j])
1776 					{	c=1; break; }
1777 				}
1778 			}
1779 			else if (!includeBones.empty())
1780 			{
1781 				c = 1;
1782 				for (int j = 0; j < includeBones.size(); j++)
1783 				{
1784 					if (idx == includeBones[j])
1785 					{	c=0; break; }
1786 				}
1787 			}
1788 			if (b->animated==Bone::ANIM_NONE)
1789 			{
1790 				c = 1;
1791 			}
1792 			if (!c)
1793 			{
1794 
1795 				BoneKeyframe *bkey1 = key1->getBoneKeyframe(idx);
1796 				BoneKeyframe *bkey2 = key2->getBoneKeyframe(idx);
1797 				if (bkey1 && bkey2)
1798 				{
1799 					if (!animating && fallThru > 0)
1800 					{
1801 						//HACK: TODO: fix this up nice like below
1802 						Vector p = Vector((bkey2->x-bkey1->x)*dt+bkey1->x, (bkey2->y-bkey1->y)*dt+bkey1->y);
1803 						float rot = (bkey2->rot - bkey1->rot)*dt + bkey1->rot;
1804 						p = Vector((p.x-b->position.x)*fallThru+b->position.x, (p.y-b->position.y)*fallThru+b->position.y);
1805 						rot = (rot-b->rotation.z)*fallThru + b->rotation.z;
1806 						if (b->animated==Bone::ANIM_ALL || b->animated==Bone::ANIM_POS)
1807 							b->position = p;
1808 						if (b->animated==Bone::ANIM_ALL || b->animated==Bone::ANIM_ROT)
1809 							b->rotation.z = rot;
1810 					}
1811 					else
1812 					{
1813 						int lerpType = key2->lerpType;
1814 						//k(0)×(2u3-3u2+1) + k(1)×(3u2-2u3)
1815 						if (b->animated==Bone::ANIM_ALL || b->animated==Bone::ANIM_POS)
1816 						{
1817 							b->position = Vector(lerp(bkey1->x, bkey2->x, dt, lerpType), lerp(bkey1->y, bkey2->y, dt, lerpType));
1818 						}
1819 						if (b->animated==Bone::ANIM_ALL || b->animated==Bone::ANIM_ROT)
1820 						{
1821 							b->rotation.z = lerp(bkey1->rot, bkey2->rot, dt, lerpType);
1822 						}
1823 						if (b->animated==Bone::ANIM_ALL && (bkey1->doScale || bkey2->doScale))
1824 						{
1825 							b->scale.x = lerp(bkey1->sx, bkey2->sx, dt, lerpType);
1826 							b->scale.y = lerp(bkey1->sy, bkey2->sy, dt, lerpType);
1827 						}
1828 						if (b->animated==Bone::ANIM_ALL && !b->changeStrip.empty())
1829 						{
1830 							if (bkey2->strip.size() < b->changeStrip.size())
1831 								bkey2->strip.resize(b->changeStrip.size());
1832 							if (bkey1->strip.size() < b->changeStrip.size())
1833 								bkey1->strip.resize(b->changeStrip.size());
1834 							for (int i = 0; i < b->changeStrip.size(); i++)
1835 							{
1836 								b->changeStrip[i] = Vector(lerp(bkey1->strip[i].x, bkey2->strip[i].x, dt, lerpType), lerp(bkey1->strip[i].y, bkey2->strip[i].y, dt, lerpType));
1837 							}
1838 							b->setGridPoints(b->stripVert, b->changeStrip);
1839 						}
1840 					}
1841 				}
1842 			}
1843 		}
1844 	}
1845 }
1846 
setFreeze(bool f)1847 void SkeletalSprite::setFreeze(bool f)
1848 {
1849 	frozen = f;
1850 }
1851 
updateBones()1852 void SkeletalSprite::updateBones()
1853 {
1854 	if (!frozen)
1855 	{
1856 		for (int i = 0; i < animLayers.size(); i++)
1857 		{
1858 			animLayers[i].updateBones();
1859 		}
1860 	}
1861 	/*
1862 	for (int i = animLayers.size()-1; i >= 0; i--)
1863 	{
1864 		if (animLayers[i].animating)
1865 		{
1866 			animLayers[i].updateBones();
1867 			return;
1868 		}
1869 	}
1870 	*/
1871 
1872 }
1873 
isAnimating(int layer)1874 bool SkeletalSprite::isAnimating(int layer)
1875 {
1876 	return animLayers[layer].animating;
1877 }
1878 
setTimeMultiplier(float t,int layer)1879 void SkeletalSprite::setTimeMultiplier(float t, int layer)
1880 {
1881 	animLayers[layer].timeMultiplier = t;
1882 }
1883 
getSelectedBone(bool mouseBased)1884 Bone* SkeletalSprite::getSelectedBone(bool mouseBased)
1885 {
1886 	if (!loaded) return 0;
1887 	if (mouseBased)
1888 	{
1889 		float closestDist = HUGE_VALF;
1890 		Bone *b = 0;
1891 		Vector p = core->mouse.position;
1892 		for (int i = 0; i < bones.size(); i++)
1893 		{
1894 			if (bones[i]->renderQuad || core->getShiftState())
1895 			{
1896 				bones[i]->color = Vector(1,1,1);
1897 				if (bones[i]->renderQuad && bones[i]->isCoordinateInsideWorld(p))
1898 				{
1899 					float dist = (bones[i]->getWorldPosition() - p).getSquaredLength2D();
1900 					if (dist <= closestDist)
1901 					{
1902 						closestDist = dist;
1903 						b = bones[i];
1904 						selectedBone = i;
1905 					}
1906 				}
1907 			}
1908 		}
1909 		if (b)
1910 		{
1911 			b->color = Vector(1,0,0);
1912 		}
1913 		return b;
1914 	}
1915 	// else
1916 	if (!bones.empty() && selectedBone >= 0 && selectedBone < bones.size())
1917 		return bones[selectedBone];
1918 
1919 	return 0;
1920 }
1921 
1922 
updateSelectedBoneColor()1923 void SkeletalSprite::updateSelectedBoneColor()
1924 {
1925 	for (int i = 0; i < bones.size(); i++)
1926 	{
1927 		bones[i]->color = Vector(1,1,1);
1928 	}
1929 	Bone *b = bones[selectedBone];
1930 	if (b)
1931 		b->color = Vector(0.5,0.5,1);
1932 }
1933 
setSelectedBone(int b)1934 void SkeletalSprite::setSelectedBone(int b)
1935 {
1936 	selectedBone = b;
1937 	updateSelectedBoneColor();
1938 }
1939 
selectPrevBone()1940 void SkeletalSprite::selectPrevBone()
1941 {
1942 	selectedBone++;
1943 	if (selectedBone >= bones.size())
1944 		selectedBone = 0;
1945 	updateSelectedBoneColor();
1946 }
1947 
selectNextBone()1948 void SkeletalSprite::selectNextBone()
1949 {
1950 	selectedBone--;
1951 	if (selectedBone < 0)
1952 		selectedBone = bones.size()-1;
1953 	updateSelectedBoneColor();
1954 }
1955 
1956 
1957