[v4] spine v3.8

This commit is contained in:
halx99 2020-01-05 03:09:32 +08:00
parent 0d5a07450d
commit a2eb8507bb
42 changed files with 10477 additions and 3659 deletions

View File

@ -49,7 +49,7 @@ include(audio/CMakeLists.txt)
# default value for cocos2dx extensions modules build # default value for cocos2dx extensions modules build
option(BUILD_EDITOR_COCOSTUDIO "Build editor support for cocostudio" ON) option(BUILD_EDITOR_COCOSTUDIO "Build editor support for cocostudio" ON)
option(BUILD_EDITOR_SPINE "Build editor support for spine" OFF) option(BUILD_EDITOR_SPINE "Build editor support for spine" ON)
option(BUILD_EXTENSIONS "Build extension library" ON) option(BUILD_EXTENSIONS "Build extension library" ON)
if(BUILD_EDITOR_COCOSTUDIO) if(BUILD_EDITOR_COCOSTUDIO)
@ -58,7 +58,11 @@ if(BUILD_EDITOR_COCOSTUDIO)
endif(BUILD_EDITOR_COCOSTUDIO) endif(BUILD_EDITOR_COCOSTUDIO)
if(BUILD_EDITOR_SPINE) if(BUILD_EDITOR_SPINE)
include(editor-support/spine/CMakeLists.txt) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/editor-support/spine/CMakeLists.txt")
include(editor-support/spine/CMakeLists.txt)
else()
message(WARNING "${CMAKE_CURRENT_SOURCE_DIR}/editor-support/spine/CMakeLists.txt not found!")
endif()
set(COCOS_EDITOR_SUPPORT_SRC ${COCOS_EDITOR_SUPPORT_SRC} ${COCOS_SPINE_SRC} ${COCOS_SPINE_HEADER}) set(COCOS_EDITOR_SUPPORT_SRC ${COCOS_EDITOR_SUPPORT_SRC} ${COCOS_SPINE_SRC} ${COCOS_SPINE_HEADER})
endif(BUILD_EDITOR_SPINE) endif(BUILD_EDITOR_SPINE)

View File

