mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-25 22:23:42 +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 DrawOrderFolderTimeline;
|
||||
|
||||
friend class DrawOrderTimeline;
|
||||
|
||||
friend class EventTimeline;
|
||||
|
||||
@ -257,6 +257,8 @@ namespace spine {
|
||||
|
||||
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,
|
||||
float value2, float scale);
|
||||
};
|
||||
|
||||
@ -88,6 +88,9 @@ namespace spine {
|
||||
/// @return May be NULL.
|
||||
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
|
||||
/// set.
|
||||
const String &getName();
|
||||
|
||||
@ -111,6 +111,8 @@ namespace spine {
|
||||
|
||||
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);
|
||||
|
||||
int findSlotIndex(SkeletonData *skeletonData, const String &slotName, Array<Timeline *> timelines);
|
||||
|
||||
@ -45,6 +45,7 @@ namespace spine {
|
||||
/// Stores the setup pose for a Slider
|
||||
class SP_API SliderData : public ConstraintDataGeneric<Slider, SliderPose> {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonData;
|
||||
friend class SkeletonJson;
|
||||
friend class Slider;
|
||||
friend class SliderMixTimeline;
|
||||
|
||||
@ -55,6 +55,7 @@
|
||||
#include <spine/ArrayUtils.h>
|
||||
#include <spine/CurveTimeline.h>
|
||||
#include <spine/DeformTimeline.h>
|
||||
#include <spine/DrawOrderFolderTimeline.h>
|
||||
#include <spine/DrawOrderTimeline.h>
|
||||
#include <spine/Event.h>
|
||||
#include <spine/EventData.h>
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <spine/AttachmentTimeline.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/DrawOrderFolderTimeline.h>
|
||||
#include <spine/DrawOrderTimeline.h>
|
||||
#include <spine/Event.h>
|
||||
#include <spine/EventTimeline.h>
|
||||
@ -444,7 +445,8 @@ void EventQueue::drain() {
|
||||
break;
|
||||
case EventType_Event:
|
||||
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
|
||||
trackEntry->_listenerObject->callback(&state, queueEntry._type, trackEntry, queueEntry._event);
|
||||
if (!state._listenerObject)
|
||||
@ -1203,7 +1205,8 @@ continue_outer:
|
||||
timelineMode[i] = Subsequent;
|
||||
} else {
|
||||
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;
|
||||
} else {
|
||||
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/ArrayUtils.h>
|
||||
#include <spine/DeformTimeline.h>
|
||||
#include <spine/DrawOrderFolderTimeline.h>
|
||||
#include <spine/DrawOrderTimeline.h>
|
||||
#include <spine/Event.h>
|
||||
#include <spine/EventData.h>
|
||||
@ -1304,33 +1305,33 @@ Animation *SkeletonBinary::readAnimation(DataInput &input, const String &name, S
|
||||
}
|
||||
|
||||
// Draw order timeline.
|
||||
size_t slotCount = skeletonData._slots.size();
|
||||
size_t drawOrderCount = (size_t) input.readInt(true);
|
||||
if (drawOrderCount > 0) {
|
||||
DrawOrderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderTimeline(drawOrderCount);
|
||||
size_t slotCount = skeletonData._slots.size();
|
||||
for (size_t i = 0; i < drawOrderCount; ++i) {
|
||||
float time = input.readFloat();
|
||||
size_t offsetCount = (size_t) input.readInt(true);
|
||||
Array<int> drawOrder;
|
||||
drawOrder.setSize(slotCount, 0);
|
||||
for (int ii = (int) slotCount - 1; ii >= 0; --ii) drawOrder[ii] = -1;
|
||||
Array<int> unchanged;
|
||||
unchanged.setSize(slotCount - offsetCount, 0);
|
||||
size_t originalIndex = 0, unchangedIndex = 0;
|
||||
for (size_t ii = 0; ii < offsetCount; ++ii) {
|
||||
size_t slotIndex = (size_t) input.readInt(true);
|
||||
// Collect unchanged items.
|
||||
while (originalIndex != slotIndex) unchanged[unchangedIndex++] = (int) originalIndex++;
|
||||
// Set changed items.
|
||||
size_t index = originalIndex;
|
||||
drawOrder[index + (size_t) input.readInt(true)] = (int) originalIndex++;
|
||||
}
|
||||
// Collect remaining unchanged items.
|
||||
while (originalIndex < slotCount) unchanged[unchangedIndex++] = (int) originalIndex++;
|
||||
// Fill in unchanged items.
|
||||
for (int ii = (int) slotCount - 1; ii >= 0; --ii)
|
||||
if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex];
|
||||
timeline->setFrame(i, time, &drawOrder);
|
||||
readDrawOrder(input, slotCount, drawOrder);
|
||||
timeline->setFrame(i, time, drawOrder.size() == 0 ? NULL : &drawOrder);
|
||||
}
|
||||
timelines.add(timeline);
|
||||
}
|
||||
|
||||
// Draw order folder timelines.
|
||||
size_t folderCount = (size_t) input.readInt(true);
|
||||
for (size_t i = 0; i < folderCount; ++i) {
|
||||
size_t folderSlotCount = (size_t) input.readInt(true);
|
||||
Array<int> folderSlots;
|
||||
folderSlots.setSize(folderSlotCount, 0);
|
||||
for (size_t ii = 0; ii < folderSlotCount; ++ii) folderSlots[ii] = input.readInt(true);
|
||||
size_t keyCount = (size_t) input.readInt(true);
|
||||
DrawOrderFolderTimeline *timeline = new (__FILE__, __LINE__) DrawOrderFolderTimeline(keyCount, folderSlots, slotCount);
|
||||
for (size_t ii = 0; ii < keyCount; ++ii) {
|
||||
float time = input.readFloat();
|
||||
Array<int> drawOrder;
|
||||
readDrawOrder(input, folderSlotCount, drawOrder);
|
||||
timeline->setFrame(ii, time, drawOrder.size() == 0 ? NULL : &drawOrder);
|
||||
}
|
||||
timelines.add(timeline);
|
||||
}
|
||||
@ -1409,6 +1410,27 @@ void SkeletonBinary::readTimeline(DataInput &input, Array<Timeline *> &timelines
|
||||
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,
|
||||
float value2, float scale) {
|
||||
float cx1 = input.readFloat();
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
#include <spine/Skin.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/TransformConstraintData.h>
|
||||
#include <spine/SliderData.h>
|
||||
|
||||
#include <spine/ArrayUtils.h>
|
||||
|
||||
@ -84,6 +85,17 @@ Animation *SkeletonData::findAnimation(const String &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() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
@ -47,6 +47,7 @@
|
||||
#include <spine/ColorTimeline.h>
|
||||
#include <spine/ArrayUtils.h>
|
||||
#include <spine/DeformTimeline.h>
|
||||
#include <spine/DrawOrderFolderTimeline.h>
|
||||
#include <spine/DrawOrderTimeline.h>
|
||||
#include <spine/Event.h>
|
||||
#include <spine/EventData.h>
|
||||
@ -1242,8 +1243,13 @@ Animation *SkeletonJson::readAnimation(Json *map, SkeletonData *skeletonData) {
|
||||
return NULL;
|
||||
}
|
||||
for (Json *slotMap = attachmentsMap->_child; slotMap; slotMap = slotMap->_next) {
|
||||
int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines);
|
||||
if (slotIndex == -1) return NULL;
|
||||
SlotData *slot = skeletonData->findSlot(slotMap->_name);
|
||||
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) {
|
||||
Attachment *attachment = skin->getAttachment(slotIndex, attachmentMap->_name);
|
||||
if (!attachment) {
|
||||
@ -1327,36 +1333,48 @@ Animation *SkeletonJson::readAnimation(Json *map, SkeletonData *skeletonData) {
|
||||
int frame = 0;
|
||||
for (Json *keyMap = drawOrder->_child; keyMap; keyMap = keyMap->_next, ++frame) {
|
||||
Array<int> drawOrder2;
|
||||
Json *offsets = Json::getItem(keyMap, "offsets");
|
||||
if (offsets) {
|
||||
drawOrder2.setSize(slotCount, 0);
|
||||
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];
|
||||
if (!readDrawOrder(skeletonData, keyMap, slotCount, NULL, drawOrder2)) {
|
||||
ArrayUtils::deleteElements(timelines);
|
||||
return NULL;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// 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.
|
||||
Json *events = Json::getItem(map, "events");
|
||||
if (events) {
|
||||
@ -1462,6 +1480,49 @@ int SkeletonJson::findSlotIndex(SkeletonData *skeletonData, const String &slotNa
|
||||
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) {
|
||||
_error = String(value1).append(value2);
|
||||
delete root;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user