diff --git a/AUTHORS b/AUTHORS index 794f5aa344..5b7f259bb1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -354,6 +354,7 @@ Developers: flamingo (flaming0) Null pointer check in order to prevent crashes. + Updating spine-runtime to EsotericSoftware/spine-runtimes@5f90386. rtissera (Romain TISSERAND) Adding missing JNIEXPORT / JNICALL declarations. @@ -440,6 +441,9 @@ Developers: Lee, Jae-Hong (pyrasis) Maintainer of tizen port. + lumendes + Updating spine-runtime to EsotericSoftware/spine-runtimes@5f90386. + Retired Core Developers: WenSheng Yang Author of windows port, CCTextField, diff --git a/extensions/Android.mk b/extensions/Android.mk index c0536fffa4..56f68e9dcb 100644 --- a/extensions/Android.mk +++ b/extensions/Android.mk @@ -71,6 +71,8 @@ spine/Skin.cpp \ spine/Slot.cpp \ spine/SlotData.cpp \ spine/extension.cpp \ +spine/CCSkeletonAnimation.cpp \ +spine/CCSkeleton.cpp \ spine/spine-cocos2dx.cpp LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static diff --git a/extensions/proj.linux/Makefile b/extensions/proj.linux/Makefile index 89d9b192ff..08a9816bc1 100644 --- a/extensions/proj.linux/Makefile +++ b/extensions/proj.linux/Makefile @@ -74,7 +74,9 @@ SOURCES = ../CCBReader/CCBFileLoader.cpp \ ../spine/Slot.cpp \ ../spine/SlotData.cpp \ ../spine/extension.cpp \ -../spine/spine-cocos2dx.cpp +../spine/spine-cocos2dx.cpp \ +../spine/CCSkeleton.cpp \ +../spine/CCSkeletonAnimation.cpp include $(COCOS_ROOT)/cocos2dx/proj.linux/cocos2dx.mk diff --git a/extensions/proj.nacl/Makefile b/extensions/proj.nacl/Makefile index 2dbd7d6df9..958eded1a5 100644 --- a/extensions/proj.nacl/Makefile +++ b/extensions/proj.nacl/Makefile @@ -60,6 +60,8 @@ EXTENSIONS_SOURCES = ../CCBReader/CCBFileLoader.cpp \ ../spine/Slot.cpp \ ../spine/SlotData.cpp \ ../spine/extension.cpp \ +../spine/CCSkeleton.cpp \ +../spine/CCSkeletonAnimation.cpp \ ../spine/spine-cocos2dx.cpp all: diff --git a/extensions/proj.win32/libExtensions.vcxproj b/extensions/proj.win32/libExtensions.vcxproj index d09282a53e..b21dca514f 100644 --- a/extensions/proj.win32/libExtensions.vcxproj +++ b/extensions/proj.win32/libExtensions.vcxproj @@ -1,247 +1,251 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {21B2C324-891F-48EA-AD1A-5AE13DE12E28} - Extensions.win32 - Win32Proj - - - - StaticLibrary - Unicode - true - v100 - v110 - v110_xp - - - StaticLibrary - Unicode - v100 - v110 - v110_xp - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)$(Configuration).win32\ - $(Configuration).win32\ - $(SolutionDir)$(Configuration).win32\ - $(Configuration).win32\ - AllRules.ruleset - - - AllRules.ruleset - - - - - $(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\lib;$(LibraryPath) - - - $(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\lib;$(LibraryPath) - - - - Disabled + + + + + Debug + Win32 + + + Release + Win32 + + + + {21B2C324-891F-48EA-AD1A-5AE13DE12E28} + Extensions.win32 + Win32Proj + + + + StaticLibrary + Unicode + true + v100 + v110 + v110_xp + + + StaticLibrary + Unicode + v100 + v110 + v110_xp + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration).win32\ + $(Configuration).win32\ + $(SolutionDir)$(Configuration).win32\ + $(Configuration).win32\ + AllRules.ruleset + + + AllRules.ruleset + + + + + $(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\lib;$(LibraryPath) + + + $(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\lib;$(LibraryPath) + + + + Disabled $(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\include;$(ProjectDir)..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\external\sqlite3\include;$(ProjectDir)..\..\external;$(ProjectDir)..\..\external\libwebsockets\win32\include;$(ProjectDir)..\..\cocos2dx;$(ProjectDir)..\..\cocos2dx\include;$(ProjectDir)..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\zlib;$(ProjectDir)..\..\CocosDenshion\include;..\;%(AdditionalIncludeDirectories) - WIN32;_WINDOWS;_DEBUG;_LIB;COCOS2D_DEBUG=1;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level3 - EditAndContinue - 4267;4251;4244;%(DisableSpecificWarnings) - - - - - MaxSpeed - true + WIN32;_WINDOWS;_DEBUG;_LIB;COCOS2D_DEBUG=1;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + 4267;4251;4244;%(DisableSpecificWarnings) + + + + + MaxSpeed + true $(MSBuildProgramFiles32)\Microsoft SDKs\Windows\v7.1A\include;$(ProjectDir)..\..\external\chipmunk\include\chipmunk;$(ProjectDir)..\..\external\sqlite3\include;$(ProjectDir)..\..\external;$(ProjectDir)..\..\external\libwebsockets\win32\include;$(ProjectDir)..\..\cocos2dx;$(ProjectDir)..\..\cocos2dx\include;$(ProjectDir)..\..\cocos2dx\kazmath\include;$(ProjectDir)..\..\cocos2dx\platform\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\pthread;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\OGLES;$(ProjectDir)..\..\cocos2dx\platform\third_party\win32\zlib;$(ProjectDir)..\..\CocosDenshion\include;..\;%(AdditionalIncludeDirectories) - WIN32;_WINDOWS;NDEBUG;_LIB;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - - Level3 - ProgramDatabase - 4267;4251;4244;%(DisableSpecificWarnings) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + WIN32;_WINDOWS;NDEBUG;_LIB;CC_ENABLE_CHIPMUNK_INTEGRATION=1;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + 4267;4251;4244;%(DisableSpecificWarnings) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extensions/proj.win32/libExtensions.vcxproj.filters b/extensions/proj.win32/libExtensions.vcxproj.filters index 99c9b8c8a2..7e3b728aa7 100644 --- a/extensions/proj.win32/libExtensions.vcxproj.filters +++ b/extensions/proj.win32/libExtensions.vcxproj.filters @@ -1,476 +1,488 @@ - - - - - {d37545ef-285b-4315-9fca-40da6fc2a6c9} - - - {202b519b-b5e0-499f-b3b8-ed5da144b248} - - - {c07abd14-e9dd-4e2d-85c4-a180070161b4} - - - {46797895-f71d-4ddb-b381-d0884e678d39} - - - {d5806151-7ae1-4fef-af5a-2fa1d1c7377b} - - - {4da8061d-80f3-45fd-aa7e-2c0a96701b79} - - - {5d186e3d-0aaf-4904-a5d8-e5cb0f35f4cc} - - - {49487dbe-5758-436a-b014-8e2edc6b33ae} - - - {ff4b5934-99d4-4ea7-9f50-a774192d9ca9} - + + + + + {d37545ef-285b-4315-9fca-40da6fc2a6c9} + + + {202b519b-b5e0-499f-b3b8-ed5da144b248} + + + {c07abd14-e9dd-4e2d-85c4-a180070161b4} + + + {46797895-f71d-4ddb-b381-d0884e678d39} + + + {d5806151-7ae1-4fef-af5a-2fa1d1c7377b} + + + {4da8061d-80f3-45fd-aa7e-2c0a96701b79} + + + {5d186e3d-0aaf-4904-a5d8-e5cb0f35f4cc} + + + {49487dbe-5758-436a-b014-8e2edc6b33ae} + + + {ff4b5934-99d4-4ea7-9f50-a774192d9ca9} + {2a7741ff-87a5-41c8-8e51-d7a1cf0c8e4d} - - - - GUI\CCScrollView - - + + + + GUI\CCScrollView + + network - - - GUI\CCScrollView - - - GUI\CCScrollView - - - GUI\CCScrollView - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - physics_nodes - - - physics_nodes - - - LocalStorage - - - GUI\CCEditBox - - - GUI\CCEditBox - - - GUI\CCEditBox - - - AssetsManager - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - + + + GUI\CCScrollView + + + GUI\CCScrollView + + + GUI\CCScrollView + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + physics_nodes + + + physics_nodes + + + LocalStorage + + + GUI\CCEditBox + + + GUI\CCEditBox + + + GUI\CCEditBox + + + AssetsManager + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + network - - - - GUI\CCScrollView - - - - + + + + GUI\CCScrollView + + + + network - - + + network - - + + network - - - GUI\CCScrollView - - - GUI\CCScrollView - - - GUI\CCScrollView - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - CCBReader - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - GUI\CCControlExtension - - - physics_nodes - - - physics_nodes - - - LocalStorage - - - GUI\CCEditBox - - - GUI\CCEditBox - - - GUI\CCEditBox - - - GUI\CCEditBox - - - AssetsManager - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - - - spine - + + + GUI\CCScrollView + + + GUI\CCScrollView + + + GUI\CCScrollView + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + CCBReader + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + GUI\CCControlExtension + + + physics_nodes + + + physics_nodes + + + LocalStorage + + + GUI\CCEditBox + + + GUI\CCEditBox + + + GUI\CCEditBox + + + GUI\CCEditBox + + + AssetsManager + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + + + spine + network - - \ No newline at end of file + + spine + + + spine + + + diff --git a/extensions/spine/Animation.cpp b/extensions/spine/Animation.cpp index 548ccfee50..2b0c621687 100644 --- a/extensions/spine/Animation.cpp +++ b/extensions/spine/Animation.cpp @@ -42,21 +42,32 @@ void Animation_dispose (Animation* self) { for (i = 0; i < self->timelineCount; ++i) Timeline_dispose(self->timelines[i]); FREE(self->timelines); + FREE(self->name); FREE(self); } void Animation_apply (const Animation* self, Skeleton* skeleton, float time, int/*bool*/loop) { - if (loop && self->duration) time = fmodf(time, self->duration); - int i, n = self->timelineCount; + +#ifdef __STDC_VERSION__ + if (loop && self->duration) time = fmodf(time, self->duration); +#else + if (loop && self->duration) time = (float)fmod(time, self->duration); +#endif + for (i = 0; i < n; ++i) Timeline_apply(self->timelines[i], skeleton, time, 1); } void Animation_mix (const Animation* self, Skeleton* skeleton, float time, int/*bool*/loop, float alpha) { - if (loop && self->duration) time = fmodf(time, self->duration); - int i, n = self->timelineCount; + +#ifdef __STDC_VERSION__ + if (loop && self->duration) time = fmodf(time, self->duration); +#else + if (loop && self->duration) time = (float)fmod(time, self->duration); +#endif + for (i = 0; i < n; ++i) Timeline_apply(self->timelines[i], skeleton, time, alpha); } @@ -68,10 +79,10 @@ typedef struct _TimelineVtable { void (*dispose) (Timeline* self); } _TimelineVtable; -void _Timeline_init (Timeline* self, // - void (*dispose) (Timeline* self), // +void _Timeline_init (Timeline* self, /**/ + void (*dispose) (Timeline* self), /**/ void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha)) { - CONST_CAST(void*, self->vtable) = NEW(_TimelineVtable); + CONST_CAST(_TimelineVtable*, self->vtable) = NEW(_TimelineVtable); VTABLE(Timeline, self) ->dispose = dispose; VTABLE(Timeline, self) ->apply = apply; } @@ -94,8 +105,8 @@ static const float CURVE_LINEAR = 0; static const float CURVE_STEPPED = -1; static const int CURVE_SEGMENTS = 10; -void _CurveTimeline_init (CurveTimeline* self, int frameCount, // - void (*dispose) (Timeline* self), // +void _CurveTimeline_init (CurveTimeline* self, int frameCount, /**/ + void (*dispose) (Timeline* self), /**/ void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha)) { _Timeline_init(SUPER(self), dispose, apply); self->curves = CALLOC(float, (frameCount - 1) * 6); @@ -136,17 +147,24 @@ void CurveTimeline_setCurve (CurveTimeline* self, int frameIndex, float cx1, flo } float CurveTimeline_getCurvePercent (const CurveTimeline* self, int frameIndex, float percent) { + float dfy; + float ddfx; + float ddfy; + float dddfx; + float dddfy; + float x, y; + int i; int curveIndex = frameIndex * 6; float dfx = self->curves[curveIndex]; if (dfx == CURVE_LINEAR) return percent; if (dfx == CURVE_STEPPED) return 0; - float dfy = self->curves[curveIndex + 1]; - float ddfx = self->curves[curveIndex + 2]; - float ddfy = self->curves[curveIndex + 3]; - float dddfx = self->curves[curveIndex + 4]; - float dddfy = self->curves[curveIndex + 5]; - float x = dfx, y = dfy; - int i = CURVE_SEGMENTS - 2; + dfy = self->curves[curveIndex + 1]; + ddfx = self->curves[curveIndex + 2]; + ddfy = self->curves[curveIndex + 3]; + dddfx = self->curves[curveIndex + 4]; + dddfy = self->curves[curveIndex + 5]; + x = dfx, y = dfy; + i = CURVE_SEGMENTS - 2; while (1) { if (x >= percent) { float lastX = x - dfx; @@ -167,10 +185,10 @@ float CurveTimeline_getCurvePercent (const CurveTimeline* self, int frameIndex, /* @param target After the first and before the last entry. */ static int binarySearch (float *values, int valuesLength, float target, int step) { - int low = 0; + int low = 0, current; int high = valuesLength / step - 2; if (high == 0) return step; - int current = high >> 1; + current = high >> 1; while (1) { if (values[(current + 1) * step] <= target) low = current + 1; @@ -201,7 +219,7 @@ void _BaseTimeline_dispose (Timeline* timeline) { } /* Many timelines have structure identical to struct BaseTimeline and extend CurveTimeline. **/ -struct BaseTimeline* _BaseTimeline_create (int frameCount, int frameSize, // +struct BaseTimeline* _BaseTimeline_create (int frameCount, int frameSize, /**/ void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha)) { struct BaseTimeline* self = NEW(struct BaseTimeline); @@ -219,11 +237,15 @@ static const int ROTATE_LAST_FRAME_TIME = -2; static const int ROTATE_FRAME_VALUE = 1; void _RotateTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float time, float alpha) { + Bone *bone; + int frameIndex; + float lastFrameValue, frameTime, percent, amount; + RotateTimeline* self = SUB_CAST(RotateTimeline, timeline); if (time < self->frames[0]) return; /* Time is before first frame. */ - Bone *bone = skeleton->bones[self->boneIndex]; + bone = skeleton->bones[self->boneIndex]; if (time >= self->frames[self->framesLength - 2]) { /* Time is after last frame. */ float amount = bone->data->rotation + self->frames[self->framesLength - 1] - bone->rotation; @@ -236,13 +258,13 @@ void _RotateTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float } /* Interpolate between the last frame and the current frame. */ - int frameIndex = binarySearch(self->frames, self->framesLength, time, 2); - float lastFrameValue = self->frames[frameIndex - 1]; - float frameTime = self->frames[frameIndex]; - float percent = 1 - (time - frameTime) / (self->frames[frameIndex + ROTATE_LAST_FRAME_TIME] - frameTime); + frameIndex = binarySearch(self->frames, self->framesLength, time, 2); + lastFrameValue = self->frames[frameIndex - 1]; + frameTime = self->frames[frameIndex]; + percent = 1 - (time - frameTime) / (self->frames[frameIndex + ROTATE_LAST_FRAME_TIME] - frameTime); percent = CurveTimeline_getCurvePercent(SUPER(self), frameIndex / 2 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent)); - float amount = self->frames[frameIndex + ROTATE_FRAME_VALUE] - lastFrameValue; + amount = self->frames[frameIndex + ROTATE_FRAME_VALUE] - lastFrameValue; while (amount > 180) amount -= 360; while (amount < -180) @@ -272,11 +294,15 @@ static const int TRANSLATE_FRAME_X = 1; static const int TRANSLATE_FRAME_Y = 2; void _TranslateTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float time, float alpha) { + Bone *bone; + int frameIndex; + float lastFrameX, lastFrameY, frameTime, percent; + TranslateTimeline* self = SUB_CAST(TranslateTimeline, timeline); if (time < self->frames[0]) return; /* Time is before first frame. */ - Bone *bone = skeleton->bones[self->boneIndex]; + bone = skeleton->bones[self->boneIndex]; if (time >= self->frames[self->framesLength - 3]) { /* Time is after last frame. */ bone->x += (bone->data->x + self->frames[self->framesLength - 2] - bone->x) * alpha; @@ -285,11 +311,11 @@ void _TranslateTimeline_apply (const Timeline* timeline, Skeleton* skeleton, flo } /* Interpolate between the last frame and the current frame. */ - int frameIndex = binarySearch(self->frames, self->framesLength, time, 3); - float lastFrameX = self->frames[frameIndex - 2]; - float lastFrameY = self->frames[frameIndex - 1]; - float frameTime = self->frames[frameIndex]; - float percent = 1 - (time - frameTime) / (self->frames[frameIndex + TRANSLATE_LAST_FRAME_TIME] - frameTime); + frameIndex = binarySearch(self->frames, self->framesLength, time, 3); + lastFrameX = self->frames[frameIndex - 2]; + lastFrameY = self->frames[frameIndex - 1]; + frameTime = self->frames[frameIndex]; + percent = 1 - (time - frameTime) / (self->frames[frameIndex + TRANSLATE_LAST_FRAME_TIME] - frameTime); percent = CurveTimeline_getCurvePercent(SUPER(self), frameIndex / 3 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent)); bone->x += (bone->data->x + lastFrameX + (self->frames[frameIndex + TRANSLATE_FRAME_X] - lastFrameX) * percent - bone->x) @@ -312,11 +338,15 @@ void TranslateTimeline_setFrame (TranslateTimeline* self, int frameIndex, float /**/ void _ScaleTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float time, float alpha) { - ScaleTimeline* self = SUB_CAST(ScaleTimeline, timeline); + Bone *bone; + int frameIndex; + float lastFrameX, lastFrameY, frameTime, percent; + ScaleTimeline* self = SUB_CAST(ScaleTimeline, timeline); + if (time < self->frames[0]) return; /* Time is before first frame. */ - Bone *bone = skeleton->bones[self->boneIndex]; + bone = skeleton->bones[self->boneIndex]; if (time >= self->frames[self->framesLength - 3]) { /* Time is after last frame. */ bone->scaleX += (bone->data->scaleX - 1 + self->frames[self->framesLength - 2] - bone->scaleX) * alpha; bone->scaleY += (bone->data->scaleY - 1 + self->frames[self->framesLength - 1] - bone->scaleY) * alpha; @@ -324,11 +354,11 @@ void _ScaleTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float t } /* Interpolate between the last frame and the current frame. */ - int frameIndex = binarySearch(self->frames, self->framesLength, time, 3); - float lastFrameX = self->frames[frameIndex - 2]; - float lastFrameY = self->frames[frameIndex - 1]; - float frameTime = self->frames[frameIndex]; - float percent = 1 - (time - frameTime) / (self->frames[frameIndex + TRANSLATE_LAST_FRAME_TIME] - frameTime); + frameIndex = binarySearch(self->frames, self->framesLength, time, 3); + lastFrameX = self->frames[frameIndex - 2]; + lastFrameY = self->frames[frameIndex - 1]; + frameTime = self->frames[frameIndex]; + percent = 1 - (time - frameTime) / (self->frames[frameIndex + TRANSLATE_LAST_FRAME_TIME] - frameTime); percent = CurveTimeline_getCurvePercent(SUPER(self), frameIndex / 3 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent)); bone->scaleX += (bone->data->scaleX - 1 + lastFrameX + (self->frames[frameIndex + TRANSLATE_FRAME_X] - lastFrameX) * percent @@ -354,11 +384,15 @@ static const int COLOR_FRAME_B = 3; static const int COLOR_FRAME_A = 4; void _ColorTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float time, float alpha) { + Slot *slot; + int frameIndex; + float lastFrameR, lastFrameG, lastFrameB, lastFrameA, percent, frameTime; + float r, g, b, a; ColorTimeline* self = (ColorTimeline*)timeline; if (time < self->frames[0]) return; /* Time is before first frame. */ - Slot *slot = skeleton->slots[self->slotIndex]; + slot = skeleton->slots[self->slotIndex]; if (time >= self->frames[self->framesLength - 5]) { /* Time is after last frame. */ int i = self->framesLength - 1; @@ -370,19 +404,19 @@ void _ColorTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float t } /* Interpolate between the last frame and the current frame. */ - int frameIndex = binarySearch(self->frames, self->framesLength, time, 5); - float lastFrameR = self->frames[frameIndex - 4]; - float lastFrameG = self->frames[frameIndex - 3]; - float lastFrameB = self->frames[frameIndex - 2]; - float lastFrameA = self->frames[frameIndex - 1]; - float frameTime = self->frames[frameIndex]; - float percent = 1 - (time - frameTime) / (self->frames[frameIndex + COLOR_LAST_FRAME_TIME] - frameTime); + frameIndex = binarySearch(self->frames, self->framesLength, time, 5); + lastFrameR = self->frames[frameIndex - 4]; + lastFrameG = self->frames[frameIndex - 3]; + lastFrameB = self->frames[frameIndex - 2]; + lastFrameA = self->frames[frameIndex - 1]; + frameTime = self->frames[frameIndex]; + percent = 1 - (time - frameTime) / (self->frames[frameIndex + COLOR_LAST_FRAME_TIME] - frameTime); percent = CurveTimeline_getCurvePercent(SUPER(self), frameIndex / 5 - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent)); - float r = lastFrameR + (self->frames[frameIndex + COLOR_FRAME_R] - lastFrameR) * percent; - float g = lastFrameG + (self->frames[frameIndex + COLOR_FRAME_G] - lastFrameG) * percent; - float b = lastFrameB + (self->frames[frameIndex + COLOR_FRAME_B] - lastFrameB) * percent; - float a = lastFrameA + (self->frames[frameIndex + COLOR_FRAME_A] - lastFrameA) * percent; + r = lastFrameR + (self->frames[frameIndex + COLOR_FRAME_R] - lastFrameR) * percent; + g = lastFrameG + (self->frames[frameIndex + COLOR_FRAME_G] - lastFrameG) * percent; + b = lastFrameB + (self->frames[frameIndex + COLOR_FRAME_B] - lastFrameB) * percent; + a = lastFrameA + (self->frames[frameIndex + COLOR_FRAME_A] - lastFrameA) * percent; if (alpha < 1) { slot->r += (r - slot->r) * alpha; slot->g += (g - slot->g) * alpha; @@ -412,30 +446,33 @@ void ColorTimeline_setFrame (ColorTimeline* self, int frameIndex, float time, fl /**/ void _AttachmentTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float time, float alpha) { + int frameIndex; + const char* attachmentName; AttachmentTimeline* self = (AttachmentTimeline*)timeline; if (time < self->frames[0]) return; /* Time is before first frame. */ - int frameIndex; if (time >= self->frames[self->framesLength - 1]) /* Time is after last frame. */ frameIndex = self->framesLength - 1; else frameIndex = binarySearch(self->frames, self->framesLength, time, 1) - 1; - const char* attachmentName = self->attachmentNames[frameIndex]; + attachmentName = self->attachmentNames[frameIndex]; Slot_setAttachment(skeleton->slots[self->slotIndex], attachmentName ? Skeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0); } void _AttachmentTimeline_dispose (Timeline* timeline) { - _Timeline_deinit(timeline); - AttachmentTimeline* self = (AttachmentTimeline*)timeline; - + AttachmentTimeline* self; int i; + + _Timeline_deinit(timeline); + self = (AttachmentTimeline*)timeline; + for (i = 0; i < self->framesLength; ++i) FREE(self->attachmentNames[i]); FREE(self->attachmentNames); - + FREE(self->frames); FREE(self); } @@ -459,4 +496,4 @@ void AttachmentTimeline_setFrame (AttachmentTimeline* self, int frameIndex, floa self->attachmentNames[frameIndex] = 0; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/AnimationState.cpp b/extensions/spine/AnimationState.cpp index 4cf7307d36..be2bde367d 100644 --- a/extensions/spine/AnimationState.cpp +++ b/extensions/spine/AnimationState.cpp @@ -25,9 +25,18 @@ #include #include +#include namespace cocos2d { namespace extension { +typedef struct _Entry _Entry; +struct _Entry { + Animation* animation; + int/*bool*/loop; + float delay; + _Entry* next; +}; + typedef struct { AnimationState super; Animation *previous; @@ -35,6 +44,7 @@ typedef struct { int/*bool*/previousLoop; float mixTime; float mixDuration; + _Entry* queue; } _Internal; AnimationState* AnimationState_create (AnimationStateData* data) { @@ -43,37 +53,57 @@ AnimationState* AnimationState_create (AnimationStateData* data) { return self; } +void _AnimationState_clearQueue (AnimationState* self) { + _Internal* internal = SUB_CAST(_Internal, self); + _Entry* entry = internal->queue; + while (entry) { + _Entry* nextEntry = entry->next; + FREE(entry); + entry = nextEntry; + } + internal->queue = 0; +} + void AnimationState_dispose (AnimationState* self) { + _AnimationState_clearQueue(self); FREE(self); } -void AnimationState_update (AnimationState* self, float delta) { - self->time += delta; - SUB_CAST(_Internal, self) ->previousTime += delta; - SUB_CAST(_Internal, self) ->mixTime += delta; -} +void AnimationState_addAnimation (AnimationState* self, Animation* animation, int/*bool*/loop, float delay) { + _Entry* existingEntry; + Animation* previousAnimation; -void AnimationState_apply (AnimationState* self, Skeleton* skeleton) { - if (!self->animation) return; _Internal* internal = SUB_CAST(_Internal, self); - if (internal->previous) { - Animation_apply(internal->previous, skeleton, internal->previousTime, internal->previousLoop); - float alpha = internal->mixTime / internal->mixDuration; - if (alpha >= 1) { - alpha = 1; - internal->previous = 0; - } - Animation_mix(self->animation, skeleton, self->time, self->loop, alpha); - } else - Animation_apply(self->animation, skeleton, self->time, self->loop); + _Entry* entry = NEW(_Entry); + entry->animation = animation; + entry->loop = loop; + + existingEntry = internal->queue; + if (existingEntry) { + while (existingEntry->next) + existingEntry = existingEntry->next; + existingEntry->next = entry; + previousAnimation = existingEntry->animation; + } else { + internal->queue = entry; + previousAnimation = self->animation; + } + + if (delay <= 0) { + if (previousAnimation) + delay = previousAnimation->duration - AnimationStateData_getMix(self->data, previousAnimation, animation) + delay; + else + delay = 0; + } + entry->delay = delay; } -void AnimationState_setAnimationByName (AnimationState* self, const char* animationName, int/**/loop) { - Animation* animation = SkeletonData_findAnimation(self->data->skeletonData, animationName); - AnimationState_setAnimation(self, animation, loop); +void AnimationState_addAnimationByName (AnimationState* self, const char* animationName, int/*bool*/loop, float delay) { + Animation* animation = animationName ? SkeletonData_findAnimation(self->data->skeletonData, animationName) : 0; + AnimationState_addAnimation(self, animation, loop, delay); } -void AnimationState_setAnimation (AnimationState* self, Animation* newAnimation, int/**/loop) { +void _AnimationState_setAnimation (AnimationState* self, Animation* newAnimation, int/*bool*/loop) { _Internal* internal = SUB_CAST(_Internal, self); internal->previous = 0; if (newAnimation && self->animation && self->data) { @@ -90,13 +120,59 @@ void AnimationState_setAnimation (AnimationState* self, Animation* newAnimation, self->time = 0; } +void AnimationState_setAnimation (AnimationState* self, Animation* newAnimation, int/*bool*/loop) { + _AnimationState_clearQueue(self); + _AnimationState_setAnimation(self, newAnimation, loop); +} + +void AnimationState_setAnimationByName (AnimationState* self, const char* animationName, int/*bool*/loop) { + Animation* animation = animationName ? SkeletonData_findAnimation(self->data->skeletonData, animationName) : 0; + AnimationState_setAnimation(self, animation, loop); +} + void AnimationState_clearAnimation (AnimationState* self) { - SUB_CAST(_Internal, self) ->previous = 0; + _Internal* internal = SUB_CAST(_Internal, self); + internal->previous = 0; CONST_CAST(Animation*, self->animation) = 0; + _AnimationState_clearQueue(self); +} + +void AnimationState_update (AnimationState* self, float delta) { + _Entry* next; + _Internal* internal = SUB_CAST(_Internal, self); + + self->time += delta; + internal->previousTime += delta; + internal->mixTime += delta; + + if (internal->queue && self->time >= internal->queue->delay) { + _AnimationState_setAnimation(self, internal->queue->animation, internal->queue->loop); + next = internal->queue->next; + FREE(internal->queue); + internal->queue = next; + } +} + +void AnimationState_apply (AnimationState* self, Skeleton* skeleton) { + _Internal* internal; + float alpha; + + if (!self->animation) return; + internal = SUB_CAST(_Internal, self); + if (internal->previous) { + Animation_apply(internal->previous, skeleton, internal->previousTime, internal->previousLoop); + alpha = internal->mixTime / internal->mixDuration; + if (alpha >= 1) { + alpha = 1; + internal->previous = 0; + } + Animation_mix(self->animation, skeleton, self->time, self->loop, alpha); + } else + Animation_apply(self->animation, skeleton, self->time, self->loop); } int/*bool*/AnimationState_isComplete (AnimationState* self) { return !self->animation || self->time >= self->animation->duration; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/AnimationState.h b/extensions/spine/AnimationState.h index 97e511adc2..5362281660 100644 --- a/extensions/spine/AnimationState.h +++ b/extensions/spine/AnimationState.h @@ -46,9 +46,17 @@ void AnimationState_update (AnimationState* self, float delta); void AnimationState_apply (AnimationState* self, struct Skeleton* skeleton); /* @param animationName May be 0. */ -void AnimationState_setAnimationByName (AnimationState* self, const char* animationName, int/**/loop); +void AnimationState_setAnimationByName (AnimationState* self, const char* animationName, int/*bool*/loop); /* @param animation May be 0. */ -void AnimationState_setAnimation (AnimationState* self, Animation* animation, int/**/loop); +void AnimationState_setAnimation (AnimationState* self, Animation* animation, int/*bool*/loop); + +/** @param animationName May be 0. + * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ +void AnimationState_addAnimationByName (AnimationState* self, const char* animationName, int/*bool*/loop, float delay); +/** @param animation May be 0. + * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */ +void AnimationState_addAnimation (AnimationState* self, Animation* animation, int/*bool*/loop, float delay); + void AnimationState_clearAnimation (AnimationState* self); int/*bool*/AnimationState_isComplete (AnimationState* self); diff --git a/extensions/spine/AnimationStateData.cpp b/extensions/spine/AnimationStateData.cpp index abc398b1ea..1c9bf8ed1a 100644 --- a/extensions/spine/AnimationStateData.cpp +++ b/extensions/spine/AnimationStateData.cpp @@ -74,37 +74,43 @@ AnimationStateData* AnimationStateData_create (SkeletonData* skeletonData) { } void AnimationStateData_dispose (AnimationStateData* self) { + _ToEntry* toEntry; + _ToEntry* nextToEntry; + _FromEntry* nextFromEntry; + _FromEntry* fromEntry = (_FromEntry*)self->entries; while (fromEntry) { - _ToEntry* toEntry = fromEntry->toEntries; + toEntry = fromEntry->toEntries; while (toEntry) { - _ToEntry* next = toEntry->next; + nextToEntry = toEntry->next; _ToEntry_dispose(toEntry); - toEntry = next; + toEntry = nextToEntry; } - _FromEntry* next = fromEntry->next; + nextFromEntry = fromEntry->next; _FromEntry_dispose(fromEntry); - fromEntry = next; + fromEntry = nextFromEntry; } FREE(self); } void AnimationStateData_setMixByName (AnimationStateData* self, const char* fromName, const char* toName, float duration) { + Animation* to; Animation* from = SkeletonData_findAnimation(self->skeletonData, fromName); if (!from) return; - Animation* to = SkeletonData_findAnimation(self->skeletonData, toName); + to = SkeletonData_findAnimation(self->skeletonData, toName); if (!to) return; AnimationStateData_setMix(self, from, to, duration); } void AnimationStateData_setMix (AnimationStateData* self, Animation* from, Animation* to, float duration) { /* Find existing FromEntry. */ + _ToEntry* toEntry; _FromEntry* fromEntry = (_FromEntry*)self->entries; while (fromEntry) { if (fromEntry->animation == from) { /* Find existing ToEntry. */ - _ToEntry* toEntry = fromEntry->toEntries; + toEntry = fromEntry->toEntries; while (toEntry) { if (toEntry->animation == to) { toEntry->duration = duration; @@ -119,9 +125,9 @@ void AnimationStateData_setMix (AnimationStateData* self, Animation* from, Anima if (!fromEntry) { fromEntry = _FromEntry_create(from); fromEntry->next = (_FromEntry*)self->entries; - CONST_CAST(void*, self->entries) = fromEntry; + CONST_CAST(_FromEntry*, self->entries) = fromEntry; } - _ToEntry* toEntry = _ToEntry_create(to, duration); + toEntry = _ToEntry_create(to, duration); toEntry->next = fromEntry->toEntries; fromEntry->toEntries = toEntry; } @@ -141,4 +147,4 @@ float AnimationStateData_getMix (AnimationStateData* self, Animation* from, Anim return 0; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/Atlas.cpp b/extensions/spine/Atlas.cpp index 33ac844d60..7f04c26550 100644 --- a/extensions/spine/Atlas.cpp +++ b/extensions/spine/Atlas.cpp @@ -36,8 +36,9 @@ AtlasPage* AtlasPage_create (const char* name) { } void AtlasPage_dispose (AtlasPage* self) { - FREE(self->name); _AtlasPage_disposeTexture(self); + FREE(self->name); + FREE(self); } /**/ @@ -55,14 +56,9 @@ void AtlasRegion_dispose (AtlasRegion* self) { /**/ -typedef struct _struct_Str { +typedef struct { const char* begin; const char* end; - - _struct_Str() - : begin(NULL) - , end(NULL) { - } } Str; static void trim (Str* str) { @@ -119,10 +115,11 @@ static int readValue (const char* end, Str* str) { /* Returns the number of tuple values read (2, 4, or 0 for failure). */ static int readTuple (const char* end, Str tuple[]) { + int i; Str str; readLine(0, end, &str); if (!beginPast(&str, ':')) return 0; - int i = 0; + for (i = 0; i < 3; ++i) { tuple[i].begin = str.begin; if (!beginPast(&str, ',')) { @@ -172,6 +169,7 @@ static const char* textureFilterNames[] = {"Nearest", "Linear", "MipMap", "MipMa "MipMapNearestLinear", "MipMapLinearLinear"}; Atlas* Atlas_readAtlas (const char* begin, int length, const char* dir) { + int count; const char* end = begin + length; int dirLength = strlen(dir); int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\'; @@ -241,10 +239,14 @@ Atlas* Atlas_readAtlas (const char* begin, int length, const char* dir) { region->u = region->x / (float)page->width; region->v = region->y / (float)page->height; - region->u2 = (region->x + region->width) / (float)page->width; - region->v2 = (region->y + region->height) / (float)page->height; + if (region->rotate) { + region->u2 = (region->x + region->height) / (float)page->width; + region->v2 = (region->y + region->width) / (float)page->height; + } else { + region->u2 = (region->x + region->width) / (float)page->width; + region->v2 = (region->y + region->height) / (float)page->height; + } - int count; if (!(count = readTuple(end, tuple))) return abortAtlas(self); if (count == 4) { /* split is optional */ region->splits = MALLOC(int, 4); @@ -269,8 +271,8 @@ Atlas* Atlas_readAtlas (const char* begin, int length, const char* dir) { region->originalHeight = toInt(tuple + 1); readTuple(end, tuple); - region->offsetX = (float)toInt(tuple); - region->offsetY = (float)toInt(tuple + 1); + region->offsetX = toInt(tuple); + region->offsetY = toInt(tuple + 1); if (!readValue(end, &str)) return abortAtlas(self); region->index = toInt(&str); @@ -281,6 +283,11 @@ Atlas* Atlas_readAtlas (const char* begin, int length, const char* dir) { } Atlas* Atlas_readAtlasFile (const char* path) { + int dirLength; + char *dir; + int length; + const char* data; + Atlas* atlas = 0; /* Get directory from atlas path. */ @@ -288,13 +295,12 @@ Atlas* Atlas_readAtlasFile (const char* path) { const char* lastBackwardSlash = strrchr(path, '\\'); const char* lastSlash = lastForwardSlash > lastBackwardSlash ? lastForwardSlash : lastBackwardSlash; if (lastSlash == path) lastSlash++; /* Never drop starting slash. */ - int dirLength = lastSlash ? lastSlash - path : 0; - char* dir = MALLOC(char, dirLength + 1); + dirLength = lastSlash ? lastSlash - path : 0; + dir = MALLOC(char, dirLength + 1); memcpy(dir, path, dirLength); dir[dirLength] = '\0'; - int length; - const char* data = _Util_readFile(path, &length); + data = _Util_readFile(path, &length); if (data) atlas = Atlas_readAtlas(data, length, dir); FREE(data); @@ -303,6 +309,7 @@ Atlas* Atlas_readAtlasFile (const char* path) { } void Atlas_dispose (Atlas* self) { + AtlasRegion* region, *nextRegion; AtlasPage* page = self->pages; while (page) { AtlasPage* nextPage = page->next; @@ -310,9 +317,9 @@ void Atlas_dispose (Atlas* self) { page = nextPage; } - AtlasRegion* region = self->regions; + region = self->regions; while (region) { - AtlasRegion* nextRegion = region->next; + nextRegion = region->next; AtlasRegion_dispose(region); region = nextRegion; } @@ -329,4 +336,4 @@ AtlasRegion* Atlas_findRegion (const Atlas* self, const char* name) { return 0; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/Atlas.h b/extensions/spine/Atlas.h index a7aa3e39cf..ea5ca9b781 100644 --- a/extensions/spine/Atlas.h +++ b/extensions/spine/Atlas.h @@ -53,7 +53,7 @@ struct AtlasPage { AtlasFilter minFilter, magFilter; AtlasWrap uWrap, vWrap; - void* texture; + void* rendererObject; int width, height; AtlasPage* next; @@ -69,7 +69,7 @@ struct AtlasRegion { const char* name; int x, y, width, height; float u, v, u2, v2; - float offsetX, offsetY; + int offsetX, offsetY; int originalWidth, originalHeight; int index; int/*bool*/rotate; diff --git a/extensions/spine/AtlasAttachmentLoader.cpp b/extensions/spine/AtlasAttachmentLoader.cpp index c0f613a6ef..ce064df6eb 100644 --- a/extensions/spine/AtlasAttachmentLoader.cpp +++ b/extensions/spine/AtlasAttachmentLoader.cpp @@ -32,13 +32,21 @@ Attachment* _AtlasAttachmentLoader_newAttachment (AttachmentLoader* loader, Skin AtlasAttachmentLoader* self = SUB_CAST(AtlasAttachmentLoader, loader); switch (type) { case ATTACHMENT_REGION: { + RegionAttachment* attachment; AtlasRegion* region = Atlas_findRegion(self->atlas, name); if (!region) { _AttachmentLoader_setError(loader, "Region not found: ", name); return 0; } - RegionAttachment* attachment = RegionAttachment_create(name); - attachment->region = region; + attachment = RegionAttachment_create(name); + attachment->rendererObject = region; + RegionAttachment_setUVs(attachment, region->u, region->v, region->u2, region->v2, region->rotate); + attachment->regionOffsetX = region->offsetX; + attachment->regionOffsetY = region->offsetY; + attachment->regionWidth = region->width; + attachment->regionHeight = region->height; + attachment->regionOriginalWidth = region->originalWidth; + attachment->regionOriginalHeight = region->originalHeight; return SUPER(attachment); } default: @@ -54,4 +62,4 @@ AtlasAttachmentLoader* AtlasAttachmentLoader_create (Atlas* atlas) { return self; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/Attachment.cpp b/extensions/spine/Attachment.cpp index 1f1ba913a9..9e96370e2d 100644 --- a/extensions/spine/Attachment.cpp +++ b/extensions/spine/Attachment.cpp @@ -33,10 +33,10 @@ typedef struct _AttachmentVtable { void (*dispose) (Attachment* self); } _AttachmentVtable; -void _Attachment_init (Attachment* self, const char* name, AttachmentType type, // +void _Attachment_init (Attachment* self, const char* name, AttachmentType type, /**/ void (*dispose) (Attachment* self)) { - CONST_CAST(void*, self->vtable) = NEW(_AttachmentVtable); + CONST_CAST(_AttachmentVtable*, self->vtable) = NEW(_AttachmentVtable); VTABLE(Attachment, self) ->dispose = dispose; MALLOC_STR(self->name, name); @@ -50,6 +50,7 @@ void _Attachment_deinit (Attachment* self) { void Attachment_dispose (Attachment* self) { VTABLE(Attachment, self) ->dispose(self); + FREE(self); } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/AttachmentLoader.cpp b/extensions/spine/AttachmentLoader.cpp index b6e401d23a..00e5502116 100644 --- a/extensions/spine/AttachmentLoader.cpp +++ b/extensions/spine/AttachmentLoader.cpp @@ -34,10 +34,10 @@ typedef struct _AttachmentLoaderVtable { void (*dispose) (AttachmentLoader* self); } _AttachmentLoaderVtable; -void _AttachmentLoader_init (AttachmentLoader* self, // - void (*dispose) (AttachmentLoader* self), // +void _AttachmentLoader_init (AttachmentLoader* self, /**/ + void (*dispose) (AttachmentLoader* self), /**/ Attachment* (*newAttachment) (AttachmentLoader* self, Skin* skin, AttachmentType type, const char* name)) { - CONST_CAST(void*, self->vtable) = NEW(_AttachmentLoaderVtable); + CONST_CAST(_AttachmentLoaderVtable*, self->vtable) = NEW(_AttachmentLoaderVtable); VTABLE(AttachmentLoader, self) ->dispose = dispose; VTABLE(AttachmentLoader, self) ->newAttachment = newAttachment; } @@ -50,6 +50,7 @@ void _AttachmentLoader_deinit (AttachmentLoader* self) { void AttachmentLoader_dispose (AttachmentLoader* self) { VTABLE(AttachmentLoader, self) ->dispose(self); + FREE(self); } Attachment* AttachmentLoader_newAttachment (AttachmentLoader* self, Skin* skin, AttachmentType type, const char* name) { @@ -73,4 +74,4 @@ void _AttachmentLoader_setUnknownTypeError (AttachmentLoader* self, AttachmentTy _AttachmentLoader_setError(self, "Unknown attachment type: ", buffer); } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/AttachmentLoader.h b/extensions/spine/AttachmentLoader.h index 8d6e202960..5fd81f5eb8 100644 --- a/extensions/spine/AttachmentLoader.h +++ b/extensions/spine/AttachmentLoader.h @@ -37,6 +37,9 @@ struct AttachmentLoader { const char* error2; const void* const vtable; +#ifdef __cplusplus + AttachmentLoader () : error1(0), error2(0), vtable(0) {} +#endif }; void AttachmentLoader_dispose (AttachmentLoader* self); diff --git a/extensions/spine/Bone.cpp b/extensions/spine/Bone.cpp index 2d0c85fa79..17030f6405 100644 --- a/extensions/spine/Bone.cpp +++ b/extensions/spine/Bone.cpp @@ -39,7 +39,7 @@ Bone* Bone_create (BoneData* data, Bone* parent) { Bone* self = NEW(Bone); CONST_CAST(BoneData*, self->data) = data; CONST_CAST(Bone*, self->parent) = parent; - Bone_setToBindPose(self); + Bone_setToSetupPose(self); return self; } @@ -47,7 +47,7 @@ void Bone_dispose (Bone* self) { FREE(self); } -void Bone_setToBindPose (Bone* self) { +void Bone_setToSetupPose (Bone* self) { self->x = self->data->x; self->y = self->data->y; self->rotation = self->data->rotation; @@ -56,6 +56,7 @@ void Bone_setToBindPose (Bone* self) { } void Bone_updateWorldTransform (Bone* self, int flipX, int flipY) { + float radians, cosine, sine; if (self->parent) { CONST_CAST(float, self->worldX) = self->x * self->parent->m00 + self->y * self->parent->m01 + self->parent->worldX; CONST_CAST(float, self->worldY) = self->x * self->parent->m10 + self->y * self->parent->m11 + self->parent->worldY; @@ -63,15 +64,20 @@ void Bone_updateWorldTransform (Bone* self, int flipX, int flipY) { CONST_CAST(float, self->worldScaleY) = self->parent->worldScaleY * self->scaleY; CONST_CAST(float, self->worldRotation) = self->parent->worldRotation + self->rotation; } else { - CONST_CAST(float, self->worldX) = self->x; - CONST_CAST(float, self->worldY) = self->y; + CONST_CAST(float, self->worldX) = flipX ? -self->x : self->x; + CONST_CAST(float, self->worldY) = flipX ? -self->y : self->y; CONST_CAST(float, self->worldScaleX) = self->scaleX; CONST_CAST(float, self->worldScaleY) = self->scaleY; CONST_CAST(float, self->worldRotation) = self->rotation; } - float radians = (float)(self->worldRotation * 3.1415926535897932385 / 180); - float cosine = cosf(radians); - float sine = sinf(radians); + radians = (float)(self->worldRotation * 3.1415926535897932385 / 180); +#ifdef __STDC_VERSION__ + cosine = cosf(radians); + sine = sinf(radians); +#else + cosine = (float)cos(radians); + sine = (float)sin(radians); +#endif CONST_CAST(float, self->m00) = cosine * self->worldScaleX; CONST_CAST(float, self->m10) = sine * self->worldScaleX; CONST_CAST(float, self->m01) = -sine * self->worldScaleY; @@ -90,4 +96,4 @@ void Bone_updateWorldTransform (Bone* self, int flipX, int flipY) { } } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/Bone.h b/extensions/spine/Bone.h index 6471bfc7d9..3f4688a728 100644 --- a/extensions/spine/Bone.h +++ b/extensions/spine/Bone.h @@ -50,7 +50,7 @@ void Bone_setYDown (int/*bool*/yDown); Bone* Bone_create (BoneData* data, Bone* parent); void Bone_dispose (Bone* self); -void Bone_setToBindPose (Bone* self); +void Bone_setToSetupPose (Bone* self); void Bone_updateWorldTransform (Bone* self, int/*bool*/flipX, int/*bool*/flipY); diff --git a/extensions/spine/BoneData.cpp b/extensions/spine/BoneData.cpp index d41e32e2d0..09c356bb3d 100644 --- a/extensions/spine/BoneData.cpp +++ b/extensions/spine/BoneData.cpp @@ -42,4 +42,4 @@ void BoneData_dispose (BoneData* self) { FREE(self); } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/CCSkeleton.cpp b/extensions/spine/CCSkeleton.cpp new file mode 100644 index 0000000000..844ee49454 --- /dev/null +++ b/extensions/spine/CCSkeleton.cpp @@ -0,0 +1,290 @@ +/******************************************************************************* + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include + +USING_NS_CC; +using std::min; +using std::max; + +namespace cocos2d { namespace extension { + +CCSkeleton* CCSkeleton::createWithData (SkeletonData* skeletonData, bool ownsSkeletonData) { + CCSkeleton* node = new CCSkeleton(skeletonData, ownsSkeletonData); + node->autorelease(); + return node; +} + +CCSkeleton* CCSkeleton::createWithFile (const char* skeletonDataFile, Atlas* atlas, float scale) { + CCSkeleton* node = new CCSkeleton(skeletonDataFile, atlas, scale); + node->autorelease(); + return node; +} + +CCSkeleton* CCSkeleton::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) { + CCSkeleton* node = new CCSkeleton(skeletonDataFile, atlasFile, scale); + node->autorelease(); + return node; +} + +void CCSkeleton::initialize () { + atlas = 0; + debugSlots = false; + debugBones = false; + timeScale = 1; + + blendFunc.src = GL_ONE; + blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; + setOpacityModifyRGB(true); + + setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor)); + scheduleUpdate(); +} + +void CCSkeleton::setSkeletonData (SkeletonData *skeletonData, bool ownsSkeletonData) { + skeleton = Skeleton_create(skeletonData); + rootBone = skeleton->bones[0]; + this->ownsSkeletonData = ownsSkeletonData; +} + +CCSkeleton::CCSkeleton () { + initialize(); +} + +CCSkeleton::CCSkeleton (SkeletonData *skeletonData, bool ownsSkeletonData) { + initialize(); + + setSkeletonData(skeletonData, ownsSkeletonData); +} + +CCSkeleton::CCSkeleton (const char* skeletonDataFile, Atlas* atlas, float scale) { + initialize(); + + SkeletonJson* json = SkeletonJson_create(atlas); + json->scale = scale; + SkeletonData* skeletonData = SkeletonJson_readSkeletonDataFile(json, skeletonDataFile); + CCAssert(skeletonData, json->error ? json->error : "Error reading skeleton data."); + SkeletonJson_dispose(json); + + setSkeletonData(skeletonData, true); +} + +CCSkeleton::CCSkeleton (const char* skeletonDataFile, const char* atlasFile, float scale) { + initialize(); + + atlas = Atlas_readAtlasFile(atlasFile); + CCAssert(atlas, "Error reading atlas file."); + + SkeletonJson* json = SkeletonJson_create(atlas); + json->scale = scale; + SkeletonData* skeletonData = SkeletonJson_readSkeletonDataFile(json, skeletonDataFile); + CCAssert(skeletonData, json->error ? json->error : "Error reading skeleton data file."); + SkeletonJson_dispose(json); + + setSkeletonData(skeletonData, true); +} + +CCSkeleton::~CCSkeleton () { + if (ownsSkeletonData) SkeletonData_dispose(skeleton->data); + if (atlas) Atlas_dispose(atlas); + Skeleton_dispose(skeleton); +} + +void CCSkeleton::update (float deltaTime) { + Skeleton_update(skeleton, deltaTime * timeScale); +} + +void CCSkeleton::draw () { + CC_NODE_DRAW_SETUP(); + + ccGLBlendFunc(blendFunc.src, blendFunc.dst); + ccColor3B color = getColor(); + skeleton->r = color.r / (float)255; + skeleton->g = color.g / (float)255; + skeleton->b = color.b / (float)255; + skeleton->a = getOpacity() / (float)255; + if (premultipliedAlpha) { + skeleton->r *= skeleton->a; + skeleton->g *= skeleton->a; + skeleton->b *= skeleton->a; + } + + CCTextureAtlas* textureAtlas = 0; + ccV3F_C4B_T2F_Quad quad; + quad.tl.vertices.z = 0; + quad.tr.vertices.z = 0; + quad.bl.vertices.z = 0; + quad.br.vertices.z = 0; + for (int i = 0, n = skeleton->slotCount; i < n; i++) { + Slot* slot = skeleton->slots[i]; + if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue; + RegionAttachment* attachment = (RegionAttachment*)slot->attachment; + CCTextureAtlas* regionTextureAtlas = getTextureAtlas(attachment); + if (regionTextureAtlas != textureAtlas) { + if (textureAtlas) { + textureAtlas->drawQuads(); + textureAtlas->removeAllQuads(); + } + } + textureAtlas = regionTextureAtlas; + if (textureAtlas->getCapacity() == textureAtlas->getTotalQuads() && + !textureAtlas->resizeCapacity(textureAtlas->getCapacity() * 2)) return; + RegionAttachment_updateQuad(attachment, slot, &quad, premultipliedAlpha); + textureAtlas->updateQuad(&quad, textureAtlas->getTotalQuads()); + } + if (textureAtlas) { + textureAtlas->drawQuads(); + textureAtlas->removeAllQuads(); + } + + if (debugSlots) { + // Slots. + ccDrawColor4B(0, 0, 255, 255); + glLineWidth(1); + CCPoint points[4]; + ccV3F_C4B_T2F_Quad quad; + for (int i = 0, n = skeleton->slotCount; i < n; i++) { + Slot* slot = skeleton->slots[i]; + if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue; + RegionAttachment* attachment = (RegionAttachment*)slot->attachment; + RegionAttachment_updateQuad(attachment, slot, &quad); + points[0] = ccp(quad.bl.vertices.x, quad.bl.vertices.y); + points[1] = ccp(quad.br.vertices.x, quad.br.vertices.y); + points[2] = ccp(quad.tr.vertices.x, quad.tr.vertices.y); + points[3] = ccp(quad.tl.vertices.x, quad.tl.vertices.y); + ccDrawPoly(points, 4, true); + } + } + if (debugBones) { + // Bone lengths. + glLineWidth(2); + ccDrawColor4B(255, 0, 0, 255); + for (int i = 0, n = skeleton->boneCount; i < n; i++) { + Bone *bone = skeleton->bones[i]; + float x = bone->data->length * bone->m00 + bone->worldX; + float y = bone->data->length * bone->m10 + bone->worldY; + ccDrawLine(ccp(bone->worldX, bone->worldY), ccp(x, y)); + } + // Bone origins. + ccPointSize(4); + ccDrawColor4B(0, 0, 255, 255); // Root bone is blue. + for (int i = 0, n = skeleton->boneCount; i < n; i++) { + Bone *bone = skeleton->bones[i]; + ccDrawPoint(ccp(bone->worldX, bone->worldY)); + if (i == 0) ccDrawColor4B(0, 255, 0, 255); + } + } +} + +CCTextureAtlas* CCSkeleton::getTextureAtlas (RegionAttachment* regionAttachment) const { + return (CCTextureAtlas*)((AtlasRegion*)regionAttachment->rendererObject)->page->rendererObject; +} + +CCRect CCSkeleton::boundingBox () { + float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN; + float scaleX = getScaleX(); + float scaleY = getScaleY(); + float vertices[8]; + for (int i = 0; i < skeleton->slotCount; ++i) { + Slot* slot = skeleton->slots[i]; + if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue; + RegionAttachment* attachment = (RegionAttachment*)slot->attachment; + RegionAttachment_computeVertices(attachment, slot->skeleton->x, slot->skeleton->y, slot->bone, vertices); + minX = min(minX, vertices[VERTEX_X1] * scaleX); + minY = min(minY, vertices[VERTEX_Y1] * scaleY); + maxX = max(maxX, vertices[VERTEX_X1] * scaleX); + maxY = max(maxY, vertices[VERTEX_Y1] * scaleY); + minX = min(minX, vertices[VERTEX_X4] * scaleX); + minY = min(minY, vertices[VERTEX_Y4] * scaleY); + maxX = max(maxX, vertices[VERTEX_X4] * scaleX); + maxY = max(maxY, vertices[VERTEX_Y4] * scaleY); + minX = min(minX, vertices[VERTEX_X2] * scaleX); + minY = min(minY, vertices[VERTEX_Y2] * scaleY); + maxX = max(maxX, vertices[VERTEX_X2] * scaleX); + maxY = max(maxY, vertices[VERTEX_Y2] * scaleY); + minX = min(minX, vertices[VERTEX_X3] * scaleX); + minY = min(minY, vertices[VERTEX_Y3] * scaleY); + maxX = max(maxX, vertices[VERTEX_X3] * scaleX); + maxY = max(maxY, vertices[VERTEX_Y3] * scaleY); + } + CCPoint position = getPosition(); + return CCRectMake(position.x + minX, position.y + minY, maxX - minX, maxY - minY); +} + +// --- Convenience methods for Skeleton_* functions. + +void CCSkeleton::updateWorldTransform () { + Skeleton_updateWorldTransform(skeleton); +} + +void CCSkeleton::setToSetupPose () { + Skeleton_setToSetupPose(skeleton); +} +void CCSkeleton::setBonesToSetupPose () { + Skeleton_setBonesToSetupPose(skeleton); +} +void CCSkeleton::setSlotsToSetupPose () { + Skeleton_setSlotsToSetupPose(skeleton); +} + +Bone* CCSkeleton::findBone (const char* boneName) const { + return Skeleton_findBone(skeleton, boneName); +} + +Slot* CCSkeleton::findSlot (const char* slotName) const { + return Skeleton_findSlot(skeleton, slotName); +} + +bool CCSkeleton::setSkin (const char* skinName) { + return Skeleton_setSkinByName(skeleton, skinName) ? true : false; +} + +Attachment* CCSkeleton::getAttachment (const char* slotName, const char* attachmentName) const { + return Skeleton_getAttachmentForSlotName(skeleton, slotName, attachmentName); +} +bool CCSkeleton::setAttachment (const char* slotName, const char* attachmentName) { + return Skeleton_setAttachment(skeleton, slotName, attachmentName) ? true : false; +} + +// --- CCBlendProtocol + +ccBlendFunc CCSkeleton::getBlendFunc () { + return blendFunc; +} + +void CCSkeleton::setBlendFunc (ccBlendFunc blendFunc) { + this->blendFunc = blendFunc; +} + +void CCSkeleton::setOpacityModifyRGB (bool value) { + premultipliedAlpha = value; +} + +bool CCSkeleton::isOpacityModifyRGB () { + return premultipliedAlpha; +} + +}} // namespace cocos2d { namespace extension { diff --git a/extensions/spine/CCSkeleton.h b/extensions/spine/CCSkeleton.h new file mode 100644 index 0000000000..12bc66664f --- /dev/null +++ b/extensions/spine/CCSkeleton.h @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#ifndef SPINE_CCSKELETON_H_ +#define SPINE_CCSKELETON_H_ + +#include +#include "cocos2d.h" + +namespace cocos2d { namespace extension { + +/** +Draws a skeleton. +*/ +class CCSkeleton: public cocos2d::CCNodeRGBA, public cocos2d::CCBlendProtocol { +public: + Skeleton* skeleton; + Bone* rootBone; + float timeScale; + bool debugSlots; + bool debugBones; + bool premultipliedAlpha; + + static CCSkeleton* createWithData (SkeletonData* skeletonData, bool ownsSkeletonData = false); + static CCSkeleton* createWithFile (const char* skeletonDataFile, Atlas* atlas, float scale = 1); + static CCSkeleton* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 1); + + CCSkeleton (SkeletonData* skeletonData, bool ownsSkeletonData = false); + CCSkeleton (const char* skeletonDataFile, Atlas* atlas, float scale = 1); + CCSkeleton (const char* skeletonDataFile, const char* atlasFile, float scale = 1); + + virtual ~CCSkeleton (); + + virtual void update (float deltaTime); + virtual void draw (); + virtual cocos2d::CCRect boundingBox (); + + // --- Convenience methods for common Skeleton_* functions. + void updateWorldTransform (); + + void setToSetupPose (); + void setBonesToSetupPose (); + void setSlotsToSetupPose (); + + /* Returns 0 if the bone was not found. */ + Bone* findBone (const char* boneName) const; + /* Returns 0 if the slot was not found. */ + Slot* findSlot (const char* slotName) const; + + /* Sets the skin used to look up attachments not found in the SkeletonData defaultSkin. Attachments from the new skin are + * attached if the corresponding attachment from the old skin was attached. Returns false if the skin was not found. + * @param skin May be 0.*/ + bool setSkin (const char* skinName); + + /* Returns 0 if the slot or attachment was not found. */ + Attachment* getAttachment (const char* slotName, const char* attachmentName) const; + /* Returns false if the slot or attachment was not found. */ + bool setAttachment (const char* slotName, const char* attachmentName); + + // --- CCBlendProtocol + CC_PROPERTY(cocos2d::ccBlendFunc, blendFunc, BlendFunc); + virtual void setOpacityModifyRGB (bool value); + virtual bool isOpacityModifyRGB (); + +protected: + CCSkeleton (); + void setSkeletonData (SkeletonData* skeletonData, bool ownsSkeletonData); + cocos2d::CCTextureAtlas* getTextureAtlas (RegionAttachment* regionAttachment) const; + +private: + bool ownsSkeletonData; + Atlas* atlas; + void initialize (); +}; + +}} // namespace cocos2d { namespace extension { + +#endif /* SPINE_CCSKELETON_H_ */ diff --git a/extensions/spine/CCSkeletonAnimation.cpp b/extensions/spine/CCSkeletonAnimation.cpp new file mode 100644 index 0000000000..28f87e0f74 --- /dev/null +++ b/extensions/spine/CCSkeletonAnimation.cpp @@ -0,0 +1,142 @@ +/******************************************************************************* + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include +#include + +USING_NS_CC; +using std::min; +using std::max; +using std::vector; + +namespace cocos2d { namespace extension { + +CCSkeletonAnimation* CCSkeletonAnimation::createWithData (SkeletonData* skeletonData) { + CCSkeletonAnimation* node = new CCSkeletonAnimation(skeletonData); + node->autorelease(); + return node; +} + +CCSkeletonAnimation* CCSkeletonAnimation::createWithFile (const char* skeletonDataFile, Atlas* atlas, float scale) { + CCSkeletonAnimation* node = new CCSkeletonAnimation(skeletonDataFile, atlas, scale); + node->autorelease(); + return node; +} + +CCSkeletonAnimation* CCSkeletonAnimation::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) { + CCSkeletonAnimation* node = new CCSkeletonAnimation(skeletonDataFile, atlasFile, scale); + node->autorelease(); + return node; +} + +CCSkeletonAnimation::CCSkeletonAnimation (SkeletonData *skeletonData) + : CCSkeleton(skeletonData) { + addAnimationState(); +} + +CCSkeletonAnimation::CCSkeletonAnimation (const char* skeletonDataFile, Atlas* atlas, float scale) + : CCSkeleton(skeletonDataFile, atlas, scale) { + addAnimationState(); +} + +CCSkeletonAnimation::CCSkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale) + : CCSkeleton(skeletonDataFile, atlasFile, scale) { + addAnimationState(); +} + +CCSkeletonAnimation::~CCSkeletonAnimation () { + for (std::vector::iterator iter = stateDatas.begin(); iter != stateDatas.end(); ++iter) + AnimationStateData_dispose(*iter); + + for (std::vector::iterator iter = states.begin(); iter != states.end(); ++iter) + AnimationState_dispose(*iter); +} + +void CCSkeletonAnimation::update (float deltaTime) { + super::update(deltaTime); + + deltaTime *= timeScale; + for (std::vector::iterator iter = states.begin(); iter != states.end(); ++iter) { + AnimationState_update(*iter, deltaTime); + AnimationState_apply(*iter, skeleton); + } + Skeleton_updateWorldTransform(skeleton); +} + +void CCSkeletonAnimation::addAnimationState (AnimationStateData* stateData) { + if (!stateData) { + stateData = AnimationStateData_create(skeleton->data); + stateDatas.push_back(stateData); + } + AnimationState* state = AnimationState_create(stateData); + states.push_back(state); +} + +void CCSkeletonAnimation::setAnimationStateData (AnimationStateData* stateData, int stateIndex) { + CCAssert(stateIndex >= 0 && stateIndex < (int)states.size(), "stateIndex out of range."); + CCAssert(stateData, "stateData cannot be null."); + + AnimationState* state = states[stateIndex]; + for (std::vector::iterator iter = stateDatas.begin(); iter != stateDatas.end(); ++iter) { + if (state->data == *iter) { + AnimationStateData_dispose(state->data); + stateDatas.erase(iter); + break; + } + } + for (std::vector::iterator iter = states.begin(); iter != states.end(); ++iter) { + if (state == *iter) { + states.erase(iter); + break; + } + } + AnimationState_dispose(state); + + state = AnimationState_create(stateData); + states[stateIndex] = state; +} + +void CCSkeletonAnimation::setMix (const char* fromAnimation, const char* toAnimation, float duration, int stateIndex) { + CCAssert(stateIndex >= 0 && stateIndex < (int)states.size(), "stateIndex out of range."); + AnimationStateData_setMixByName(states[stateIndex]->data, fromAnimation, toAnimation, duration); +} + +void CCSkeletonAnimation::setAnimation (const char* name, bool loop, int stateIndex) { + CCAssert(stateIndex >= 0 && stateIndex < (int)states.size(), "stateIndex out of range."); + AnimationState_setAnimationByName(states[stateIndex], name, loop); +} + +void CCSkeletonAnimation::addAnimation (const char* name, bool loop, float delay, int stateIndex) { + CCAssert(stateIndex >= 0 && stateIndex < (int)states.size(), "stateIndex out of range."); + AnimationState_addAnimationByName(states[stateIndex], name, loop, delay); +} + +void CCSkeletonAnimation::clearAnimation (int stateIndex) { + CCAssert(stateIndex >= 0 && stateIndex < (int)states.size(), "stateIndex out of range."); + AnimationState_clearAnimation(states[stateIndex]); +} + +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/CCSkeletonAnimation.h b/extensions/spine/CCSkeletonAnimation.h new file mode 100644 index 0000000000..e38ef9c19e --- /dev/null +++ b/extensions/spine/CCSkeletonAnimation.h @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2013, Esoteric Software + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#ifndef SPINE_CCSKELETONANIMATION_H_ +#define SPINE_CCSKELETONANIMATION_H_ + +#include +#include +#include "cocos2d.h" + +namespace cocos2d { namespace extension { + +/** +Draws an animated skeleton, providing a simple API for applying one or more animations and queuing animations to be played later. +*/ +class CCSkeletonAnimation: public CCSkeleton { +public: + std::vector states; + + static CCSkeletonAnimation* createWithData (SkeletonData* skeletonData); + static CCSkeletonAnimation* createWithFile (const char* skeletonDataFile, Atlas* atlas, float scale = 1); + static CCSkeletonAnimation* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 1); + + CCSkeletonAnimation (SkeletonData* skeletonData); + CCSkeletonAnimation (const char* skeletonDataFile, Atlas* atlas, float scale = 1); + CCSkeletonAnimation (const char* skeletonDataFile, const char* atlasFile, float scale = 1); + + virtual ~CCSkeletonAnimation (); + + virtual void update (float deltaTime); + + void addAnimationState (AnimationStateData* stateData = 0); + void setAnimationStateData (AnimationStateData* stateData, int stateIndex = 0); + void setMix (const char* fromAnimation, const char* toAnimation, float duration, int stateIndex = 0); + void setAnimation (const char* name, bool loop, int stateIndex = 0); + void addAnimation (const char* name, bool loop, float delay = 0, int stateIndex = 0); + void clearAnimation (int stateIndex = 0); + +protected: + CCSkeletonAnimation (); + +private: + typedef CCSkeleton super; + std::vector stateDatas; + + void initialize (); +}; + +}} // namespace cocos2d { namespace extension { + +#endif /* SPINE_CCSKELETONANIMATION_H_ */ diff --git a/extensions/spine/Json.cpp b/extensions/spine/Json.cpp index b2cda20d5a..656b8e52bb 100644 --- a/extensions/spine/Json.cpp +++ b/extensions/spine/Json.cpp @@ -90,7 +90,7 @@ static const char* parse_number (Json *item, const char* num) { subscale = (subscale * 10) + (*num++ - '0'); /* Number? */ } - n = sign * n * pow(10.0f, (scale + subscale * signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + n = sign * n * (float)pow(10.0f, (scale + subscale * signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ item->valuefloat = n; item->valueint = (int)n; @@ -372,4 +372,4 @@ int Json_getInt (Json* value, const char* name, int defaultValue) { return value ? (int)value->valuefloat : defaultValue; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/RegionAttachment.cpp b/extensions/spine/RegionAttachment.cpp index cc26532e64..585df7af8f 100644 --- a/extensions/spine/RegionAttachment.cpp +++ b/extensions/spine/RegionAttachment.cpp @@ -37,29 +37,43 @@ RegionAttachment* RegionAttachment_create (const char* name) { return self; } -void RegionAttachment_updateOffset (RegionAttachment* self) { - float localX2 = self->width / 2; - float localY2 = self->height / 2; - float localX = -localX2; - float localY = -localY2; - if (self->region->rotate) { - localX += self->region->offsetX / self->region->originalWidth * self->height; - localY += self->region->offsetY / self->region->originalHeight * self->width; - localX2 -= (self->region->originalWidth - self->region->offsetX - self->region->height) / self->region->originalWidth * self->width; - localY2 -= (self->region->originalHeight - self->region->offsetY - self->region->width) / self->region->originalHeight * self->height; +void RegionAttachment_setUVs (RegionAttachment* self, float u, float v, float u2, float v2, int/*bool*/rotate) { + if (rotate) { + self->uvs[VERTEX_X2] = u; + self->uvs[VERTEX_Y2] = v2; + self->uvs[VERTEX_X3] = u; + self->uvs[VERTEX_Y3] = v; + self->uvs[VERTEX_X4] = u2; + self->uvs[VERTEX_Y4] = v; + self->uvs[VERTEX_X1] = u2; + self->uvs[VERTEX_Y1] = v2; } else { - localX += self->region->offsetX / self->region->originalWidth * self->width; - localY += self->region->offsetY / self->region->originalHeight * self->height; - localX2 -= (self->region->originalWidth - self->region->offsetX - self->region->width) / self->region->originalWidth * self->width; - localY2 -= (self->region->originalHeight - self->region->offsetY - self->region->height) / self->region->originalHeight * self->height; + self->uvs[VERTEX_X1] = u; + self->uvs[VERTEX_Y1] = v2; + self->uvs[VERTEX_X2] = u; + self->uvs[VERTEX_Y2] = v; + self->uvs[VERTEX_X3] = u2; + self->uvs[VERTEX_Y3] = v; + self->uvs[VERTEX_X4] = u2; + self->uvs[VERTEX_Y4] = v2; } - localX *= self->scaleX; - localY *= self->scaleY; - localX2 *= self->scaleX; - localY2 *= self->scaleY; +} + +void RegionAttachment_updateOffset (RegionAttachment* self) { + float regionScaleX = self->width / self->regionOriginalWidth * self->scaleX; + float regionScaleY = self->height / self->regionOriginalHeight * self->scaleY; + float localX = -self->width / 2 * self->scaleX + self->regionOffsetX * regionScaleX; + float localY = -self->height / 2 * self->scaleY + self->regionOffsetY * regionScaleY; + float localX2 = localX + self->regionWidth * regionScaleX; + float localY2 = localY + self->regionHeight * regionScaleY; float radians = (float)(self->rotation * 3.1415926535897932385 / 180); +#ifdef __STDC_VERSION__ float cosine = cosf(radians); float sine = sinf(radians); +#else + float cosine = (float)cos(radians); + float sine = (float)sin(radians); +#endif float localXCos = localX * cosine + self->x; float localXSin = localX * sine; float localYCos = localY * cosine + self->y; @@ -78,17 +92,18 @@ void RegionAttachment_updateOffset (RegionAttachment* self) { self->offset[VERTEX_Y4] = localYCos + localX2Sin; } -void RegionAttachment_updateVertices (RegionAttachment* self, Slot* slot) { +void RegionAttachment_computeVertices (RegionAttachment* self, float x, float y, Bone* bone, float* vertices) { float* offset = self->offset; - Bone* bone = slot->bone; - self->vertices[VERTEX_X1] = offset[VERTEX_X1] * bone->m00 + offset[VERTEX_Y1] * bone->m01 + bone->worldX; - self->vertices[VERTEX_Y1] = offset[VERTEX_X1] * bone->m10 + offset[VERTEX_Y1] * bone->m11 + bone->worldY; - self->vertices[VERTEX_X2] = offset[VERTEX_X2] * bone->m00 + offset[VERTEX_Y2] * bone->m01 + bone->worldX; - self->vertices[VERTEX_Y2] = offset[VERTEX_X2] * bone->m10 + offset[VERTEX_Y2] * bone->m11 + bone->worldY; - self->vertices[VERTEX_X3] = offset[VERTEX_X3] * bone->m00 + offset[VERTEX_Y3] * bone->m01 + bone->worldX; - self->vertices[VERTEX_Y3] = offset[VERTEX_X3] * bone->m10 + offset[VERTEX_Y3] * bone->m11 + bone->worldY; - self->vertices[VERTEX_X4] = offset[VERTEX_X4] * bone->m00 + offset[VERTEX_Y4] * bone->m01 + bone->worldX; - self->vertices[VERTEX_Y4] = offset[VERTEX_X4] * bone->m10 + offset[VERTEX_Y4] * bone->m11 + bone->worldY; + x += bone->worldX; + y += bone->worldY; + vertices[VERTEX_X1] = offset[VERTEX_X1] * bone->m00 + offset[VERTEX_Y1] * bone->m01 + x; + vertices[VERTEX_Y1] = offset[VERTEX_X1] * bone->m10 + offset[VERTEX_Y1] * bone->m11 + y; + vertices[VERTEX_X2] = offset[VERTEX_X2] * bone->m00 + offset[VERTEX_Y2] * bone->m01 + x; + vertices[VERTEX_Y2] = offset[VERTEX_X2] * bone->m10 + offset[VERTEX_Y2] * bone->m11 + y; + vertices[VERTEX_X3] = offset[VERTEX_X3] * bone->m00 + offset[VERTEX_Y3] * bone->m01 + x; + vertices[VERTEX_Y3] = offset[VERTEX_X3] * bone->m10 + offset[VERTEX_Y3] * bone->m11 + y; + vertices[VERTEX_X4] = offset[VERTEX_X4] * bone->m00 + offset[VERTEX_Y4] * bone->m01 + x; + vertices[VERTEX_Y4] = offset[VERTEX_X4] * bone->m10 + offset[VERTEX_Y4] * bone->m11 + y; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/RegionAttachment.h b/extensions/spine/RegionAttachment.h index b866ef0d5f..8374c812b2 100644 --- a/extensions/spine/RegionAttachment.h +++ b/extensions/spine/RegionAttachment.h @@ -40,16 +40,20 @@ typedef struct RegionAttachment RegionAttachment; struct RegionAttachment { Attachment super; float x, y, scaleX, scaleY, rotation, width, height; - AtlasRegion* region; + + void* rendererObject; + int regionOffsetX, regionOffsetY; /* Pixels stripped from the bottom left, unrotated. */ + int regionWidth, regionHeight; /* Unrotated, stripped pixel size. */ + int regionOriginalWidth, regionOriginalHeight; /* Unrotated, unstripped pixel size. */ + float offset[8]; - float vertices[8]; float uvs[8]; }; RegionAttachment* RegionAttachment_create (const char* name); - +void RegionAttachment_setUVs (RegionAttachment* self, float u, float v, float u2, float v2, int/*bool*/rotate); void RegionAttachment_updateOffset (RegionAttachment* self); -void RegionAttachment_updateVertices (RegionAttachment* self, Slot* slot); +void RegionAttachment_computeVertices (RegionAttachment* self, float x, float y, Bone* bone, float* vertices); }} // namespace cocos2d { namespace extension { diff --git a/extensions/spine/Skeleton.cpp b/extensions/spine/Skeleton.cpp index 003d34adf8..033e46bf02 100644 --- a/extensions/spine/Skeleton.cpp +++ b/extensions/spine/Skeleton.cpp @@ -30,12 +30,14 @@ namespace cocos2d { namespace extension { Skeleton* Skeleton_create (SkeletonData* data) { + int i, ii; + Skeleton* self = NEW(Skeleton); CONST_CAST(SkeletonData*, self->data) = data; self->boneCount = self->data->boneCount; self->bones = MALLOC(Bone*, self->boneCount); - int i, ii; + for (i = 0; i < self->boneCount; ++i) { BoneData* boneData = self->data->bones[i]; Bone* parent = 0; @@ -58,14 +60,13 @@ Skeleton* Skeleton_create (SkeletonData* data) { SlotData *slotData = data->slots[i]; /* Find bone for the slotData's boneData. */ - Bone *bone = NULL; + Bone* bone = 0; for (ii = 0; ii < self->boneCount; ++ii) { if (data->bones[ii] == slotData->boneData) { bone = self->bones[ii]; break; } } - self->slots[i] = Slot_create(slotData, self, bone); } @@ -91,6 +92,7 @@ void Skeleton_dispose (Skeleton* self) { FREE(self->slots); FREE(self->drawOrder); + FREE(self); } void Skeleton_updateWorldTransform (const Skeleton* self) { @@ -99,21 +101,21 @@ void Skeleton_updateWorldTransform (const Skeleton* self) { Bone_updateWorldTransform(self->bones[i], self->flipX, self->flipY); } -void Skeleton_setToBindPose (const Skeleton* self) { - Skeleton_setBonesToBindPose(self); - Skeleton_setSlotsToBindPose(self); +void Skeleton_setToSetupPose (const Skeleton* self) { + Skeleton_setBonesToSetupPose(self); + Skeleton_setSlotsToSetupPose(self); } -void Skeleton_setBonesToBindPose (const Skeleton* self) { +void Skeleton_setBonesToSetupPose (const Skeleton* self) { int i; for (i = 0; i < self->boneCount; ++i) - Bone_setToBindPose(self->bones[i]); + Bone_setToSetupPose(self->bones[i]); } -void Skeleton_setSlotsToBindPose (const Skeleton* self) { +void Skeleton_setSlotsToSetupPose (const Skeleton* self) { int i; for (i = 0; i < self->slotCount; ++i) - Slot_setToBindPose(self->slots[i]); + Slot_setToSetupPose(self->slots[i]); } Bone* Skeleton_findBone (const Skeleton* self, const char* boneName) { @@ -145,11 +147,12 @@ int Skeleton_findSlotIndex (const Skeleton* self, const char* slotName) { } int Skeleton_setSkinByName (Skeleton* self, const char* skinName) { + Skin *skin; if (!skinName) { Skeleton_setSkin(self, 0); return 1; } - Skin *skin = SkeletonData_findSkin(self->data, skinName); + skin = SkeletonData_findSkin(self->data, skinName); if (!skin) return 0; Skeleton_setSkin(self, skin); return 1; @@ -196,4 +199,4 @@ void Skeleton_update (Skeleton* self, float deltaTime) { self->time += deltaTime; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/Skeleton.h b/extensions/spine/Skeleton.h index 2ebf45260c..54fa5aa0d4 100644 --- a/extensions/spine/Skeleton.h +++ b/extensions/spine/Skeleton.h @@ -48,6 +48,7 @@ struct Skeleton { float r, g, b, a; float time; int/*bool*/flipX, flipY; + float x, y; }; Skeleton* Skeleton_create (SkeletonData* data); @@ -55,9 +56,9 @@ void Skeleton_dispose (Skeleton* self); void Skeleton_updateWorldTransform (const Skeleton* self); -void Skeleton_setToBindPose (const Skeleton* self); -void Skeleton_setBonesToBindPose (const Skeleton* self); -void Skeleton_setSlotsToBindPose (const Skeleton* self); +void Skeleton_setToSetupPose (const Skeleton* self); +void Skeleton_setBonesToSetupPose (const Skeleton* self); +void Skeleton_setSlotsToSetupPose (const Skeleton* self); /* Returns 0 if the bone was not found. */ Bone* Skeleton_findBone (const Skeleton* self, const char* boneName); diff --git a/extensions/spine/SkeletonData.cpp b/extensions/spine/SkeletonData.cpp index e7ab6f4466..9f781dc4f2 100644 --- a/extensions/spine/SkeletonData.cpp +++ b/extensions/spine/SkeletonData.cpp @@ -96,4 +96,4 @@ Animation* SkeletonData_findAnimation (const SkeletonData* self, const char* ani return 0; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/SkeletonJson.cpp b/extensions/spine/SkeletonJson.cpp index acc5a51654..965a43f2a5 100644 --- a/extensions/spine/SkeletonJson.cpp +++ b/extensions/spine/SkeletonJson.cpp @@ -60,24 +60,28 @@ void SkeletonJson_dispose (SkeletonJson* self) { } void _SkeletonJson_setError (SkeletonJson* self, Json* root, const char* value1, const char* value2) { - FREE(self->error); char message[256]; + int length; + FREE(self->error); strcpy(message, value1); - int length = strlen(value1); + length = strlen(value1); if (value2) strncat(message + length, value2, 256 - length); MALLOC_STR(self->error, message); if (root) Json_dispose(root); } static float toColor (const char* value, int index) { + char digits[3]; + char *error; + int color; + if (strlen(value) != 8) return -1; value += index * 2; - char digits[3]; + digits[0] = *value; digits[1] = *(value + 1); digits[2] = '\0'; - char* error; - int color = strtoul(digits, &error, 16); + color = strtoul(digits, &error, 16); if (*error != 0) return -1; return color / (float)255; } @@ -94,6 +98,8 @@ static void readCurve (CurveTimeline* timeline, int frameIndex, Json* frame) { } static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, SkeletonData *skeletonData) { + Animation* animation; + Json* bones = Json_getItem(root, "bones"); int boneCount = bones ? Json_getSize(bones) : 0; @@ -106,12 +112,13 @@ static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, S timelineCount += Json_getSize(Json_getItemAt(bones, i)); for (i = 0; i < slotCount; ++i) timelineCount += Json_getSize(Json_getItemAt(slots, i)); - Animation* animation = Animation_create(root->name, timelineCount); + animation = Animation_create(root->name, timelineCount); animation->timelineCount = 0; skeletonData->animations[skeletonData->animationCount] = animation; skeletonData->animationCount++; for (i = 0; i < boneCount; ++i) { + int timelineCount; Json* boneMap = Json_getItemAt(bones, i); const char* boneName = boneMap->name; @@ -123,13 +130,15 @@ static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, S return 0; } - int timelineCount = Json_getSize(boneMap); + timelineCount = Json_getSize(boneMap); for (ii = 0; ii < timelineCount; ++ii) { + float duration; Json* timelineArray = Json_getItemAt(boneMap, ii); int frameCount = Json_getSize(timelineArray); const char* timelineType = timelineArray->name; if (strcmp(timelineType, "rotate") == 0) { + RotateTimeline *timeline = RotateTimeline_create(frameCount); timeline->boneIndex = boneIndex; for (iii = 0; iii < frameCount; ++iii) { @@ -138,14 +147,14 @@ static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, S readCurve(SUPER(timeline), iii, frame); } animation->timelines[animation->timelineCount++] = (Timeline*)timeline; - float duration = timeline->frames[frameCount * 2 - 2]; + duration = timeline->frames[frameCount * 2 - 2]; if (duration > animation->duration) animation->duration = duration; } else { int isScale = strcmp(timelineType, "scale") == 0; if (isScale || strcmp(timelineType, "translate") == 0) { - TranslateTimeline *timeline = isScale ? ScaleTimeline_create(frameCount) : TranslateTimeline_create(frameCount); float scale = isScale ? 1 : self->scale; + TranslateTimeline *timeline = isScale ? ScaleTimeline_create(frameCount) : TranslateTimeline_create(frameCount); timeline->boneIndex = boneIndex; for (iii = 0; iii < frameCount; ++iii) { Json* frame = Json_getItemAt(timelineArray, iii); @@ -154,7 +163,7 @@ static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, S readCurve(SUPER(timeline), iii, frame); } animation->timelines[animation->timelineCount++] = (Timeline*)timeline; - float duration = timeline->frames[frameCount * 3 - 3]; + duration = timeline->frames[frameCount * 3 - 3]; if (duration > animation->duration) animation->duration = duration; } else { Animation_dispose(animation); @@ -166,6 +175,7 @@ static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, S } for (i = 0; i < slotCount; ++i) { + int timelineCount; Json* slotMap = Json_getItemAt(slots, i); const char* slotName = slotMap->name; @@ -176,8 +186,9 @@ static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, S return 0; } - int timelineCount = Json_getSize(slotMap); + timelineCount = Json_getSize(slotMap); for (ii = 0; ii < timelineCount; ++ii) { + float duration; Json* timelineArray = Json_getItemAt(slotMap, ii); int frameCount = Json_getSize(timelineArray); const char* timelineType = timelineArray->name; @@ -193,7 +204,7 @@ static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, S readCurve(SUPER(timeline), iii, frame); } animation->timelines[animation->timelineCount++] = (Timeline*)timeline; - float duration = timeline->frames[frameCount * 5 - 5]; + duration = timeline->frames[frameCount * 5 - 5]; if (duration > animation->duration) animation->duration = duration; } else if (strcmp(timelineType, "attachment") == 0) { @@ -206,7 +217,7 @@ static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, S name->type == Json_NULL ? 0 : name->valuestring); } animation->timelines[animation->timelineCount++] = (Timeline*)timeline; - float duration = timeline->frames[frameCount - 1]; + duration = timeline->frames[frameCount - 1]; if (duration > animation->duration) animation->duration = duration; } else { @@ -222,34 +233,42 @@ static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, S SkeletonData* SkeletonJson_readSkeletonDataFile (SkeletonJson* self, const char* path) { int length; + SkeletonData* skeletonData; const char* json = _Util_readFile(path, &length); if (!json) { _SkeletonJson_setError(self, 0, "Unable to read skeleton file: ", path); return 0; } - SkeletonData* skeletonData = SkeletonJson_readSkeletonData(self, json); + skeletonData = SkeletonJson_readSkeletonData(self, json); FREE(json); return skeletonData; } SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* json) { + SkeletonData* skeletonData; + Json *root, *bones; + int i, ii, iii, boneCount; + Json* slots; + Json* skinsMap; + Json* animations; + FREE(self->error); CONST_CAST(char*, self->error) = 0; - Json* root = Json_create(json); + root = Json_create(json); if (!root) { _SkeletonJson_setError(self, 0, "Invalid skeleton JSON: ", Json_getError()); return 0; } - SkeletonData* skeletonData = SkeletonData_create(); - int i, ii, iii; + skeletonData = SkeletonData_create(); - Json* bones = Json_getItem(root, "bones"); - int boneCount = Json_getSize(bones); + bones = Json_getItem(root, "bones"); + boneCount = Json_getSize(bones); skeletonData->bones = MALLOC(BoneData*, boneCount); for (i = 0; i < boneCount; ++i) { Json* boneMap = Json_getItemAt(bones, i); + BoneData* boneData; const char* boneName = Json_getString(boneMap, "name", 0); @@ -264,7 +283,7 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso } } - BoneData* boneData = BoneData_create(boneName, parent); + boneData = BoneData_create(boneName, parent); boneData->length = Json_getFloat(boneMap, "length", 0) * self->scale; boneData->x = Json_getFloat(boneMap, "x", 0) * self->scale; boneData->y = Json_getFloat(boneMap, "y", 0) * self->scale; @@ -276,11 +295,14 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso skeletonData->boneCount++; } - Json* slots = Json_getItem(root, "slots"); + slots = Json_getItem(root, "slots"); if (slots) { int slotCount = Json_getSize(slots); skeletonData->slots = MALLOC(SlotData*, slotCount); for (i = 0; i < slotCount; ++i) { + SlotData* slotData; + const char* color; + Json *attachmentItem; Json* slotMap = Json_getItemAt(slots, i); const char* slotName = Json_getString(slotMap, "name", 0); @@ -293,9 +315,9 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso return 0; } - SlotData* slotData = SlotData_create(slotName, boneData); + slotData = SlotData_create(slotName, boneData); - const char* color = Json_getString(slotMap, "color", 0); + color = Json_getString(slotMap, "color", 0); if (color) { slotData->r = toColor(color, 0); slotData->g = toColor(color, 1); @@ -303,7 +325,7 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso slotData->a = toColor(color, 3); } - Json *attachmentItem = Json_getItem(slotMap, "attachment"); + attachmentItem = Json_getItem(slotMap, "attachment"); if (attachmentItem) SlotData_setAttachmentName(slotData, attachmentItem->valuestring); skeletonData->slots[i] = slotData; @@ -311,7 +333,7 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso } } - Json* skinsMap = Json_getItem(root, "skins"); + skinsMap = Json_getItem(root, "skins"); if (skinsMap) { int skinCount = Json_getSize(skinsMap); skeletonData->skins = MALLOC(Skin*, skinCount); @@ -319,11 +341,13 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso Json* slotMap = Json_getItemAt(skinsMap, i); const char* skinName = slotMap->name; Skin *skin = Skin_create(skinName); + int slotNameCount; + skeletonData->skins[i] = skin; skeletonData->skinCount++; if (strcmp(skinName, "default") == 0) skeletonData->defaultSkin = skin; - int slotNameCount = Json_getSize(slotMap); + slotNameCount = Json_getSize(slotMap); for (ii = 0; ii < slotNameCount; ++ii) { Json* attachmentsMap = Json_getItemAt(slotMap, ii); const char* slotName = attachmentsMap->name; @@ -331,6 +355,7 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso int attachmentCount = Json_getSize(attachmentsMap); for (iii = 0; iii < attachmentCount; ++iii) { + Attachment* attachment; Json* attachmentMap = Json_getItemAt(attachmentsMap, iii); const char* skinAttachmentName = attachmentMap->name; const char* attachmentName = Json_getString(attachmentMap, "name", skinAttachmentName); @@ -347,7 +372,7 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso return 0; } - Attachment* attachment = AttachmentLoader_newAttachment(self->attachmentLoader, skin, type, attachmentName); + attachment = AttachmentLoader_newAttachment(self->attachmentLoader, skin, type, attachmentName); if (!attachment) { if (self->attachmentLoader->error1) { SkeletonData_dispose(skeletonData); @@ -375,7 +400,7 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso } } - Json* animations = Json_getItem(root, "animations"); + animations = Json_getItem(root, "animations"); if (animations) { int animationCount = Json_getSize(animations); skeletonData->animations = MALLOC(Animation*, animationCount); @@ -389,4 +414,4 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso return skeletonData; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/Skin.cpp b/extensions/spine/Skin.cpp index 2cf3c8c36f..d689c472ab 100644 --- a/extensions/spine/Skin.cpp +++ b/extensions/spine/Skin.cpp @@ -25,7 +25,6 @@ #include #include -#include namespace cocos2d { namespace extension { @@ -65,11 +64,11 @@ Skin* Skin_create (const char* name) { } void Skin_dispose (Skin* self) { - _Entry* entry = SUB_CAST(_Internal, self)->entries; + _Entry* entry = SUB_CAST(_Internal, self) ->entries; while (entry) { - _Entry* nextEtry = entry->next; + _Entry* nextEntry = entry->next; _Entry_dispose(entry); - entry = nextEtry; + entry = nextEntry; } FREE(self->name); @@ -78,8 +77,8 @@ void Skin_dispose (Skin* self) { void Skin_addAttachment (Skin* self, int slotIndex, const char* name, Attachment* attachment) { _Entry* newEntry = _Entry_create(slotIndex, name, attachment); - newEntry->next = SUB_CAST(_Internal, self)->entries; - SUB_CAST(_Internal, self)->entries = newEntry; + newEntry->next = SUB_CAST(_Internal, self) ->entries; + SUB_CAST(_Internal, self) ->entries = newEntry; } Attachment* Skin_getAttachment (const Skin* self, int slotIndex, const char* name) { @@ -91,6 +90,19 @@ Attachment* Skin_getAttachment (const Skin* self, int slotIndex, const char* nam return 0; } +const char* Skin_getAttachmentName (const Skin* self, int slotIndex, int attachmentIndex) { + const _Entry* entry = SUB_CAST(_Internal, self) ->entries; + int i = 0; + while (entry) { + if (entry->slotIndex == slotIndex) { + if (i == attachmentIndex) return entry->name; + i++; + } + entry = entry->next; + } + return 0; +} + void Skin_attachAll (const Skin* self, Skeleton* skeleton, const Skin* oldSkin) { const _Entry *entry = SUB_CAST(_Internal, oldSkin) ->entries; while (entry) { @@ -103,4 +115,4 @@ void Skin_attachAll (const Skin* self, Skeleton* skeleton, const Skin* oldSkin) } } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/Skin.h b/extensions/spine/Skin.h index 72b8a44ca9..f8d76a56f8 100644 --- a/extensions/spine/Skin.h +++ b/extensions/spine/Skin.h @@ -44,6 +44,9 @@ void Skin_addAttachment (Skin* self, int slotIndex, const char* name, Attachment /* Returns 0 if the attachment was not found. */ Attachment* Skin_getAttachment (const Skin* self, int slotIndex, const char* name); +/* Returns 0 if the slot or attachment was not found. */ +const char* Skin_getAttachmentName (const Skin* self, int slotIndex, int attachmentIndex); + /** Attach each attachment in this skin if the corresponding attachment in oldSkin is currently attached. */ void Skin_attachAll (const Skin* self, struct Skeleton* skeleton, const Skin* oldSkin); diff --git a/extensions/spine/Slot.cpp b/extensions/spine/Slot.cpp index eb582a7d3c..a17fdc1d78 100644 --- a/extensions/spine/Slot.cpp +++ b/extensions/spine/Slot.cpp @@ -39,7 +39,7 @@ Slot* Slot_create (SlotData* data, Skeleton* skeleton, Bone* bone) { CONST_CAST(SlotData*, self->data) = data; CONST_CAST(Skeleton*, self->skeleton) = skeleton; CONST_CAST(Bone*, self->bone) = bone; - Slot_setToBindPose(self); + Slot_setToSetupPose(self); return self; } @@ -60,13 +60,13 @@ float Slot_getAttachmentTime (const Slot* self) { return self->skeleton->time - SUB_CAST(_Internal, self) ->attachmentTime; } -void Slot_setToBindPose (Slot* self) { +void Slot_setToSetupPose (Slot* self) { + Attachment* attachment = 0; self->r = self->data->r; self->g = self->data->g; self->b = self->data->b; self->a = self->data->a; - Attachment* attachment = 0; if (self->data->attachmentName) { /* Find slot index. */ int i; @@ -80,4 +80,4 @@ void Slot_setToBindPose (Slot* self) { Slot_setAttachment(self, attachment); } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/Slot.h b/extensions/spine/Slot.h index aa8d7d768e..47b2a7f05d 100644 --- a/extensions/spine/Slot.h +++ b/extensions/spine/Slot.h @@ -51,7 +51,7 @@ void Slot_setAttachment (Slot* self, Attachment* attachment); void Slot_setAttachmentTime (Slot* self, float time); float Slot_getAttachmentTime (const Slot* self); -void Slot_setToBindPose (Slot* self); +void Slot_setToSetupPose (Slot* self); }} // namespace cocos2d { namespace extension { diff --git a/extensions/spine/SlotData.cpp b/extensions/spine/SlotData.cpp index e25c9ebc64..5f1478e6d2 100644 --- a/extensions/spine/SlotData.cpp +++ b/extensions/spine/SlotData.cpp @@ -53,4 +53,4 @@ void SlotData_setAttachmentName (SlotData* self, const char* attachmentName) { CONST_CAST(char*, self->attachmentName) = 0; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/SlotData.h b/extensions/spine/SlotData.h index 9c431ff93e..660c30695c 100644 --- a/extensions/spine/SlotData.h +++ b/extensions/spine/SlotData.h @@ -40,7 +40,7 @@ typedef struct { SlotData* SlotData_create (const char* name, BoneData* boneData); void SlotData_dispose (SlotData* self); -/* @param attachmentName May be 0 for no bind pose attachment. */ +/* @param attachmentName May be 0 for no setup pose attachment. */ void SlotData_setAttachmentName (SlotData* self, const char* attachmentName); }} // namespace cocos2d { namespace extension { diff --git a/extensions/spine/extension.cpp b/extensions/spine/extension.cpp index 8d6ef8f62f..2f973c73f8 100644 --- a/extensions/spine/extension.cpp +++ b/extensions/spine/extension.cpp @@ -51,6 +51,7 @@ void _setFree (void (*free) (void* ptr)) { } char* _readFile (const char* path, int* length) { + char *data; FILE *file = fopen(path, "rb"); if (!file) return 0; @@ -58,12 +59,11 @@ char* _readFile (const char* path, int* length) { *length = ftell(file); fseek(file, 0, SEEK_SET); - char* data = MALLOC(char, *length); - int rtn = fread(data, 1, *length, file); + data = MALLOC(char, *length); + fread(data, 1, *length, file); fclose(file); - if (rtn != *length) return 0; return data; } -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/extension.h b/extensions/spine/extension.h index 3847ed6eb3..37ae496e4b 100644 --- a/extensions/spine/extension.h +++ b/extensions/spine/extension.h @@ -113,8 +113,8 @@ char* _readFile (const char* path, int* length); /**/ -void _AttachmentLoader_init (AttachmentLoader* self, // - void (*dispose) (AttachmentLoader* self), // +void _AttachmentLoader_init (AttachmentLoader* self, /**/ + void (*dispose) (AttachmentLoader* self), /**/ Attachment* (*newAttachment) (AttachmentLoader* self, Skin* skin, AttachmentType type, const char* name)); void _AttachmentLoader_deinit (AttachmentLoader* self); void _AttachmentLoader_setError (AttachmentLoader* self, const char* error1, const char* error2); @@ -122,21 +122,21 @@ void _AttachmentLoader_setUnknownTypeError (AttachmentLoader* self, AttachmentTy /**/ -void _Attachment_init (Attachment* self, const char* name, AttachmentType type, // +void _Attachment_init (Attachment* self, const char* name, AttachmentType type, /**/ void (*dispose) (Attachment* self)); void _Attachment_deinit (Attachment* self); /**/ -void _Timeline_init (Timeline* self, // - void (*dispose) (Timeline* self), // +void _Timeline_init (Timeline* self, /**/ + void (*dispose) (Timeline* self), /**/ void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha)); void _Timeline_deinit (Timeline* self); /**/ -void _CurveTimeline_init (CurveTimeline* self, int frameCount, // - void (*dispose) (Timeline* self), // +void _CurveTimeline_init (CurveTimeline* self, int frameCount, /**/ + void (*dispose) (Timeline* self), /**/ void (*apply) (const Timeline* self, Skeleton* skeleton, float time, float alpha)); void _CurveTimeline_deinit (CurveTimeline* self); diff --git a/extensions/spine/spine-cocos2dx.cpp b/extensions/spine/spine-cocos2dx.cpp index d2bd54c245..bcb2394116 100644 --- a/extensions/spine/spine-cocos2dx.cpp +++ b/extensions/spine/spine-cocos2dx.cpp @@ -27,45 +27,46 @@ #include USING_NS_CC; -using std::min; -using std::max; + namespace cocos2d { namespace extension { void _AtlasPage_createTexture (AtlasPage* self, const char* path) { CCTexture2D* texture = CCTextureCache::sharedTextureCache()->addImage(path); CCTextureAtlas* textureAtlas = CCTextureAtlas::createWithTexture(texture, 4); textureAtlas->retain(); - self->texture = textureAtlas; - - // Using getContentSize to make it supports the strategy of loading resources in cocos2d-x. - -// self->width = texture->getPixelsWide(); -// self->height = texture->getPixelsHigh(); - - self->width = texture->getContentSize().width; - self->height = texture->getContentSize().height; + self->rendererObject = textureAtlas; + self->width = texture->getPixelsWide(); + self->height = texture->getPixelsHigh(); } void _AtlasPage_disposeTexture (AtlasPage* self) { - ((CCTextureAtlas*)self->texture)->release(); + ((CCTextureAtlas*)self->rendererObject)->release(); } char* _Util_readFile (const char* path, int* length) { unsigned long size; - char* data = reinterpret_cast(CCFileUtils::sharedFileUtils()->getFileData(path, "r", &size)); + char* data = reinterpret_cast(CCFileUtils::sharedFileUtils()->getFileData( + CCFileUtils::sharedFileUtils()->fullPathForFilename(path).c_str(), "r", &size)); *length = size; return data; } /**/ -void RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, ccV3F_C4B_T2F_Quad* quad) { - RegionAttachment_updateVertices(self, slot); +void RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, ccV3F_C4B_T2F_Quad* quad, bool premultipliedAlpha) { + float vertices[8]; + RegionAttachment_computeVertices(self, slot->skeleton->x, slot->skeleton->y, slot->bone, vertices); GLubyte r = slot->skeleton->r * slot->r * 255; GLubyte g = slot->skeleton->g * slot->g * 255; GLubyte b = slot->skeleton->b * slot->b * 255; - GLubyte a = slot->skeleton->a * slot->a * 255; + float normalizedAlpha = slot->skeleton->a * slot->a; + if (premultipliedAlpha) { + r *= normalizedAlpha; + g *= normalizedAlpha; + b *= normalizedAlpha; + } + GLubyte a = normalizedAlpha * 255; quad->bl.colors.r = r; quad->bl.colors.g = g; quad->bl.colors.b = b; @@ -83,225 +84,23 @@ void RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, ccV3F_C4B_ quad->br.colors.b = b; quad->br.colors.a = a; - quad->bl.vertices.x = self->vertices[VERTEX_X1]; - quad->bl.vertices.y = self->vertices[VERTEX_Y1]; - quad->tl.vertices.x = self->vertices[VERTEX_X2]; - quad->tl.vertices.y = self->vertices[VERTEX_Y2]; - quad->tr.vertices.x = self->vertices[VERTEX_X3]; - quad->tr.vertices.y = self->vertices[VERTEX_Y3]; - quad->br.vertices.x = self->vertices[VERTEX_X4]; - quad->br.vertices.y = self->vertices[VERTEX_Y4]; + quad->bl.vertices.x = vertices[VERTEX_X1]; + quad->bl.vertices.y = vertices[VERTEX_Y1]; + quad->tl.vertices.x = vertices[VERTEX_X2]; + quad->tl.vertices.y = vertices[VERTEX_Y2]; + quad->tr.vertices.x = vertices[VERTEX_X3]; + quad->tr.vertices.y = vertices[VERTEX_Y3]; + quad->br.vertices.x = vertices[VERTEX_X4]; + quad->br.vertices.y = vertices[VERTEX_Y4]; - if (self->region->rotate) { - quad->tl.texCoords.u = self->region->u; - quad->tl.texCoords.v = self->region->v2; - quad->tr.texCoords.u = self->region->u; - quad->tr.texCoords.v = self->region->v; - quad->br.texCoords.u = self->region->u2; - quad->br.texCoords.v = self->region->v; - quad->bl.texCoords.u = self->region->u2; - quad->bl.texCoords.v = self->region->v2; - } else { - quad->bl.texCoords.u = self->region->u; - quad->bl.texCoords.v = self->region->v2; - quad->tl.texCoords.u = self->region->u; - quad->tl.texCoords.v = self->region->v; - quad->tr.texCoords.u = self->region->u2; - quad->tr.texCoords.v = self->region->v; - quad->br.texCoords.u = self->region->u2; - quad->br.texCoords.v = self->region->v2; - } + quad->bl.texCoords.u = self->uvs[VERTEX_X1]; + quad->bl.texCoords.v = self->uvs[VERTEX_Y1]; + quad->tl.texCoords.u = self->uvs[VERTEX_X2]; + quad->tl.texCoords.v = self->uvs[VERTEX_Y2]; + quad->tr.texCoords.u = self->uvs[VERTEX_X3]; + quad->tr.texCoords.v = self->uvs[VERTEX_Y3]; + quad->br.texCoords.u = self->uvs[VERTEX_X4]; + quad->br.texCoords.v = self->uvs[VERTEX_Y4]; } -/**/ - -CCSkeleton* CCSkeleton::createWithFile (const char* skeletonDataFile, Atlas* atlas, float scale) { - SkeletonJson* json = SkeletonJson_create(atlas); - json->scale = scale; - SkeletonData* skeletonData = SkeletonJson_readSkeletonDataFile(json, skeletonDataFile); - SkeletonJson_dispose(json); - CCSkeleton* node = skeletonData ? createWithData(skeletonData) : 0; - node->ownsSkeleton = true; - return node; -} - -CCSkeleton* CCSkeleton::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) { - Atlas* atlas = Atlas_readAtlasFile(atlasFile); - if (!atlas) return 0; - SkeletonJson* json = SkeletonJson_create(atlas); - json->scale = scale; - SkeletonData* skeletonData = SkeletonJson_readSkeletonDataFile(json, skeletonDataFile); - SkeletonJson_dispose(json); - if (!skeletonData) { - Atlas_dispose(atlas); - return 0; - } - CCSkeleton* node = createWithData(skeletonData); - node->ownsSkeleton = true; - node->atlas = atlas; - return node; -} - -CCSkeleton* CCSkeleton::createWithData (SkeletonData* skeletonData, AnimationStateData* stateData) { - CCSkeleton* node = new CCSkeleton(skeletonData, stateData); - node->autorelease(); - return node; -} - -CCSkeleton::CCSkeleton (SkeletonData *skeletonData, AnimationStateData *stateData) : - ownsSkeleton(false), ownsStateData(false), atlas(0), - skeleton(0), state(0), debugSlots(false), debugBones(false) { - CONST_CAST(Skeleton*, skeleton) = Skeleton_create(skeletonData); - - if (!stateData) { - stateData = AnimationStateData_create(skeletonData); - ownsStateData = true; - } - CONST_CAST(AnimationState*, state) = AnimationState_create(stateData); - - blendFunc.src = GL_ONE; - blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; - - timeScale = 1; - - setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor)); - scheduleUpdate(); -} - -CCSkeleton::~CCSkeleton () { - if (ownsSkeleton) Skeleton_dispose(skeleton); - if (ownsStateData) AnimationStateData_dispose(state->data); - if (atlas) Atlas_dispose(atlas); - AnimationState_dispose(state); -} - -void CCSkeleton::update (float deltaTime) { - Skeleton_update(skeleton, deltaTime); - AnimationState_update(state, deltaTime * timeScale); - AnimationState_apply(state, skeleton); - Skeleton_updateWorldTransform(skeleton); -} - -void CCSkeleton::draw () { - CC_NODE_DRAW_SETUP(); - - ccGLBlendFunc(blendFunc.src, blendFunc.dst); - ccColor3B color = getColor(); - skeleton->r = color.r / (float)255; - skeleton->g = color.g / (float)255; - skeleton->b = color.b / (float)255; - skeleton->a = getOpacity() / (float)255; - - CCTextureAtlas* textureAtlas = 0; - ccV3F_C4B_T2F_Quad quad; - quad.tl.vertices.z = 0; - quad.tr.vertices.z = 0; - quad.bl.vertices.z = 0; - quad.br.vertices.z = 0; - for (int i = 0, n = skeleton->slotCount; i < n; i++) { - Slot* slot = skeleton->slots[i]; - if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue; - RegionAttachment* attachment = (RegionAttachment*)slot->attachment; - CCTextureAtlas* regionTextureAtlas = (CCTextureAtlas*)attachment->region->page->texture; - if (regionTextureAtlas != textureAtlas) { - if (textureAtlas) { - textureAtlas->drawQuads(); - textureAtlas->removeAllQuads(); - } - } - textureAtlas = regionTextureAtlas; - if (textureAtlas->getCapacity() == textureAtlas->getTotalQuads() && - !textureAtlas->resizeCapacity(textureAtlas->getCapacity() * 2)) return; - RegionAttachment_updateQuad(attachment, slot, &quad); - textureAtlas->updateQuad(&quad, textureAtlas->getTotalQuads()); - } - if (textureAtlas) { - textureAtlas->drawQuads(); - textureAtlas->removeAllQuads(); - } - - if (debugSlots) { - // Slots. - ccDrawColor4B(0, 0, 255, 255); - glLineWidth(1); - CCPoint points[4]; - ccV3F_C4B_T2F_Quad quad; - for (int i = 0, n = skeleton->slotCount; i < n; i++) { - Slot* slot = skeleton->slots[i]; - if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue; - RegionAttachment* attachment = (RegionAttachment*)slot->attachment; - RegionAttachment_updateQuad(attachment, slot, &quad); - points[0] = ccp(quad.bl.vertices.x, quad.bl.vertices.y); - points[1] = ccp(quad.br.vertices.x, quad.br.vertices.y); - points[2] = ccp(quad.tr.vertices.x, quad.tr.vertices.y); - points[3] = ccp(quad.tl.vertices.x, quad.tl.vertices.y); - ccDrawPoly(points, 4, true); - } - } - if (debugBones) { - // Bone lengths. - glLineWidth(2); - ccDrawColor4B(255, 0, 0, 255); - for (int i = 0, n = skeleton->boneCount; i < n; i++) { - Bone *bone = skeleton->bones[i]; - float x = bone->data->length * bone->m00 + bone->worldX; - float y = bone->data->length * bone->m10 + bone->worldY; - ccDrawLine(ccp(bone->worldX, bone->worldY), ccp(x, y)); - } - // Bone origins. - ccPointSize(4); - ccDrawColor4B(0, 0, 255, 255); // Root bone is blue. - for (int i = 0, n = skeleton->boneCount; i < n; i++) { - Bone *bone = skeleton->bones[i]; - ccDrawPoint(ccp(bone->worldX, bone->worldY)); - if (i == 0) ccDrawColor4B(0, 255, 0, 255); - } - } -} - -CCRect CCSkeleton::boundingBox () { - float minX = FLT_MAX, minY = FLT_MAX, maxX = FLT_MIN, maxY = FLT_MIN; - float scaleX = getScaleX(); - float scaleY = getScaleY(); - ccV3F_C4B_T2F_Quad quad; - for (int i = 0; i < skeleton->slotCount; ++i) { - Slot* slot = skeleton->slots[i]; - if (!slot->attachment || slot->attachment->type != ATTACHMENT_REGION) continue; - RegionAttachment* attachment = (RegionAttachment*)slot->attachment; - RegionAttachment_updateQuad(attachment, slot, &quad); - minX = min(minX, quad.bl.vertices.x * scaleX); - minY = min(minY, quad.bl.vertices.y * scaleY); - maxX = max(maxX, quad.bl.vertices.x * scaleX); - maxY = max(maxY, quad.bl.vertices.y * scaleY); - minX = min(minX, quad.br.vertices.x * scaleX); - minY = min(minY, quad.br.vertices.y * scaleY); - maxX = max(maxX, quad.br.vertices.x * scaleX); - maxY = max(maxY, quad.br.vertices.y * scaleY); - minX = min(minX, quad.tl.vertices.x * scaleX); - minY = min(minY, quad.tl.vertices.y * scaleY); - maxX = max(maxX, quad.tl.vertices.x * scaleX); - maxY = max(maxY, quad.tl.vertices.y * scaleY); - minX = min(minX, quad.tr.vertices.x * scaleX); - minY = min(minY, quad.tr.vertices.y * scaleY); - maxX = max(maxX, quad.tr.vertices.x * scaleX); - maxY = max(maxY, quad.tr.vertices.y * scaleY); - } - CCPoint position = getPosition(); - minX = position.x + minX; - minY = position.y + minY; - maxX = position.x + maxX; - maxY = position.y + maxY; - return CCRectMake(minX, minY, maxX - minX, maxY - minY); -} - -// CCBlendProtocol - -ccBlendFunc CCSkeleton::getBlendFunc () { - return blendFunc; -} - -void CCSkeleton::setBlendFunc (ccBlendFunc blendFunc) { - this->blendFunc = blendFunc; -} - -}} // namespace cocos2d { namespace extension { +}} // namespace cocos2d { namespace extension { \ No newline at end of file diff --git a/extensions/spine/spine-cocos2dx.h b/extensions/spine/spine-cocos2dx.h index 0569d3dc4f..baa42de009 100644 --- a/extensions/spine/spine-cocos2dx.h +++ b/extensions/spine/spine-cocos2dx.h @@ -28,40 +28,12 @@ #include #include "cocos2d.h" +#include +#include namespace cocos2d { namespace extension { -class CCSkeleton: public cocos2d::CCNodeRGBA, public cocos2d::CCBlendProtocol { -private: - bool ownsSkeleton; - bool ownsStateData; - Atlas* atlas; - -public: - Skeleton* const skeleton; - AnimationState* const state; - float timeScale; - bool debugSlots; - bool debugBones; - - static CCSkeleton* createWithFile (const char* skeletonDataFile, Atlas* atlas, float scale = 1); - static CCSkeleton* createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale = 1); - static CCSkeleton* createWithData (SkeletonData* skeletonData, AnimationStateData* stateData = 0); - - CCSkeleton (SkeletonData* skeletonData, AnimationStateData* stateData = 0); - virtual ~CCSkeleton (); - - virtual void update (float deltaTime); - virtual void draw (); - virtual cocos2d::CCRect boundingBox (); - - // CCBlendProtocol - CC_PROPERTY(cocos2d::ccBlendFunc, blendFunc, BlendFunc); -}; - -/**/ - -void RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, cocos2d::ccV3F_C4B_T2F_Quad* quad); +void RegionAttachment_updateQuad (RegionAttachment* self, Slot* slot, cocos2d::ccV3F_C4B_T2F_Quad* quad, bool premultiplied = false); }} // namespace cocos2d { namespace extension { diff --git a/samples/Cpp/TestCpp/Classes/SpineTest/SpineTest.cpp b/samples/Cpp/TestCpp/Classes/SpineTest/SpineTest.cpp index 087211e3bf..703eb6b6b0 100644 --- a/samples/Cpp/TestCpp/Classes/SpineTest/SpineTest.cpp +++ b/samples/Cpp/TestCpp/Classes/SpineTest/SpineTest.cpp @@ -48,10 +48,11 @@ void SpineTestScene::runThisTest() bool SpineTestLayer::init () { if (!CCLayer::init()) return false; - skeletonNode = CCSkeleton::createWithFile("spine/spineboy.json", "spine/spineboy.atlas"); - AnimationStateData_setMixByName(skeletonNode->state->data, "walk", "jump", 0.4f); - AnimationStateData_setMixByName(skeletonNode->state->data, "jump", "walk", 0.4f); - AnimationState_setAnimationByName(skeletonNode->state, "walk", true); + skeletonNode = CCSkeletonAnimation::createWithFile("spine/spineboy.json", "spine/spineboy.atlas"); + skeletonNode->setMix("walk", "jump", 0.4f); + skeletonNode->setMix("jump", "walk", 0.4f); + skeletonNode->setAnimation("walk", true); + skeletonNode->timeScale = 0.3f; skeletonNode->debugBones = true; @@ -70,9 +71,11 @@ bool SpineTestLayer::init () { } void SpineTestLayer::update (float deltaTime) { - if (skeletonNode->state->loop) { - if (skeletonNode->state->time > 2) AnimationState_setAnimationByName(skeletonNode->state, "jump", false); + if (skeletonNode->states[0]->loop) { + if (skeletonNode->states[0]->time > 2) + skeletonNode->setAnimation("jump", false); } else { - if (skeletonNode->state->time > 1) AnimationState_setAnimationByName(skeletonNode->state, "walk", true); + if (skeletonNode->states[0]->time > 1) + skeletonNode->setAnimation("walk", true); } } diff --git a/samples/Cpp/TestCpp/Classes/SpineTest/SpineTest.h b/samples/Cpp/TestCpp/Classes/SpineTest/SpineTest.h index 10eadbc3b5..091ee3f44c 100644 --- a/samples/Cpp/TestCpp/Classes/SpineTest/SpineTest.h +++ b/samples/Cpp/TestCpp/Classes/SpineTest/SpineTest.h @@ -38,7 +38,7 @@ public: class SpineTestLayer: public cocos2d::CCLayer { private: - cocos2d::extension::CCSkeleton* skeletonNode; + cocos2d::extension::CCSkeletonAnimation* skeletonNode; public: diff --git a/samples/Cpp/TestCpp/proj.ios/TestCpp.xcodeproj/project.pbxproj.REMOVED.git-id b/samples/Cpp/TestCpp/proj.ios/TestCpp.xcodeproj/project.pbxproj.REMOVED.git-id index 4ae6853675..2101b868d1 100644 --- a/samples/Cpp/TestCpp/proj.ios/TestCpp.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/samples/Cpp/TestCpp/proj.ios/TestCpp.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -b95526a387e924fd628b7408ad3b7da4814a1f11 \ No newline at end of file +a236c647a983eee2393f9d63d67c7ae1817a3ed8 \ No newline at end of file diff --git a/samples/Cpp/TestCpp/proj.mac/TestCpp.xcodeproj/project.pbxproj.REMOVED.git-id b/samples/Cpp/TestCpp/proj.mac/TestCpp.xcodeproj/project.pbxproj.REMOVED.git-id index eb941ccebb..029eebaf77 100644 --- a/samples/Cpp/TestCpp/proj.mac/TestCpp.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/samples/Cpp/TestCpp/proj.mac/TestCpp.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -5bf596dcac34b37a7ba44a2063590fb43de53efb \ No newline at end of file +267a49c99f5d0f31e0b8d65f8d4df421a06de76f \ No newline at end of file