@ -1,8 +1,8 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2019, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
@ -15,16 +15,16 @@
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#include <spine/AttachmentVertices.h> #include <spine/AttachmentVertices.h>
@ -35,6 +35,7 @@ namespace spine {
AttachmentVertices::AttachmentVertices (Texture2D* texture, int verticesCount, unsigned short* triangles, int trianglesCount) { AttachmentVertices::AttachmentVertices (Texture2D* texture, int verticesCount, unsigned short* triangles, int trianglesCount) {
_texture = texture; _texture = texture;
if (_texture) _texture->retain();
_triangles = new TrianglesCommand::Triangles(); _triangles = new TrianglesCommand::Triangles();
_triangles->verts = new V3F_C4B_T2F[verticesCount]; _triangles->verts = new V3F_C4B_T2F[verticesCount];
@ -46,6 +47,7 @@ AttachmentVertices::AttachmentVertices (Texture2D* texture, int verticesCount, u
AttachmentVertices::~AttachmentVertices () { AttachmentVertices::~AttachmentVertices () {
delete [] _triangles->verts; delete [] _triangles->verts;
delete _triangles; delete _triangles;
if (_texture) _texture->release();
} }
} }

View File

@ -1,8 +1,8 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2019, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
@ -15,16 +15,16 @@
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#ifndef SPINE_ATTACHMENTVERTICES_H_ #ifndef SPINE_ATTACHMENTVERTICES_H_

View File

@ -1,17 +1,10 @@
set(COCOS_SPINE_HEADER
editor-support/spine/AttachmentVertices.h
editor-support/spine/SkeletonAnimation.h
editor-support/spine/SkeletonBatch.h
editor-support/spine/SkeletonRenderer.h
editor-support/spine/SkeletonTwoColorBatch.h
editor-support/spine/spine-cocos2dx.h
)
set(COCOS_SPINE_SRC file(GLOB_RECURSE COCOS_SPINE_SRC
editor-support/spine/AttachmentVertices.cpp ${CMAKE_CURRENT_LIST_DIR}/*.cpp
editor-support/spine/SkeletonAnimation.cpp ${CMAKE_CURRENT_LIST_DIR}/**/*.cpp
editor-support/spine/SkeletonBatch.cpp )
editor-support/spine/SkeletonRenderer.cpp
editor-support/spine/SkeletonTwoColorBatch.cpp file(GLOB_RECURSE COCOS_SPINE_HEADER
editor-support/spine/spine-cocos2dx.cpp ${CMAKE_CURRENT_LIST_DIR}/*.h
) ${CMAKE_CURRENT_LIST_DIR}/**/*.h
)

View File

@ -1,8 +1,8 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2019, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
@ -15,16 +15,16 @@
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#include <spine/SkeletonAnimation.h> #include <spine/SkeletonAnimation.h>
@ -40,25 +40,26 @@ using std::vector;
namespace spine { namespace spine {
typedef struct _TrackEntryListeners { typedef struct _TrackEntryListeners {
StartListener startListener; StartListener startListener;
InterruptListener interruptListener; InterruptListener interruptListener;
EndListener endListener; EndListener endListener;
DisposeListener disposeListener; DisposeListener disposeListener;
CompleteListener completeListener; CompleteListener completeListener;
EventListener eventListener; EventListener eventListener;
} _TrackEntryListeners; } _TrackEntryListeners;
void animationCallback (AnimationState* state, EventType type, TrackEntry* entry, Event* event) { void animationCallback (AnimationState* state, EventType type, TrackEntry* entry, Event* event) {
((SkeletonAnimation*)state->getRendererObject())->onAnimationStateEvent(entry, type, event); ((SkeletonAnimation*)state->getRendererObject())->onAnimationStateEvent(entry, type, event);
} }
void trackEntryCallback (AnimationState* state, EventType type, TrackEntry* entry, Event* event) { void trackEntryCallback (AnimationState* state, EventType type, TrackEntry* entry, Event* event) {
((SkeletonAnimation*)state->getRendererObject())->onTrackEntryEvent(entry, type, event); ((SkeletonAnimation*)state->getRendererObject())->onTrackEntryEvent(entry, type, event);
if (type == EventType_Dispose) if (type == EventType_Dispose) {
if (entry->getRendererObject()) { if (entry->getRendererObject()) {
delete (spine::_TrackEntryListeners*)entry->getRendererObject(); delete (spine::_TrackEntryListeners*)entry->getRendererObject();
entry->setRendererObject(NULL); entry->setRendererObject(NULL);
} }
}
} }
static _TrackEntryListeners* getListeners (TrackEntry* entry) { static _TrackEntryListeners* getListeners (TrackEntry* entry) {
@ -68,7 +69,7 @@ static _TrackEntryListeners* getListeners (TrackEntry* entry) {
} }
return (_TrackEntryListeners*)entry->getRendererObject(); return (_TrackEntryListeners*)entry->getRendererObject();
} }
// //
SkeletonAnimation* SkeletonAnimation::createWithData (SkeletonData* skeletonData, bool ownsSkeletonData) { SkeletonAnimation* SkeletonAnimation::createWithData (SkeletonData* skeletonData, bool ownsSkeletonData) {
@ -111,6 +112,7 @@ void SkeletonAnimation::initialize () {
super::initialize(); super::initialize();
_ownsAnimationStateData = true; _ownsAnimationStateData = true;
_updateOnlyIfVisible = false;
_state = new (__FILE__, __LINE__) AnimationState(new (__FILE__, __LINE__) AnimationStateData(_skeleton->getData())); _state = new (__FILE__, __LINE__) AnimationState(new (__FILE__, __LINE__) AnimationStateData(_skeleton->getData()));
_state->setRendererObject(this); _state->setRendererObject(this);
_state->setListener(animationCallback); _state->setListener(animationCallback);
@ -128,12 +130,16 @@ SkeletonAnimation::~SkeletonAnimation () {
} }
void SkeletonAnimation::update (float deltaTime) { void SkeletonAnimation::update (float deltaTime) {
if (_updateOnlyIfVisible && !isVisible()) return;
super::update(deltaTime); super::update(deltaTime);
deltaTime *= _timeScale; deltaTime *= _timeScale;
if (_preUpdateListener) _preUpdateListener(this);
_state->update(deltaTime); _state->update(deltaTime);
_state->apply(*_skeleton); _state->apply(*_skeleton);
_skeleton->updateWorldTransform(); _skeleton->updateWorldTransform();
if (_postUpdateListener) _postUpdateListener(this);
} }
void SkeletonAnimation::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t transformFlags) { void SkeletonAnimation::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t transformFlags) {
@ -147,7 +153,7 @@ void SkeletonAnimation::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &t
void SkeletonAnimation::setAnimationStateData (AnimationStateData* stateData) { void SkeletonAnimation::setAnimationStateData (AnimationStateData* stateData) {
CCASSERT(stateData, "stateData cannot be null."); CCASSERT(stateData, "stateData cannot be null.");
if (_ownsAnimationStateData) delete _state->getData(); if (_ownsAnimationStateData) delete _state->getData();
delete _state; delete _state;
_ownsAnimationStateData = false; _ownsAnimationStateData = false;
@ -177,7 +183,7 @@ TrackEntry* SkeletonAnimation::addAnimation (int trackIndex, const std::string&
} }
return _state->addAnimation(trackIndex, animation, loop, delay); return _state->addAnimation(trackIndex, animation, loop, delay);
} }
TrackEntry* SkeletonAnimation::setEmptyAnimation (int trackIndex, float mixDuration) { TrackEntry* SkeletonAnimation::setEmptyAnimation (int trackIndex, float mixDuration) {
return _state->setEmptyAnimation(trackIndex, mixDuration); return _state->setEmptyAnimation(trackIndex, mixDuration);
} }
@ -211,15 +217,15 @@ void SkeletonAnimation::onAnimationStateEvent (TrackEntry* entry, EventType type
case EventType_Start: case EventType_Start:
if (_startListener) _startListener(entry); if (_startListener) _startListener(entry);
break; break;
case EventType_Interrupt: case EventType_Interrupt:
if (_interruptListener) _interruptListener(entry); if (_interruptListener) _interruptListener(entry);
break; break;
case EventType_End: case EventType_End:
if (_endListener) _endListener(entry); if (_endListener) _endListener(entry);
break; break;
case EventType_Dispose: case EventType_Dispose:
if (_disposeListener) _disposeListener(entry); if (_disposeListener) _disposeListener(entry);
break; break;
case EventType_Complete: case EventType_Complete:
if (_completeListener) _completeListener(entry); if (_completeListener) _completeListener(entry);
break; break;
@ -236,15 +242,15 @@ void SkeletonAnimation::onTrackEntryEvent (TrackEntry* entry, EventType type, Ev
case EventType_Start: case EventType_Start:
if (listeners->startListener) listeners->startListener(entry); if (listeners->startListener) listeners->startListener(entry);
break; break;
case EventType_Interrupt: case EventType_Interrupt:
if (listeners->interruptListener) listeners->interruptListener(entry); if (listeners->interruptListener) listeners->interruptListener(entry);
break; break;
case EventType_End: case EventType_End:
if (listeners->endListener) listeners->endListener(entry); if (listeners->endListener) listeners->endListener(entry);
break; break;
case EventType_Dispose: case EventType_Dispose:
if (listeners->disposeListener) listeners->disposeListener(entry); if (listeners->disposeListener) listeners->disposeListener(entry);
break; break;
case EventType_Complete: case EventType_Complete:
if (listeners->completeListener) listeners->completeListener(entry); if (listeners->completeListener) listeners->completeListener(entry);
break; break;
@ -257,17 +263,17 @@ void SkeletonAnimation::onTrackEntryEvent (TrackEntry* entry, EventType type, Ev
void SkeletonAnimation::setStartListener (const StartListener& listener) { void SkeletonAnimation::setStartListener (const StartListener& listener) {
_startListener = listener; _startListener = listener;
} }
void SkeletonAnimation::setInterruptListener (const InterruptListener& listener) { void SkeletonAnimation::setInterruptListener (const InterruptListener& listener) {
_interruptListener = listener; _interruptListener = listener;
} }
void SkeletonAnimation::setEndListener (const EndListener& listener) { void SkeletonAnimation::setEndListener (const EndListener& listener) {
_endListener = listener; _endListener = listener;
} }
void SkeletonAnimation::setDisposeListener (const DisposeListener& listener) { void SkeletonAnimation::setDisposeListener (const DisposeListener& listener) {
_disposeListener = listener; _disposeListener = listener;
} }
void SkeletonAnimation::setCompleteListener (const CompleteListener& listener) { void SkeletonAnimation::setCompleteListener (const CompleteListener& listener) {
@ -278,20 +284,28 @@ void SkeletonAnimation::setEventListener (const EventListener& listener) {
_eventListener = listener; _eventListener = listener;
} }
void SkeletonAnimation::setPreUpdateWorldTransformsListener(const UpdateWorldTransformsListener &listener) {
_preUpdateListener = listener;
}
void SkeletonAnimation::setPostUpdateWorldTransformsListener(const UpdateWorldTransformsListener &listener) {
_postUpdateListener = listener;
}
void SkeletonAnimation::setTrackStartListener (TrackEntry* entry, const StartListener& listener) { void SkeletonAnimation::setTrackStartListener (TrackEntry* entry, const StartListener& listener) {
getListeners(entry)->startListener = listener; getListeners(entry)->startListener = listener;
} }
void SkeletonAnimation::setTrackInterruptListener (TrackEntry* entry, const InterruptListener& listener) { void SkeletonAnimation::setTrackInterruptListener (TrackEntry* entry, const InterruptListener& listener) {
getListeners(entry)->interruptListener = listener; getListeners(entry)->interruptListener = listener;
} }
void SkeletonAnimation::setTrackEndListener (TrackEntry* entry, const EndListener& listener) { void SkeletonAnimation::setTrackEndListener (TrackEntry* entry, const EndListener& listener) {
getListeners(entry)->endListener = listener; getListeners(entry)->endListener = listener;
} }
void SkeletonAnimation::setTrackDisposeListener (TrackEntry* entry, const DisposeListener& listener) { void SkeletonAnimation::setTrackDisposeListener (TrackEntry* entry, const DisposeListener& listener) {
getListeners(entry)->disposeListener = listener; getListeners(entry)->disposeListener = listener;
} }
void SkeletonAnimation::setTrackCompleteListener (TrackEntry* entry, const CompleteListener& listener) { void SkeletonAnimation::setTrackCompleteListener (TrackEntry* entry, const CompleteListener& listener) {
@ -306,4 +320,8 @@ AnimationState* SkeletonAnimation::getState() const {
return _state; return _state;
} }
void SkeletonAnimation::setUpdateOnlyIfVisible(bool status) {
_updateOnlyIfVisible = status;
}
} }

View File

@ -1,8 +1,8 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2019, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
@ -15,33 +15,36 @@
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#ifndef SPINE_SKELETONANIMATION_H_ #ifndef SPINE_SKELETONANIMATION_H_
#define SPINE_SKELETONANIMATION_H_ #define SPINE_SKELETONANIMATION_H_
#define SPINE_SHORT_NAMES
#include <spine/spine.h> #include <spine/spine.h>
#include <spine/SkeletonRenderer.h> #include <spine/spine-cocos2dx.h>
#include "cocos2d.h" #include "cocos2d.h"
namespace spine { namespace spine {
class SkeletonAnimation;
typedef std::function<void(TrackEntry* entry)> StartListener; typedef std::function<void(TrackEntry* entry)> StartListener;
typedef std::function<void(TrackEntry* entry)> InterruptListener; typedef std::function<void(TrackEntry* entry)> InterruptListener;
typedef std::function<void(TrackEntry* entry)> EndListener; typedef std::function<void(TrackEntry* entry)> EndListener;
typedef std::function<void(TrackEntry* entry)> DisposeListener; typedef std::function<void(TrackEntry* entry)> DisposeListener;
typedef std::function<void(TrackEntry* entry)> CompleteListener; typedef std::function<void(TrackEntry* entry)> CompleteListener;
typedef std::function<void(TrackEntry* entry, Event* event)> EventListener; typedef std::function<void(TrackEntry* entry, Event* event)> EventListener;
typedef std::function<void(SkeletonAnimation* node)> UpdateWorldTransformsListener;
/** Draws an animated skeleton, providing an AnimationState for applying one or more animations and queuing animations to be /** Draws an animated skeleton, providing an AnimationState for applying one or more animations and queuing animations to be
* played later. */ * played later. */
@ -82,16 +85,18 @@ public:
void clearTrack (int trackIndex = 0); void clearTrack (int trackIndex = 0);
void setStartListener (const StartListener& listener); void setStartListener (const StartListener& listener);
void setInterruptListener (const InterruptListener& listener); void setInterruptListener (const InterruptListener& listener);
void setEndListener (const EndListener& listener); void setEndListener (const EndListener& listener);
void setDisposeListener (const DisposeListener& listener); void setDisposeListener (const DisposeListener& listener);
void setCompleteListener (const CompleteListener& listener); void setCompleteListener (const CompleteListener& listener);
void setEventListener (const EventListener& listener); void setEventListener (const EventListener& listener);
void setPreUpdateWorldTransformsListener(const UpdateWorldTransformsListener& listener);
void setPostUpdateWorldTransformsListener(const UpdateWorldTransformsListener& listener);
void setTrackStartListener (TrackEntry* entry, const StartListener& listener); void setTrackStartListener (TrackEntry* entry, const StartListener& listener);
void setTrackInterruptListener (TrackEntry* entry, const InterruptListener& listener); void setTrackInterruptListener (TrackEntry* entry, const InterruptListener& listener);
void setTrackEndListener (TrackEntry* entry, const EndListener& listener); void setTrackEndListener (TrackEntry* entry, const EndListener& listener);
void setTrackDisposeListener (TrackEntry* entry, const DisposeListener& listener); void setTrackDisposeListener (TrackEntry* entry, const DisposeListener& listener);
void setTrackCompleteListener (TrackEntry* entry, const CompleteListener& listener); void setTrackCompleteListener (TrackEntry* entry, const CompleteListener& listener);
void setTrackEventListener (TrackEntry* entry, const EventListener& listener); void setTrackEventListener (TrackEntry* entry, const EventListener& listener);
@ -99,6 +104,7 @@ public:
virtual void onTrackEntryEvent (TrackEntry* entry, EventType type, Event* event); virtual void onTrackEntryEvent (TrackEntry* entry, EventType type, Event* event);
AnimationState* getState() const; AnimationState* getState() const;
void setUpdateOnlyIfVisible(bool status);
CC_CONSTRUCTOR_ACCESS: CC_CONSTRUCTOR_ACCESS:
SkeletonAnimation (); SkeletonAnimation ();
@ -109,14 +115,17 @@ protected:
AnimationState* _state; AnimationState* _state;
bool _ownsAnimationStateData; bool _ownsAnimationStateData;
bool _updateOnlyIfVisible;
bool _firstDraw; bool _firstDraw;
StartListener _startListener; StartListener _startListener;
InterruptListener _interruptListener; InterruptListener _interruptListener;
EndListener _endListener; EndListener _endListener;
DisposeListener _disposeListener; DisposeListener _disposeListener;
CompleteListener _completeListener; CompleteListener _completeListener;
EventListener _eventListener; EventListener _eventListener;
UpdateWorldTransformsListener _preUpdateListener;
UpdateWorldTransformsListener _postUpdateListener;
private: private:
typedef SkeletonRenderer super; typedef SkeletonRenderer super;

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2019, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
@ -15,28 +15,28 @@
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#ifndef SPINE_SKELETONRENDERER_H_ #ifndef SPINE_SKELETONRENDERER_H_
#define SPINE_SKELETONRENDERER_H_ #define SPINE_SKELETONRENDERER_H_
#include <spine/spine.h>
#include "cocos2d.h" #include "cocos2d.h"
#include <spine/spine.h>
namespace spine { namespace spine {
class AttachmentVertices; class AttachmentVertices;
/* Draws a skeleton. */ /* Draws a skeleton. */
class SkeletonRenderer: public cocos2d::Node, public cocos2d::BlendProtocol { class SkeletonRenderer: public cocos2d::Node, public cocos2d::BlendProtocol {
public: public:
@ -45,48 +45,50 @@ namespace spine {
static SkeletonRenderer* createWithData (SkeletonData* skeletonData, bool ownsSkeletonData = false); static SkeletonRenderer* createWithData (SkeletonData* skeletonData, bool ownsSkeletonData = false);
static SkeletonRenderer* createWithFile (const std::string& skeletonDataFile, Atlas* atlas, float scale = 1); static SkeletonRenderer* createWithFile (const std::string& skeletonDataFile, Atlas* atlas, float scale = 1);
static SkeletonRenderer* createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1); static SkeletonRenderer* createWithFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);
virtual void update (float deltaTime) override; void update (float deltaTime) override;
virtual void draw (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags) override; void draw (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags) override;
virtual void drawDebug (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags); cocos2d::Rect getBoundingBox () const override;
virtual cocos2d::Rect getBoundingBox () const override; void onEnter () override;
virtual void onEnter () override; void onExit () override;
virtual void onExit () override;
Skeleton* getSkeleton() const;
Skeleton* getSkeleton();
void setTimeScale(float scale); void setTimeScale(float scale);
float getTimeScale() const; float getTimeScale() const;
/* */ /* */
void setDebugSlotsEnabled(bool enabled); void setDebugSlotsEnabled(bool enabled);
bool getDebugSlotsEnabled() const; bool getDebugSlotsEnabled() const;
void setDebugBonesEnabled(bool enabled); void setDebugBonesEnabled(bool enabled);
bool getDebugBonesEnabled() const; bool getDebugBonesEnabled() const;
void setDebugMeshesEnabled(bool enabled); void setDebugMeshesEnabled(bool enabled);
bool getDebugMeshesEnabled() const; bool getDebugMeshesEnabled() const;
void setDebugBoundingRectEnabled(bool enabled);
bool getDebugBoundingRectEnabled() const;
// --- Convenience methods for common Skeleton_* functions. // --- Convenience methods for common Skeleton_* functions.
void updateWorldTransform (); void updateWorldTransform ();
void setToSetupPose (); void setToSetupPose ();
void setBonesToSetupPose (); void setBonesToSetupPose ();
void setSlotsToSetupPose (); void setSlotsToSetupPose ();
/* Returns 0 if the bone was not found. */ /* Returns 0 if the bone was not found. */
Bone* findBone (const std::string& boneName) const; Bone* findBone (const std::string& boneName) const;
/* Returns 0 if the slot was not found. */ /* Returns 0 if the slot was not found. */
Slot* findSlot (const std::string& slotName) const; Slot* findSlot (const std::string& slotName) const;
/* Sets the skin used to look up attachments not found in the SkeletonData defaultSkin. Attachments from the new skin are /* 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. * attached if the corresponding attachment from the old skin was attached.
* @param skin May be empty string ("") for no skin.*/ * @param skin May be empty string ("") for no skin.*/
void setSkin (const std::string& skinName); void setSkin (const std::string& skinName);
/** @param skin May be 0 for no skin.*/ /** @param skin May be 0 for no skin.*/
void setSkin (const char* skinName); void setSkin (const char* skinName);
/* Returns 0 if the slot or attachment was not found. */ /* Returns 0 if the slot or attachment was not found. */
Attachment* getAttachment (const std::string& slotName, const std::string& attachmentName) const; Attachment* getAttachment (const std::string& slotName, const std::string& attachmentName) const;
/* Returns false if the slot or attachment was not found. /* Returns false if the slot or attachment was not found.
@ -94,55 +96,53 @@ namespace spine {
bool setAttachment (const std::string& slotName, const std::string& attachmentName); bool setAttachment (const std::string& slotName, const std::string& attachmentName);
/* @param attachmentName May be 0 for no attachment. */ /* @param attachmentName May be 0 for no attachment. */
bool setAttachment (const std::string& slotName, const char* attachmentName); bool setAttachment (const std::string& slotName, const char* attachmentName);
/* Enables/disables two color tinting for this instance. May break batching */ /* Enables/disables two color tinting for this instance. May break batching */
void setTwoColorTint(bool enabled); void setTwoColorTint(bool enabled);
/* Whether two color tinting is enabled */ /* Whether two color tinting is enabled */
bool isTwoColorTint(); bool isTwoColorTint();
/* Sets the vertex effect to be used, set to 0 to disable vertex effects */ /* Sets the vertex effect to be used, set to 0 to disable vertex effects */
void setVertexEffect(VertexEffect* effect); void setVertexEffect(VertexEffect* effect);
/* Sets the range of slots that should be rendered. Use -1, -1 to clear the range */ /* Sets the range of slots that should be rendered. Use -1, -1 to clear the range */
void setSlotsRange(int startSlotIndex, int endSlotIndex); void setSlotsRange(int startSlotIndex, int endSlotIndex);
// --- BlendProtocol // --- BlendProtocol
virtual void setBlendFunc (const cocos2d::BlendFunc& blendFunc)override; void setBlendFunc (const cocos2d::BlendFunc& blendFunc)override;
virtual const cocos2d::BlendFunc& getBlendFunc () const override; const cocos2d::BlendFunc& getBlendFunc () const override;
virtual void setOpacityModifyRGB (bool value) override; void setOpacityModifyRGB (bool value) override;
virtual bool isOpacityModifyRGB () const override; bool isOpacityModifyRGB () const override;
// Frees global memory used for temporay vertex transformations.
static void destroyScratchBuffers();
CC_CONSTRUCTOR_ACCESS: CC_CONSTRUCTOR_ACCESS:
SkeletonRenderer (); SkeletonRenderer ();
SkeletonRenderer(Skeleton* skeleton, bool ownsSkeleton = false, bool ownsSkeletonData = false, bool ownsAtlas = false); SkeletonRenderer(Skeleton* skeleton, bool ownsSkeleton = false, bool ownsSkeletonData = false, bool ownsAtlas = false);
SkeletonRenderer (SkeletonData* skeletonData, bool ownsSkeletonData = false); SkeletonRenderer (SkeletonData* skeletonData, bool ownsSkeletonData = false);
SkeletonRenderer (const std::string& skeletonDataFile, Atlas* atlas, float scale = 1); SkeletonRenderer (const std::string& skeletonDataFile, Atlas* atlas, float scale = 1);
SkeletonRenderer (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1); SkeletonRenderer (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);
virtual ~SkeletonRenderer (); virtual ~SkeletonRenderer ();
void initWithSkeleton(Skeleton* skeleton, bool ownsSkeleton = false, bool ownsSkeletonData = false, bool ownsAtlas = false); void initWithSkeleton(Skeleton* skeleton, bool ownsSkeleton = false, bool ownsSkeletonData = false, bool ownsAtlas = false);
void initWithData (SkeletonData* skeletonData, bool ownsSkeletonData = false); void initWithData (SkeletonData* skeletonData, bool ownsSkeletonData = false);
void initWithJsonFile (const std::string& skeletonDataFile, Atlas* atlas, float scale = 1); void initWithJsonFile (const std::string& skeletonDataFile, Atlas* atlas, float scale = 1);
void initWithJsonFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1); void initWithJsonFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);
void initWithBinaryFile (const std::string& skeletonDataFile, Atlas* atlas, float scale = 1); void initWithBinaryFile (const std::string& skeletonDataFile, Atlas* atlas, float scale = 1);
void initWithBinaryFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1); void initWithBinaryFile (const std::string& skeletonDataFile, const std::string& atlasFile, float scale = 1);
virtual void initialize (); virtual void initialize ();
protected: protected:
void setSkeletonData (SkeletonData* skeletonData, bool ownsSkeletonData); void setSkeletonData (SkeletonData* skeletonData, bool ownsSkeletonData);
void setupGLProgramState(bool twoColorTintEnabled); void setupGLProgramState(bool twoColorTintEnabled);
virtual void drawDebug (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t transformFlags);
bool _ownsSkeletonData; bool _ownsSkeletonData;
bool _ownsSkeleton; bool _ownsSkeleton;
bool _ownsAtlas; bool _ownsAtlas = false;
Atlas* _atlas; Atlas* _atlas;
AttachmentLoader* _attachmentLoader; AttachmentLoader* _attachmentLoader;
cocos2d::CustomCommand _debugCommand;
cocos2d::BlendFunc _blendFunc; cocos2d::BlendFunc _blendFunc;
bool _premultipliedAlpha; bool _premultipliedAlpha;
Skeleton* _skeleton; Skeleton* _skeleton;
@ -150,13 +150,16 @@ namespace spine {
bool _debugSlots; bool _debugSlots;
bool _debugBones; bool _debugBones;
bool _debugMeshes; bool _debugMeshes;
bool _debugBoundingRect;
SkeletonClipping* _clipper; SkeletonClipping* _clipper;
VertexEffect* _effect; VertexEffect* _effect;
bool _twoColorTintEnabled = false; cocos2d::Rect _boundingRect;
int _startSlotIndex; int _startSlotIndex;
int _endSlotIndex; int _endSlotIndex;
bool _twoColorTint;
}; };
} }
#endif /* SPINE_SKELETONRENDERER_H_ */ #endif /* SPINE_SKELETONRENDERER_H_ */

View File

@ -1,8 +1,8 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2019, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
@ -15,16 +15,16 @@
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#include <spine/spine-cocos2dx.h> #include <spine/spine-cocos2dx.h>
@ -48,7 +48,7 @@ static void setAttachmentVertices(RegionAttachment* attachment) {
vertices[i].texCoords.u = attachment->getUVs()[ii]; vertices[i].texCoords.u = attachment->getUVs()[ii];
vertices[i].texCoords.v = attachment->getUVs()[ii + 1]; vertices[i].texCoords.v = attachment->getUVs()[ii + 1];
} }
attachment->setRendererObject(attachmentVertices, deleteAttachmentVertices); attachment->setRendererObject(attachmentVertices, deleteAttachmentVertices);
} }
static void setAttachmentVertices(MeshAttachment* attachment) { static void setAttachmentVertices(MeshAttachment* attachment) {
@ -63,7 +63,7 @@ static void setAttachmentVertices(MeshAttachment* attachment) {
attachment->setRendererObject(attachmentVertices, deleteAttachmentVertices); attachment->setRendererObject(attachmentVertices, deleteAttachmentVertices);
} }
Cocos2dAtlasAttachmentLoader::Cocos2dAtlasAttachmentLoader(Atlas* atlas): AtlasAttachmentLoader(atlas) { Cocos2dAtlasAttachmentLoader::Cocos2dAtlasAttachmentLoader(Atlas* atlas): AtlasAttachmentLoader(atlas) {
} }
Cocos2dAtlasAttachmentLoader::~Cocos2dAtlasAttachmentLoader() { } Cocos2dAtlasAttachmentLoader::~Cocos2dAtlasAttachmentLoader() { }
@ -107,29 +107,29 @@ backend::SamplerFilter filter (TextureFilter filter) {
#else #else
GLuint wrap (TextureWrap wrap) { GLuint wrap (TextureWrap wrap) {
return wrap == TextureWrap_ClampToEdge ? GL_CLAMP_TO_EDGE : GL_REPEAT; return wrap == TextureWrap_ClampToEdge ? GL_CLAMP_TO_EDGE : GL_REPEAT;
} }
GLuint filter (TextureFilter filter) { GLuint filter (TextureFilter filter) {
switch (filter) { switch (filter) {
case TextureFilter_Unknown: case TextureFilter_Unknown:
break; break;
case TextureFilter_Nearest: case TextureFilter_Nearest:
return GL_NEAREST; return GL_NEAREST;
case TextureFilter_Linear: case TextureFilter_Linear:
return GL_LINEAR; return GL_LINEAR;
case TextureFilter_MipMap: case TextureFilter_MipMap:
return GL_LINEAR_MIPMAP_LINEAR; return GL_LINEAR_MIPMAP_LINEAR;
case TextureFilter_MipMapNearestNearest: case TextureFilter_MipMapNearestNearest:
return GL_NEAREST_MIPMAP_NEAREST; return GL_NEAREST_MIPMAP_NEAREST;
case TextureFilter_MipMapLinearNearest: case TextureFilter_MipMapLinearNearest:
return GL_LINEAR_MIPMAP_NEAREST; return GL_LINEAR_MIPMAP_NEAREST;
case TextureFilter_MipMapNearestLinear: case TextureFilter_MipMapNearestLinear:
return GL_NEAREST_MIPMAP_LINEAR; return GL_NEAREST_MIPMAP_LINEAR;
case TextureFilter_MipMapLinearLinear: case TextureFilter_MipMapLinearLinear:
return GL_LINEAR_MIPMAP_LINEAR; return GL_LINEAR_MIPMAP_LINEAR;
} }
return GL_LINEAR; return GL_LINEAR;
} }
#endif #endif
@ -140,32 +140,36 @@ Cocos2dTextureLoader::~Cocos2dTextureLoader() { }
void Cocos2dTextureLoader::load(AtlasPage& page, const spine::String& path) { void Cocos2dTextureLoader::load(AtlasPage& page, const spine::String& path) {
Texture2D* texture = Director::getInstance()->getTextureCache()->addImage(path.buffer()); Texture2D* texture = Director::getInstance()->getTextureCache()->addImage(path.buffer());
CCASSERT(texture != nullptr, "Invalid image"); CCASSERT(texture != nullptr, "Invalid image");
texture->retain(); if (texture) {
texture->retain();
#if COCOS2D_VERSION >= 0x0040000 #if COCOS2D_VERSION >= 0x0040000
Texture2D::TexParams textureParams(filter(page.minFilter), filter(page.magFilter), wrap(page.uWrap), wrap(page.vWrap)); Texture2D::TexParams textureParams(filter(page.minFilter), filter(page.magFilter), wrap(page.uWrap), wrap(page.vWrap));
#else #else
Texture2D::TexParams textureParams = {filter(page.minFilter), filter(page.magFilter), wrap(page.uWrap), wrap(page.vWrap)}; Texture2D::TexParams textureParams = {filter(page.minFilter), filter(page.magFilter), wrap(page.uWrap), wrap(page.vWrap)};
#endif #endif
texture->setTexParameters(textureParams); texture->setTexParameters(textureParams);
page.setRendererObject(texture); page.setRendererObject(texture);
page.width = texture->getPixelsWide(); page.width = texture->getPixelsWide();
page.height = texture->getPixelsHigh(); page.height = texture->getPixelsHigh();
}
} }
void Cocos2dTextureLoader::unload(void* texture) { void Cocos2dTextureLoader::unload(void* texture) {
((Texture2D*)texture)->release(); if (texture) {
((Texture2D*)texture)->release();
}
} }
Cocos2dExtension::Cocos2dExtension() : DefaultSpineExtension() { } Cocos2dExtension::Cocos2dExtension() : DefaultSpineExtension() { }
Cocos2dExtension::~Cocos2dExtension() { } Cocos2dExtension::~Cocos2dExtension() { }
char *Cocos2dExtension::_readFile(const spine::String &path, int *length) { char *Cocos2dExtension::_readFile(const spine::String &path, int *length) {
Data data = FileUtils::getInstance()->getDataFromFile(FileUtils::getInstance()->fullPathForFilename(path.buffer())); Data data = FileUtils::getInstance()->getDataFromFile(FileUtils::getInstance()->fullPathForFilename(path.buffer()));
if (data.isNull()) return 0; if (data.isNull()) return nullptr;
// avoid buffer overflow (int is shorter than ssize_t in certain platforms) // avoid buffer overflow (int is shorter than ssize_t in certain platforms)
#if COCOS2D_VERSION >= 0x00031200 #if COCOS2D_VERSION >= 0x00031200
ssize_t tmpLen; ssize_t tmpLen;
@ -180,8 +184,6 @@ char *Cocos2dExtension::_readFile(const spine::String &path, int *length) {
#endif #endif
} }
//SpineExtension *spine::getDefaultExtension () { SpineExtension *spine::getDefaultExtension () {
// return new Cocos2dExtension(); return new Cocos2dExtension();
//} }
static int __preinit_spine_extension = (spine::SpineExtension::setInstance(new Cocos2dExtension()), 0);

View File

@ -1,8 +1,8 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2019, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
@ -15,27 +15,35 @@
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#ifndef SPINE_COCOS2DX_H_ #ifndef SPINE_COCOS2DX_H_
#define SPINE_COCOS2DX_H_ #define SPINE_COCOS2DX_H_
#define SPINE_SHORT_NAMES
#include <spine/spine.h> #include <spine/spine.h>
#include "cocos2d.h" #include "cocos2d.h"
#include <spine/SkeletonRenderer.h> #include <spine/SkeletonRenderer.h>
#if COCOS2D_VERSION < 0x00040000
#include <spine/v3/SkeletonBatch.h>
#include <spine/v3/SkeletonTwoColorBatch.h>
#else
#include <spine/v4/SkeletonBatch.h>
#include <spine/v4/SkeletonTwoColorBatch.h>
#endif
#include <spine/SkeletonAnimation.h> #include <spine/SkeletonAnimation.h>
#include <spine/SkeletonBatch.h>
namespace spine { namespace spine {
class Cocos2dAtlasAttachmentLoader: public AtlasAttachmentLoader { class Cocos2dAtlasAttachmentLoader: public AtlasAttachmentLoader {
@ -44,7 +52,7 @@ namespace spine {
virtual ~Cocos2dAtlasAttachmentLoader(); virtual ~Cocos2dAtlasAttachmentLoader();
virtual void configureAttachment(Attachment* attachment); virtual void configureAttachment(Attachment* attachment);
}; };
class Cocos2dTextureLoader: public TextureLoader { class Cocos2dTextureLoader: public TextureLoader {
public: public:
Cocos2dTextureLoader(); Cocos2dTextureLoader();
@ -52,10 +60,10 @@ namespace spine {
virtual ~Cocos2dTextureLoader(); virtual ~Cocos2dTextureLoader();
virtual void load(AtlasPage& page, const String& path); virtual void load(AtlasPage& page, const String& path);
virtual void unload(void* texture); virtual void unload(void* texture);
}; };
class Cocos2dExtension: public DefaultSpineExtension { class Cocos2dExtension: public DefaultSpineExtension {
public: public:
Cocos2dExtension(); Cocos2dExtension();

View File

@ -0,0 +1,155 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/spine-cocos2dx.h>
#if COCOS2D_VERSION < 0x00040000
#include <spine/Extension.h>
#include <algorithm>
USING_NS_CC;
#define EVENT_AFTER_DRAW_RESET_POSITION "director_after_draw"
using std::max;
#define INITIAL_SIZE (10000)
namespace spine {
static SkeletonBatch* instance = nullptr;
SkeletonBatch* SkeletonBatch::getInstance () {
if (!instance) instance = new SkeletonBatch();
return instance;
}
void SkeletonBatch::destroyInstance () {
if (instance) {
delete instance;
instance = nullptr;
}
}
SkeletonBatch::SkeletonBatch () {
for (unsigned int i = 0; i < INITIAL_SIZE; i++) {
_commandsPool.push_back(new TrianglesCommand());
}
reset ();
// callback after drawing is finished so we can clear out the batch state
// for the next frame
Director::getInstance()->getEventDispatcher()->addCustomEventListener(EVENT_AFTER_DRAW_RESET_POSITION, [this](EventCustom* eventCustom){
this->update(0);
});;
}
SkeletonBatch::~SkeletonBatch () {
Director::getInstance()->getEventDispatcher()->removeCustomEventListeners(EVENT_AFTER_DRAW_RESET_POSITION);
for (unsigned int i = 0; i < _commandsPool.size(); i++) {
delete _commandsPool[i];
_commandsPool[i] = nullptr;
}
}
void SkeletonBatch::update (float delta) {
reset();
}
cocos2d::V3F_C4B_T2F* SkeletonBatch::allocateVertices(uint32_t numVertices) {
if (_vertices.size() - _numVertices < numVertices) {
cocos2d::V3F_C4B_T2F* oldData = _vertices.data();
_vertices.resize((_vertices.size() + numVertices) * 2 + 1);
cocos2d::V3F_C4B_T2F* newData = _vertices.data();
for (uint32_t i = 0; i < this->_nextFreeCommand; i++) {
TrianglesCommand* command = _commandsPool[i];
cocos2d::TrianglesCommand::Triangles& triangles = (cocos2d::TrianglesCommand::Triangles&)command->getTriangles();
triangles.verts = newData + (triangles.verts - oldData);
}
}
cocos2d::V3F_C4B_T2F* vertices = _vertices.data() + _numVertices;
_numVertices += numVertices;
return vertices;
}
void SkeletonBatch::deallocateVertices(uint32_t numVertices) {
_numVertices -= numVertices;
}
unsigned short* SkeletonBatch::allocateIndices(uint32_t numIndices) {
if (_indices.getCapacity() - _indices.size() < numIndices) {
unsigned short* oldData = _indices.buffer();
int oldSize = _indices.size();
_indices.ensureCapacity(_indices.size() + numIndices);
unsigned short* newData = _indices.buffer();
for (uint32_t i = 0; i < this->_nextFreeCommand; i++) {
TrianglesCommand* command = _commandsPool[i];
cocos2d::TrianglesCommand::Triangles& triangles = (cocos2d::TrianglesCommand::Triangles&)command->getTriangles();
if (triangles.indices >= oldData && triangles.indices < oldData + oldSize) {
triangles.indices = newData + (triangles.indices - oldData);
}
}
}
unsigned short* indices = _indices.buffer() + _indices.size();
_indices.setSize(_indices.size() + numIndices, 0);
return indices;
}
void SkeletonBatch::deallocateIndices(uint32_t numIndices) {
_indices.setSize(_indices.size() - numIndices, 0);
}
cocos2d::TrianglesCommand* SkeletonBatch::addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, cocos2d::GLProgramState* glProgramState, cocos2d::BlendFunc blendType, const cocos2d::TrianglesCommand::Triangles& triangles, const cocos2d::Mat4& mv, uint32_t flags) {
TrianglesCommand* command = nextFreeCommand();
command->init(globalOrder, texture, glProgramState, blendType, triangles, mv, flags);
renderer->addCommand(command);
return command;
}
void SkeletonBatch::reset() {
_nextFreeCommand = 0;
_numVertices = 0;
_indices.setSize(0, 0);
}
cocos2d::TrianglesCommand* SkeletonBatch::nextFreeCommand() {
if (_commandsPool.size() <= _nextFreeCommand) {
unsigned int newSize = _commandsPool.size() * 2 + 1;
for (int i = _commandsPool.size(); i < newSize; i++) {
_commandsPool.push_back(new TrianglesCommand());
}
}
return _commandsPool[_nextFreeCommand++];
}
}
#endif

View File

@ -0,0 +1,79 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_SKELETONBATCH_H_
#define SPINE_SKELETONBATCH_H_
#include "cocos2d.h"
#if COCOS2D_VERSION < 0x00040000
#include <spine/spine.h>
#include <vector>
namespace spine {
class SkeletonBatch {
public:
static SkeletonBatch* getInstance ();
static void destroyInstance ();
void update (float delta);
cocos2d::V3F_C4B_T2F* allocateVertices(uint32_t numVertices);
void deallocateVertices(uint32_t numVertices);
unsigned short* allocateIndices(uint32_t numIndices);
void deallocateIndices(uint32_t numVertices);
cocos2d::TrianglesCommand* addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, cocos2d::GLProgramState* glProgramState, cocos2d::BlendFunc blendType, const cocos2d::TrianglesCommand::Triangles& triangles, const cocos2d::Mat4& mv, uint32_t flags);
protected:
SkeletonBatch ();
virtual ~SkeletonBatch ();
void reset ();
cocos2d::TrianglesCommand* nextFreeCommand ();
// pool of commands
std::vector<cocos2d::TrianglesCommand*> _commandsPool;
uint32_t _nextFreeCommand;
// pool of vertices
std::vector<cocos2d::V3F_C4B_T2F> _vertices;
uint32_t _numVertices;
// pool of indices
Vector<unsigned short> _indices;
};
}
#endif
#endif // SPINE_SKELETONBATCH_H_

View File

@ -0,0 +1,351 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include <spine/spine-cocos2dx.h>
#if COCOS2D_VERSION < 0x00040000
#include <spine/Extension.h>
#include <algorithm>
USING_NS_CC;
#define EVENT_AFTER_DRAW_RESET_POSITION "director_after_draw"
using std::max;
#define INITIAL_SIZE (10000)
#define MAX_VERTICES 64000
#define MAX_INDICES 64000
#define STRINGIFY(A) #A
namespace spine {
TwoColorTrianglesCommand::TwoColorTrianglesCommand() :_materialID(0), _textureID(0), _glProgramState(nullptr), _glProgram(nullptr), _blendType(BlendFunc::DISABLE), _alphaTextureID(0) {
_type = RenderCommand::Type::CUSTOM_COMMAND;
func = [this]() { draw(); };
}
void TwoColorTrianglesCommand::init(float globalOrder, GLuint textureID, GLProgramState* glProgramState, BlendFunc blendType, const TwoColorTriangles& triangles, const Mat4& mv, uint32_t flags) {
CCASSERT(glProgramState, "Invalid GLProgramState");
CCASSERT(glProgramState->getVertexAttribsFlags() == 0, "No custom attributes are supported in QuadCommand");
RenderCommand::init(globalOrder, mv, flags);
_triangles = triangles;
if(_triangles.indexCount % 3 != 0) {
int count = _triangles.indexCount;
_triangles.indexCount = count / 3 * 3;
CCLOGERROR("Resize indexCount from %d to %d, size must be multiple times of 3", count, _triangles.indexCount);
}
_mv = mv;
if( _textureID != textureID || _blendType.src != blendType.src || _blendType.dst != blendType.dst ||
_glProgramState != glProgramState ||
_glProgram != glProgramState->getGLProgram()) {
_textureID = textureID;
_blendType = blendType;
_glProgramState = glProgramState;
_glProgram = glProgramState->getGLProgram();
generateMaterialID();
}
}
TwoColorTrianglesCommand::~TwoColorTrianglesCommand() {
}
void TwoColorTrianglesCommand::generateMaterialID() {
// do not batch if using custom uniforms (since we cannot batch) it
if(_glProgramState->getUniformCount() > 0) {
_materialID = Renderer::MATERIAL_ID_DO_NOT_BATCH;
setSkipBatching(true);
}
else {
int glProgram = (int)_glProgram->getProgram();
_materialID = glProgram + (int)_textureID + (int)_blendType.src + (int)_blendType.dst;
}
}
void TwoColorTrianglesCommand::useMaterial() const {
//Set texture
GL::bindTexture2D(_textureID);
if (_alphaTextureID > 0) {
// ANDROID ETC1 ALPHA supports.
GL::bindTexture2DN(1, _alphaTextureID);
}
//set blend mode
GL::blendFunc(_blendType.src, _blendType.dst);
_glProgramState->apply(_mv);
}
void TwoColorTrianglesCommand::draw() {
SkeletonTwoColorBatch::getInstance()->batch(this);
}
const char* TWO_COLOR_TINT_VERTEX_SHADER = STRINGIFY(
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec4 a_color2;
attribute vec2 a_texCoords;
\n#ifdef GL_ES\n
varying lowp vec4 v_light;
varying lowp vec4 v_dark;
varying mediump vec2 v_texCoord;
\n#else\n
varying vec4 v_light;
varying vec4 v_dark;
varying vec2 v_texCoord;
\n#endif\n
void main() {
v_light = a_color;
v_dark = a_color2;
v_texCoord = a_texCoords;
gl_Position = CC_PMatrix * a_position;
}
);
const char* TWO_COLOR_TINT_FRAGMENT_SHADER = STRINGIFY(
\n#ifdef GL_ES\n
precision lowp float;
\n#endif\n
varying vec4 v_light;
varying vec4 v_dark;
varying vec2 v_texCoord;
void main() {
vec4 texColor = texture2D(CC_Texture0, v_texCoord);
float alpha = texColor.a * v_light.a;
gl_FragColor.a = alpha;
gl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;
}
);
static SkeletonTwoColorBatch* instance = nullptr;
SkeletonTwoColorBatch* SkeletonTwoColorBatch::getInstance () {
if (!instance) instance = new SkeletonTwoColorBatch();
return instance;
}
void SkeletonTwoColorBatch::destroyInstance () {
if (instance) {
delete instance;
instance = nullptr;
}
}
SkeletonTwoColorBatch::SkeletonTwoColorBatch () : _vertexBuffer(0), _indexBuffer(0) {
for (unsigned int i = 0; i < INITIAL_SIZE; i++) {
_commandsPool.push_back(new TwoColorTrianglesCommand());
}
reset ();
// callback after drawing is finished so we can clear out the batch state
// for the next frame
Director::getInstance()->getEventDispatcher()->addCustomEventListener(EVENT_AFTER_DRAW_RESET_POSITION, [this](EventCustom* eventCustom){
this->update(0);
});
_twoColorTintShader = cocos2d::GLProgram::createWithByteArrays(TWO_COLOR_TINT_VERTEX_SHADER, TWO_COLOR_TINT_FRAGMENT_SHADER);
_twoColorTintShaderState = GLProgramState::getOrCreateWithGLProgram(_twoColorTintShader);
_twoColorTintShaderState->retain();
glGenBuffers(1, &_vertexBufferHandle);
_vertexBuffer = new V3F_C4B_C4B_T2F[MAX_VERTICES];
glGenBuffers(1, &_indexBufferHandle);
_indexBuffer = new unsigned short[MAX_INDICES];
_positionAttributeLocation = _twoColorTintShader->getAttribLocation("a_position");
_colorAttributeLocation = _twoColorTintShader->getAttribLocation("a_color");
_color2AttributeLocation = _twoColorTintShader->getAttribLocation("a_color2");
_texCoordsAttributeLocation = _twoColorTintShader->getAttribLocation("a_texCoords");
}
SkeletonTwoColorBatch::~SkeletonTwoColorBatch () {
Director::getInstance()->getEventDispatcher()->removeCustomEventListeners(EVENT_AFTER_DRAW_RESET_POSITION);
for (unsigned int i = 0; i < _commandsPool.size(); i++) {
delete _commandsPool[i];
_commandsPool[i] = nullptr;
}
_twoColorTintShader->release();
delete[] _vertexBuffer;
delete[] _indexBuffer;
}
void SkeletonTwoColorBatch::update (float delta) {
reset();
}
V3F_C4B_C4B_T2F* SkeletonTwoColorBatch::allocateVertices(uint32_t numVertices) {
if (_vertices.size() - _numVertices < numVertices) {
V3F_C4B_C4B_T2F* oldData = _vertices.data();
_vertices.resize((_vertices.size() + numVertices) * 2 + 1);
V3F_C4B_C4B_T2F* newData = _vertices.data();
for (uint32_t i = 0; i < this->_nextFreeCommand; i++) {
TwoColorTrianglesCommand* command = _commandsPool[i];
TwoColorTriangles& triangles = (TwoColorTriangles&)command->getTriangles();
triangles.verts = newData + (triangles.verts - oldData);
}
}
V3F_C4B_C4B_T2F* vertices = _vertices.data() + _numVertices;
_numVertices += numVertices;
return vertices;
}
void SkeletonTwoColorBatch::deallocateVertices(uint32_t numVertices) {
_numVertices -= numVertices;
}
unsigned short* SkeletonTwoColorBatch::allocateIndices(uint32_t numIndices) {
if (_indices.getCapacity() - _indices.size() < numIndices) {
unsigned short* oldData = _indices.buffer();
int oldSize =_indices.size();
_indices.ensureCapacity(_indices.size() + numIndices);
unsigned short* newData = _indices.buffer();
for (uint32_t i = 0; i < this->_nextFreeCommand; i++) {
TwoColorTrianglesCommand* command = _commandsPool[i];
TwoColorTriangles& triangles = (TwoColorTriangles&)command->getTriangles();
if (triangles.indices >= oldData && triangles.indices < oldData + oldSize) {
triangles.indices = newData + (triangles.indices - oldData);
}
}
}
unsigned short* indices = _indices.buffer() + _indices.size();
_indices.setSize(_indices.size() + numIndices, 0);
return indices;
}
void SkeletonTwoColorBatch::deallocateIndices(uint32_t numIndices) {
_indices.setSize(_indices.size() - numIndices, 0);
}
TwoColorTrianglesCommand* SkeletonTwoColorBatch::addCommand(cocos2d::Renderer* renderer, float globalOrder, GLuint textureID, cocos2d::GLProgramState* glProgramState, cocos2d::BlendFunc blendType, const TwoColorTriangles& triangles, const cocos2d::Mat4& mv, uint32_t flags) {
TwoColorTrianglesCommand* command = nextFreeCommand();
command->init(globalOrder, textureID, glProgramState, blendType, triangles, mv, flags);
renderer->addCommand(command);
return command;
}
void SkeletonTwoColorBatch::batch (TwoColorTrianglesCommand* command) {
if (_numVerticesBuffer + command->getTriangles().vertCount >= MAX_VERTICES || _numIndicesBuffer + command->getTriangles().indexCount >= MAX_INDICES) {
flush(_lastCommand);
}
uint32_t materialID = command->getMaterialID();
if (_lastCommand && _lastCommand->getMaterialID() != materialID) {
flush(_lastCommand);
}
memcpy(_vertexBuffer + _numVerticesBuffer, command->getTriangles().verts, sizeof(V3F_C4B_C4B_T2F) * command->getTriangles().vertCount);
const Mat4& modelView = command->getModelView();
for (int i = _numVerticesBuffer; i < _numVerticesBuffer + command->getTriangles().vertCount; i++) {
modelView.transformPoint(&_vertexBuffer[i].position);
}
unsigned short vertexOffset = (unsigned short)_numVerticesBuffer;
unsigned short* indices = command->getTriangles().indices;
for (int i = 0, j = _numIndicesBuffer; i < command->getTriangles().indexCount; i++, j++) {
_indexBuffer[j] = indices[i] + vertexOffset;
}
_numVerticesBuffer += command->getTriangles().vertCount;
_numIndicesBuffer += command->getTriangles().indexCount;
if (command->isForceFlush()) {
flush(command);
}
_lastCommand = command;
}
void SkeletonTwoColorBatch::flush (TwoColorTrianglesCommand* materialCommand) {
if (!materialCommand)
return;
materialCommand->useMaterial();
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferHandle);
glBufferData(GL_ARRAY_BUFFER, sizeof(V3F_C4B_C4B_T2F) * _numVerticesBuffer , _vertexBuffer, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(_positionAttributeLocation);
glEnableVertexAttribArray(_colorAttributeLocation);
glEnableVertexAttribArray(_color2AttributeLocation);
glEnableVertexAttribArray(_texCoordsAttributeLocation);
glVertexAttribPointer(_positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_C4B_T2F), (GLvoid*)offsetof(V3F_C4B_C4B_T2F, position));
glVertexAttribPointer(_colorAttributeLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_C4B_T2F), (GLvoid*)offsetof(V3F_C4B_C4B_T2F, color));
glVertexAttribPointer(_color2AttributeLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_C4B_T2F), (GLvoid*)offsetof(V3F_C4B_C4B_T2F, color2));
glVertexAttribPointer(_texCoordsAttributeLocation, 2, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_C4B_T2F), (GLvoid*)offsetof(V3F_C4B_C4B_T2F, texCoords));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * _numIndicesBuffer, _indexBuffer, GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLES, (GLsizei)_numIndicesBuffer, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
_numVerticesBuffer = 0;
_numIndicesBuffer = 0;
_numBatches++;
}
void SkeletonTwoColorBatch::reset() {
_nextFreeCommand = 0;
_numVertices = 0;
_indices.setSize(0, 0);
_numVerticesBuffer = 0;
_numIndicesBuffer = 0;
_lastCommand = nullptr;
_numBatches = 0;
}
TwoColorTrianglesCommand* SkeletonTwoColorBatch::nextFreeCommand() {
if (_commandsPool.size() <= _nextFreeCommand) {
unsigned int newSize = _commandsPool.size() * 2 + 1;
for (int i = _commandsPool.size(); i < newSize; i++) {
_commandsPool.push_back(new TwoColorTrianglesCommand());
}
}
TwoColorTrianglesCommand* command = _commandsPool[_nextFreeCommand++];
command->setForceFlush(false);
return command;
}
}
#endif

View File

@ -0,0 +1,172 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) 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
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_SKELETONTWOCOLORBATCH_H_
#define SPINE_SKELETONTWOCOLORBATCH_H_
#include "cocos2d.h"
#if COCOS2D_VERSION < 0x00040000
#include <spine/spine.h>
#include <vector>
namespace spine {
struct V3F_C4B_C4B_T2F {
cocos2d::Vec3 position;
cocos2d::Color4B color;
cocos2d::Color4B color2;
cocos2d::Tex2F texCoords;
};
struct TwoColorTriangles {
V3F_C4B_C4B_T2F* verts;
unsigned short* indices;
int vertCount;
int indexCount;
};
class TwoColorTrianglesCommand : public cocos2d::CustomCommand {
public:
TwoColorTrianglesCommand();
~TwoColorTrianglesCommand();
void init(float globalOrder, GLuint textureID, cocos2d::GLProgramState* glProgramState, cocos2d::BlendFunc blendType, const TwoColorTriangles& triangles, const cocos2d::Mat4& mv, uint32_t flags);
void useMaterial() const;
inline uint32_t getMaterialID() const { return _materialID; }
inline GLuint getTextureID() const { return _textureID; }
inline const TwoColorTriangles& getTriangles() const { return _triangles; }
inline ssize_t getVertexCount() const { return _triangles.vertCount; }
inline ssize_t getIndexCount() const { return _triangles.indexCount; }
inline const V3F_C4B_C4B_T2F* getVertices() const { return _triangles.verts; }
inline const unsigned short* getIndices() const { return _triangles.indices; }
inline cocos2d::GLProgramState* getGLProgramState() const { return _glProgramState; }
inline cocos2d::BlendFunc getBlendType() const { return _blendType; }
inline const cocos2d::Mat4& getModelView() const { return _mv; }
void draw ();
void setForceFlush (bool forceFlush) { _forceFlush = forceFlush; }
bool isForceFlush () { return _forceFlush; };
protected:
void generateMaterialID();
uint32_t _materialID;
GLuint _textureID;
cocos2d::GLProgramState* _glProgramState;
cocos2d::GLProgram* _glProgram;
cocos2d::BlendFunc _blendType;
TwoColorTriangles _triangles;
cocos2d::Mat4 _mv;
GLuint _alphaTextureID;
bool _forceFlush;
};
class SkeletonTwoColorBatch {
public:
static SkeletonTwoColorBatch* getInstance ();
static void destroyInstance ();
void update (float delta);
V3F_C4B_C4B_T2F* allocateVertices(uint32_t numVertices);
void deallocateVertices(uint32_t numVertices);
unsigned short* allocateIndices(uint32_t numIndices);
void deallocateIndices(uint32_t numIndices);
TwoColorTrianglesCommand* addCommand(cocos2d::Renderer* renderer, float globalOrder, GLuint textureID, cocos2d::GLProgramState* glProgramState, cocos2d::BlendFunc blendType, const TwoColorTriangles& triangles, const cocos2d::Mat4& mv, uint32_t flags);
cocos2d::GLProgramState* getTwoColorTintProgramState () { return _twoColorTintShaderState; }
void batch (TwoColorTrianglesCommand* command);
void flush (TwoColorTrianglesCommand* materialCommand);
uint32_t getNumBatches () { return _numBatches; };
protected:
SkeletonTwoColorBatch ();
virtual ~SkeletonTwoColorBatch ();
void reset ();
TwoColorTrianglesCommand* nextFreeCommand ();
// pool of commands
std::vector<TwoColorTrianglesCommand*> _commandsPool;
uint32_t _nextFreeCommand;
// pool of vertices
std::vector<V3F_C4B_C4B_T2F> _vertices;
uint32_t _numVertices;
// pool of indices
Vector<unsigned short> _indices;
// two color tint shader and state
cocos2d::GLProgram* _twoColorTintShader;
cocos2d::GLProgramState* _twoColorTintShaderState;
// VBO handles & attribute locations
GLuint _vertexBufferHandle;
V3F_C4B_C4B_T2F* _vertexBuffer;
uint32_t _numVerticesBuffer;
GLuint _indexBufferHandle;
uint32_t _numIndicesBuffer;
unsigned short* _indexBuffer;
GLint _positionAttributeLocation;
GLint _colorAttributeLocation;
GLint _color2AttributeLocation;
GLint _texCoordsAttributeLocation;
// last batched command, needed for flushing to set material
TwoColorTrianglesCommand* _lastCommand;
// number of batches in the last frame
uint32_t _numBatches;
};
}
#endif
#endif // SPINE_SKELETONTWOCOLORBATCH_H_

View File

@ -1,8 +1,8 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2019, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
@ -15,19 +15,21 @@
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#include <spine/SkeletonBatch.h> #include <spine/spine-cocos2dx.h>
#if COCOS2D_VERSION >= 0x00040000
#include <spine/Extension.h> #include <spine/Extension.h>
#include <algorithm> #include <algorithm>
@ -56,36 +58,38 @@ void SkeletonBatch::destroyInstance () {
} }
SkeletonBatch::SkeletonBatch () { SkeletonBatch::SkeletonBatch () {
auto program = backend::Device::getInstance()->newProgram(positionTextureColor_vert, positionTextureColor_frag);
_programState = std::make_shared<backend::ProgramState>(program);
program->autorelease();
auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR);
_programState = std::make_shared<backend::ProgramState>(program);
auto vertexLayout = _programState->getVertexLayout(); auto vertexLayout = _programState->getVertexLayout();
vertexLayout->setAttribute("a_position", 0, backend::VertexFormat::FLOAT3, offsetof(V3F_C4B_T2F, vertices), false); auto locPosition = _programState->getAttributeLocation("a_position");
vertexLayout->setAttribute("a_color", 2, backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true); auto locTexcoord = _programState->getAttributeLocation("a_texCoord");
vertexLayout->setAttribute("a_texCoord", 1, backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), false); auto locColor = _programState->getAttributeLocation("a_color");
vertexLayout->setAttribute("a_position", locPosition, backend::VertexFormat::FLOAT3, offsetof(V3F_C4B_T2F, vertices), false);
vertexLayout->setAttribute("a_color", locColor, backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true);
vertexLayout->setAttribute("a_texCoord", locTexcoord, backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), false);
vertexLayout->setLayout(sizeof(_vertices[0])); vertexLayout->setLayout(sizeof(_vertices[0]));
_locMVP = _programState->getUniformLocation("u_MVPMatrix"); _locMVP = _programState->getUniformLocation("u_MVPMatrix");
_locTexture = _programState->getUniformLocation("u_texture"); _locTexture = _programState->getUniformLocation("u_texture");
for (unsigned int i = 0; i < INITIAL_SIZE; i++) { for (unsigned int i = 0; i < INITIAL_SIZE; i++) {
_commandsPool.push_back(createNewTrianglesCommand()); _commandsPool.push_back(createNewTrianglesCommand());
} }
reset (); reset();
// callback after drawing is finished so we can clear out the batch state // callback after drawing is finished so we can clear out the batch state
// for the next frame // for the next frame
Director::getInstance()->getEventDispatcher()->addCustomEventListener(EVENT_AFTER_DRAW_RESET_POSITION, [this](EventCustom* eventCustom){ Director::getInstance()->getEventDispatcher()->addCustomEventListener(EVENT_AFTER_DRAW_RESET_POSITION, [this](EventCustom* eventCustom) {
this->update(0); this->update(0);
});; });;
} }
SkeletonBatch::~SkeletonBatch () { SkeletonBatch::~SkeletonBatch () {
Director::getInstance()->getEventDispatcher()->removeCustomEventListeners(EVENT_AFTER_DRAW_RESET_POSITION); Director::getInstance()->getEventDispatcher()->removeCustomEventListeners(EVENT_AFTER_DRAW_RESET_POSITION);
for (unsigned int i = 0; i < _commandsPool.size(); i++) { for (unsigned int i = 0; i < _commandsPool.size(); i++) {
CC_SAFE_RELEASE(_commandsPool[i]->getPipelineDescriptor().programState); CC_SAFE_RELEASE(_commandsPool[i]->getPipelineDescriptor().programState);
delete _commandsPool[i]; delete _commandsPool[i];
@ -96,7 +100,7 @@ SkeletonBatch::~SkeletonBatch () {
void SkeletonBatch::update (float delta) { void SkeletonBatch::update (float delta) {
reset(); reset();
} }
cocos2d::V3F_C4B_T2F* SkeletonBatch::allocateVertices(uint32_t numVertices) { cocos2d::V3F_C4B_T2F* SkeletonBatch::allocateVertices(uint32_t numVertices) {
if (_vertices.size() - _numVertices < numVertices) { if (_vertices.size() - _numVertices < numVertices) {
cocos2d::V3F_C4B_T2F* oldData = _vertices.data(); cocos2d::V3F_C4B_T2F* oldData = _vertices.data();
@ -108,18 +112,18 @@ cocos2d::V3F_C4B_T2F* SkeletonBatch::allocateVertices(uint32_t numVertices) {
triangles.verts = newData + (triangles.verts - oldData); triangles.verts = newData + (triangles.verts - oldData);
} }
} }
cocos2d::V3F_C4B_T2F* vertices = _vertices.data() + _numVertices; cocos2d::V3F_C4B_T2F* vertices = _vertices.data() + _numVertices;
_numVertices += numVertices; _numVertices += numVertices;
return vertices; return vertices;
} }
void SkeletonBatch::deallocateVertices(uint32_t numVertices) { void SkeletonBatch::deallocateVertices(uint32_t numVertices) {
_numVertices -= numVertices; _numVertices -= numVertices;
} }
unsigned short* SkeletonBatch::allocateIndices(uint32_t numIndices) { unsigned short* SkeletonBatch::allocateIndices(uint32_t numIndices) {
if (_indices.getCapacity() - _indices.size() < numIndices) { if (_indices.getCapacity() - _indices.size() < numIndices) {
unsigned short* oldData = _indices.buffer(); unsigned short* oldData = _indices.buffer();
int oldSize = _indices.size(); int oldSize = _indices.size();
@ -133,7 +137,7 @@ unsigned short* SkeletonBatch::allocateIndices(uint32_t numIndices) {
} }
} }
} }
unsigned short* indices = _indices.buffer() + _indices.size(); unsigned short* indices = _indices.buffer() + _indices.size();
_indices.setSize(_indices.size() + numIndices, 0); _indices.setSize(_indices.size() + numIndices, 0);
return indices; return indices;
@ -143,11 +147,10 @@ void SkeletonBatch::deallocateIndices(uint32_t numIndices) {
_indices.setSize(_indices.size() - numIndices, 0); _indices.setSize(_indices.size() - numIndices, 0);
} }
cocos2d::TrianglesCommand* SkeletonBatch::addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, cocos2d::BlendFunc blendType, const cocos2d::TrianglesCommand::Triangles& triangles, const cocos2d::Mat4& mv, uint32_t flags) { cocos2d::TrianglesCommand* SkeletonBatch::addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, cocos2d::BlendFunc blendType, const cocos2d::TrianglesCommand::Triangles& triangles, const cocos2d::Mat4& mv, uint32_t flags) {
TrianglesCommand* command = nextFreeCommand(); TrianglesCommand* command = nextFreeCommand();
const cocos2d::Mat4& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); const cocos2d::Mat4& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
auto &pipelineDescriptor = command->getPipelineDescriptor();
auto programState = command->getPipelineDescriptor().programState; auto programState = command->getPipelineDescriptor().programState;
CCASSERT(programState, "programState should not be null"); CCASSERT(programState, "programState should not be null");
@ -167,13 +170,13 @@ void SkeletonBatch::reset() {
} }
cocos2d::TrianglesCommand* SkeletonBatch::nextFreeCommand() { cocos2d::TrianglesCommand* SkeletonBatch::nextFreeCommand() {
if (_commandsPool.size() <= _nextFreeCommand) { if (_commandsPool.size() <= _nextFreeCommand) {
unsigned int newSize = _commandsPool.size() * 2 + 1; unsigned int newSize = _commandsPool.size() * 2 + 1;
for (int i = _commandsPool.size(); i < newSize; i++) { for (int i = _commandsPool.size(); i < newSize; i++) {
_commandsPool.push_back(createNewTrianglesCommand()); _commandsPool.push_back(createNewTrianglesCommand());
} }
} }
auto *command = _commandsPool[_nextFreeCommand++]; auto* command = _commandsPool[_nextFreeCommand++];
auto& pipelineDescriptor = command->getPipelineDescriptor(); auto& pipelineDescriptor = command->getPipelineDescriptor();
if (pipelineDescriptor.programState == nullptr) if (pipelineDescriptor.programState == nullptr)
{ {
@ -188,3 +191,5 @@ cocos2d::TrianglesCommand *SkeletonBatch::createNewTrianglesCommand() {
return command; return command;
} }
} }
#endif

View File

@ -1,8 +1,8 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2019, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
@ -15,23 +15,25 @@
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#ifndef SPINE_SKELETONBATCH_H_ #ifndef SPINE_SKELETONBATCH_H_
#define SPINE_SKELETONBATCH_H_ #define SPINE_SKELETONBATCH_H_
#define SPINE_SHORT_NAMES
#include <spine/spine.h>
#include "cocos2d.h" #include "cocos2d.h"
#if COCOS2D_VERSION >= 0x00040000
#include <spine/spine.h>
#include <vector> #include <vector>
namespace spine { namespace spine {
@ -77,4 +79,6 @@ namespace spine {
} }
#endif
#endif // SPINE_SKELETONBATCH_H_ #endif // SPINE_SKELETONBATCH_H_

View File

@ -1,8 +1,8 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2019, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
@ -15,18 +15,21 @@
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#include <spine/SkeletonTwoColorBatch.h>
#include <spine/spine-cocos2dx.h>
#if COCOS2D_VERSION >= 0x00040000
#include <spine/Extension.h> #include <spine/Extension.h>
#include <algorithm> #include <algorithm>
#include <stddef.h> // offsetof #include <stddef.h> // offsetof
@ -103,7 +106,7 @@ namespace {
return; return;
} }
auto program = backend::Device::getInstance()->newProgram(TWO_COLOR_TINT_VERTEX_SHADER, TWO_COLOR_TINT_FRAGMENT_SHADER); auto program = backend::Device::getInstance()->newProgram(TWO_COLOR_TINT_VERTEX_SHADER, TWO_COLOR_TINT_FRAGMENT_SHADER);
auto *programState = new backend::ProgramState(program); auto* programState = new backend::ProgramState(program);
program->autorelease(); program->autorelease();
__locPMatrix = programState->getUniformLocation("u_PMatrix"); __locPMatrix = programState->getUniformLocation("u_PMatrix");
@ -111,10 +114,15 @@ namespace {
auto layout = programState->getVertexLayout(); auto layout = programState->getVertexLayout();
layout->setAttribute("a_position", 0, backend::VertexFormat::FLOAT3, offsetof(spine::V3F_C4B_C4B_T2F, position), false); auto locPosition = programState->getAttributeLocation("a_position");
layout->setAttribute("a_color", 1, backend::VertexFormat::UBYTE4, offsetof(spine::V3F_C4B_C4B_T2F, color), true); auto locTexcoord = programState->getAttributeLocation("a_texCoords");
layout->setAttribute("a_color2", 2, backend::VertexFormat::UBYTE4, offsetof(spine::V3F_C4B_C4B_T2F, color2), true); auto locColor = programState->getAttributeLocation("a_color");
layout->setAttribute("a_texCoords", 3, backend::VertexFormat::FLOAT2, offsetof(spine::V3F_C4B_C4B_T2F, texCoords), false); auto locColor2 = programState->getAttributeLocation("a_color2");
layout->setAttribute("a_position", locPosition, backend::VertexFormat::FLOAT3, offsetof(spine::V3F_C4B_C4B_T2F, position), false);
layout->setAttribute("a_color", locColor, backend::VertexFormat::UBYTE4, offsetof(spine::V3F_C4B_C4B_T2F, color), true);
layout->setAttribute("a_color2", locColor2, backend::VertexFormat::UBYTE4, offsetof(spine::V3F_C4B_C4B_T2F, color2), true);
layout->setAttribute("a_texCoords", locTexcoord, backend::VertexFormat::FLOAT2, offsetof(spine::V3F_C4B_C4B_T2F, texCoords), false);
layout->setLayout(sizeof(spine::V3F_C4B_C4B_T2F)); layout->setLayout(sizeof(spine::V3F_C4B_C4B_T2F));
__twoColorProgramState = std::shared_ptr<backend::ProgramState>(programState); __twoColorProgramState = std::shared_ptr<backend::ProgramState>(programState);
@ -124,7 +132,7 @@ namespace {
namespace spine { namespace spine {
TwoColorTrianglesCommand::TwoColorTrianglesCommand() :_materialID(0), _texture(nullptr), _blendType(BlendFunc::DISABLE), _alphaTextureID(0) { TwoColorTrianglesCommand::TwoColorTrianglesCommand() :_materialID(0), _texture(nullptr), _blendType(BlendFunc::DISABLE) {
_type = RenderCommand::Type::CUSTOM_COMMAND; _type = RenderCommand::Type::CUSTOM_COMMAND;
} }
@ -132,7 +140,7 @@ void TwoColorTrianglesCommand::init(float globalOrder, cocos2d::Texture2D *textu
updateCommandPipelineDescriptor(); updateCommandPipelineDescriptor();
const cocos2d::Mat4& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); const cocos2d::Mat4& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
auto finalMatrix = projectionMat * mv; auto finalMatrix = projectionMat * mv;
_programState->setUniform(_locPMatrix, finalMatrix.m, sizeof(finalMatrix.m)); _programState->setUniform(_locPMatrix, finalMatrix.m, sizeof(finalMatrix.m));
@ -151,11 +159,11 @@ void TwoColorTrianglesCommand::init(float globalOrder, cocos2d::Texture2D *textu
_mv = mv; _mv = mv;
if (_blendType.src != blendType.src || _blendType.dst != blendType.dst || if (_blendType.src != blendType.src || _blendType.dst != blendType.dst ||
_texture != texture->getBackendTexture() || _pipelineDescriptor.programState != _programState) _texture != texture->getBackendTexture() || _pipelineDescriptor.programState != _programState)
{ {
_texture = texture->getBackendTexture(); _texture = texture->getBackendTexture();
_blendType = blendType; _blendType = blendType;
_prog = _programState->getProgram(); _prog = _programState->getProgram();
auto& blendDescriptor = _pipelineDescriptor.blendDescriptor; auto& blendDescriptor = _pipelineDescriptor.blendDescriptor;
@ -177,13 +185,13 @@ void TwoColorTrianglesCommand::updateCommandPipelineDescriptor()
} }
CC_SAFE_RELEASE_NULL(_programState); CC_SAFE_RELEASE_NULL(_programState);
_programState = __twoColorProgramState->clone(); _programState = __twoColorProgramState->clone();
_locPMatrix = __locPMatrix; _locPMatrix = __locPMatrix;
_locTexture = __locTexture; _locTexture = __locTexture;
_pipelineDescriptor.programState = _programState; _pipelineDescriptor.programState = _programState;
} }
TwoColorTrianglesCommand::~TwoColorTrianglesCommand() TwoColorTrianglesCommand::~TwoColorTrianglesCommand()
{ {
CC_SAFE_RELEASE_NULL(_programState); CC_SAFE_RELEASE_NULL(_programState);
} }
@ -223,7 +231,7 @@ void TwoColorTrianglesCommand::updateVertexAndIndexBuffer(Renderer *r, V3F_C4B_C
createVertexBuffer(sizeof(V3F_C4B_C4B_T2F), verticesSize, CustomCommand::BufferUsage::DYNAMIC); createVertexBuffer(sizeof(V3F_C4B_C4B_T2F), verticesSize, CustomCommand::BufferUsage::DYNAMIC);
if(indicesSize != _indexCapacity) if(indicesSize != _indexCapacity)
createIndexBuffer(CustomCommand::IndexFormat::U_SHORT, indicesSize, CustomCommand::BufferUsage::DYNAMIC); createIndexBuffer(CustomCommand::IndexFormat::U_SHORT, indicesSize, CustomCommand::BufferUsage::DYNAMIC);
updateVertexBuffer(vertices, sizeof(V3F_C4B_C4B_T2F) * verticesSize); updateVertexBuffer(vertices, sizeof(V3F_C4B_C4B_T2F) * verticesSize);
updateIndexBuffer(indices, sizeof(uint16_t) * indicesSize); updateIndexBuffer(indices, sizeof(uint16_t) * indicesSize);
} }
@ -248,20 +256,20 @@ SkeletonTwoColorBatch::SkeletonTwoColorBatch () : _vertexBuffer(0), _indexBuffer
for (unsigned int i = 0; i < INITIAL_SIZE; i++) { for (unsigned int i = 0; i < INITIAL_SIZE; i++) {
_commandsPool.push_back(new TwoColorTrianglesCommand()); _commandsPool.push_back(new TwoColorTrianglesCommand());
} }
reset (); reset ();
// callback after drawing is finished so we can clear out the batch state // callback after drawing is finished so we can clear out the batch state
// for the next frame // for the next frame
Director::getInstance()->getEventDispatcher()->addCustomEventListener(EVENT_AFTER_DRAW_RESET_POSITION, [this](EventCustom* eventCustom){ Director::getInstance()->getEventDispatcher()->addCustomEventListener(EVENT_AFTER_DRAW_RESET_POSITION, [this](EventCustom* eventCustom){
this->update(0); this->update(0);
}); });
} }
SkeletonTwoColorBatch::~SkeletonTwoColorBatch () { SkeletonTwoColorBatch::~SkeletonTwoColorBatch () {
Director::getInstance()->getEventDispatcher()->removeCustomEventListeners(EVENT_AFTER_DRAW_RESET_POSITION); Director::getInstance()->getEventDispatcher()->removeCustomEventListeners(EVENT_AFTER_DRAW_RESET_POSITION);
for (unsigned int i = 0; i < _commandsPool.size(); i++) { for (unsigned int i = 0; i < _commandsPool.size(); i++) {
delete _commandsPool[i]; delete _commandsPool[i];
_commandsPool[i] = nullptr; _commandsPool[i] = nullptr;
@ -271,7 +279,7 @@ SkeletonTwoColorBatch::~SkeletonTwoColorBatch () {
delete[] _indexBuffer; delete[] _indexBuffer;
} }
void SkeletonTwoColorBatch::update (float delta) { void SkeletonTwoColorBatch::update (float delta) {
reset(); reset();
} }
@ -286,13 +294,13 @@ V3F_C4B_C4B_T2F* SkeletonTwoColorBatch::allocateVertices(uint32_t numVertices) {
triangles.verts = newData + (triangles.verts - oldData); triangles.verts = newData + (triangles.verts - oldData);
} }
} }
V3F_C4B_C4B_T2F* vertices = _vertices.data() + _numVertices; V3F_C4B_C4B_T2F* vertices = _vertices.data() + _numVertices;
_numVertices += numVertices; _numVertices += numVertices;
return vertices; return vertices;
} }
void SkeletonTwoColorBatch::deallocateVertices(uint32_t numVertices) { void SkeletonTwoColorBatch::deallocateVertices(uint32_t numVertices) {
_numVertices -= numVertices; _numVertices -= numVertices;
} }
@ -312,7 +320,7 @@ unsigned short* SkeletonTwoColorBatch::allocateIndices(uint32_t numIndices) {
} }
} }
} }
unsigned short* indices = _indices.buffer() + _indices.size(); unsigned short* indices = _indices.buffer() + _indices.size();
_indices.setSize(_indices.size() + numIndices, 0); _indices.setSize(_indices.size() + numIndices, 0);
return indices; return indices;
@ -326,45 +334,45 @@ TwoColorTrianglesCommand* SkeletonTwoColorBatch::addCommand(cocos2d::Renderer* r
TwoColorTrianglesCommand* command = nextFreeCommand(); TwoColorTrianglesCommand* command = nextFreeCommand();
command->init(globalOrder, texture, blendType, triangles, mv, flags); command->init(globalOrder, texture, blendType, triangles, mv, flags);
command->updateVertexAndIndexBuffer(renderer, triangles.verts, triangles.vertCount, triangles.indices, triangles.indexCount); command->updateVertexAndIndexBuffer(renderer, triangles.verts, triangles.vertCount, triangles.indices, triangles.indexCount);
renderer->addCommand(command); renderer->addCommand(command);
return command; return command;
} }
void SkeletonTwoColorBatch::batch (cocos2d::Renderer *renderer, TwoColorTrianglesCommand* command) { void SkeletonTwoColorBatch::batch (cocos2d::Renderer *renderer, TwoColorTrianglesCommand* command) {
if (_numVerticesBuffer + command->getTriangles().vertCount >= MAX_VERTICES || _numIndicesBuffer + command->getTriangles().indexCount >= MAX_INDICES) { if (_numVerticesBuffer + command->getTriangles().vertCount >= MAX_VERTICES || _numIndicesBuffer + command->getTriangles().indexCount >= MAX_INDICES) {
flush(renderer, _lastCommand); flush(renderer, _lastCommand);
} }
uint32_t materialID = command->getMaterialID(); uint32_t materialID = command->getMaterialID();
if (_lastCommand && _lastCommand->getMaterialID() != materialID) { if (_lastCommand && _lastCommand->getMaterialID() != materialID) {
flush(renderer, _lastCommand); flush(renderer, _lastCommand);
} }
memcpy(_vertexBuffer + _numVerticesBuffer, command->getTriangles().verts, sizeof(V3F_C4B_C4B_T2F) * command->getTriangles().vertCount); memcpy(_vertexBuffer + _numVerticesBuffer, command->getTriangles().verts, sizeof(V3F_C4B_C4B_T2F) * command->getTriangles().vertCount);
const Mat4& modelView = command->getModelView(); const Mat4& modelView = command->getModelView();
for (int i = _numVerticesBuffer; i < _numVerticesBuffer + command->getTriangles().vertCount; i++) { for (int i = _numVerticesBuffer; i < _numVerticesBuffer + command->getTriangles().vertCount; i++) {
modelView.transformPoint(&_vertexBuffer[i].position); modelView.transformPoint(&_vertexBuffer[i].position);
} }
unsigned short vertexOffset = (unsigned short)_numVerticesBuffer; unsigned short vertexOffset = (unsigned short)_numVerticesBuffer;
unsigned short* indices = command->getTriangles().indices; unsigned short* indices = command->getTriangles().indices;
for (int i = 0, j = _numIndicesBuffer; i < command->getTriangles().indexCount; i++, j++) { for (int i = 0, j = _numIndicesBuffer; i < command->getTriangles().indexCount; i++, j++) {
_indexBuffer[j] = indices[i] + vertexOffset; _indexBuffer[j] = indices[i] + vertexOffset;
} }
_numVerticesBuffer += command->getTriangles().vertCount; _numVerticesBuffer += command->getTriangles().vertCount;
_numIndicesBuffer += command->getTriangles().indexCount; _numIndicesBuffer += command->getTriangles().indexCount;
if (command->isForceFlush()) { if (command->isForceFlush()) {
flush(renderer, command); flush(renderer, command);
} }
_lastCommand = command; _lastCommand = command;
} }
void SkeletonTwoColorBatch::flush (cocos2d::Renderer *renderer, TwoColorTrianglesCommand* materialCommand) { void SkeletonTwoColorBatch::flush (cocos2d::Renderer *renderer, TwoColorTrianglesCommand* materialCommand) {
if (!materialCommand) if (!materialCommand)
return; return;
materialCommand->updateVertexAndIndexBuffer(renderer, _vertexBuffer, _numVerticesBuffer, _indexBuffer, _numIndicesBuffer); materialCommand->updateVertexAndIndexBuffer(renderer, _vertexBuffer, _numVerticesBuffer, _indexBuffer, _numIndicesBuffer);
renderer->addCommand(materialCommand); renderer->addCommand(materialCommand);
@ -396,3 +404,5 @@ TwoColorTrianglesCommand* SkeletonTwoColorBatch::nextFreeCommand() {
return command; return command;
} }
} }
#endif

