mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[cpp] Port cf45806b, 409bf9d6, 0e16ef9c from libgdx
This commit is contained in:
parent
2ba91231f3
commit
275e702bc8
74
spine-cpp/include/spine/DrawOrderFolderTimeline.h
Normal file
74
spine-cpp/include/spine/DrawOrderFolderTimeline.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Spine Runtimes License Agreement
|
||||||
|
* Last updated April 5, 2025. Replaces all prior versions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2025, 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_DrawOrderFolderTimeline_h
|
||||||
|
#define Spine_DrawOrderFolderTimeline_h
|
||||||
|
|
||||||
|
#include <spine/Timeline.h>
|
||||||
|
|
||||||
|
namespace spine {
|
||||||
|
/// Changes a subset of a skeleton's Skeleton::getDrawOrder().
|
||||||
|
class SP_API DrawOrderFolderTimeline : public Timeline {
|
||||||
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
|
friend class SkeletonJson;
|
||||||
|
|
||||||
|
RTTI_DECL
|
||||||
|
|
||||||
|
public:
|
||||||
|
DrawOrderFolderTimeline(size_t frameCount, Array<int> &slots, size_t slotCount);
|
||||||
|
|
||||||
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||||
|
MixDirection direction, bool appliedPose) override;
|
||||||
|
|
||||||
|
size_t getFrameCount();
|
||||||
|
|
||||||
|
/// The Skeleton::getSlots() indices that this timeline affects, in setup order.
|
||||||
|
Array<int> &getSlots();
|
||||||
|
|
||||||
|
/// The draw order for each frame. See setFrame().
|
||||||
|
Array<Array<int>> &getDrawOrders();
|
||||||
|
|
||||||
|
/// Sets the time and draw order for the specified frame.
|
||||||
|
/// @param frame Between 0 and frameCount, inclusive.
|
||||||
|
/// @param time The frame time in seconds.
|
||||||
|
/// @param drawOrder Ordered getSlots() indices, or null to use setup pose order.
|
||||||
|
void setFrame(size_t frame, float time, Array<int> *drawOrder);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Array<int> _slots;
|
||||||
|
Array<bool> _inFolder;
|
||||||
|
Array<Array<int>> _drawOrders;
|
||||||
|
|
||||||
|
void setup(Skeleton &skeleton);
|
||||||
|
void apply(Skeleton &skeleton, Array<int> &drawOrder);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Spine_DrawOrderFolderTimeline_h */
|
||||||
@ -88,6 +88,8 @@ namespace spine {
|
|||||||
|
|
||||||
friend class DeformTimeline;
|
friend class DeformTimeline;
|
||||||
|
|
||||||
|
friend class DrawOrderFolderTimeline;
|
||||||
|
|
||||||
friend class DrawOrderTimeline;
|
friend class DrawOrderTimeline;
|
||||||
|
|
||||||
friend class EventTimeline;
|
friend class EventTimeline;
|
||||||
|
|||||||
@ -257,6 +257,8 @@ namespace spine {
|
|||||||
|
|
||||||
void readTimeline(DataInput &input, Array<Timeline *> &timelines, BoneTimeline2 &timeline, float scale);
|
void readTimeline(DataInput &input, Array<Timeline *> &timelines, BoneTimeline2 &timeline, float scale);
|
||||||
|
|
||||||
|
void readDrawOrder(DataInput &input, size_t slotCount, Array<int> &drawOrder);
|
||||||
|
|
||||||
void setBezier(DataInput &input, CurveTimeline &timeline, int bezier, int frame, int value, float time1, float time2, float value1,
|
void setBezier(DataInput &input, CurveTimeline &timeline, int bezier, int frame, int value, float time1, float time2, float value1,
|
||||||
float value2, float scale);
|
float value2, float scale);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -88,6 +88,9 @@ namespace spine {
|
|||||||
/// @return May be NULL.
|
/// @return May be NULL.
|
||||||
Animation *findAnimation(const String &animationName);
|
Animation *findAnimation(const String &animationName);
|
||||||
|
|
||||||
|
/// Collects animations used by slider constraints.
|
||||||
|
Array<Animation *> &findSliderAnimations(Array<Animation *> &animations);
|
||||||
|
|
||||||
/// The skeleton's name, which by default is the name of the skeleton data file when possible, or null when a name hasn't been
|
/// The skeleton's name, which by default is the name of the skeleton data file when possible, or null when a name hasn't been
|
||||||
/// set.
|
/// set.
|
||||||
const String &getName();
|
const String &getName();
|
||||||
|
|||||||
@ -111,6 +111,8 @@ namespace spine {
|
|||||||
|
|
||||||
void readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength);
|
void readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength);
|
||||||
|
|
||||||
|
bool readDrawOrder(SkeletonData *skeletonData, Json *keyMap, int slotCount, const Array<int> *folderSlots, Array<int> &drawOrder);
|
||||||
|
|
||||||
void setError(Json *root, const String &value1, const String &value2);
|
void setError(Json *root, const String &value1, const String &value2);
|
||||||
|
|
||||||
int findSlotIndex(SkeletonData *skeletonData, const String &slotName, Array<Timeline *> timelines);
|
int findSlotIndex(SkeletonData *skeletonData, const String &slotName, Array<Timeline *> timelines);
|
||||||
|
|||||||
@ -45,6 +45,7 @@ namespace spine {
|
|||||||
/// Stores the setup pose for a Slider
|
/// Stores the setup pose for a Slider
|
||||||
class SP_API SliderData : public ConstraintDataGeneric<Slider, SliderPose> {
|
class SP_API SliderData : public ConstraintDataGeneric<Slider, SliderPose> {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
friend class SkeletonData;
|
||||||
friend class SkeletonJson;
|
friend class SkeletonJson;
|
||||||
friend class Slider;
|
friend class Slider;
|
||||||
friend class SliderMixTimeline;
|
friend class SliderMixTimeline;
|
||||||
|
|||||||
@ -55,6 +55,7 @@
|
|||||||
#include <spine/ArrayUtils.h>
|
#include <spine/ArrayUtils.h>
|
||||||
#include <spine/CurveTimeline.h>
|
#include <spine/CurveTimeline.h>
|
||||||
#include <spine/DeformTimeline.h>
|
#include <spine/DeformTimeline.h>
|
||||||
|
#include <spine/DrawOrderFolderTimeline.h>
|
||||||
#include <spine/DrawOrderTimeline.h>
|
#include <spine/DrawOrderTimeline.h>
|
||||||
#include <spine/Event.h>
|
#include <spine/Event.h>
|
||||||
#include <spine/EventData.h>
|
#include <spine/EventData.h>
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
#include <spine/AttachmentTimeline.h>
|
#include <spine/AttachmentTimeline.h>
|
||||||
#include <spine/Bone.h>
|
#include <spine/Bone.h>
|
||||||
#include <spine/BoneData.h>
|
#include <spine/BoneData.h>
|
||||||
|
#include <spine/DrawOrderFolderTimeline.h>
|
||||||
#include <spine/DrawOrderTimeline.h>
|
#include <spine/DrawOrderTimeline.h>
|
||||||
#include <spine/Event.h>
|
#include <spine/Event.h>
|
||||||
#include <spine/EventTimeline.h>
|
#include <spine/EventTimeline.h>
|
||||||
@ -444,7 +445,8 @@ void EventQueue::drain() {
|
|||||||
break;
|
break;
|
||||||
case EventType_Event:
|
case EventType_Event:
|
||||||
if (!trackEntry->_listenerObject)
|
if (!trackEntry->_listenerObject)
|
||||||
SP_INVOKE_ANIMATION_LISTENER(trackEntry->_listener, state, queueEntry._type, trackEntry, queueEntry._event, trackEntry->_listenerUserData);
|
SP_INVOKE_ANIMATION_LISTENER(trackEntry->_listener, state, queueEntry._type, trackEntry, queueEntry._event,
|
||||||
|
trackEntry->_listenerUserData);
|
||||||
else
|
else
|
||||||
trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, queueEntry._event);
|
trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, queueEntry._event);
|
||||||
if (!state._listenerObject)
|
if (!state._listenerObject)
|
||||||
@ -1203,7 +1205,8 @@ continue_outer:
|
|||||||
timelineMode[i] = Subsequent;
|
timelineMode[i] = Subsequent;
|
||||||
} else {
|
} else {
|
||||||
if (to == NULL || timeline->getRTTI().isExactly(AttachmentTimeline::rtti) || timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) ||
|
if (to == NULL || timeline->getRTTI().isExactly(AttachmentTimeline::rtti) || timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) ||
|
||||||
timeline->getRTTI().isExactly(EventTimeline::rtti) || !to->_animation->hasTimeline(ids)) {
|
timeline->getRTTI().isExactly(DrawOrderFolderTimeline::rtti) || timeline->getRTTI().isExactly(EventTimeline::rtti) ||
|
||||||
|
!to->_animation->hasTimeline(ids)) {
|
||||||
timelineMode[i] = First;
|
timelineMode[i] = First;
|
||||||
} else {
|
} else {
|
||||||
for (TrackEntry *next = to->_mixingTo; next != NULL; next = next->_mixingTo) {
|
for (TrackEntry *next = to->_mixingTo; next != NULL; next = next->_mixingTo) {
|
||||||
|
|||||||
115
spine-cpp/src/spine/DrawOrderFolderTimeline.cpp
Normal file
115
spine-cpp/src/spine/DrawOrderFolderTimeline.cpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Spine Runtimes License Agreement
|
||||||
|
* Last updated April 5, 2025. Replaces all prior versions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2025, 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/DrawOrderFolderTimeline.h>
|
||||||
|
|
||||||
|
#include <spine/Animation.h>
|
||||||
|
#include <spine/Event.h>
|
||||||
|
#include <spine/Property.h>
|
||||||
|
#include <spine/Skeleton.h>
|
||||||
|
#include <spine/Slot.h>
|
||||||
|
#include <spine/SlotData.h>
|
||||||
|
|
||||||
|
using namespace spine;
|
||||||
|
|
||||||
|
RTTI_IMPL(DrawOrderFolderTimeline, Timeline)
|
||||||
|
|
||||||
|
DrawOrderFolderTimeline::DrawOrderFolderTimeline(size_t frameCount, Array<int> &slots, size_t slotCount) : Timeline(frameCount, 1) {
|
||||||
|
PropertyId ids[] = {((PropertyId) Property_DrawOrder << 32)};
|
||||||
|
setPropertyIds(ids, 1);
|
||||||
|
|
||||||
|
_slots.addAll(slots);
|
||||||
|
_drawOrders.ensureCapacity(frameCount);
|
||||||
|
_inFolder.setSize(slotCount, false);
|
||||||
|
for (size_t i = 0; i < _slots.size(); ++i) _inFolder[_slots[i]] = true;
|
||||||
|
for (size_t i = 0; i < frameCount; ++i) {
|
||||||
|
Array<int> vec;
|
||||||
|
_drawOrders.add(vec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawOrderFolderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||||
|
MixDirection direction, bool appliedPose) {
|
||||||
|
SP_UNUSED(lastTime);
|
||||||
|
SP_UNUSED(events);
|
||||||
|
SP_UNUSED(alpha);
|
||||||
|
SP_UNUSED(appliedPose);
|
||||||
|
|
||||||
|
if (direction == MixDirection_Out) {
|
||||||
|
if (blend == MixBlend_Setup) setup(skeleton);
|
||||||
|
} else if (time < _frames[0]) {
|
||||||
|
if (blend == MixBlend_Setup || blend == MixBlend_First) setup(skeleton);
|
||||||
|
} else {
|
||||||
|
Array<int> &drawOrder = _drawOrders[Animation::search(_frames, time)];
|
||||||
|
if (drawOrder.size() == 0)
|
||||||
|
setup(skeleton);
|
||||||
|
else
|
||||||
|
apply(skeleton, drawOrder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DrawOrderFolderTimeline::getFrameCount() {
|
||||||
|
return _frames.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<int> &DrawOrderFolderTimeline::getSlots() {
|
||||||
|
return _slots;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<Array<int>> &DrawOrderFolderTimeline::getDrawOrders() {
|
||||||
|
return _drawOrders;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawOrderFolderTimeline::setFrame(size_t frame, float time, Array<int> *drawOrder) {
|
||||||
|
_frames[frame] = time;
|
||||||
|
_drawOrders[frame].clear();
|
||||||
|
if (drawOrder != NULL) _drawOrders[frame].addAll(*drawOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawOrderFolderTimeline::setup(Skeleton &skeleton) {
|
||||||
|
Array<Slot *> &drawOrder = skeleton._drawOrder;
|
||||||
|
Array<Slot *> &allSlots = skeleton._slots;
|
||||||
|
for (size_t i = 0, found = 0, done = _slots.size();; ++i) {
|
||||||
|
if (_inFolder[drawOrder[i]->getData().getIndex()]) {
|
||||||
|
drawOrder[i] = allSlots[_slots[found]];
|
||||||
|
if (++found == done) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawOrderFolderTimeline::apply(Skeleton &skeleton, Array<int> &drawOrderIndices) {
|
||||||
|
Array<Slot *> &drawOrder = skeleton._drawOrder;
|
||||||
|
Array<Slot *> &allSlots = skeleton._slots;
|
||||||
|
for (size_t i = 0, found = 0, done = _slots.size();; ++i) {
|
||||||
|
if (_inFolder[drawOrder[i]->getData().getIndex()]) {
|
||||||
|
drawOrder[i] = allSlots[_slots[drawOrderIndices[found]]];
|
||||||
|
if (++found == done) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -47,6 +47,7 @@
|
|||||||
#include <spine/ColorTimeline.h>
|
#include <spine/ColorTimeline.h>
|
||||||
#include <spine/ArrayUtils.h>
|
#include <spine/ArrayUtils.h>
|
||||||
#include <spine/DeformTimeline.h>
|
#include <spine/DeformTimeline.h>
|
||||||
|
#include <spine/DrawOrderFolderTimeline.h>
|
||||||
#include <spine/DrawOrderTimeline.h>
|
#include <spine/DrawOrderTimeline.h>
|
||||||
#include <spine/Event.h>
|
#include <spine/Event.h>
|
||||||
#include <spine/EventData.h>
|
#include <spine/EventData.h>
|
||||||
@ -1304,33 +1305,33 @@ Animation *SkeletonBinary::readAnimation(DataInput &input, const String &name, S
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw order timeline.
|
// Draw order timeline.
|
||||||
|
size_t slotCount = skeletonData._slots.size();
|
||||||
size_t drawOrderCount = (size_t) input.readInt(true);
|
size_t drawOrderCount = (size_t) input.readInt(true);
|
||||||
if (drawOrderCount > 0) {
|
if (drawOrderCount > 0) {
|
||||||
DrawOrderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderTimeline(drawOrderCount);
|
DrawOrderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderTimeline(drawOrderCount);
|
||||||
size_t slotCount = skeletonData._slots.size();
|
|
||||||
for (size_t i = 0; i < drawOrderCount; ++i) {
|
for (size_t i = 0; i < drawOrderCount; ++i) {
|
||||||
float time = input.readFloat();
|
float time = input.readFloat();
|
||||||
size_t offsetCount = (size_t) input.readInt(true);
|
|
||||||
Array<int> drawOrder;
|
Array<int> drawOrder;
|
||||||
drawOrder.setSize(slotCount, 0);
|
readDrawOrder(input, slotCount, drawOrder);
|
||||||
for (int ii = (int) slotCount - 1; ii >= 0; --ii) drawOrder[ii] = -1;
|
timeline->setFrame(i, time, drawOrder.size() == 0 ? NULL : &drawOrder);
|
||||||
Array<int> unchanged;
|
}
|
||||||
unchanged.setSize(slotCount - offsetCount, 0);
|
timelines.add(timeline);
|
||||||
size_t originalIndex = 0, unchangedIndex = 0;
|
}
|
||||||
for (size_t ii = 0; ii < offsetCount; ++ii) {
|
|
||||||
size_t slotIndex = (size_t) input.readInt(true);
|
// Draw order folder timelines.
|
||||||
// Collect unchanged items.
|
size_t folderCount = (size_t) input.readInt(true);
|
||||||
while (originalIndex != slotIndex) unchanged[unchangedIndex++] = (int) originalIndex++;
|
for (size_t i = 0; i < folderCount; ++i) {
|
||||||
// Set changed items.
|
size_t folderSlotCount = (size_t) input.readInt(true);
|
||||||
size_t index = originalIndex;
|
Array<int> folderSlots;
|
||||||
drawOrder[index + (size_t) input.readInt(true)] = (int) originalIndex++;
|
folderSlots.setSize(folderSlotCount, 0);
|
||||||
}
|
for (size_t ii = 0; ii < folderSlotCount; ++ii) folderSlots[ii] = input.readInt(true);
|
||||||
// Collect remaining unchanged items.
|
size_t keyCount = (size_t) input.readInt(true);
|
||||||
while (originalIndex < slotCount) unchanged[unchangedIndex++] = (int) originalIndex++;
|
DrawOrderFolderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderFolderTimeline(keyCount, folderSlots, slotCount);
|
||||||
// Fill in unchanged items.
|
for (size_t ii = 0; ii < keyCount; ++ii) {
|
||||||
for (int ii = (int) slotCount - 1; ii >= 0; --ii)
|
float time = input.readFloat();
|
||||||
if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex];
|
Array<int> drawOrder;
|
||||||
timeline->setFrame(i, time, &drawOrder);
|
readDrawOrder(input, folderSlotCount, drawOrder);
|
||||||
|
timeline->setFrame(ii, time, drawOrder.size() == 0 ? NULL : &drawOrder);
|
||||||
}
|
}
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
}
|
}
|
||||||
@ -1409,6 +1410,27 @@ void SkeletonBinary::readTimeline(DataInput &input, Array<Timeline *> &timelines
|
|||||||
timelines.add(&timeline);
|
timelines.add(&timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkeletonBinary::readDrawOrder(DataInput &input, size_t slotCount, Array<int> &drawOrder) {
|
||||||
|
size_t changeCount = (size_t) input.readInt(true);
|
||||||
|
drawOrder.clear();
|
||||||
|
if (changeCount == 0) return;
|
||||||
|
|
||||||
|
drawOrder.setSize(slotCount, 0);
|
||||||
|
for (int i = (int) slotCount - 1; i >= 0; --i) drawOrder[i] = -1;
|
||||||
|
Array<int> unchanged;
|
||||||
|
unchanged.setSize(slotCount - changeCount, 0);
|
||||||
|
size_t originalIndex = 0, unchangedIndex = 0;
|
||||||
|
for (size_t i = 0; i < changeCount; ++i) {
|
||||||
|
size_t slotIndex = (size_t) input.readInt(true);
|
||||||
|
while (originalIndex != slotIndex) unchanged[unchangedIndex++] = (int) originalIndex++;
|
||||||
|
size_t index = originalIndex;
|
||||||
|
drawOrder[index + (size_t) input.readInt(true)] = (int) originalIndex++;
|
||||||
|
}
|
||||||
|
while (originalIndex < slotCount) unchanged[unchangedIndex++] = (int) originalIndex++;
|
||||||
|
for (int i = (int) slotCount - 1; i >= 0; --i)
|
||||||
|
if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex];
|
||||||
|
}
|
||||||
|
|
||||||
void SkeletonBinary::setBezier(DataInput &input, CurveTimeline &timeline, int bezier, int frame, int value, float time1, float time2, float value1,
|
void SkeletonBinary::setBezier(DataInput &input, CurveTimeline &timeline, int bezier, int frame, int value, float time1, float time2, float value1,
|
||||||
float value2, float scale) {
|
float value2, float scale) {
|
||||||
float cx1 = input.readFloat();
|
float cx1 = input.readFloat();
|
||||||
|
|||||||
@ -39,6 +39,7 @@
|
|||||||
#include <spine/Skin.h>
|
#include <spine/Skin.h>
|
||||||
#include <spine/SlotData.h>
|
#include <spine/SlotData.h>
|
||||||
#include <spine/TransformConstraintData.h>
|
#include <spine/TransformConstraintData.h>
|
||||||
|
#include <spine/SliderData.h>
|
||||||
|
|
||||||
#include <spine/ArrayUtils.h>
|
#include <spine/ArrayUtils.h>
|
||||||
|
|
||||||
@ -84,6 +85,17 @@ Animation *SkeletonData::findAnimation(const String &animationName) {
|
|||||||
return ArrayUtils::findWithName(_animations, animationName);
|
return ArrayUtils::findWithName(_animations, animationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Array<Animation *> &SkeletonData::findSliderAnimations(Array<Animation *> &animations) {
|
||||||
|
for (size_t i = 0, n = _constraints.size(); i < n; i++) {
|
||||||
|
ConstraintData *constraint = _constraints[i];
|
||||||
|
if (constraint->getRTTI().instanceOf(SliderData::rtti)) {
|
||||||
|
SliderData *data = static_cast<SliderData *>(constraint);
|
||||||
|
if (data->_animation != NULL) animations.add(data->_animation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return animations;
|
||||||
|
}
|
||||||
|
|
||||||
const String &SkeletonData::getName() {
|
const String &SkeletonData::getName() {
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,7 @@
|
|||||||
#include <spine/ColorTimeline.h>
|
#include <spine/ColorTimeline.h>
|
||||||
#include <spine/ArrayUtils.h>
|
#include <spine/ArrayUtils.h>
|
||||||
#include <spine/DeformTimeline.h>
|
#include <spine/DeformTimeline.h>
|
||||||
|
#include <spine/DrawOrderFolderTimeline.h>
|
||||||
#include <spine/DrawOrderTimeline.h>
|
#include <spine/DrawOrderTimeline.h>
|
||||||
#include <spine/Event.h>
|
#include <spine/Event.h>
|
||||||
#include <spine/EventData.h>
|
#include <spine/EventData.h>
|
||||||
@ -1242,8 +1243,13 @@ Animation *SkeletonJson::readAnimation(Json *map, SkeletonData *skeletonData) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (Json *slotMap = attachmentsMap->_child; slotMap; slotMap = slotMap->_next) {
|
for (Json *slotMap = attachmentsMap->_child; slotMap; slotMap = slotMap->_next) {
|
||||||
int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines);
|
SlotData *slot = skeletonData->findSlot(slotMap->_name);
|
||||||
if (slotIndex == -1) return NULL;
|
if (!slot) {
|
||||||
|
ArrayUtils::deleteElements(timelines);
|
||||||
|
setError(NULL, "Attachment slot not found: ", slotMap->_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
int slotIndex = slot->getIndex();
|
||||||
for (Json *attachmentMap = slotMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) {
|
for (Json *attachmentMap = slotMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) {
|
||||||
Attachment *attachment = skin->getAttachment(slotIndex, attachmentMap->_name);
|
Attachment *attachment = skin->getAttachment(slotIndex, attachmentMap->_name);
|
||||||
if (!attachment) {
|
if (!attachment) {
|
||||||
@ -1327,36 +1333,48 @@ Animation *SkeletonJson::readAnimation(Json *map, SkeletonData *skeletonData) {
|
|||||||
int frame = 0;
|
int frame = 0;
|
||||||
for (Json *keyMap = drawOrder->_child; keyMap; keyMap = keyMap->_next, ++frame) {
|
for (Json *keyMap = drawOrder->_child; keyMap; keyMap = keyMap->_next, ++frame) {
|
||||||
Array<int> drawOrder2;
|
Array<int> drawOrder2;
|
||||||
Json *offsets = Json::getItem(keyMap, "offsets");
|
if (!readDrawOrder(skeletonData, keyMap, slotCount, NULL, drawOrder2)) {
|
||||||
if (offsets) {
|
ArrayUtils::deleteElements(timelines);
|
||||||
drawOrder2.setSize(slotCount, 0);
|
return NULL;
|
||||||
for (int i = slotCount - 1; i >= 0; i--) drawOrder2[i] = -1;
|
|
||||||
Array<int> unchanged;
|
|
||||||
unchanged.setSize(slotCount - offsets->_size, 0);
|
|
||||||
int originalIndex = 0, unchangedIndex = 0;
|
|
||||||
for (Json *offsetMap = offsets->_child; offsetMap; offsetMap = offsetMap->_next) {
|
|
||||||
SlotData *slot = skeletonData->findSlot(Json::getString(offsetMap, "slot", 0));
|
|
||||||
if (!slot) {
|
|
||||||
ArrayUtils::deleteElements(timelines);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
/* Collect unchanged items. */
|
|
||||||
while (originalIndex != slot->_index) unchanged[unchangedIndex++] = originalIndex++;
|
|
||||||
/* Set changed items. */
|
|
||||||
int index = originalIndex;
|
|
||||||
drawOrder2[index + Json::getInt(offsetMap, "offset", 0)] = originalIndex++;
|
|
||||||
}
|
|
||||||
/* Collect remaining unchanged items. */
|
|
||||||
while (originalIndex < slotCount) unchanged[unchangedIndex++] = originalIndex++;
|
|
||||||
/* Fill in unchanged items. */
|
|
||||||
for (int i = slotCount - 1; i >= 0; i--)
|
|
||||||
if (drawOrder2[i] == -1) drawOrder2[i] = unchanged[--unchangedIndex];
|
|
||||||
}
|
}
|
||||||
timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), &drawOrder2);
|
timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), drawOrder2.size() == 0 ? NULL : &drawOrder2);
|
||||||
}
|
}
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw order folder timelines.
|
||||||
|
Json *drawOrderFolder = Json::getItem(map, "drawOrderFolder");
|
||||||
|
if (drawOrderFolder) {
|
||||||
|
for (Json *timelineMap = drawOrderFolder->_child; timelineMap; timelineMap = timelineMap->_next) {
|
||||||
|
Json *slotEntry = Json::getItem(timelineMap, "slots");
|
||||||
|
Array<int> folderSlots;
|
||||||
|
folderSlots.setSize(slotEntry ? slotEntry->_size : 0, 0);
|
||||||
|
int ii = 0;
|
||||||
|
for (Json *entry = slotEntry ? slotEntry->_child : NULL; entry; entry = entry->_next, ++ii) {
|
||||||
|
SlotData *slot = skeletonData->findSlot(entry->_valueString);
|
||||||
|
if (!slot) {
|
||||||
|
ArrayUtils::deleteElements(timelines);
|
||||||
|
setError(NULL, "Draw order folder slot not found: ", entry->_valueString);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
folderSlots[ii] = slot->getIndex();
|
||||||
|
}
|
||||||
|
Json *keyMap = Json::getItem(timelineMap, "keys");
|
||||||
|
DrawOrderFolderTimeline *timeline = new (__FILE__, __LINE__)
|
||||||
|
DrawOrderFolderTimeline(keyMap ? keyMap->_size : 0, folderSlots, skeletonData->_slots.size());
|
||||||
|
int frame = 0;
|
||||||
|
for (Json *entry = keyMap ? keyMap->_child : NULL; entry; entry = entry->_next, ++frame) {
|
||||||
|
Array<int> folderDrawOrder;
|
||||||
|
if (!readDrawOrder(skeletonData, entry, (int) folderSlots.size(), &folderSlots, folderDrawOrder)) {
|
||||||
|
ArrayUtils::deleteElements(timelines);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
timeline->setFrame(frame, Json::getFloat(entry, "time", 0), folderDrawOrder.size() == 0 ? NULL : &folderDrawOrder);
|
||||||
|
}
|
||||||
|
timelines.add(timeline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Event timeline.
|
// Event timeline.
|
||||||
Json *events = Json::getItem(map, "events");
|
Json *events = Json::getItem(map, "events");
|
||||||
if (events) {
|
if (events) {
|
||||||
@ -1462,6 +1480,49 @@ int SkeletonJson::findSlotIndex(SkeletonData *skeletonData, const String &slotNa
|
|||||||
return slotIndex;
|
return slotIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkeletonJson::readDrawOrder(SkeletonData *skeletonData, Json *keyMap, int slotCount, const Array<int> *folderSlots, Array<int> &drawOrder) {
|
||||||
|
Json *changes = Json::getItem(keyMap, "offsets");
|
||||||
|
drawOrder.clear();
|
||||||
|
if (changes == NULL) return true;
|
||||||
|
|
||||||
|
drawOrder.setSize(slotCount, 0);
|
||||||
|
for (int i = slotCount - 1; i >= 0; i--) drawOrder[i] = -1;
|
||||||
|
Array<int> unchanged;
|
||||||
|
unchanged.setSize(slotCount - changes->_size, 0);
|
||||||
|
int originalIndex = 0, unchangedIndex = 0;
|
||||||
|
for (Json *offsetMap = changes->_child; offsetMap; offsetMap = offsetMap->_next) {
|
||||||
|
const char *slotName = Json::getString(offsetMap, "slot", 0);
|
||||||
|
SlotData *slot = skeletonData->findSlot(slotName);
|
||||||
|
if (slot == NULL) {
|
||||||
|
setError(NULL, "Draw order slot not found: ", slotName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int index;
|
||||||
|
if (folderSlots == NULL) {
|
||||||
|
index = slot->getIndex();
|
||||||
|
} else {
|
||||||
|
index = -1;
|
||||||
|
for (int i = 0; i < slotCount; i++) {
|
||||||
|
if ((*folderSlots)[i] == slot->getIndex()) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index == -1) {
|
||||||
|
setError(NULL, "Slot not in folder: ", slotName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (originalIndex != index) unchanged[unchangedIndex++] = originalIndex++;
|
||||||
|
int drawOrderIndex = originalIndex;
|
||||||
|
drawOrder[drawOrderIndex + Json::getInt(offsetMap, "offset", 0)] = originalIndex++;
|
||||||
|
}
|
||||||
|
while (originalIndex < slotCount) unchanged[unchangedIndex++] = originalIndex++;
|
||||||
|
for (int i = slotCount - 1; i >= 0; i--)
|
||||||
|
if (drawOrder[i] == -1) drawOrder[i] = unchanged[--unchangedIndex];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void SkeletonJson::setError(Json *root, const String &value1, const String &value2) {
|
void SkeletonJson::setError(Json *root, const String &value1, const String &value2) {
|
||||||
_error = String(value1).append(value2);
|
_error = String(value1).append(value2);
|
||||||
delete root;
|
delete root;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user