View File

@ -1,8 +1,8 @@
/****************************************************************************** /******************************************************************************
* Spine Runtimes License Agreement * Spine Runtimes License Agreement
* Last updated May 1, 2019. Replaces all prior versions. * Last updated January 1, 2020. Replaces all prior versions.
* *
* Copyright (c) 2013-2019, Esoteric Software LLC * Copyright (c) 2013-2020, Esoteric Software LLC
* *
* Integration of the Spine Runtimes into software or otherwise creating * Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and * derivative works of the Spine Runtimes is permitted under the terms and
@ -15,23 +15,25 @@
* Spine Editor license and redistribution of the Products in any form must * Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice. * include this license and copyright notice.
* *
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#ifndef SPINE_SKELETONTWOCOLORBATCH_H_ #ifndef SPINE_SKELETONTWOCOLORBATCH_H_
#define SPINE_SKELETONTWOCOLORBATCH_H_ #define SPINE_SKELETONTWOCOLORBATCH_H_
#define SPINE_SHORT_NAMES
#include <spine/spine.h>
#include "cocos2d.h" #include "cocos2d.h"
#if COCOS2D_VERSION >= 0x00040000
#include <spine/spine.h>
#include <vector> #include <vector>
namespace spine { namespace spine {
@ -99,7 +101,6 @@ namespace spine {
cocos2d::BlendFunc _blendType; cocos2d::BlendFunc _blendType;
TwoColorTriangles _triangles; TwoColorTriangles _triangles;
cocos2d::Mat4 _mv; cocos2d::Mat4 _mv;
GLuint _alphaTextureID;
bool _forceFlush; bool _forceFlush;
}; };
@ -146,7 +147,6 @@ namespace spine {
// VBO handles & attribute locations // VBO handles & attribute locations
GLuint _vertexBufferHandle;
V3F_C4B_C4B_T2F* _vertexBuffer; V3F_C4B_C4B_T2F* _vertexBuffer;
uint32_t _numVerticesBuffer; uint32_t _numVerticesBuffer;
uint32_t _numIndicesBuffer; uint32_t _numIndicesBuffer;
@ -160,4 +160,6 @@ namespace spine {
}; };
} }
#endif
#endif // SPINE_SKELETONTWOCOLORBATCH_H_ #endif // SPINE_SKELETONTWOCOLORBATCH_H_

View File

@ -43,12 +43,12 @@ namespace cocos2d { namespace network {
DownloadTask::DownloadTask(const std::string& srcUrl, DownloadTask::DownloadTask(const std::string& srcUrl,
const std::string& storagePath, const std::string& storagePath,
const std::string& md5checksum, const std::string& checksum,
const std::string& identifier) const std::string& identifier)
{ {
this->requestURL = srcUrl; this->requestURL = srcUrl;
this->storagePath = storagePath; this->storagePath = storagePath;
this->md5checksum = md5checksum; this->checksum = checksum;
this->identifier = identifier; this->identifier = identifier;
} }

File diff suppressed because it is too large Load Diff

View File

@ -52,6 +52,14 @@ int register_all_cocos2dx_spine(lua_State* tolua_S);

View File

@ -48,8 +48,7 @@ LuaSkeletonAnimation::~LuaSkeletonAnimation()
LuaSkeletonAnimation* LuaSkeletonAnimation::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale) LuaSkeletonAnimation* LuaSkeletonAnimation::createWithFile (const char* skeletonDataFile, const char* atlasFile, float scale)
{ {
LuaSkeletonAnimation* node = new (std::nothrow) LuaSkeletonAnimation(); LuaSkeletonAnimation* node = new (std::nothrow) LuaSkeletonAnimation();
static spine::Cocos2dTextureLoader s_loader; spine::Atlas* atlas = new spine::Atlas(atlasFile, nullptr);
spine::Atlas* atlas = new spine::Atlas(atlasFile, &s_loader);
node->initWithJsonFile(skeletonDataFile, atlas, scale); node->initWithJsonFile(skeletonDataFile, atlas, scale);
node->autorelease(); node->autorelease();
return node; return node;

View File

@ -153,8 +153,8 @@ list(APPEND GAME_HEADER
Classes/SceneTest/SceneTest.h Classes/SceneTest/SceneTest.h
Classes/ReleasePoolTest/ReleasePoolTest.h Classes/ReleasePoolTest/ReleasePoolTest.h
Classes/InputTest/MouseTest.h Classes/InputTest/MouseTest.h
# Classes/SpineTest/SpineTest.h Classes/SpineTest/SpineTest.h
# Classes/Scene3DTest/Scene3DTest.h # Classes/Scene3DTest/Scene3DTest.h
Classes/ParticleTest/ParticleTest.h Classes/ParticleTest/ParticleTest.h
Classes/EffectsTest/EffectsTest.h Classes/EffectsTest/EffectsTest.h
Classes/UITest/UITest.h Classes/UITest/UITest.h
@ -278,8 +278,8 @@ list(APPEND GAME_SOURCE
Classes/SchedulerTest/SchedulerTest.cpp Classes/SchedulerTest/SchedulerTest.cpp
Classes/ShaderTest/ShaderTest.cpp Classes/ShaderTest/ShaderTest.cpp
Classes/ShaderTest/ShaderTest2.cpp Classes/ShaderTest/ShaderTest2.cpp
#Classes/SpineTest/SpineTest.cpp Classes/SpineTest/SpineTest.cpp
# Classes/Scene3DTest/Scene3DTest.cpp # Classes/Scene3DTest/Scene3DTest.cpp
Classes/Sprite3DTest/DrawNode3D.cpp Classes/Sprite3DTest/DrawNode3D.cpp
Classes/Sprite3DTest/Sprite3DTest.cpp Classes/Sprite3DTest/Sprite3DTest.cpp
Classes/SpritePolygonTest/SpritePolygonTest.cpp Classes/SpritePolygonTest/SpritePolygonTest.cpp

View File

@ -33,204 +33,452 @@ using namespace cocos2d;
using namespace std; using namespace std;
using namespace spine; using namespace spine;
#define NUM_SKELETONS 50
#define SPINE_NODE_SCALE_FACTOR 0.4
static Cocos2dTextureLoader textureLoader;
PowInterpolation pow2(2);
PowOutInterpolation powOut2(2);
SwirlVertexEffect effect(400, powOut2);
#define SCALE_SKELETON_NODE(node) do { if(node) node->setScale(SPINE_NODE_SCALE_FACTOR); } while(false)
//------------------------------------------------------------------ //------------------------------------------------------------------
// //
// SpineTestScene // SpineTestScene
// //
//------------------------------------------------------------------ //------------------------------------------------------------------
SpineTests::SpineTests() SpineTests::SpineTests()
{ {
auto fu = FileUtils::getInstance();
_searchPaths = fu->getSearchPaths();
fu->addSearchPath("spine", true);
ADD_TEST_CASE(BatchingExample); ADD_TEST_CASE(BatchingExample);
ADD_TEST_CASE(CoinExample); ADD_TEST_CASE(CoinExample);
ADD_TEST_CASE(GoblinsExample); ADD_TEST_CASE(GoblinsExample);
ADD_TEST_CASE(IKExample);
ADD_TEST_CASE(MixAndMatchExample);
ADD_TEST_CASE(RaptorExample); ADD_TEST_CASE(RaptorExample);
ADD_TEST_CASE(SkeletonRendererSeparatorExample);
ADD_TEST_CASE(SpineboyExample); ADD_TEST_CASE(SpineboyExample);
ADD_TEST_CASE(TankExample); ADD_TEST_CASE(TankExample);
#ifdef COCOS2D_DEBUG
debugExtension = new DebugExtension(SpineExtension::getInstance());
#endif
}
SpineTests::~SpineTests()
{
FileUtils::getInstance()->setSearchPaths(_searchPaths);
SkeletonBatch::destroyInstance();
SkeletonTwoColorBatch::destroyInstance();
#ifdef COCOS2D_DEBUG
debugExtension->reportLeaks();
delete debugExtension;
#endif
} }
SpineTestLayer::SpineTestLayer() SpineTestLayer::SpineTestLayer()
: _title("") : _title("")
{} {}
SpineTestLayer::~SpineTestLayer()
{
}
std::string SpineTestLayer::title() const std::string SpineTestLayer::title() const
{ {
return _title; return _title;
} }
bool SpineTestLayer::init()
{
if (!TestCase::init()) return false;
EventListenerTouchOneByOne* listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = [this](Touch* touch, cocos2d::Event* event) -> bool {
if (!skeletonNode) return true;
_touchIndex = (_touchIndex + 1) % 3;
if (_touchIndex == 0)
{
skeletonNode->setDebugBonesEnabled(false);
skeletonNode->setTimeScale(1.0f);
}
else if (_touchIndex == 1)
{
skeletonNode->setDebugBonesEnabled(true);
skeletonNode->setTimeScale(1.0f);
}
else if (_touchIndex == 2)
{
skeletonNode->setDebugBonesEnabled(true);
skeletonNode->setTimeScale(0.3f);
}
return true;
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
SCALE_SKELETON_NODE(skeletonNode);
return true;
}
// BatchingExample // BatchingExample
bool BatchingExample::init () { bool BatchingExample::init () {
if (!SpineTestLayer::init()) return false; if (!SpineTestLayer::init()) return false;
_title = "BatchingExample"; _title = "Batching";
// Load the texture atlas. _atlas = new (__FILE__, __LINE__) Atlas("spineboy.atlas", &textureLoader, true);
_atlas = spAtlas_createFromFile("spine/spineboy.atlas", 0);
CCASSERT(_atlas, "Error reading atlas file."); CCASSERT(_atlas, "Error reading atlas file.");
// This attachment loader configures attachments with data needed for cocos2d-x rendering. // This attachment loader configures attachments with data needed for cocos2d-x rendering.
// Do not dispose the attachment loader until the skeleton data is disposed! // Do not dispose the attachment loader until the skeleton data is disposed!
_attachmentLoader = (spAttachmentLoader*)Cocos2dAttachmentLoader_create(_atlas); _attachmentLoader = new (__FILE__, __LINE__) Cocos2dAtlasAttachmentLoader(_atlas);
// Load the skeleton data. // Load the skeleton data.
spSkeletonJson* json = spSkeletonJson_createWithLoader(_attachmentLoader); SkeletonJson* json = new (__FILE__, __LINE__) SkeletonJson(_attachmentLoader);
json->scale = 0.6f; // Resizes skeleton data to 60% of the size it was in Spine. json->setScale(0.6f); // Resizes skeleton data to 60% of the size it was in Spine.
_skeletonData = spSkeletonJson_readSkeletonDataFile(json, "spine/spineboy-ess.json"); _skeletonData = json->readSkeletonDataFile("spineboy-pro.json");
CCASSERT(_skeletonData, json->error ? json->error : "Error reading skeleton data file."); CCASSERT(_skeletonData, json->getError().isEmpty() ? json->getError().buffer() : "Error reading skeleton data file.");
spSkeletonJson_dispose(json); delete json;
// Setup mix times. // Setup mix times.
_stateData = spAnimationStateData_create(_skeletonData); _stateData = new (__FILE__, __LINE__) AnimationStateData(_skeletonData);
spAnimationStateData_setMixByName(_stateData, "walk", "jump", 0.2f); _stateData->setMix("walk", "jump", 0.2f);
spAnimationStateData_setMixByName(_stateData, "jump", "run", 0.2f); _stateData->setMix("jump", "run", 0.2f);
int xMin = _contentSize.width * 0.10f, xMax = _contentSize.width * 0.90f; int xMin = _contentSize.width * 0.10f, xMax = _contentSize.width * 0.90f;
int yMin = 0, yMax = _contentSize.height * 0.7f; int yMin = 0, yMax = _contentSize.height * 0.7f;
for (int i = 0; i < 50; i++) { for (int i = 0; i < NUM_SKELETONS; i++) {
// Each skeleton node shares the same atlas, skeleton data, and mix times. // Each skeleton node shares the same atlas, skeleton data, and mix times.
SkeletonAnimation* skeletonNode = SkeletonAnimation::createWithData(_skeletonData, false); SkeletonAnimation* skeletonNode = SkeletonAnimation::createWithData(_skeletonData, false);
skeletonNode->setAnimationStateData(_stateData); skeletonNode->setAnimationStateData(_stateData);
skeletonNode->setAnimation(0, "walk", true); skeletonNode->setAnimation(0, "walk", true);
skeletonNode->addAnimation(0, "jump", false, 3); skeletonNode->addAnimation(0, "jump", true, RandomHelper::random_int(0, 300) / 100.0f);
skeletonNode->addAnimation(0, "run", true); skeletonNode->addAnimation(0, "run", true);
// alternative setting two color tint for groups of 10 skeletons
// should end up with #skeletons / 10 batches
// if (j++ < 10)
// skeletonNode->setTwoColorTint(true);
// if (j == 20) j = 0;
// skeletonNode->setTwoColorTint(true);
skeletonNode->setPosition(Vec2( skeletonNode->setPosition(Vec2(
RandomHelper::random_int(xMin, xMax), RandomHelper::random_int(xMin, xMax),
RandomHelper::random_int(yMin, yMax) RandomHelper::random_int(yMin, yMax)
)); ));
skeletonNode->setScale(0.8);
addChild(skeletonNode); addChild(skeletonNode);
} }
SCALE_SKELETON_NODE(skeletonNode);
return true; return true;
} }
BatchingExample::~BatchingExample () {
BatchingExample::~BatchingExample() {
// SkeletonAnimation instances are cocos2d-x nodes and are disposed of automatically as normal, but the data created // SkeletonAnimation instances are cocos2d-x nodes and are disposed of automatically as normal, but the data created
// manually to be shared across multiple SkeletonAnimations needs to be disposed of manually. // manually to be shared across multiple SkeletonAnimations needs to be disposed of manually.
spSkeletonData_dispose(_skeletonData);
spAnimationStateData_dispose(_stateData); delete _skeletonData;
spAttachmentLoader_dispose(_attachmentLoader); delete _stateData;
spAtlas_dispose(_atlas); delete _attachmentLoader;
delete _atlas;
} }
// CoinExample
bool CoinExample::init () { bool CoinExample::init() {
if (!SpineTestLayer::init()) return false; if (!SpineTestLayer::init()) return false;
_title = "CoinExample"; _title = "Coin";
skeletonNode = SkeletonAnimation::createWithJsonFile("spine/coin-pro.json", "spine/coin.atlas", 1.f);
skeletonNode->setAnimation(0, "rotate", true); skeletonNode = SkeletonAnimation::createWithBinaryFile("coin-pro.skel", "coin.atlas", 1);
skeletonNode->setAnimation(0, "animation", true);
skeletonNode->setPosition(Vec2(_contentSize.width / 2, 100));
skeletonNode->setPosition(Vec2(_contentSize.width / 2, _contentSize.height / 2));
addChild(skeletonNode); addChild(skeletonNode);
scheduleUpdate();
SCALE_SKELETON_NODE(skeletonNode);
return true; return true;
} }
// GoblinsExample
bool GoblinsExample::init () {
bool GoblinsExample::init() {
if (!SpineTestLayer::init()) return false; if (!SpineTestLayer::init()) return false;
_title = "GoblinsExample"; _title = "Goblins";
skeletonNode = SkeletonAnimation::createWithJsonFile("goblins-pro.json", "goblins.atlas", 1.5f);
skeletonNode = SkeletonAnimation::createWithJsonFile("spine/goblins-pro.json", "spine/goblins.atlas", 1.5f);
skeletonNode->setAnimation(0, "walk", true); skeletonNode->setAnimation(0, "walk", true);
skeletonNode->setSkin("goblin"); skeletonNode->setSkin("goblin");
skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20)); skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20));
skeletonNode->setScale(0.6);
addChild(skeletonNode); addChild(skeletonNode);
SCALE_SKELETON_NODE(skeletonNode);
return true; return true;
} }
// RaptorExample
bool RaptorExample::init () { bool IKExample::init() {
if (!SpineTestLayer::init()) return false; if (!SpineTestLayer::init()) return false;
_title = "RaptorExample"; _title = "IKExample";
skeletonNode = SkeletonAnimation::createWithJsonFile("spine/raptor-pro.json", "spine/raptor.atlas", 0.5f);
// Load the Spineboy skeleton and create a SkeletonAnimation node from it
skeletonNode->setAnimation(0, "walk", true); // centered on the screen.
skeletonNode->setAnimation(1, "empty", false); skeletonNode = SkeletonAnimation::createWithJsonFile("spineboy-pro.json", "spineboy.atlas", 0.6f);
skeletonNode->addAnimation(1, "gungrab", false, 2);
skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20)); skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20));
skeletonNode->setScale(0.6);
addChild(skeletonNode); addChild(skeletonNode);
// Queue the "walk" animation on the first track.
skeletonNode->setAnimation(0, "walk", true);
// Queue the "aim" animation on a higher track.
// It consists of a single frame that positions
// the back arm and gun such that they point at
// the "crosshair" bone. By setting this
// animation on a higher track, it overrides
// any changes to the back arm and gun made
// by the walk animation, allowing us to
// mix the two. The mouse position following
// is performed in the lambda below.
skeletonNode->setAnimation(1, "aim", true);
// Next we setup a listener that receives and stores
// the current mouse location. The location is converted
// to the skeleton's coordinate system.
EventListenerMouse* mouseListener = EventListenerMouse::create();
mouseListener->onMouseMove = [this](cocos2d::Event* event) -> void {
// convert the mosue location to the skeleton's coordinate space
// and store it.
EventMouse* mouseEvent = dynamic_cast<EventMouse*>(event);
position = skeletonNode->convertToNodeSpace(mouseEvent->getLocationInView());
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(mouseListener, this);
// Position the "crosshair" bone at the mouse
// location.
//
// When setting the crosshair bone position
// to the mouse position, we need to translate
// from "skeleton space" to "local bone space".
// Note that the local bone space is calculated
// using the bone's parent worldToLocal() function!
//
// After updating the bone position based on the
// converted mouse location, we call updateWorldTransforms()
// again so the change of the IK target position is
// applied to the rest of the skeleton.
skeletonNode->setPostUpdateWorldTransformsListener([this](SkeletonAnimation* node) -> void {
Bone* crosshair = node->findBone("crosshair"); // The bone should be cached
float localX = 0, localY = 0;
crosshair->getParent()->worldToLocal(position.x, position.y, localX, localY);
crosshair->setX(localX);
crosshair->setY(localY);
crosshair->setAppliedValid(false);
node->getSkeleton()->updateWorldTransform();
});
SCALE_SKELETON_NODE(skeletonNode);
return true; return true;
} }
// SpineboyExample
bool SpineboyExample::init () {
MixAndMatchExample::~MixAndMatchExample() {
delete skin;
}
bool MixAndMatchExample::init() {
if (!SpineTestLayer::init()) return false; if (!SpineTestLayer::init()) return false;
_title = "SpineboyExample"; _title = "Mix and Match";
skeletonNode = SkeletonAnimation::createWithJsonFile("spine/spineboy-ess.json", "spine/spineboy.atlas", 0.6f);
skeletonNode->setStartListener( [] (spTrackEntry* entry) { skeletonNode = SkeletonAnimation::createWithBinaryFile("mix-and-match-pro.skel", "mix-and-match.atlas", 0.5);
log("%d start: %s", entry->trackIndex, entry->animation->name); skeletonNode->setAnimation(0, "dance", true);
});
skeletonNode->setInterruptListener( [] (spTrackEntry* entry) { // Create a new skin, by mixing and matching other skins
log("%d interrupt", entry->trackIndex); // that fit together. Items making up the girl are individual
}); // skins. Using the skin API, a new skin is created which is
skeletonNode->setEndListener( [] (spTrackEntry* entry) { // a combination of all these individual item skins.
log("%d end", entry->trackIndex); SkeletonData* skeletonData = skeletonNode->getSkeleton()->getData();
}); skin = new (__FILE__, __LINE__) Skin("mix-and-match");
skeletonNode->setCompleteListener( [] (spTrackEntry* entry) { skin->addSkin(skeletonData->findSkin("skin-base"));
log("%d complete", entry->trackIndex); skin->addSkin(skeletonData->findSkin("nose/short"));
}); skin->addSkin(skeletonData->findSkin("eyelids/girly"));
skeletonNode->setDisposeListener( [] (spTrackEntry* entry) { skin->addSkin(skeletonData->findSkin("eyes/violet"));
log("%d dispose", entry->trackIndex); skin->addSkin(skeletonData->findSkin("hair/brown"));
}); skin->addSkin(skeletonData->findSkin("clothes/hoodie-orange"));
skeletonNode->setEventListener( [] (spTrackEntry* entry, spEvent* event) { skin->addSkin(skeletonData->findSkin("legs/pants-jeans"));
log("%d event: %s, %d, %f, %s", entry->trackIndex, event->data->name, event->intValue, event->floatValue, event->stringValue); skin->addSkin(skeletonData->findSkin("accessories/bag"));
}); skin->addSkin(skeletonData->findSkin("accessories/hat-red-yellow"));
skeletonNode->getSkeleton()->setSkin(skin);
skeletonNode->setMix("walk", "jump", 0.4);
skeletonNode->setMix("jump", "run", 0.4); skeletonNode->setPosition(Vec2(_contentSize.width / 2, _contentSize.height / 2 - 100 ));
skeletonNode->setAnimation(0, "walk", true);
spTrackEntry* jumpEntry = skeletonNode->addAnimation(0, "jump", false, 1);
skeletonNode->addAnimation(0, "run", true);
skeletonNode->setTrackStartListener(jumpEntry, [] (spTrackEntry* entry) {
log("jumped!");
});
// skeletonNode->addAnimation(1, "test", true);
// skeletonNode->runAction(RepeatForever::create(Sequence::create(FadeOut::create(1), FadeIn::create(1), DelayTime::create(5), NULL)));
skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20));
skeletonNode->setScale(0.8);
addChild(skeletonNode); addChild(skeletonNode);
SCALE_SKELETON_NODE(skeletonNode);
return true;
}
bool RaptorExample::init() {
if (!SpineTestLayer::init()) return false;
_title = "Raptor";
skeletonNode = SkeletonAnimation::createWithJsonFile("raptor-pro.json", "raptor.atlas", 0.5f);
skeletonNode->setAnimation(0, "walk", true);
skeletonNode->addAnimation(1, "gun-grab", false, 2);
skeletonNode->setTwoColorTint(true);
effect.setCenterY(200);
swirlTime = 0;
skeletonNode->setVertexEffect(&effect);
skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20));
addChild(skeletonNode);
scheduleUpdate(); scheduleUpdate();
SCALE_SKELETON_NODE(skeletonNode);
return true; return true;
} }
void SpineboyExample::update (float deltaTime) { void RaptorExample::update(float fDelta) {
swirlTime += fDelta;
float percent = spine::MathUtil::fmod(swirlTime, 2);
if (percent > 1) percent = 1 - (percent - 1);
effect.setAngle(pow2.interpolate(-60.0f, 60.0f, percent));
}
bool SkeletonRendererSeparatorExample::init() {
if (!SpineTestLayer::init()) return false;
_title = "Seperator";
// Spineboy's back, which will manage the animation and GPU resources
// will render only the front slots of Spineboy
skeletonNode = SkeletonAnimation::createWithJsonFile("spineboy-pro.json", "spineboy.atlas", 0.6f);
skeletonNode->setMix("walk", "jump", 0.4);
skeletonNode->setAnimation(0, "walk", true);
skeletonNode->setSlotsRange(skeletonNode->findSlot("rear-upper-arm")->getData().getIndex(), skeletonNode->findSlot("rear-shin")->getData().getIndex());
skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20));
// A simple rectangle to go between the front and back slots of Spineboy
betweenNode = DrawNode::create();
Vec2 rect[4];
rect[0] = Vec2(0, 0);
rect[1] = Vec2(40, 0);
rect[2] = Vec2(40, 200);
rect[3] = Vec2(0, 200);
betweenNode->drawPolygon(rect, 4, Color4F(1, 0, 0, 1), 1, Color4F(1, 0, 0, 1));
betweenNode->setPosition(Vec2(_contentSize.width / 2 + 30, 20));
// Spineboy's front, doesn't manage any skeleton, animation or GPU resources, but simply
// renders the back slots of Spineboy. The skeleton, animatio state and GPU resources
// are shared with the front node!
frontNode = SkeletonRenderer::createWithSkeleton(skeletonNode->getSkeleton());
frontNode->setSlotsRange(frontNode->findSlot("neck")->getData().getIndex(), -1);
frontNode->setPosition(Vec2(_contentSize.width / 2, 20));
// Add the front, between and back node in the correct order to this scene
addChild(skeletonNode);
addChild(betweenNode);
addChild(frontNode);
scheduleUpdate();
SCALE_SKELETON_NODE(skeletonNode);
SCALE_SKELETON_NODE(frontNode);
return true;
}
void SkeletonRendererSeparatorExample::update(float deltaTime) {
// Test releasing memory. // Test releasing memory.
// Director::getInstance()->replaceScene(SpineboyExample::scene()); // Director::getInstance()->replaceScene(SpineboyExample::scene());
} }
// TankExample
bool TankExample::init () { bool SpineboyExample::init() {
if (!SpineTestLayer::init()) return false; if (!SpineTestLayer::init()) return false;
_title = "TankExample"; _title = "Spineboy";
skeletonNode = SkeletonAnimation::createWithJsonFile("spine/tank-pro.json", "spine/tank.atlas", 0.5f);
skeletonNode->setAnimation(0, "drive", true); skeletonNode = SkeletonAnimation::createWithJsonFile("spineboy-pro.json", "spineboy.atlas", 0.6f);
skeletonNode->setPosition(Vec2(_contentSize.width / 2 + 400, 20)); skeletonNode->setStartListener([](TrackEntry* entry) {
skeletonNode->setScale(0.8); log("%d start: %s", entry->getTrackIndex(), entry->getAnimation()->getName().buffer());
});
skeletonNode->setInterruptListener([](TrackEntry* entry) {
log("%d interrupt", entry->getTrackIndex());
});
skeletonNode->setEndListener([](TrackEntry* entry) {
log("%d end", entry->getTrackIndex());
});
skeletonNode->setCompleteListener([](TrackEntry* entry) {
log("%d complete", entry->getTrackIndex());
});
skeletonNode->setDisposeListener([](TrackEntry* entry) {
log("%d dispose", entry->getTrackIndex());
});
skeletonNode->setEventListener([](TrackEntry* entry, spine::Event* event) {
log("%d event: %s, %d, %f, %s", entry->getTrackIndex(), event->getData().getName().buffer(), event->getIntValue(), event->getFloatValue(), event->getStringValue().buffer());
});
skeletonNode->setMix("walk", "jump", 0.4);
skeletonNode->setMix("jump", "run", 0.4);
skeletonNode->setAnimation(0, "walk", true);
TrackEntry* jumpEntry = skeletonNode->addAnimation(0, "jump", false, 1);
skeletonNode->addAnimation(0, "run", true);
skeletonNode->setTrackStartListener(jumpEntry, [](TrackEntry* entry) {
log("jumped!");
});
// skeletonNode->addAnimation(1, "test", true);
// skeletonNode->runAction(RepeatForever::create(Sequence::create(FadeOut::create(1), FadeIn::create(1), DelayTime::create(5), NULL)));
skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20));
addChild(skeletonNode); addChild(skeletonNode);
scheduleUpdate();
SCALE_SKELETON_NODE(skeletonNode);
return true;
}
void SpineboyExample::update(float deltaTime) {
// Test releasing memory.
// Director::getInstance()->replaceScene(SpineboyExample::scene());
}
bool TankExample::init() {
if (!SpineTestLayer::init()) return false;
_title = "Tank";
skeletonNode = SkeletonAnimation::createWithBinaryFile("tank-pro.skel", "tank.atlas", 0.5f);
skeletonNode->setAnimation(0, "shoot", true);
skeletonNode->setPosition(Vec2(_contentSize.width / 2 + 400, 20));
addChild(skeletonNode);
SCALE_SKELETON_NODE(skeletonNode);
return true; return true;
} }

View File

@ -30,83 +30,138 @@
#include "../BaseTest.h" #include "../BaseTest.h"
#include <spine/spine-cocos2dx.h> #include <spine/spine-cocos2dx.h>
DEFINE_TEST_SUITE(SpineTests); #ifdef COCOS2D_DEBUG
#include <spine/Debug.h>
#endif
//DEFINE_TEST_SUITE(SpineTests);
class SpineTests : public TestSuite
{
public:
SpineTests();
virtual ~SpineTests();
private:
std::vector<std::string> _searchPaths;
#ifdef COCOS2D_DEBUG
spine::DebugExtension* debugExtension = nullptr;
#endif
};
class SpineTestLayer : public TestCase class SpineTestLayer : public TestCase
{ {
public: public:
SpineTestLayer(); SpineTestLayer();
virtual ~SpineTestLayer();
virtual std::string title() const;
virtual bool init();
virtual std::string title() const override;
protected: protected:
std::string _title; std::string _title;
spine::SkeletonAnimation* skeletonNode = nullptr;
int _touchIndex = 0;
}; };
class BatchingExample: public SpineTestLayer {
class BatchingExample : public SpineTestLayer {
public: public:
CREATE_FUNC(BatchingExample); CREATE_FUNC(BatchingExample);
~BatchingExample (); ~BatchingExample();
virtual bool init ();
protected:
spAtlas* _atlas;
spAttachmentLoader* _attachmentLoader;
spSkeletonData* _skeletonData;
spAnimationStateData* _stateData;
};
class CoinExample: public SpineTestLayer
{
public:
CREATE_FUNC(CoinExample);
virtual bool init(); virtual bool init();
private: protected:
spine::SkeletonAnimation* skeletonNode; spine::Atlas* _atlas;
spine::AttachmentLoader* _attachmentLoader;
spine::SkeletonData* _skeletonData;
spine::AnimationStateData* _stateData;
}; };
class CoinExample : public SpineTestLayer {
public:
CREATE_FUNC(CoinExample);
virtual bool init();
};
class GoblinsExample : public SpineTestLayer { class GoblinsExample : public SpineTestLayer {
public: public:
CREATE_FUNC(GoblinsExample); CREATE_FUNC(GoblinsExample);
virtual bool init (); virtual bool init ();
};
class IKExample : public SpineTestLayer {
public:
CREATE_FUNC(IKExample);
virtual bool init();
private: private:
spine::SkeletonAnimation* skeletonNode; cocos2d::Vec2 position;
};
class MixAndMatchExample : public SpineTestLayer {
public:
CREATE_FUNC(MixAndMatchExample);
virtual bool init();
virtual ~MixAndMatchExample();
private:
spine::Skin* skin;
}; };
class RaptorExample : public SpineTestLayer { class RaptorExample : public SpineTestLayer {
public: public:
CREATE_FUNC(RaptorExample); CREATE_FUNC(RaptorExample);
virtual bool init (); virtual bool init();
virtual void update(float fDelta);
private: private:
spine::SkeletonAnimation* skeletonNode; float swirlTime;
};
class SkeletonRendererSeparatorExample : public SpineTestLayer {
public:
CREATE_FUNC(SkeletonRendererSeparatorExample);
virtual bool init();
virtual void update(float deltaTime);
private:
spine::SkeletonRenderer* frontNode;
cocos2d::DrawNode* betweenNode;
}; };
class SpineboyExample : public SpineTestLayer { class SpineboyExample : public SpineTestLayer {
public: public:
CREATE_FUNC (SpineboyExample); CREATE_FUNC(SpineboyExample);
virtual bool init (); virtual bool init();
virtual void update (float deltaTime); virtual void update(float deltaTime);
private:
spine::SkeletonAnimation* skeletonNode;
}; };
class TankExample : public SpineTestLayer { class TankExample : public SpineTestLayer {
public: public:
CREATE_FUNC(TankExample); CREATE_FUNC(TankExample);
virtual bool init (); virtual bool init();
private:
spine::SkeletonAnimation* skeletonNode;
}; };
#endif // _EXAMPLELAYER_H_ #endif // _EXAMPLELAYER_H_

View File

@ -93,7 +93,7 @@ public:
addTest("Node: Physics3D", []() { return new Physics3DTests(); } ); addTest("Node: Physics3D", []() { return new Physics3DTests(); } );
addTest("Node: RenderTexture", [](){return new RenderTextureTests(); }); addTest("Node: RenderTexture", [](){return new RenderTextureTests(); });
addTest("Node: Scene", [](){return new SceneTests(); }); addTest("Node: Scene", [](){return new SceneTests(); });
// addTest("Node: Spine", [](){return new SpineTests(); }); addTest("Node: Spine", [](){return new SpineTests(); });
addTest("Node: Sprite", [](){return new SpriteTests(); }); addTest("Node: Sprite", [](){return new SpriteTests(); });
addTest("Node: Sprite3D", [](){ return new Sprite3DTests(); }); addTest("Node: Sprite3D", [](){ return new Sprite3DTests(); });
addTest("Node: SpritePolygon", [](){return new (std::nothrow) SpritePolygonTest(); }); addTest("Node: SpritePolygon", [](){return new (std::nothrow) SpritePolygonTest(); });

Binary file not shown.

View File

@ -1,26 +1,54 @@
coin.png coin.png
size: 1024,256 size: 1024,1024
format: RGBA8888 format: RGBA8888
filter: Linear,Linear filter: Linear,Linear
repeat: none repeat: none
coin coin-front-logo
rotate: false rotate: false
xy: 2, 2 xy: 2, 609
size: 259, 245 size: 305, 302
orig: 259, 245 orig: 305, 302
offset: 0, 0 offset: 0, 0
index: -1 index: -1
coin-invert coin-front-shine-logo
rotate: false rotate: false
xy: 263, 2 xy: 309, 629
size: 259, 245 size: 282, 282
orig: 259, 245 orig: 282, 282
offset: 0, 0
index: -1
coin-front-shine-spineboy
rotate: false
xy: 2, 21
size: 282, 282
orig: 282, 282
offset: 0, 0
index: -1
coin-front-spineboy
rotate: false
xy: 2, 305
size: 305, 302
orig: 305, 302
offset: 0, 0
index: -1
coin-side-round
rotate: false
xy: 309, 345
size: 144, 282
orig: 144, 282
offset: 0, 0
index: -1
coin-side-straight
rotate: true
xy: 2, 2
size: 17, 282
orig: 17, 282
offset: 0, 0 offset: 0, 0
index: -1 index: -1
shine shine
rotate: false rotate: false
xy: 524, 2 xy: 593, 666
size: 72, 245 size: 72, 245
orig: 72, 245 orig: 72, 245
offset: 0, 0 offset: 0, 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 393 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 KiB

File diff suppressed because one or more lines are too long

View File

@ -1,299 +1,271 @@
raptor.png raptor.png
size: 1024,1024 size: 1024,512
format: RGBA8888 format: RGBA8888
filter: Linear,Linear filter: Linear,Linear
repeat: none repeat: none
back-arm back-arm
rotate: true rotate: false
xy: 274, 394 xy: 895, 295
size: 46, 29 size: 46, 25
orig: 46, 29 orig: 46, 25
offset: 0, 0 offset: 0, 0
index: -1 index: -1
back-bracer back-bracer
rotate: true rotate: true
xy: 140, 247 xy: 992, 216
size: 39, 28 size: 39, 28
orig: 39, 28 orig: 39, 28
offset: 0, 0 offset: 0, 0
index: -1 index: -1
back-hand back-hand
rotate: false rotate: false
xy: 824, 699 xy: 594, 58
size: 36, 34 size: 36, 34
orig: 36, 34 orig: 36, 34
offset: 0, 0 offset: 0, 0
index: -1 index: -1
back-knee back-knee
rotate: false rotate: true
xy: 360, 507 xy: 729, 86
size: 49, 67 size: 49, 67
orig: 49, 67 orig: 49, 67
offset: 0, 0 offset: 0, 0
index: -1 index: -1
back-thigh back-thigh
rotate: true rotate: false
xy: 140, 206 xy: 379, 2
size: 39, 24 size: 39, 24
orig: 39, 24 orig: 39, 24
offset: 0, 0 offset: 0, 0
index: -1 index: -1
dust01
rotate: false
xy: 219, 299
size: 48, 37
orig: 48, 37
offset: 0, 0
index: -1
dust02
rotate: false
xy: 895, 833
size: 43, 44
orig: 43, 44
offset: 0, 0
index: -1
dust03
rotate: true
xy: 167, 445
size: 31, 26
orig: 31, 26
offset: 0, 0
index: -1
eyes-open eyes-open
rotate: true rotate: true
xy: 2, 2 xy: 902, 194
size: 47, 45 size: 47, 45
orig: 47, 45 orig: 47, 45
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-arm front-arm
rotate: false rotate: false
xy: 470, 544 xy: 945, 306
size: 48, 30 size: 48, 26
orig: 48, 30 orig: 48, 26
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-bracer front-bracer
rotate: true rotate: false
xy: 274, 351 xy: 949, 197
size: 41, 29 size: 41, 29
orig: 41, 29 orig: 41, 29
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-hand front-hand
rotate: false rotate: false
xy: 827, 773 xy: 949, 266
size: 41, 38 size: 41, 38
orig: 41, 38 orig: 41, 38
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-open-hand front-open-hand
rotate: false rotate: false
xy: 360, 461 xy: 875, 148
size: 43, 44 size: 43, 44
orig: 43, 44 orig: 43, 44
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-thigh front-thigh
rotate: false rotate: true
xy: 411, 545 xy: 793, 171
size: 57, 29 size: 57, 29
orig: 57, 29 orig: 57, 29
offset: 0, 0 offset: 0, 0
index: -1 index: -1
gun gun
rotate: false rotate: true
xy: 195, 442 xy: 379, 28
size: 107, 103 size: 107, 103
orig: 107, 103 orig: 107, 103
offset: 0, 0 offset: 0, 0
index: -1 index: -1
gun-nohand gun-nohand
rotate: false rotate: false
xy: 167, 338 xy: 487, 87
size: 105, 102 size: 105, 102
orig: 105, 102 orig: 105, 102
offset: 0, 0 offset: 0, 0
index: -1 index: -1
head head
rotate: false rotate: false
xy: 2, 137 xy: 807, 361
size: 136, 149 size: 136, 149
orig: 136, 149 orig: 136, 149
offset: 0, 0 offset: 0, 0
index: -1 index: -1
lower-leg lower-leg
rotate: true rotate: false
xy: 648, 667 xy: 827, 195
size: 73, 98 size: 73, 98
orig: 73, 98 orig: 73, 98
offset: 0, 0 offset: 0, 0
index: -1 index: -1
mouth-grind mouth-grind
rotate: true rotate: true
xy: 49, 2 xy: 920, 145
size: 47, 30 size: 47, 30
orig: 47, 30 orig: 47, 30
offset: 0, 0 offset: 0, 0
index: -1 index: -1
mouth-smile mouth-smile
rotate: true rotate: true
xy: 81, 2 xy: 992, 257
size: 47, 30 size: 47, 30
orig: 47, 30 orig: 47, 30
offset: 0, 0 offset: 0, 0
index: -1 index: -1
neck neck
rotate: false rotate: false
xy: 626, 631 xy: 359, 114
size: 18, 21 size: 18, 21
orig: 18, 21 orig: 18, 21
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-arm-back raptor-back-arm
rotate: true rotate: false
xy: 538, 570 xy: 653, 142
size: 82, 86 size: 82, 86
orig: 82, 86 orig: 82, 86
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-body raptor-body
rotate: false rotate: false
xy: 2, 737 xy: 2, 277
size: 632, 285 size: 632, 233
orig: 632, 285 orig: 632, 233
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-front-arm raptor-front-arm
rotate: true rotate: true
xy: 544, 654 xy: 484, 4
size: 81, 102 size: 81, 102
orig: 81, 102 orig: 81, 102
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-front-leg raptor-front-leg
rotate: false rotate: false
xy: 2, 478 xy: 2, 18
size: 191, 257 size: 191, 257
orig: 191, 257 orig: 191, 257
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-hindleg-back raptor-hindleg-back
rotate: false rotate: false
xy: 636, 807 xy: 636, 295
size: 169, 215 size: 169, 215
orig: 169, 215 orig: 169, 215
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-horn raptor-horn
rotate: false rotate: false
xy: 360, 655 xy: 195, 22
size: 182, 80 size: 182, 80
orig: 182, 80 orig: 182, 80
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-horn-back raptor-horn-back
rotate: false rotate: true
xy: 360, 576 xy: 945, 334
size: 176, 77 size: 176, 77
orig: 176, 77 orig: 176, 77
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-jaw raptor-jaw
rotate: false rotate: false
xy: 807, 879 xy: 359, 137
size: 153, 143 size: 126, 138
orig: 153, 143 orig: 126, 138
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-jaw-tooth raptor-jaw-tooth
rotate: true rotate: true
xy: 940, 840 xy: 895, 322
size: 37, 48 size: 37, 48
orig: 37, 48 orig: 37, 48
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-mouth-inside raptor-mouth-inside
rotate: true rotate: true
xy: 827, 735 xy: 949, 228
size: 36, 41 size: 36, 41
orig: 36, 41 orig: 36, 41
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-saddle-noshadow raptor-saddle-strap-back
rotate: false
xy: 2, 288
size: 163, 188
orig: 163, 188
offset: 0, 0
index: -1
raptor-saddle-strap-front
rotate: false
xy: 962, 927
size: 57, 95
orig: 57, 95
offset: 0, 0
index: -1
raptor-saddle-strap-rear
rotate: true rotate: true
xy: 748, 686 xy: 653, 86
size: 54, 74 size: 54, 74
orig: 54, 74 orig: 54, 74
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-saddle-strap-front
rotate: false
xy: 594, 94
size: 57, 95
orig: 57, 95
offset: 0, 0
index: -1
raptor-saddle-w-shadow raptor-saddle-w-shadow
rotate: false rotate: false
xy: 195, 547 xy: 195, 104
size: 163, 188 size: 162, 171
orig: 163, 188 orig: 162, 171
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-tail-shadow raptor-tail-shadow
rotate: false rotate: false
xy: 636, 742 xy: 636, 230
size: 189, 63 size: 189, 63
orig: 189, 63 orig: 189, 63
offset: 0, 0 offset: 0, 0
index: -1 index: -1
raptor-tongue raptor-tongue
rotate: false rotate: false
xy: 807, 813 xy: 807, 295
size: 86, 64 size: 86, 64
orig: 86, 64 orig: 86, 64
offset: 0, 0 offset: 0, 0
index: -1 index: -1
stirrup-back stirrup-back
rotate: false rotate: true
xy: 411, 508 xy: 952, 151
size: 44, 35 size: 44, 35
orig: 44, 35 orig: 44, 35
offset: 0, 0 offset: 0, 0
index: -1 index: -1
stirrup-front stirrup-front
rotate: true rotate: false
xy: 167, 291 xy: 902, 243
size: 45, 50 size: 45, 50
orig: 45, 50 orig: 45, 50
offset: 0, 0 offset: 0, 0
index: -1 index: -1
stirrup-strap stirrup-strap
rotate: false rotate: false
xy: 962, 879 xy: 824, 147
size: 49, 46 size: 49, 46
orig: 49, 46 orig: 49, 46
offset: 0, 0 offset: 0, 0
index: -1 index: -1
torso torso
rotate: false rotate: false
xy: 304, 454 xy: 737, 137
size: 54, 91 size: 54, 91
orig: 54, 91 orig: 54, 91
offset: 0, 0 offset: 0, 0
index: -1 index: -1
visor visor
rotate: false rotate: false
xy: 2, 51 xy: 487, 191
size: 131, 84 size: 131, 84
orig: 131, 84 orig: 131, 84
offset: 0, 0 offset: 0, 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 KiB

After

Width:  |  Height:  |  Size: 469 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,306 +1,285 @@
spineboy.png spineboy.png
size: 1024,512 size: 1024,256
format: RGBA8888 format: RGBA8888
filter: Linear,Linear filter: Linear,Linear
repeat: none repeat: none
crosshair crosshair
rotate: false rotate: false
xy: 794, 167 xy: 352, 7
size: 45, 45 size: 45, 45
orig: 45, 45 orig: 45, 45
offset: 0, 0 offset: 0, 0
index: -1 index: -1
dust01
rotate: false
xy: 960, 190
size: 48, 37
orig: 48, 37
offset: 0, 0
index: -1
dust02
rotate: false
xy: 392, 2
size: 43, 44
orig: 43, 44
offset: 0, 0
index: -1
dust03
rotate: false
xy: 841, 163
size: 31, 26
orig: 31, 26
offset: 0, 0
index: -1
eye-indifferent eye-indifferent
rotate: false rotate: false
xy: 960, 229 xy: 862, 105
size: 47, 45 size: 47, 45
orig: 47, 45 orig: 47, 45
offset: 0, 0 offset: 0, 0
index: -1 index: -1
eye-surprised eye-surprised
rotate: false rotate: false
xy: 745, 167 xy: 505, 79
size: 47, 45 size: 47, 45
orig: 47, 45 orig: 47, 45
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-bracer front-bracer
rotate: false rotate: false
xy: 547, 2 xy: 826, 66
size: 29, 40 size: 29, 40
orig: 29, 40 orig: 29, 40
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-fist-closed front-fist-closed
rotate: false rotate: false
xy: 920, 190 xy: 786, 65
size: 38, 41 size: 38, 41
orig: 38, 41 orig: 38, 41
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-fist-open front-fist-open
rotate: false rotate: true
xy: 437, 2 xy: 710, 51
size: 43, 44 size: 43, 44
orig: 43, 44 orig: 43, 44
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-foot front-foot
rotate: false rotate: false
xy: 482, 11 xy: 210, 6
size: 63, 35 size: 63, 35
orig: 63, 35 orig: 63, 35
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-shin front-shin
rotate: true rotate: true
xy: 866, 233 xy: 665, 128
size: 41, 92 size: 41, 92
orig: 41, 92 orig: 41, 92
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-thigh front-thigh
rotate: false rotate: true
xy: 719, 155 xy: 2, 2
size: 24, 56 size: 23, 56
orig: 24, 56 orig: 23, 56
offset: 0, 0 offset: 0, 0
index: -1 index: -1
front-upper-arm front-upper-arm
rotate: false rotate: false
xy: 719, 104 xy: 250, 205
size: 27, 49 size: 23, 49
orig: 27, 49 orig: 23, 49
offset: 0, 0 offset: 0, 0
index: -1 index: -1
goggles goggles
rotate: false rotate: false
xy: 881, 276 xy: 665, 171
size: 131, 83 size: 131, 83
orig: 131, 83 orig: 131, 83
offset: 0, 0 offset: 0, 0
index: -1 index: -1
gun gun
rotate: false rotate: false
xy: 612, 109 xy: 798, 152
size: 105, 102 size: 105, 102
orig: 105, 102 orig: 105, 102
offset: 0, 0 offset: 0, 0
index: -1 index: -1
head head
rotate: false rotate: false
xy: 881, 361 xy: 2, 27
size: 136, 149 size: 136, 149
orig: 136, 149 orig: 136, 149
offset: 0, 0 offset: 0, 0
index: -1 index: -1
hoverboard-board hoverboard-board
rotate: false rotate: false
xy: 2, 38 xy: 2, 178
size: 246, 76 size: 246, 76
orig: 246, 76 orig: 246, 76
offset: 0, 0 offset: 0, 0
index: -1 index: -1
hoverboard-thruster hoverboard-thruster
rotate: true rotate: true
xy: 578, 12 xy: 722, 96
size: 30, 32 size: 30, 32
orig: 30, 32 orig: 30, 32
offset: 0, 0 offset: 0, 0
index: -1 index: -1
hoverglow-small hoverglow-small
rotate: true rotate: false
xy: 572, 44 xy: 275, 81
size: 137, 38 size: 137, 38
orig: 137, 38 orig: 137, 38
offset: 0, 0 offset: 0, 0
index: -1 index: -1
mouth-grind mouth-grind
rotate: true rotate: false
xy: 713, 55 xy: 614, 97
size: 47, 30 size: 47, 30
orig: 47, 30 orig: 47, 30
offset: 0, 0 offset: 0, 0
index: -1 index: -1
mouth-oooo mouth-oooo
rotate: true rotate: false
xy: 713, 6 xy: 612, 65
size: 47, 30 size: 47, 30
orig: 47, 30 orig: 47, 30
offset: 0, 0 offset: 0, 0
index: -1 index: -1
mouth-smile mouth-smile
rotate: false rotate: false
xy: 748, 135 xy: 661, 64
size: 47, 30 size: 47, 30
orig: 47, 30 orig: 47, 30
offset: 0, 0 offset: 0, 0
index: -1 index: -1
muzzle-glow muzzle-glow
rotate: false rotate: false
xy: 612, 8 xy: 382, 54
size: 99, 99 size: 25, 25
orig: 99, 99 orig: 25, 25
offset: 0, 0 offset: 0, 0
index: -1 index: -1
muzzle-ring muzzle-ring
rotate: false rotate: true
xy: 302, 190 xy: 275, 54
size: 25, 105 size: 25, 105
orig: 25, 105 orig: 25, 105
offset: 0, 0 offset: 0, 0
index: -1 index: -1
muzzle01 muzzle01
rotate: false rotate: true
xy: 336, 335 xy: 911, 95
size: 271, 175 size: 67, 40
orig: 271, 175 orig: 67, 40
offset: 0, 0 offset: 0, 0
index: -1 index: -1
muzzle02 muzzle02
rotate: false rotate: false
xy: 609, 341 xy: 792, 108
size: 270, 169 size: 68, 42
orig: 270, 169 orig: 68, 42
offset: 0, 0 offset: 0, 0
index: -1 index: -1
muzzle03 muzzle03
rotate: false rotate: true
xy: 2, 297 xy: 956, 171
size: 332, 213 size: 83, 53
orig: 332, 213 orig: 83, 53
offset: 0, 0 offset: 0, 0
index: -1 index: -1
muzzle04 muzzle04
rotate: false rotate: false
xy: 2, 116 xy: 275, 7
size: 298, 179 size: 75, 45
orig: 298, 179 orig: 75, 45
offset: 0, 0 offset: 0, 0
index: -1 index: -1
muzzle05 muzzle05
rotate: false rotate: false
xy: 336, 183 xy: 140, 3
size: 269, 150 size: 68, 38
orig: 269, 150 orig: 68, 38
offset: 0, 0 offset: 0, 0
index: -1 index: -1
neck neck
rotate: false rotate: false
xy: 841, 191 xy: 250, 182
size: 18, 21 size: 18, 21
orig: 18, 21 orig: 18, 21
offset: 0, 0 offset: 0, 0
index: -1 index: -1
portal-bg portal-bg
rotate: false rotate: false
xy: 302, 48 xy: 140, 43
size: 133, 133 size: 133, 133
orig: 133, 133 orig: 133, 133
offset: 0, 0 offset: 0, 0
index: -1 index: -1
portal-flare1 portal-flare1
rotate: false rotate: false
xy: 180, 6 xy: 554, 65
size: 56, 30 size: 56, 30
orig: 56, 30 orig: 56, 30
offset: 0, 0 offset: 0, 0
index: -1 index: -1
portal-flare2 portal-flare2
rotate: false rotate: true
xy: 2, 5 xy: 759, 112
size: 57, 31 size: 57, 31
orig: 57, 31 orig: 57, 31
offset: 0, 0 offset: 0, 0
index: -1 index: -1
portal-flare3 portal-flare3
rotate: false rotate: false
xy: 61, 6 xy: 554, 97
size: 58, 30 size: 58, 30
orig: 58, 30 orig: 58, 30
offset: 0, 0 offset: 0, 0
index: -1 index: -1
portal-shade portal-shade
rotate: false rotate: false
xy: 437, 48 xy: 275, 121
size: 133, 133 size: 133, 133
orig: 133, 133 orig: 133, 133
offset: 0, 0 offset: 0, 0
index: -1 index: -1
portal-streaks1 portal-streaks1
rotate: true rotate: false
xy: 609, 213 xy: 410, 126
size: 126, 128 size: 126, 128
orig: 126, 128 orig: 126, 128
offset: 0, 0 offset: 0, 0
index: -1 index: -1
portsl-streaks2 portal-streaks2
rotate: false rotate: false
xy: 739, 214 xy: 538, 129
size: 125, 125 size: 125, 125
orig: 125, 125 orig: 125, 125
offset: 0, 0 offset: 0, 0
index: -1 index: -1
rear-bracer rear-bracer
rotate: true rotate: false
xy: 797, 137 xy: 857, 67
size: 28, 36 size: 28, 36
orig: 28, 36 orig: 28, 36
offset: 0, 0 offset: 0, 0
index: -1 index: -1
rear-foot rear-foot
rotate: false rotate: false
xy: 121, 6 xy: 663, 96
size: 57, 30 size: 57, 30
orig: 57, 30 orig: 57, 30
offset: 0, 0 offset: 0, 0
index: -1 index: -1
rear-shin rear-shin
rotate: true rotate: true
xy: 301, 8 xy: 414, 86
size: 38, 89 size: 38, 89
orig: 38, 89 orig: 38, 89
offset: 0, 0 offset: 0, 0
index: -1 index: -1
rear-thigh rear-thigh
rotate: true rotate: false
xy: 866, 198 xy: 756, 63
size: 33, 52 size: 28, 47
orig: 33, 52 orig: 28, 47
offset: 0, 0 offset: 0, 0
index: -1 index: -1
rear-upper-arm rear-upper-arm
rotate: true rotate: true
xy: 748, 109 xy: 60, 5
size: 24, 44 size: 20, 44
orig: 24, 44 orig: 20, 44
offset: 0, 0 offset: 0, 0
index: -1 index: -1
torso torso
rotate: false rotate: false
xy: 250, 24 xy: 905, 164
size: 49, 90 size: 49, 90
orig: 49, 90 orig: 49, 90
offset: 0, 0 offset: 0, 0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 572 KiB

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 KiB

After

Width:  |  Height:  |  Size: 597 KiB