mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
Revert "[ue] Sync spine-cpp copy for AnimationState additive/hold rework, Skin placeholder rename"
This reverts commit 60205bf2618b1c17a14cd2cb0420208fb28cc9c2.
This commit is contained in:
parent
60205bf261
commit
a64c5e0a27
@ -1,136 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Animation.h>
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Timeline.h>
|
||||
#include <spine/BoneTimeline.h>
|
||||
#include <spine/RotateTimeline.h>
|
||||
#include <spine/TranslateTimeline.h>
|
||||
|
||||
#include <spine/ArrayUtils.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
Animation::Animation(const String &name, Array<Timeline *> &timelines, float duration)
|
||||
: _timelines(), _timelineIds(), _bones(), _duration(duration), _name(name) {
|
||||
setTimelines(timelines);
|
||||
}
|
||||
|
||||
bool Animation::hasTimeline(Array<PropertyId> &ids) {
|
||||
for (size_t i = 0; i < ids.size(); i++) {
|
||||
if (_timelineIds.containsKey(ids[i])) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Animation::~Animation() {
|
||||
ArrayUtils::deleteElements(_timelines);
|
||||
}
|
||||
|
||||
void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
if (loop && _duration != 0) {
|
||||
time = MathUtil::fmod(time, _duration);
|
||||
if (lastTime > 0) {
|
||||
lastTime = MathUtil::fmod(lastTime, _duration);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0, n = _timelines.size(); i < n; ++i) {
|
||||
_timelines[i]->apply(skeleton, lastTime, time, events, alpha, fromSetup, add, out, appliedPose);
|
||||
}
|
||||
}
|
||||
|
||||
const String &Animation::getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
const Array<int> &Animation::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
Array<Timeline *> &Animation::getTimelines() {
|
||||
return _timelines;
|
||||
}
|
||||
|
||||
float Animation::getDuration() {
|
||||
return _duration;
|
||||
}
|
||||
|
||||
void Animation::setDuration(float inValue) {
|
||||
_duration = inValue;
|
||||
}
|
||||
|
||||
int Animation::search(Array<float> &frames, float target) {
|
||||
size_t n = (int) frames.size();
|
||||
for (size_t i = 1; i < n; i++) {
|
||||
if (frames[i] > target) return (int) (i - 1);
|
||||
}
|
||||
return (int) (n - 1);
|
||||
}
|
||||
|
||||
int Animation::search(Array<float> &frames, float target, int step) {
|
||||
size_t n = frames.size();
|
||||
for (size_t i = step; i < n; i += step)
|
||||
if (frames[i] > target) return (int) (i - step);
|
||||
return (int) (n - step);
|
||||
}
|
||||
|
||||
void Animation::setTimelines(Array<Timeline *> &timelines) {
|
||||
_timelines = timelines;
|
||||
|
||||
size_t n = timelines.size();
|
||||
_timelineIds.clear();
|
||||
_bones.clear();
|
||||
|
||||
HashMap<int, bool> boneSet;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
Timeline *timeline = timelines[i];
|
||||
Array<PropertyId> &propertyIds = timeline->getPropertyIds();
|
||||
for (size_t ii = 0; ii < propertyIds.size(); ii++) {
|
||||
_timelineIds.put(propertyIds[ii], true);
|
||||
}
|
||||
|
||||
int boneIndex = -1;
|
||||
if (timeline->getRTTI().instanceOf(BoneTimeline1::rtti)) {
|
||||
boneIndex = static_cast<BoneTimeline1 *>(timeline)->getBoneIndex();
|
||||
} else if (timeline->getRTTI().instanceOf(BoneTimeline2::rtti)) {
|
||||
boneIndex = static_cast<BoneTimeline2 *>(timeline)->getBoneIndex();
|
||||
}
|
||||
|
||||
if (boneIndex >= 0 && !boneSet.containsKey(boneIndex)) {
|
||||
boneSet.put(boneIndex, true);
|
||||
_bones.add(boneIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,82 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/AnimationStateData.h>
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/SkeletonData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
AnimationStateData::AnimationStateData(SkeletonData &skeletonData) : _skeletonData(&skeletonData), _defaultMix(0) {
|
||||
}
|
||||
|
||||
void AnimationStateData::setMix(const String &fromName, const String &toName, float duration) {
|
||||
Animation *from = _skeletonData->findAnimation(fromName);
|
||||
Animation *to = _skeletonData->findAnimation(toName);
|
||||
assert(from != NULL);
|
||||
assert(to != NULL);
|
||||
|
||||
setMix(*from, *to, duration);
|
||||
}
|
||||
|
||||
void AnimationStateData::setMix(Animation &from, Animation &to, float duration) {
|
||||
AnimationPair key(&from, &to);
|
||||
_animationToMixTime.put(key, duration);
|
||||
}
|
||||
|
||||
float AnimationStateData::getMix(Animation &from, Animation &to) {
|
||||
AnimationPair key(&from, &to);
|
||||
|
||||
if (_animationToMixTime.containsKey(key)) return _animationToMixTime[key];
|
||||
return _defaultMix;
|
||||
}
|
||||
|
||||
SkeletonData &AnimationStateData::getSkeletonData() {
|
||||
return *_skeletonData;
|
||||
}
|
||||
|
||||
float AnimationStateData::getDefaultMix() {
|
||||
return _defaultMix;
|
||||
}
|
||||
|
||||
void AnimationStateData::setDefaultMix(float inValue) {
|
||||
_defaultMix = inValue;
|
||||
}
|
||||
|
||||
void AnimationStateData::clear() {
|
||||
_defaultMix = 0;
|
||||
_animationToMixTime.clear();
|
||||
}
|
||||
|
||||
AnimationStateData::AnimationPair::AnimationPair(Animation *a1, Animation *a2) : _a1(a1), _a2(a2) {
|
||||
}
|
||||
|
||||
bool AnimationStateData::AnimationPair::operator==(const AnimationPair &other) const {
|
||||
return _a1->_name == other._a1->_name && _a2->_name == other._a2->_name;
|
||||
}
|
||||
@ -1,361 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Atlas.h>
|
||||
#include <spine/ArrayUtils.h>
|
||||
#include <spine/TextureLoader.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(AtlasRegion, TextureRegion)
|
||||
|
||||
Atlas::Atlas(const String &path, TextureLoader *textureLoader, bool createTexture) : _textureLoader(textureLoader) {
|
||||
int dirLength;
|
||||
char *dir;
|
||||
int length;
|
||||
const char *data;
|
||||
|
||||
/* Get directory from atlas path. */
|
||||
const char *lastForwardSlash = strrchr(path.buffer(), '/');
|
||||
const char *lastBackwardSlash = strrchr(path.buffer(), '\\');
|
||||
const char *lastSlash = lastForwardSlash > lastBackwardSlash ? lastForwardSlash : lastBackwardSlash;
|
||||
if (lastSlash == path) lastSlash++; /* Never drop starting slash. */
|
||||
dirLength = (int) (lastSlash ? lastSlash - path.buffer() : 0);
|
||||
dir = SpineExtension::calloc<char>(dirLength + 1, __FILE__, __LINE__);
|
||||
memcpy(dir, path.buffer(), dirLength);
|
||||
dir[dirLength] = '\0';
|
||||
|
||||
data = SpineExtension::readFile(path, &length);
|
||||
if (data) {
|
||||
load(data, length, dir, createTexture);
|
||||
}
|
||||
|
||||
SpineExtension::free(data, __FILE__, __LINE__);
|
||||
SpineExtension::free(dir, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
Atlas::Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture) : _textureLoader(textureLoader) {
|
||||
load(data, length, dir, createTexture);
|
||||
}
|
||||
|
||||
Atlas::~Atlas() {
|
||||
if (_textureLoader) {
|
||||
for (size_t i = 0, n = _pages.size(); i < n; ++i) {
|
||||
_textureLoader->unload(_pages[i]->texture);
|
||||
}
|
||||
}
|
||||
ArrayUtils::deleteElements(_pages);
|
||||
ArrayUtils::deleteElements(_regions);
|
||||
}
|
||||
|
||||
void Atlas::flipV() {
|
||||
for (size_t i = 0, n = _regions.size(); i < n; ++i) {
|
||||
AtlasRegion *regionP = _regions[i];
|
||||
AtlasRegion ®ion = *regionP;
|
||||
region._v = 1 - region._v;
|
||||
region._v2 = 1 - region._v2;
|
||||
}
|
||||
}
|
||||
|
||||
AtlasRegion *Atlas::findRegion(const String &name) {
|
||||
for (size_t i = 0, n = _regions.size(); i < n; ++i)
|
||||
if (_regions[i]->_name == name) return _regions[i];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Array<AtlasPage *> &Atlas::getPages() {
|
||||
return _pages;
|
||||
}
|
||||
|
||||
Array<AtlasRegion *> &Atlas::getRegions() {
|
||||
return _regions;
|
||||
}
|
||||
|
||||
struct SimpleString {
|
||||
char *start;
|
||||
char *end;
|
||||
int length;
|
||||
|
||||
SimpleString trim() {
|
||||
while (isspace((unsigned char) *start) && start < end) start++;
|
||||
if (start == end) {
|
||||
length = (int) (end - start);
|
||||
return *this;
|
||||
}
|
||||
end--;
|
||||
while (((unsigned char) *end == '\r') && end >= start) end--;
|
||||
end++;
|
||||
length = (int) (end - start);
|
||||
return *this;
|
||||
}
|
||||
|
||||
int indexOf(char needle) {
|
||||
char *c = start;
|
||||
while (c < end) {
|
||||
if (*c == needle) return (int) (c - start);
|
||||
c++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int indexOf(char needle, int at) {
|
||||
char *c = start + at;
|
||||
while (c < end) {
|
||||
if (*c == needle) return (int) (c - start);
|
||||
c++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
SimpleString substr(int s, int e) {
|
||||
e = s + e;
|
||||
SimpleString result;
|
||||
result.start = start + s;
|
||||
result.end = start + e;
|
||||
result.length = e - s;
|
||||
return result;
|
||||
}
|
||||
|
||||
SimpleString substr(int s) {
|
||||
SimpleString result;
|
||||
result.start = start + s;
|
||||
result.end = end;
|
||||
result.length = (int) (result.end - result.start);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool equals(const char *str) {
|
||||
int otherLen = (int) strlen(str);
|
||||
if (length != otherLen) return false;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (start[i] != str[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char *copy() {
|
||||
char *string = SpineExtension::calloc<char>(length + 1, __FILE__, __LINE__);
|
||||
memcpy(string, start, length);
|
||||
string[length] = '\0';
|
||||
return string;
|
||||
}
|
||||
|
||||
int toInt() {
|
||||
return (int) strtol(start, &end, 10);
|
||||
}
|
||||
};
|
||||
|
||||
struct AtlasInput {
|
||||
const char *start;
|
||||
const char *end;
|
||||
char *index;
|
||||
int length;
|
||||
SimpleString line;
|
||||
|
||||
AtlasInput(const char *data, int length) : start(data), end(data + length), index((char *) data), length(length) {
|
||||
}
|
||||
|
||||
SimpleString *readLine() {
|
||||
if (index >= end) return 0;
|
||||
line.start = index;
|
||||
while (index < end && *index != '\n') index++;
|
||||
line.end = index;
|
||||
if (index != end) index++;
|
||||
line = line.trim();
|
||||
line.length = (int) (end - start);
|
||||
return &line;
|
||||
}
|
||||
|
||||
static int readEntry(SimpleString entry[5], SimpleString *line) {
|
||||
if (line == nullptr) return 0;
|
||||
line->trim();
|
||||
if (line->length == 0) return 0;
|
||||
|
||||
int colon = line->indexOf(':');
|
||||
if (colon == -1) return 0;
|
||||
entry[0] = line->substr(0, colon).trim();
|
||||
for (int i = 1, lastMatch = colon + 1;; i++) {
|
||||
int comma = line->indexOf(',', lastMatch);
|
||||
if (comma == -1) {
|
||||
entry[i] = line->substr(lastMatch).trim();
|
||||
return i;
|
||||
}
|
||||
entry[i] = line->substr(lastMatch, comma - lastMatch).trim();
|
||||
lastMatch = comma + 1;
|
||||
if (i == 4) return 4;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int indexOf(const char **array, int count, SimpleString *str) {
|
||||
for (int i = 0; i < count; i++)
|
||||
if (str->equals(array[i])) return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Atlas::load(const char *begin, int length, const char *dir, bool createTexture) {
|
||||
static const char *formatNames[] = {"", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", "RGBA8888"};
|
||||
static const char *textureFilterNames[] =
|
||||
{"", "Nearest", "Linear", "MipMap", "MipMapNearestNearest", "MipMapLinearNearest", "MipMapNearestLinear", "MipMapLinearLinear"};
|
||||
|
||||
int dirLength = (int) strlen(dir);
|
||||
int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\';
|
||||
AtlasInput reader(begin, length);
|
||||
SimpleString entry[5];
|
||||
AtlasPage *page = nullptr;
|
||||
|
||||
SimpleString *line = reader.readLine();
|
||||
while (line != nullptr && line->length == 0) line = reader.readLine();
|
||||
|
||||
while (true) {
|
||||
if (line == nullptr || line->length == 0) break;
|
||||
if (reader.readEntry(entry, line) == 0) break;
|
||||
line = reader.readLine();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (line == nullptr) break;
|
||||
if (line->trim().length == 0) {
|
||||
page = nullptr;
|
||||
line = reader.readLine();
|
||||
} else if (page == nullptr) {
|
||||
char *name = line->copy();
|
||||
char *path = SpineExtension::calloc<char>(dirLength + needsSlash + strlen(name) + 1, __FILE__, __LINE__);
|
||||
memcpy(path, dir, dirLength);
|
||||
if (needsSlash) path[dirLength] = '/';
|
||||
strcpy(path + dirLength + needsSlash, name);
|
||||
page = new (__FILE__, __LINE__) AtlasPage(String(name, true));
|
||||
|
||||
while (true) {
|
||||
line = reader.readLine();
|
||||
if (reader.readEntry(entry, line) == 0) break;
|
||||
if (entry[0].equals("size")) {
|
||||
page->width = entry[1].toInt();
|
||||
page->height = entry[2].toInt();
|
||||
} else if (entry[0].equals("format")) {
|
||||
page->format = (Format) indexOf(formatNames, 8, &entry[1]);
|
||||
} else if (entry[0].equals("filter")) {
|
||||
#ifdef SPINE_UE4
|
||||
page->minFilter = (SpineTextureFilter) indexOf(textureFilterNames, 8, &entry[1]);
|
||||
page->magFilter = (SpineTextureFilter) indexOf(textureFilterNames, 8, &entry[2]);
|
||||
#else
|
||||
page->minFilter = (TextureFilter) indexOf(textureFilterNames, 8, &entry[1]);
|
||||
page->magFilter = (TextureFilter) indexOf(textureFilterNames, 8, &entry[2]);
|
||||
#endif
|
||||
} else if (entry[0].equals("repeat")) {
|
||||
page->uWrap = TextureWrap_ClampToEdge;
|
||||
page->vWrap = TextureWrap_ClampToEdge;
|
||||
if (entry[1].indexOf('x') != -1) page->uWrap = TextureWrap_Repeat;
|
||||
if (entry[1].indexOf('y') != -1) page->vWrap = TextureWrap_Repeat;
|
||||
} else if (entry[0].equals("pma")) {
|
||||
page->pma = entry[1].equals("true");
|
||||
}
|
||||
}
|
||||
|
||||
page->index = (int) _pages.size();
|
||||
if (createTexture && _textureLoader) _textureLoader->load(*page, String(path));
|
||||
page->texturePath = String(path, true);
|
||||
_pages.add(page);
|
||||
} else {
|
||||
AtlasRegion *region = new (__FILE__, __LINE__) AtlasRegion();
|
||||
region->_page = page;
|
||||
region->_rendererObject = page->texture;
|
||||
region->_name = String(line->copy(), true);
|
||||
while (true) {
|
||||
line = reader.readLine();
|
||||
int count = reader.readEntry(entry, line);
|
||||
if (count == 0) break;
|
||||
if (entry[0].equals("xy")) {
|
||||
region->_x = entry[1].toInt();
|
||||
region->_y = entry[2].toInt();
|
||||
} else if (entry[0].equals("size")) {
|
||||
region->_packedWidth = entry[1].toInt();
|
||||
region->_packedHeight = entry[2].toInt();
|
||||
} else if (entry[0].equals("bounds")) {
|
||||
region->_x = entry[1].toInt();
|
||||
region->_y = entry[2].toInt();
|
||||
region->_packedWidth = entry[3].toInt();
|
||||
region->_packedHeight = entry[4].toInt();
|
||||
} else if (entry[0].equals("offset")) {
|
||||
region->_offsetX = entry[1].toInt();
|
||||
region->_offsetY = entry[2].toInt();
|
||||
} else if (entry[0].equals("orig")) {
|
||||
region->_originalWidth = entry[1].toInt();
|
||||
region->_originalHeight = entry[2].toInt();
|
||||
} else if (entry[0].equals("offsets")) {
|
||||
region->_offsetX = entry[1].toInt();
|
||||
region->_offsetY = entry[2].toInt();
|
||||
region->_originalWidth = entry[3].toInt();
|
||||
region->_originalHeight = entry[4].toInt();
|
||||
} else if (entry[0].equals("rotate")) {
|
||||
if (entry[1].equals("true")) {
|
||||
region->_degrees = 90;
|
||||
} else if (!entry[1].equals("false")) {
|
||||
region->_degrees = entry[1].toInt();
|
||||
}
|
||||
region->_rotate = region->_degrees == 90;
|
||||
} else if (entry[0].equals("index")) {
|
||||
region->_index = entry[1].toInt();
|
||||
} else {
|
||||
region->_names.add(String(entry[0].copy()));
|
||||
for (int i = 0; i < count; i++) {
|
||||
region->_values.add(entry[i + 1].toInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (region->_originalWidth == 0 && region->_originalHeight == 0) {
|
||||
region->_originalWidth = region->_packedWidth;
|
||||
region->_originalHeight = region->_packedHeight;
|
||||
}
|
||||
|
||||
region->_u = (float) region->_x / page->width;
|
||||
region->_v = (float) region->_y / page->height;
|
||||
if (region->_degrees == 90) {
|
||||
region->_u2 = (float) (region->_x + region->_packedHeight) / page->width;
|
||||
region->_v2 = (float) (region->_y + region->_packedWidth) / page->height;
|
||||
} else {
|
||||
region->_u2 = (float) (region->_x + region->_packedWidth) / page->width;
|
||||
region->_v2 = (float) (region->_y + region->_packedHeight) / page->height;
|
||||
}
|
||||
// Calculate regionWidth/Height from UV coordinates
|
||||
region->_regionWidth = abs((int) ((region->_u2 - region->_u) * page->width));
|
||||
region->_regionHeight = abs((int) ((region->_v2 - region->_v) * page->height));
|
||||
|
||||
if (region->_degrees == 90) {
|
||||
int temp = region->_packedWidth;
|
||||
region->_packedWidth = region->_packedHeight;
|
||||
region->_packedHeight = temp;
|
||||
}
|
||||
|
||||
_regions.add(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,88 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/AtlasAttachmentLoader.h>
|
||||
#include <spine/BoundingBoxAttachment.h>
|
||||
#include <spine/ClippingAttachment.h>
|
||||
#include <spine/MeshAttachment.h>
|
||||
#include <spine/PathAttachment.h>
|
||||
#include <spine/PointAttachment.h>
|
||||
#include <spine/RegionAttachment.h>
|
||||
#include <spine/Skin.h>
|
||||
|
||||
#include <spine/Atlas.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
AtlasAttachmentLoader::AtlasAttachmentLoader(Atlas &atlas) : AttachmentLoader(), _atlas(&atlas) {
|
||||
}
|
||||
|
||||
static void findRegions(Atlas *atlas, AtlasAttachmentLoader *loader, const String &name, const String &basePath, Sequence *sequence) {
|
||||
Array<TextureRegion *> ®ions = sequence->getRegions();
|
||||
for (int i = 0, n = (int) regions.size(); i < n; i++) {
|
||||
String path = sequence->getPath(basePath, i);
|
||||
regions[i] = loader->findRegion(path);
|
||||
}
|
||||
}
|
||||
|
||||
RegionAttachment *AtlasAttachmentLoader::newRegionAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) {
|
||||
SP_UNUSED(skin);
|
||||
findRegions(_atlas, this, name, path, sequence);
|
||||
return new (__FILE__, __LINE__) RegionAttachment(name, sequence);
|
||||
}
|
||||
|
||||
MeshAttachment *AtlasAttachmentLoader::newMeshAttachment(Skin &skin, const String &name, const String &path, Sequence *sequence) {
|
||||
SP_UNUSED(skin);
|
||||
findRegions(_atlas, this, name, path, sequence);
|
||||
return new (__FILE__, __LINE__) MeshAttachment(name, sequence);
|
||||
}
|
||||
|
||||
BoundingBoxAttachment *AtlasAttachmentLoader::newBoundingBoxAttachment(Skin &skin, const String &name) {
|
||||
SP_UNUSED(skin);
|
||||
return new (__FILE__, __LINE__) BoundingBoxAttachment(name);
|
||||
}
|
||||
|
||||
PathAttachment *AtlasAttachmentLoader::newPathAttachment(Skin &skin, const String &name) {
|
||||
SP_UNUSED(skin);
|
||||
return new (__FILE__, __LINE__) PathAttachment(name);
|
||||
}
|
||||
|
||||
PointAttachment *AtlasAttachmentLoader::newPointAttachment(Skin &skin, const String &name) {
|
||||
SP_UNUSED(skin);
|
||||
return new (__FILE__, __LINE__) PointAttachment(name);
|
||||
}
|
||||
|
||||
ClippingAttachment *AtlasAttachmentLoader::newClippingAttachment(Skin &skin, const String &name) {
|
||||
SP_UNUSED(skin);
|
||||
return new (__FILE__, __LINE__) ClippingAttachment(name);
|
||||
}
|
||||
|
||||
AtlasRegion *AtlasAttachmentLoader::findRegion(const String &name) {
|
||||
return _atlas->findRegion(name);
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Attachment.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_NOPARENT(Attachment)
|
||||
|
||||
Attachment::Attachment(const String &name) : _name(name), _timelineAttachment(this), _refCount(0) {
|
||||
assert(_name.length() > 0);
|
||||
}
|
||||
|
||||
Attachment::~Attachment() {
|
||||
}
|
||||
|
||||
const String &Attachment::getName() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
Attachment *Attachment::getTimelineAttachment() {
|
||||
return _timelineAttachment;
|
||||
}
|
||||
|
||||
void Attachment::setTimelineAttachment(Attachment *attachment) {
|
||||
_timelineAttachment = attachment;
|
||||
}
|
||||
|
||||
int Attachment::getRefCount() {
|
||||
return _refCount;
|
||||
}
|
||||
|
||||
void Attachment::reference() {
|
||||
_refCount++;
|
||||
}
|
||||
|
||||
void Attachment::dereference() {
|
||||
_refCount--;
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/AttachmentLoader.h>
|
||||
|
||||
#include <spine/BoundingBoxAttachment.h>
|
||||
#include <spine/ClippingAttachment.h>
|
||||
#include <spine/MeshAttachment.h>
|
||||
#include <spine/PathAttachment.h>
|
||||
#include <spine/PointAttachment.h>
|
||||
#include <spine/RegionAttachment.h>
|
||||
#include <spine/Skin.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
AttachmentLoader::AttachmentLoader() {
|
||||
}
|
||||
|
||||
AttachmentLoader::~AttachmentLoader() {
|
||||
}
|
||||
@ -1,89 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/AttachmentTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/SlotPose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_MULTI(AttachmentTimeline, Timeline, SlotTimeline)
|
||||
|
||||
AttachmentTimeline::AttachmentTimeline(size_t frameCount, int slotIndex) : Timeline(frameCount, 1), SlotTimeline(), _slotIndex(slotIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Attachment << 32) | slotIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_instant = true;
|
||||
|
||||
_attachmentNames.ensureCapacity(frameCount);
|
||||
for (size_t i = 0; i < frameCount; ++i) {
|
||||
_attachmentNames.add(String());
|
||||
}
|
||||
}
|
||||
|
||||
AttachmentTimeline::~AttachmentTimeline() {
|
||||
}
|
||||
|
||||
void AttachmentTimeline::setAttachment(Skeleton &skeleton, SlotPose &pose, String *attachmentName) {
|
||||
pose.setAttachment(attachmentName == NULL || attachmentName->isEmpty() ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName));
|
||||
}
|
||||
|
||||
void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(alpha);
|
||||
SP_UNUSED(add);
|
||||
|
||||
Slot *slot = skeleton._slots[_slotIndex];
|
||||
if (!slot->_bone.isActive()) return;
|
||||
SlotPose &pose = appliedPose ? *slot->_applied : slot->_pose;
|
||||
|
||||
if (out || time < _frames[0]) {
|
||||
if (fromSetup) setAttachment(skeleton, pose, &slot->_data._attachmentName);
|
||||
} else {
|
||||
setAttachment(skeleton, pose, &_attachmentNames[Animation::search(_frames, time)]);
|
||||
}
|
||||
}
|
||||
|
||||
void AttachmentTimeline::setFrame(int frame, float time, const String &attachmentName) {
|
||||
_frames[frame] = time;
|
||||
_attachmentNames[frame] = attachmentName;
|
||||
}
|
||||
|
||||
Array<String> &AttachmentTimeline::getAttachmentNames() {
|
||||
return _attachmentNames;
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Bone.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/BoneLocal.h>
|
||||
#include <spine/BonePose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(Bone, Update)
|
||||
|
||||
bool Bone::yDown = true;
|
||||
|
||||
Bone::Bone(BoneData &data, Bone *parent)
|
||||
: PosedGeneric<BoneData, BoneLocal, BonePose>(data), PosedActive(), _parent(parent), _children(), _sorted(false) {
|
||||
_constrained._bone = this;
|
||||
_applied->_bone = this;
|
||||
}
|
||||
|
||||
Bone::Bone(Bone &bone, Bone *parent)
|
||||
: PosedGeneric<BoneData, BoneLocal, BonePose>(bone._data), PosedActive(), _parent(parent), _children(), _sorted(false) {
|
||||
_constrained._bone = this;
|
||||
_applied->_bone = this;
|
||||
_pose.set(bone._pose);
|
||||
}
|
||||
|
||||
Bone *Bone::getParent() {
|
||||
return _parent;
|
||||
}
|
||||
|
||||
Array<Bone *> &Bone::getChildren() {
|
||||
return _children;
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/BoneData.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
BoneData::BoneData(int index, const String &name, BoneData *parent)
|
||||
: PosedDataGeneric<BoneLocal>(name), _index(index), _parent(parent), _length(0), _color(0.61f, 0.61f, 0.61f, 1.0f), _icon(), _visible(true) {
|
||||
assert(index >= 0);
|
||||
}
|
||||
|
||||
int BoneData::getIndex() {
|
||||
return _index;
|
||||
}
|
||||
|
||||
BoneData *BoneData::getParent() {
|
||||
return _parent;
|
||||
}
|
||||
|
||||
float BoneData::getLength() {
|
||||
return _length;
|
||||
}
|
||||
|
||||
void BoneData::setLength(float inValue) {
|
||||
_length = inValue;
|
||||
}
|
||||
|
||||
Color &BoneData::getColor() {
|
||||
return _color;
|
||||
}
|
||||
|
||||
const String &BoneData::getIcon() {
|
||||
return _icon;
|
||||
}
|
||||
|
||||
void BoneData::setIcon(const String &icon) {
|
||||
this->_icon = icon;
|
||||
}
|
||||
|
||||
bool BoneData::getVisible() {
|
||||
return _visible;
|
||||
}
|
||||
|
||||
void BoneData::setVisible(bool inValue) {
|
||||
this->_visible = inValue;
|
||||
}
|
||||
@ -1,128 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/BoneLocal.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
BoneLocal::BoneLocal() : _x(0), _y(0), _rotation(0), _scaleX(1), _scaleY(1), _shearX(0), _shearY(0), _inherit(Inherit_Normal) {
|
||||
}
|
||||
|
||||
BoneLocal::~BoneLocal() {
|
||||
}
|
||||
|
||||
void BoneLocal::set(BoneLocal &pose) {
|
||||
_x = pose._x;
|
||||
_y = pose._y;
|
||||
_rotation = pose._rotation;
|
||||
_scaleX = pose._scaleX;
|
||||
_scaleY = pose._scaleY;
|
||||
_shearX = pose._shearX;
|
||||
_shearY = pose._shearY;
|
||||
_inherit = pose._inherit;
|
||||
}
|
||||
|
||||
float BoneLocal::getX() {
|
||||
return _x;
|
||||
}
|
||||
|
||||
void BoneLocal::setX(float x) {
|
||||
_x = x;
|
||||
}
|
||||
|
||||
float BoneLocal::getY() {
|
||||
return _y;
|
||||
}
|
||||
|
||||
void BoneLocal::setY(float y) {
|
||||
_y = y;
|
||||
}
|
||||
|
||||
void BoneLocal::setPosition(float x, float y) {
|
||||
_x = x;
|
||||
_y = y;
|
||||
}
|
||||
|
||||
float BoneLocal::getRotation() {
|
||||
return _rotation;
|
||||
}
|
||||
|
||||
void BoneLocal::setRotation(float rotation) {
|
||||
_rotation = rotation;
|
||||
}
|
||||
|
||||
float BoneLocal::getScaleX() {
|
||||
return _scaleX;
|
||||
}
|
||||
|
||||
void BoneLocal::setScaleX(float scaleX) {
|
||||
_scaleX = scaleX;
|
||||
}
|
||||
|
||||
float BoneLocal::getScaleY() {
|
||||
return _scaleY;
|
||||
}
|
||||
|
||||
void BoneLocal::setScaleY(float scaleY) {
|
||||
_scaleY = scaleY;
|
||||
}
|
||||
|
||||
void BoneLocal::setScale(float scaleX, float scaleY) {
|
||||
_scaleX = scaleX;
|
||||
_scaleY = scaleY;
|
||||
}
|
||||
|
||||
void BoneLocal::setScale(float scale) {
|
||||
_scaleX = scale;
|
||||
_scaleY = scale;
|
||||
}
|
||||
|
||||
float BoneLocal::getShearX() {
|
||||
return _shearX;
|
||||
}
|
||||
|
||||
void BoneLocal::setShearX(float shearX) {
|
||||
_shearX = shearX;
|
||||
}
|
||||
|
||||
float BoneLocal::getShearY() {
|
||||
return _shearY;
|
||||
}
|
||||
|
||||
void BoneLocal::setShearY(float shearY) {
|
||||
_shearY = shearY;
|
||||
}
|
||||
|
||||
Inherit BoneLocal::getInherit() {
|
||||
return _inherit;
|
||||
}
|
||||
|
||||
void BoneLocal::setInherit(Inherit inherit) {
|
||||
_inherit = inherit;
|
||||
}
|
||||
@ -1,388 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, 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/BonePose.h>
|
||||
#include "spine/RTTI.h"
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Physics.h>
|
||||
#include <spine/MathUtil.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(BonePose, Update);
|
||||
|
||||
BonePose::BonePose() : BoneLocal(), _bone(nullptr), _a(0), _b(0), _worldX(0), _c(0), _d(0), _worldY(0), _world(0), _local(0) {
|
||||
}
|
||||
|
||||
BonePose::~BonePose() {
|
||||
}
|
||||
|
||||
void BonePose::update(Skeleton &skeleton, Physics physics) {
|
||||
if (_world != skeleton._update) updateWorldTransform(skeleton);
|
||||
}
|
||||
|
||||
void BonePose::updateWorldTransform(Skeleton &skeleton) {
|
||||
if (_local == skeleton._update)
|
||||
updateLocalTransform(skeleton);
|
||||
else
|
||||
_world = skeleton._update;
|
||||
|
||||
if (_bone->getParent() == nullptr) {// Root bone.
|
||||
float sx = skeleton.getScaleX(), sy = skeleton.getScaleY();
|
||||
float rx = (_rotation + _shearX) * MathUtil::Deg_Rad;
|
||||
float ry = (_rotation + 90 + _shearY) * MathUtil::Deg_Rad;
|
||||
_a = MathUtil::cos(rx) * _scaleX * sx;
|
||||
_b = MathUtil::cos(ry) * _scaleY * sx;
|
||||
_c = MathUtil::sin(rx) * _scaleX * sy;
|
||||
_d = MathUtil::sin(ry) * _scaleY * sy;
|
||||
_worldX = _x * sx + skeleton.getX();
|
||||
_worldY = _y * sy + skeleton.getY();
|
||||
return;
|
||||
}
|
||||
|
||||
BonePose &parent = _bone->getParent()->getAppliedPose();
|
||||
float pa = parent._a, pb = parent._b, pc = parent._c, pd = parent._d;
|
||||
_worldX = pa * _x + pb * _y + parent._worldX;
|
||||
_worldY = pc * _x + pd * _y + parent._worldY;
|
||||
|
||||
switch (_inherit) {
|
||||
case Inherit_Normal: {
|
||||
float rx = (_rotation + _shearX) * MathUtil::Deg_Rad;
|
||||
float ry = (_rotation + 90 + _shearY) * MathUtil::Deg_Rad;
|
||||
float la = MathUtil::cos(rx) * _scaleX;
|
||||
float lb = MathUtil::cos(ry) * _scaleY;
|
||||
float lc = MathUtil::sin(rx) * _scaleX;
|
||||
float ld = MathUtil::sin(ry) * _scaleY;
|
||||
_a = pa * la + pb * lc;
|
||||
_b = pa * lb + pb * ld;
|
||||
_c = pc * la + pd * lc;
|
||||
_d = pc * lb + pd * ld;
|
||||
return;
|
||||
}
|
||||
case Inherit_OnlyTranslation: {
|
||||
float rx = (_rotation + _shearX) * MathUtil::Deg_Rad;
|
||||
float ry = (_rotation + 90 + _shearY) * MathUtil::Deg_Rad;
|
||||
_a = MathUtil::cos(rx) * _scaleX;
|
||||
_b = MathUtil::cos(ry) * _scaleY;
|
||||
_c = MathUtil::sin(rx) * _scaleX;
|
||||
_d = MathUtil::sin(ry) * _scaleY;
|
||||
break;
|
||||
}
|
||||
case Inherit_NoRotationOrReflection: {
|
||||
float sx = 1 / skeleton.getScaleX(), sy = 1 / skeleton.getScaleY();
|
||||
pa *= sx;
|
||||
pc *= sy;
|
||||
float s = pa * pa + pc * pc, prx;
|
||||
if (s > 0.0001f) {
|
||||
s = MathUtil::abs(pa * pd * sy - pb * sx * pc) / s;
|
||||
pb = pc * s;
|
||||
pd = pa * s;
|
||||
prx = MathUtil::atan2(pc, pa) * MathUtil::Rad_Deg;
|
||||
} else {
|
||||
pa = 0;
|
||||
pc = 0;
|
||||
prx = 90 - MathUtil::atan2(pd, pb) * MathUtil::Rad_Deg;
|
||||
}
|
||||
float rx = (_rotation + _shearX - prx) * MathUtil::Deg_Rad;
|
||||
float ry = (_rotation + _shearY - prx + 90) * MathUtil::Deg_Rad;
|
||||
float la = MathUtil::cos(rx) * _scaleX;
|
||||
float lb = MathUtil::cos(ry) * _scaleY;
|
||||
float lc = MathUtil::sin(rx) * _scaleX;
|
||||
float ld = MathUtil::sin(ry) * _scaleY;
|
||||
_a = pa * la - pb * lc;
|
||||
_b = pa * lb - pb * ld;
|
||||
_c = pc * la + pd * lc;
|
||||
_d = pc * lb + pd * ld;
|
||||
break;
|
||||
}
|
||||
case Inherit_NoScale:
|
||||
case Inherit_NoScaleOrReflection: {
|
||||
float r = _rotation * MathUtil::Deg_Rad, cosR = MathUtil::cos(r), sinR = MathUtil::sin(r);
|
||||
float za = (pa * cosR + pb * sinR) / skeleton.getScaleX();
|
||||
float zc = (pc * cosR + pd * sinR) / skeleton.getScaleY();
|
||||
float s = MathUtil::sqrt(za * za + zc * zc);
|
||||
if (s > 0.00001f) s = 1 / s;
|
||||
za *= s;
|
||||
zc *= s;
|
||||
s = MathUtil::sqrt(za * za + zc * zc);
|
||||
if (_inherit == Inherit_NoScale && (pa * pd - pb * pc < 0) != ((skeleton.getScaleX() < 0) != (skeleton.getScaleY() < 0))) s = -s;
|
||||
r = MathUtil::Pi / 2 + MathUtil::atan2(zc, za);
|
||||
float zb = MathUtil::cos(r) * s;
|
||||
float zd = MathUtil::sin(r) * s;
|
||||
float rx = _shearX * MathUtil::Deg_Rad;
|
||||
float ry = (90 + _shearY) * MathUtil::Deg_Rad;
|
||||
float la = MathUtil::cos(rx) * _scaleX;
|
||||
float lb = MathUtil::cos(ry) * _scaleY;
|
||||
float lc = MathUtil::sin(rx) * _scaleX;
|
||||
float ld = MathUtil::sin(ry) * _scaleY;
|
||||
_a = za * la + zb * lc;
|
||||
_b = za * lb + zb * ld;
|
||||
_c = zc * la + zd * lc;
|
||||
_d = zc * lb + zd * ld;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_a *= skeleton.getScaleX();
|
||||
_b *= skeleton.getScaleX();
|
||||
_c *= skeleton.getScaleY();
|
||||
_d *= skeleton.getScaleY();
|
||||
}
|
||||
|
||||
void BonePose::updateLocalTransform(Skeleton &skeleton) {
|
||||
_local = 0;
|
||||
_world = skeleton._update;
|
||||
|
||||
if (_bone->getParent() == nullptr) {
|
||||
_x = _worldX - skeleton.getX();
|
||||
_y = _worldY - skeleton.getY();
|
||||
float a = this->_a, b = this->_b, c = this->_c, d = this->_d;
|
||||
_rotation = MathUtil::atan2(c, a) * MathUtil::Rad_Deg;
|
||||
_scaleX = MathUtil::sqrt(a * a + c * c);
|
||||
_scaleY = MathUtil::sqrt(b * b + d * d);
|
||||
_shearX = 0;
|
||||
_shearY = MathUtil::atan2(a * b + c * d, a * d - b * c) * MathUtil::Rad_Deg;
|
||||
return;
|
||||
}
|
||||
|
||||
BonePose &parent = _bone->getParent()->getAppliedPose();
|
||||
float pa = parent._a, pb = parent._b, pc = parent._c, pd = parent._d;
|
||||
float pid = 1 / (pa * pd - pb * pc);
|
||||
float ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid;
|
||||
float dx = _worldX - parent._worldX, dy = _worldY - parent._worldY;
|
||||
_x = (dx * ia - dy * ib);
|
||||
_y = (dy * id - dx * ic);
|
||||
|
||||
float ra, rb, rc, rd;
|
||||
if (_inherit == Inherit_OnlyTranslation) {
|
||||
ra = _a;
|
||||
rb = _b;
|
||||
rc = _c;
|
||||
rd = _d;
|
||||
} else {
|
||||
switch (_inherit) {
|
||||
case Inherit_NoRotationOrReflection: {
|
||||
float s = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
|
||||
pb = -pc * skeleton.getScaleX() * s / skeleton.getScaleY();
|
||||
pd = pa * skeleton.getScaleY() * s / skeleton.getScaleX();
|
||||
pid = 1 / (pa * pd - pb * pc);
|
||||
ia = pd * pid;
|
||||
ib = pb * pid;
|
||||
break;
|
||||
}
|
||||
case Inherit_NoScale:
|
||||
case Inherit_NoScaleOrReflection: {
|
||||
float r = _rotation * MathUtil::Deg_Rad, cosR = MathUtil::cos(r), sinR = MathUtil::sin(r);
|
||||
pa = (pa * cosR + pb * sinR) / skeleton.getScaleX();
|
||||
pc = (pc * cosR + pd * sinR) / skeleton.getScaleY();
|
||||
float s = MathUtil::sqrt(pa * pa + pc * pc);
|
||||
if (s > 0.00001f) s = 1 / s;
|
||||
pa *= s;
|
||||
pc *= s;
|
||||
s = MathUtil::sqrt(pa * pa + pc * pc);
|
||||
if (_inherit == Inherit_NoScale && (pid < 0) != ((skeleton.getScaleX() < 0) != (skeleton.getScaleY() < 0))) s = -s;
|
||||
r = MathUtil::Pi / 2 + MathUtil::atan2(pc, pa);
|
||||
pb = MathUtil::cos(r) * s;
|
||||
pd = MathUtil::sin(r) * s;
|
||||
pid = 1 / (pa * pd - pb * pc);
|
||||
ia = pd * pid;
|
||||
ib = pb * pid;
|
||||
ic = pc * pid;
|
||||
id = pa * pid;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ra = ia * _a - ib * _c;
|
||||
rb = ia * _b - ib * _d;
|
||||
rc = id * _c - ic * _a;
|
||||
rd = id * _d - ic * _b;
|
||||
}
|
||||
|
||||
_shearX = 0;
|
||||
_scaleX = MathUtil::sqrt(ra * ra + rc * rc);
|
||||
if (_scaleX > 0.0001f) {
|
||||
float det = ra * rd - rb * rc;
|
||||
_scaleY = det / _scaleX;
|
||||
_shearY = -MathUtil::atan2(ra * rb + rc * rd, det) * MathUtil::Rad_Deg;
|
||||
_rotation = MathUtil::atan2(rc, ra) * MathUtil::Rad_Deg;
|
||||
} else {
|
||||
_scaleX = 0;
|
||||
_scaleY = MathUtil::sqrt(rb * rb + rd * rd);
|
||||
_shearY = 0;
|
||||
_rotation = 90 - MathUtil::atan2(rd, rb) * MathUtil::Rad_Deg;
|
||||
}
|
||||
}
|
||||
|
||||
void BonePose::validateLocalTransform(Skeleton &skeleton) {
|
||||
if (_local == skeleton._update) updateLocalTransform(skeleton);
|
||||
}
|
||||
|
||||
void BonePose::modifyLocal(Skeleton &skeleton) {
|
||||
if (_local == skeleton._update) updateLocalTransform(skeleton);
|
||||
_world = 0;
|
||||
resetWorld(skeleton._update);
|
||||
}
|
||||
|
||||
void BonePose::modifyWorld(int update) {
|
||||
_local = update;
|
||||
_world = update;
|
||||
resetWorld(update);
|
||||
}
|
||||
|
||||
void BonePose::resetWorld(int update) {
|
||||
Array<Bone *> &children = _bone->getChildren();
|
||||
for (size_t i = 0, n = children.size(); i < n; i++) {
|
||||
BonePose &child = children[i]->getAppliedPose();
|
||||
if (child._world == update) {
|
||||
child._world = 0;
|
||||
child._local = 0;
|
||||
child.resetWorld(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float BonePose::getA() {
|
||||
return _a;
|
||||
}
|
||||
|
||||
void BonePose::setA(float a) {
|
||||
this->_a = a;
|
||||
}
|
||||
|
||||
float BonePose::getB() {
|
||||
return _b;
|
||||
}
|
||||
|
||||
void BonePose::setB(float b) {
|
||||
this->_b = b;
|
||||
}
|
||||
|
||||
float BonePose::getC() {
|
||||
return _c;
|
||||
}
|
||||
|
||||
void BonePose::setC(float c) {
|
||||
this->_c = c;
|
||||
}
|
||||
|
||||
float BonePose::getD() {
|
||||
return _d;
|
||||
}
|
||||
|
||||
void BonePose::setD(float d) {
|
||||
this->_d = d;
|
||||
}
|
||||
|
||||
float BonePose::getWorldX() {
|
||||
return _worldX;
|
||||
}
|
||||
|
||||
void BonePose::setWorldX(float worldX) {
|
||||
this->_worldX = worldX;
|
||||
}
|
||||
|
||||
float BonePose::getWorldY() {
|
||||
return _worldY;
|
||||
}
|
||||
|
||||
void BonePose::setWorldY(float worldY) {
|
||||
this->_worldY = worldY;
|
||||
}
|
||||
|
||||
float BonePose::getWorldRotationX() {
|
||||
return MathUtil::atan2(_c, _a) * MathUtil::Rad_Deg;
|
||||
}
|
||||
|
||||
float BonePose::getWorldRotationY() {
|
||||
return MathUtil::atan2(_d, _b) * MathUtil::Rad_Deg;
|
||||
}
|
||||
|
||||
float BonePose::getWorldScaleX() {
|
||||
return MathUtil::sqrt(_a * _a + _c * _c);
|
||||
}
|
||||
|
||||
float BonePose::getWorldScaleY() {
|
||||
return MathUtil::sqrt(_b * _b + _d * _d);
|
||||
}
|
||||
|
||||
|
||||
void BonePose::worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY) {
|
||||
float det = _a * _d - _b * _c;
|
||||
float x = worldX - _worldX, y = worldY - _worldY;
|
||||
outLocalX = (x * _d - y * _b) / det;
|
||||
outLocalY = (y * _a - x * _c) / det;
|
||||
}
|
||||
|
||||
void BonePose::localToWorld(float localX, float localY, float &outWorldX, float &outWorldY) {
|
||||
outWorldX = localX * _a + localY * _b + _worldX;
|
||||
outWorldY = localX * _c + localY * _d + _worldY;
|
||||
}
|
||||
|
||||
void BonePose::worldToParent(float worldX, float worldY, float &outParentX, float &outParentY) {
|
||||
if (_bone->getParent() == nullptr) {
|
||||
outParentX = worldX;
|
||||
outParentY = worldY;
|
||||
} else {
|
||||
_bone->getParent()->getAppliedPose().worldToLocal(worldX, worldY, outParentX, outParentY);
|
||||
}
|
||||
}
|
||||
|
||||
void BonePose::parentToWorld(float parentX, float parentY, float &outWorldX, float &outWorldY) {
|
||||
if (_bone->getParent() == nullptr) {
|
||||
outWorldX = parentX;
|
||||
outWorldY = parentY;
|
||||
} else {
|
||||
_bone->getParent()->getAppliedPose().localToWorld(parentX, parentY, outWorldX, outWorldY);
|
||||
}
|
||||
}
|
||||
|
||||
float BonePose::worldToLocalRotation(float worldRotation) {
|
||||
worldRotation *= MathUtil::Deg_Rad;
|
||||
float sinRot = MathUtil::sin(worldRotation), cosRot = MathUtil::cos(worldRotation);
|
||||
return MathUtil::atan2(_a * sinRot - _c * cosRot, _d * cosRot - _b * sinRot) * MathUtil::Rad_Deg + _rotation - _shearX;
|
||||
}
|
||||
|
||||
float BonePose::localToWorldRotation(float localRotation) {
|
||||
localRotation = (localRotation - _rotation - _shearX) * MathUtil::Deg_Rad;
|
||||
float sinRot = MathUtil::sin(localRotation), cosRot = MathUtil::cos(localRotation);
|
||||
return MathUtil::atan2(cosRot * _c + sinRot * _d, cosRot * _a + sinRot * _b) * MathUtil::Rad_Deg;
|
||||
}
|
||||
|
||||
void BonePose::rotateWorld(float degrees) {
|
||||
degrees *= MathUtil::Deg_Rad;
|
||||
float sinRot = MathUtil::sin(degrees), cosRot = MathUtil::cos(degrees);
|
||||
float ra = _a, rb = _b;
|
||||
_a = cosRot * ra - sinRot * _c;
|
||||
_b = cosRot * rb - sinRot * _d;
|
||||
_c = sinRot * ra + cosRot * _c;
|
||||
_d = sinRot * rb + cosRot * _d;
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/BoneTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/BoneLocal.h>
|
||||
#include <spine/Property.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
// Define static constants for BoneTimeline2
|
||||
const int BoneTimeline2::ENTRIES = 3;
|
||||
const int BoneTimeline2::VALUE1 = 1;
|
||||
const int BoneTimeline2::VALUE2 = 2;
|
||||
|
||||
RTTI_IMPL_NOPARENT(BoneTimeline)
|
||||
|
||||
RTTI_IMPL_MULTI(BoneTimeline1, CurveTimeline1, BoneTimeline)
|
||||
|
||||
BoneTimeline1::BoneTimeline1(size_t frameCount, size_t bezierCount, int boneIndex, Property property)
|
||||
: CurveTimeline1(frameCount, bezierCount), BoneTimeline(boneIndex), _boneIndex(boneIndex) {
|
||||
PropertyId ids[] = {((PropertyId) property << 32) | boneIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
void BoneTimeline1::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
|
||||
Bone *bone = skeleton._bones[_boneIndex];
|
||||
if (bone->isActive()) {
|
||||
_apply(appliedPose ? *bone->_applied : bone->_pose, bone->_data._setup, time, alpha, fromSetup, add, out);
|
||||
}
|
||||
}
|
||||
|
||||
RTTI_IMPL_MULTI(BoneTimeline2, CurveTimeline, BoneTimeline)
|
||||
|
||||
BoneTimeline2::BoneTimeline2(size_t frameCount, size_t bezierCount, int boneIndex, Property property1, Property property2)
|
||||
: CurveTimeline(frameCount, BoneTimeline2::ENTRIES, bezierCount), BoneTimeline(boneIndex), _boneIndex(boneIndex) {
|
||||
PropertyId ids[] = {((PropertyId) property1 << 32) | boneIndex, ((PropertyId) property2 << 32) | boneIndex};
|
||||
setPropertyIds(ids, 2);
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
void BoneTimeline2::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
|
||||
Bone *bone = skeleton._bones[_boneIndex];
|
||||
if (bone->isActive()) {
|
||||
_apply(appliedPose ? *bone->_applied : bone->_pose, bone->_data._setup, time, alpha, fromSetup, add, out);
|
||||
}
|
||||
}
|
||||
|
||||
void BoneTimeline2::setFrame(size_t frame, float time, float value1, float value2) {
|
||||
frame *= ENTRIES;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + VALUE1] = value1;
|
||||
_frames[frame + VALUE2] = value2;
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/BoundingBoxAttachment.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(BoundingBoxAttachment, VertexAttachment)
|
||||
|
||||
BoundingBoxAttachment::BoundingBoxAttachment(const String &name) : VertexAttachment(name), _color(0.38f, 0.94f, 0.0f, 1.0f) {
|
||||
}
|
||||
|
||||
Color &BoundingBoxAttachment::getColor() {
|
||||
return _color;
|
||||
}
|
||||
|
||||
Attachment &BoundingBoxAttachment::copy() {
|
||||
BoundingBoxAttachment *copy = new (__FILE__, __LINE__) BoundingBoxAttachment(getName());
|
||||
copyTo(*copy);
|
||||
return *copy;
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/ClippingAttachment.h>
|
||||
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(ClippingAttachment, VertexAttachment)
|
||||
|
||||
ClippingAttachment::ClippingAttachment(const String &name) : VertexAttachment(name), _endSlot(NULL), _color() {
|
||||
}
|
||||
|
||||
SlotData *ClippingAttachment::getEndSlot() {
|
||||
return _endSlot;
|
||||
}
|
||||
|
||||
void ClippingAttachment::setEndSlot(SlotData *inValue) {
|
||||
_endSlot = inValue;
|
||||
}
|
||||
|
||||
Color &ClippingAttachment::getColor() {
|
||||
return _color;
|
||||
}
|
||||
|
||||
Attachment &ClippingAttachment::copy() {
|
||||
ClippingAttachment *copy = new (__FILE__, __LINE__) ClippingAttachment(getName());
|
||||
copyTo(*copy);
|
||||
copy->_endSlot = _endSlot;
|
||||
return *copy;
|
||||
}
|
||||
@ -1,454 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/ColorTimeline.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/SlotPose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(RGBATimeline, SlotCurveTimeline)
|
||||
|
||||
RGBATimeline::RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex) : SlotCurveTimeline(frameCount, ENTRIES, bezierCount, slotIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, ((PropertyId) Property_Alpha << 32) | slotIndex};
|
||||
setPropertyIds(ids, 2);
|
||||
}
|
||||
|
||||
RGBATimeline::~RGBATimeline() {
|
||||
}
|
||||
|
||||
void RGBATimeline::setFrame(int frame, float time, float r, float g, float b, float a) {
|
||||
frame *= ENTRIES;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + R] = r;
|
||||
_frames[frame + G] = g;
|
||||
_frames[frame + B] = b;
|
||||
_frames[frame + A] = a;
|
||||
}
|
||||
|
||||
void RGBATimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) {
|
||||
SP_UNUSED(add);
|
||||
Color &color = pose._color;
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) color.set(slot._data._setup._color);
|
||||
return;
|
||||
}
|
||||
|
||||
float r, g, b, a;
|
||||
int i = Animation::search(_frames, time, ENTRIES);
|
||||
int curveType = (int) _curves[i / ENTRIES];
|
||||
switch (curveType) {
|
||||
case LINEAR: {
|
||||
float before = _frames[i];
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
a = _frames[i + A];
|
||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||
r += (_frames[i + ENTRIES + R] - r) * t;
|
||||
g += (_frames[i + ENTRIES + G] - g) * t;
|
||||
b += (_frames[i + ENTRIES + B] - b) * t;
|
||||
a += (_frames[i + ENTRIES + A] - a) * t;
|
||||
break;
|
||||
}
|
||||
case STEPPED: {
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
a = _frames[i + A];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
r = getBezierValue(time, i, R, curveType - BEZIER);
|
||||
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
||||
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||
a = getBezierValue(time, i, A, curveType + BEZIER_SIZE * 3 - BEZIER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha == 1)
|
||||
color.set(r, g, b, a);
|
||||
else {
|
||||
if (fromSetup) {
|
||||
Color &setup = slot._data._setup._color;
|
||||
color.set(setup.r + (r - setup.r) * alpha, setup.g + (g - setup.g) * alpha, setup.b + (b - setup.b) * alpha,
|
||||
setup.a + (a - setup.a) * alpha);
|
||||
} else
|
||||
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
|
||||
}
|
||||
}
|
||||
|
||||
RTTI_IMPL(RGBTimeline, SlotCurveTimeline)
|
||||
|
||||
RGBTimeline::RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex) : SlotCurveTimeline(frameCount, ENTRIES, bezierCount, slotIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
RGBTimeline::~RGBTimeline() {
|
||||
}
|
||||
|
||||
void RGBTimeline::setFrame(int frame, float time, float r, float g, float b) {
|
||||
frame <<= 2;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + R] = r;
|
||||
_frames[frame + G] = g;
|
||||
_frames[frame + B] = b;
|
||||
}
|
||||
|
||||
void RGBTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) {
|
||||
SP_UNUSED(add);
|
||||
Color &color = pose._color;
|
||||
float r, g, b;
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) {
|
||||
Color &setup = slot._data._setup._color;
|
||||
color.r = setup.r;
|
||||
color.g = setup.g;
|
||||
color.b = setup.b;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int i = Animation::search(_frames, time, ENTRIES);
|
||||
int curveType = (int) _curves[i >> 2];
|
||||
switch (curveType) {
|
||||
case LINEAR: {
|
||||
float before = _frames[i];
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||
r += (_frames[i + ENTRIES + R] - r) * t;
|
||||
g += (_frames[i + ENTRIES + G] - g) * t;
|
||||
b += (_frames[i + ENTRIES + B] - b) * t;
|
||||
break;
|
||||
}
|
||||
case STEPPED: {
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
r = getBezierValue(time, i, R, curveType - BEZIER);
|
||||
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
||||
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha != 1) {
|
||||
if (fromSetup) {
|
||||
Color &setup = slot._data._setup._color;
|
||||
r = setup.r + (r - setup.r) * alpha;
|
||||
g = setup.g + (g - setup.g) * alpha;
|
||||
b = setup.b + (b - setup.b) * alpha;
|
||||
} else {
|
||||
r = color.r + (r - color.r) * alpha;
|
||||
g = color.g + (g - color.g) * alpha;
|
||||
b = color.b + (b - color.b) * alpha;
|
||||
}
|
||||
}
|
||||
color.r = r < 0 ? 0 : (r > 1 ? 1 : r);
|
||||
color.g = g < 0 ? 0 : (g > 1 ? 1 : g);
|
||||
color.b = b < 0 ? 0 : (b > 1 ? 1 : b);
|
||||
}
|
||||
|
||||
RTTI_IMPL(AlphaTimeline, SlotCurveTimeline)
|
||||
|
||||
AlphaTimeline::AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex)
|
||||
: CurveTimeline1(frameCount, bezierCount), SlotTimeline(), _slotIndex(slotIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Alpha << 32) | slotIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
AlphaTimeline::~AlphaTimeline() {
|
||||
}
|
||||
|
||||
int AlphaTimeline::getSlotIndex() {
|
||||
return _slotIndex;
|
||||
}
|
||||
|
||||
void AlphaTimeline::setSlotIndex(int inValue) {
|
||||
_slotIndex = inValue;
|
||||
}
|
||||
|
||||
void AlphaTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(add);
|
||||
SP_UNUSED(out);
|
||||
|
||||
Slot *slot = skeleton._slots[_slotIndex];
|
||||
if (!slot->_bone._active) return;
|
||||
|
||||
Color &color = (appliedPose ? *slot->_applied : slot->_pose)._color;
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) color.a = slot->_data._setup._color.a;
|
||||
return;
|
||||
}
|
||||
|
||||
float a = getCurveValue(time);
|
||||
if (alpha != 1) {
|
||||
if (fromSetup) {
|
||||
Color &setup = slot->_data._setup._color;
|
||||
a = setup.a + (a - setup.a) * alpha;
|
||||
} else
|
||||
a = color.a + (a - color.a) * alpha;
|
||||
}
|
||||
color.a = a < 0 ? 0 : (a > 1 ? 1 : a);
|
||||
}
|
||||
|
||||
RTTI_IMPL(RGBA2Timeline, SlotCurveTimeline)
|
||||
|
||||
RGBA2Timeline::RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : SlotCurveTimeline(frameCount, ENTRIES, bezierCount, slotIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, ((PropertyId) Property_Alpha << 32) | slotIndex,
|
||||
((PropertyId) Property_Rgb2 << 32) | slotIndex};
|
||||
setPropertyIds(ids, 3);
|
||||
}
|
||||
|
||||
RGBA2Timeline::~RGBA2Timeline() {
|
||||
}
|
||||
|
||||
void RGBA2Timeline::setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2) {
|
||||
frame <<= 3;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + R] = r;
|
||||
_frames[frame + G] = g;
|
||||
_frames[frame + B] = b;
|
||||
_frames[frame + A] = a;
|
||||
_frames[frame + R2] = r2;
|
||||
_frames[frame + G2] = g2;
|
||||
_frames[frame + B2] = b2;
|
||||
}
|
||||
|
||||
void RGBA2Timeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) {
|
||||
SP_UNUSED(add);
|
||||
Color &light = pose._color;
|
||||
Color &dark = pose._darkColor;
|
||||
float r2, g2, b2;
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) {
|
||||
SlotPose &setup = slot._data._setup;
|
||||
light.set(setup._color);
|
||||
Color &setupDark = setup._darkColor;
|
||||
dark.r = setupDark.r;
|
||||
dark.g = setupDark.g;
|
||||
dark.b = setupDark.b;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float r, g, b, a;
|
||||
int i = Animation::search(_frames, time, ENTRIES);
|
||||
int curveType = (int) _curves[i >> 3];
|
||||
switch (curveType) {
|
||||
case LINEAR: {
|
||||
float before = _frames[i];
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
a = _frames[i + A];
|
||||
r2 = _frames[i + R2];
|
||||
g2 = _frames[i + G2];
|
||||
b2 = _frames[i + B2];
|
||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||
r += (_frames[i + ENTRIES + R] - r) * t;
|
||||
g += (_frames[i + ENTRIES + G] - g) * t;
|
||||
b += (_frames[i + ENTRIES + B] - b) * t;
|
||||
a += (_frames[i + ENTRIES + A] - a) * t;
|
||||
r2 += (_frames[i + ENTRIES + R2] - r2) * t;
|
||||
g2 += (_frames[i + ENTRIES + G2] - g2) * t;
|
||||
b2 += (_frames[i + ENTRIES + B2] - b2) * t;
|
||||
break;
|
||||
}
|
||||
case STEPPED: {
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
a = _frames[i + A];
|
||||
r2 = _frames[i + R2];
|
||||
g2 = _frames[i + G2];
|
||||
b2 = _frames[i + B2];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
r = getBezierValue(time, i, R, curveType - BEZIER);
|
||||
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
||||
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||
a = getBezierValue(time, i, A, curveType + BEZIER_SIZE * 3 - BEZIER);
|
||||
r2 = getBezierValue(time, i, R2, curveType + BEZIER_SIZE * 4 - BEZIER);
|
||||
g2 = getBezierValue(time, i, G2, curveType + BEZIER_SIZE * 5 - BEZIER);
|
||||
b2 = getBezierValue(time, i, B2, curveType + BEZIER_SIZE * 6 - BEZIER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha == 1)
|
||||
light.set(r, g, b, a);
|
||||
else if (fromSetup) {
|
||||
SlotPose &setup = slot._data._setup;
|
||||
Color &setupLight = setup._color;
|
||||
light.set(setupLight.r + (r - setupLight.r) * alpha, setupLight.g + (g - setupLight.g) * alpha, setupLight.b + (b - setupLight.b) * alpha,
|
||||
setupLight.a + (a - setupLight.a) * alpha);
|
||||
Color &setupDark = setup._darkColor;
|
||||
r2 = setupDark.r + (r2 - setupDark.r) * alpha;
|
||||
g2 = setupDark.g + (g2 - setupDark.g) * alpha;
|
||||
b2 = setupDark.b + (b2 - setupDark.b) * alpha;
|
||||
} else {
|
||||
light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);
|
||||
r2 = dark.r + (r2 - dark.r) * alpha;
|
||||
g2 = dark.g + (g2 - dark.g) * alpha;
|
||||
b2 = dark.b + (b2 - dark.b) * alpha;
|
||||
}
|
||||
|
||||
dark.r = r2 < 0 ? 0 : (r2 > 1 ? 1 : r2);
|
||||
dark.g = g2 < 0 ? 0 : (g2 > 1 ? 1 : g2);
|
||||
dark.b = b2 < 0 ? 0 : (b2 > 1 ? 1 : b2);
|
||||
}
|
||||
|
||||
RTTI_IMPL(RGB2Timeline, SlotCurveTimeline)
|
||||
|
||||
RGB2Timeline::RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex) : SlotCurveTimeline(frameCount, ENTRIES, bezierCount, slotIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Rgb << 32) | slotIndex, ((PropertyId) Property_Rgb2 << 32) | slotIndex};
|
||||
setPropertyIds(ids, 2);
|
||||
}
|
||||
|
||||
RGB2Timeline::~RGB2Timeline() {
|
||||
}
|
||||
|
||||
void RGB2Timeline::setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2) {
|
||||
frame *= ENTRIES;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + R] = r;
|
||||
_frames[frame + G] = g;
|
||||
_frames[frame + B] = b;
|
||||
_frames[frame + R2] = r2;
|
||||
_frames[frame + G2] = g2;
|
||||
_frames[frame + B2] = b2;
|
||||
}
|
||||
|
||||
void RGB2Timeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) {
|
||||
SP_UNUSED(add);
|
||||
Color &light = pose._color;
|
||||
Color &dark = pose._darkColor;
|
||||
float r, g, b, r2, g2, b2;
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) {
|
||||
SlotPose &setup = slot._data._setup;
|
||||
Color &setupLight = setup._color;
|
||||
Color &setupDark = setup._darkColor;
|
||||
light.r = setupLight.r;
|
||||
light.g = setupLight.g;
|
||||
light.b = setupLight.b;
|
||||
dark.r = setupDark.r;
|
||||
dark.g = setupDark.g;
|
||||
dark.b = setupDark.b;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int i = Animation::search(_frames, time, ENTRIES);
|
||||
int curveType = (int) _curves[i / ENTRIES];
|
||||
switch (curveType) {
|
||||
case LINEAR: {
|
||||
float before = _frames[i];
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
r2 = _frames[i + R2];
|
||||
g2 = _frames[i + G2];
|
||||
b2 = _frames[i + B2];
|
||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||
r += (_frames[i + ENTRIES + R] - r) * t;
|
||||
g += (_frames[i + ENTRIES + G] - g) * t;
|
||||
b += (_frames[i + ENTRIES + B] - b) * t;
|
||||
r2 += (_frames[i + ENTRIES + R2] - r2) * t;
|
||||
g2 += (_frames[i + ENTRIES + G2] - g2) * t;
|
||||
b2 += (_frames[i + ENTRIES + B2] - b2) * t;
|
||||
break;
|
||||
}
|
||||
case STEPPED: {
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
r2 = _frames[i + R2];
|
||||
g2 = _frames[i + G2];
|
||||
b2 = _frames[i + B2];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
r = getBezierValue(time, i, R, curveType - BEZIER);
|
||||
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
||||
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||
r2 = getBezierValue(time, i, R2, curveType + BEZIER_SIZE * 3 - BEZIER);
|
||||
g2 = getBezierValue(time, i, G2, curveType + BEZIER_SIZE * 4 - BEZIER);
|
||||
b2 = getBezierValue(time, i, B2, curveType + BEZIER_SIZE * 5 - BEZIER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha != 1) {
|
||||
if (fromSetup) {
|
||||
SlotPose &setup = slot._data._setup;
|
||||
Color &setupLight = setup._color;
|
||||
r = setupLight.r + (r - setupLight.r) * alpha;
|
||||
g = setupLight.g + (g - setupLight.g) * alpha;
|
||||
b = setupLight.b + (b - setupLight.b) * alpha;
|
||||
Color &setupDark = setup._darkColor;
|
||||
r2 = setupDark.r + (r2 - setupDark.r) * alpha;
|
||||
g2 = setupDark.g + (g2 - setupDark.g) * alpha;
|
||||
b2 = setupDark.b + (b2 - setupDark.b) * alpha;
|
||||
} else {
|
||||
r = light.r + (r - light.r) * alpha;
|
||||
g = light.g + (g - light.g) * alpha;
|
||||
b = light.b + (b - light.b) * alpha;
|
||||
r2 = dark.r + (r2 - dark.r) * alpha;
|
||||
g2 = dark.g + (g2 - dark.g) * alpha;
|
||||
b2 = dark.b + (b2 - dark.b) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
light.r = r < 0 ? 0 : (r > 1 ? 1 : r);
|
||||
light.g = g < 0 ? 0 : (g > 1 ? 1 : g);
|
||||
light.b = b < 0 ? 0 : (b > 1 ? 1 : b);
|
||||
dark.r = r2 < 0 ? 0 : (r2 > 1 ? 1 : r2);
|
||||
dark.g = g2 < 0 ? 0 : (g2 > 1 ? 1 : g2);
|
||||
dark.b = b2 < 0 ? 0 : (b2 > 1 ? 1 : b2);
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Constraint.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(Constraint, Update)
|
||||
|
||||
Constraint::Constraint() {
|
||||
}
|
||||
|
||||
Constraint::~Constraint() {
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/ConstraintData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_NOPARENT(ConstraintData)
|
||||
@ -1,40 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/ConstraintTimeline.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_NOPARENT(ConstraintTimeline)
|
||||
|
||||
ConstraintTimeline::ConstraintTimeline() {
|
||||
}
|
||||
|
||||
ConstraintTimeline::~ConstraintTimeline() {
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated July 28, 2023. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2023, 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/ConstraintTimeline1.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_MULTI(ConstraintTimeline1, CurveTimeline1, ConstraintTimeline)
|
||||
|
||||
ConstraintTimeline1::ConstraintTimeline1(size_t frameCount, size_t bezierCount, int constraintIndex, Property property)
|
||||
: CurveTimeline1(frameCount, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) {
|
||||
PropertyId ids[] = {((PropertyId) property << 32) | constraintIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
ConstraintTimeline1::~ConstraintTimeline1() {
|
||||
}
|
||||
@ -1,159 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/CurveTimeline.h>
|
||||
|
||||
#include <spine/MathUtil.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(CurveTimeline, Timeline)
|
||||
|
||||
CurveTimeline::CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount) : Timeline(frameCount, frameEntries) {
|
||||
_curves.setSize(frameCount + bezierCount * BEZIER_SIZE, 0);
|
||||
_curves[frameCount - 1] = STEPPED;
|
||||
}
|
||||
|
||||
CurveTimeline::~CurveTimeline() {
|
||||
}
|
||||
|
||||
void CurveTimeline::setLinear(size_t frame) {
|
||||
_curves[frame] = LINEAR;
|
||||
}
|
||||
|
||||
void CurveTimeline::setStepped(size_t frame) {
|
||||
_curves[frame] = STEPPED;
|
||||
}
|
||||
|
||||
void CurveTimeline::setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2,
|
||||
float time2, float value2) {
|
||||
size_t i = getFrameCount() + bezier * BEZIER_SIZE;
|
||||
if (value == 0) _curves[frame] = BEZIER + i;
|
||||
float tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03;
|
||||
float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 0.006;
|
||||
float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;
|
||||
float dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667;
|
||||
float x = time1 + dx, y = value1 + dy;
|
||||
for (size_t n = i + BEZIER_SIZE; i < n; i += 2) {
|
||||
_curves[i] = x;
|
||||
_curves[i + 1] = y;
|
||||
dx += ddx;
|
||||
dy += ddy;
|
||||
ddx += dddx;
|
||||
ddy += dddy;
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
float CurveTimeline::getBezierValue(float time, size_t frameIndex, size_t valueOffset, size_t i) {
|
||||
if (_curves[i] > time) {
|
||||
float x = _frames[frameIndex], y = _frames[frameIndex + valueOffset];
|
||||
return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y);
|
||||
}
|
||||
size_t n = i + BEZIER_SIZE;
|
||||
for (i += 2; i < n; i += 2) {
|
||||
if (_curves[i] >= time) {
|
||||
float x = _curves[i - 2], y = _curves[i - 1];
|
||||
return y + (time - x) / (_curves[i] - x) * (_curves[i + 1] - y);
|
||||
}
|
||||
}
|
||||
frameIndex += getFrameEntries();
|
||||
float x = _curves[n - 2], y = _curves[n - 1];
|
||||
return y + (time - x) / (_frames[frameIndex] - x) * (_frames[frameIndex + valueOffset] - y);
|
||||
}
|
||||
|
||||
Array<float> &CurveTimeline::getCurves() {
|
||||
return _curves;
|
||||
}
|
||||
|
||||
RTTI_IMPL(CurveTimeline1, CurveTimeline)
|
||||
|
||||
CurveTimeline1::CurveTimeline1(size_t frameCount, size_t bezierCount) : CurveTimeline(frameCount, CurveTimeline1::ENTRIES, bezierCount) {
|
||||
}
|
||||
|
||||
CurveTimeline1::~CurveTimeline1() {
|
||||
}
|
||||
|
||||
void CurveTimeline1::setFrame(size_t frame, float time, float value) {
|
||||
frame <<= 1;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + CurveTimeline1::VALUE] = value;
|
||||
}
|
||||
|
||||
float CurveTimeline1::getCurveValue(float time) {
|
||||
int i = (int) _frames.size() - 2;
|
||||
for (int ii = 2; ii <= i; ii += 2) {
|
||||
if (_frames[ii] > time) {
|
||||
i = ii - 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int curveType = (int) _curves[i >> 1];
|
||||
switch (curveType) {
|
||||
case CurveTimeline::LINEAR: {
|
||||
float before = _frames[i], value = _frames[i + CurveTimeline1::VALUE];
|
||||
return value +
|
||||
(time - before) / (_frames[i + CurveTimeline1::ENTRIES] - before) *
|
||||
(_frames[i + CurveTimeline1::ENTRIES + CurveTimeline1::VALUE] - value);
|
||||
}
|
||||
case CurveTimeline::STEPPED:
|
||||
return _frames[i + CurveTimeline1::VALUE];
|
||||
}
|
||||
return getBezierValue(time, i, CurveTimeline1::VALUE, curveType - CurveTimeline1::BEZIER);
|
||||
}
|
||||
|
||||
float CurveTimeline1::getRelativeValue(float time, float alpha, bool fromSetup, bool add, float current, float setup) {
|
||||
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||
float value = getCurveValue(time);
|
||||
return fromSetup ? setup + value * alpha : current + (add ? value : value + setup - current) * alpha;
|
||||
}
|
||||
|
||||
float CurveTimeline1::getAbsoluteValue(float time, float alpha, bool fromSetup, bool add, float current, float setup) {
|
||||
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||
float value = getCurveValue(time);
|
||||
return fromSetup ? setup + (value - setup) * alpha : current + (add ? value : value - current) * alpha;
|
||||
}
|
||||
|
||||
float CurveTimeline1::getAbsoluteValue(float time, float alpha, bool fromSetup, bool add, float current, float setup, float value) {
|
||||
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||
return fromSetup ? setup + (value - setup) * alpha : current + (add ? value : value - current) * alpha;
|
||||
}
|
||||
|
||||
float CurveTimeline1::getScaleValue(float time, float alpha, bool fromSetup, bool add, bool out, float current, float setup) {
|
||||
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||
float value = getCurveValue(time) * setup;
|
||||
if (alpha == 1 && !add) return value;
|
||||
float base = fromSetup ? setup : current;
|
||||
if (add) return base + (value - setup) * alpha;
|
||||
if (out) return base + (MathUtil::abs(value) * MathUtil::sign(base) - base) * alpha;
|
||||
base = MathUtil::abs(base) * MathUtil::sign(value);
|
||||
return base + (value - base) * alpha;
|
||||
}
|
||||
@ -1,269 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/DeformTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/VertexAttachment.h>
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/SlotPose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(DeformTimeline, CurveTimeline)
|
||||
|
||||
DeformTimeline::DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment &attachment)
|
||||
: SlotCurveTimeline(frameCount, 1, bezierCount, slotIndex), _attachment(&attachment) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Deform << 32) | ((slotIndex << 16 | attachment._id) & 0xffffffff)};
|
||||
setPropertyIds(ids, 1);
|
||||
_additive = true;
|
||||
|
||||
_vertices.ensureCapacity(frameCount);
|
||||
for (size_t i = 0; i < frameCount; ++i) {
|
||||
Array<float> vec;
|
||||
_vertices.add(vec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DeformTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) {
|
||||
SP_UNUSED(slot);
|
||||
Attachment *slotAttachment = pose._attachment;
|
||||
if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) {
|
||||
return;
|
||||
}
|
||||
|
||||
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(slotAttachment);
|
||||
if (vertexAttachment->getTimelineAttachment() != _attachment) {
|
||||
return;
|
||||
}
|
||||
|
||||
Array<float> &deformArray = pose._deform;
|
||||
if (deformArray.size() == 0) fromSetup = true;
|
||||
|
||||
Array<Array<float>> &vertices = _vertices;
|
||||
size_t vertexCount = vertices[0].size();
|
||||
|
||||
Array<float> &frames = _frames;
|
||||
if (time < frames[0]) {
|
||||
if (fromSetup) deformArray.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
deformArray.setSize(vertexCount, 0);
|
||||
Array<float> &deform = deformArray;
|
||||
|
||||
if (time >= frames[frames.size() - 1]) {// Time is after last frame.
|
||||
Array<float> &lastVertices = vertices[frames.size() - 1];
|
||||
if (alpha == 1) {
|
||||
if (add && !fromSetup) {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, no alpha.
|
||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||
for (size_t i = 0; i < vertexCount; i++) deform[i] += lastVertices[i] - setupVertices[i];
|
||||
} else {
|
||||
// Weighted deform offsets, no alpha.
|
||||
for (size_t i = 0; i < vertexCount; i++) deform[i] += lastVertices[i];
|
||||
}
|
||||
} else {
|
||||
// Vertex positions or deform offsets, no alpha.
|
||||
memcpy(deform.buffer(), lastVertices.buffer(), vertexCount * sizeof(float));
|
||||
}
|
||||
} else if (fromSetup) {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, with alpha.
|
||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
float setup = setupVertices[i];
|
||||
deform[i] = setup + (lastVertices[i] - setup) * alpha;
|
||||
}
|
||||
} else {
|
||||
// Weighted deform offsets, with alpha.
|
||||
for (size_t i = 0; i < vertexCount; i++) deform[i] = lastVertices[i] * alpha;
|
||||
}
|
||||
} else if (add) {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, with alpha.
|
||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||
for (size_t i = 0; i < vertexCount; i++) deform[i] += (lastVertices[i] - setupVertices[i]) * alpha;
|
||||
} else {
|
||||
// Weighted deform offsets, with alpha.
|
||||
for (size_t i = 0; i < vertexCount; i++) deform[i] += lastVertices[i] * alpha;
|
||||
}
|
||||
} else {
|
||||
// Vertex positions or deform offsets, with alpha.
|
||||
for (size_t i = 0; i < vertexCount; i++) deform[i] += (lastVertices[i] - deform[i]) * alpha;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Interpolate between the previous frame and the current frame.
|
||||
int frame = Animation::search(frames, time);
|
||||
float percent = getCurvePercent(time, frame);
|
||||
Array<float> &prevVertices = vertices[frame];
|
||||
Array<float> &nextVertices = vertices[frame + 1];
|
||||
|
||||
if (alpha == 1) {
|
||||
if (add && !fromSetup) {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, no alpha.
|
||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
float prev = prevVertices[i];
|
||||
deform[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i];
|
||||
}
|
||||
} else {
|
||||
// Weighted deform offsets, no alpha.
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
float prev = prevVertices[i];
|
||||
deform[i] += prev + (nextVertices[i] - prev) * percent;
|
||||
}
|
||||
}
|
||||
} else if (percent == 0) {
|
||||
memcpy(deform.buffer(), prevVertices.buffer(), vertexCount * sizeof(float));
|
||||
} else {
|
||||
// Vertex positions or deform offsets, no alpha.
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
float prev = prevVertices[i];
|
||||
deform[i] = prev + (nextVertices[i] - prev) * percent;
|
||||
}
|
||||
}
|
||||
} else if (fromSetup) {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, with alpha.
|
||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
float prev = prevVertices[i], setup = setupVertices[i];
|
||||
deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
|
||||
}
|
||||
} else {
|
||||
// Weighted deform offsets, with alpha.
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
float prev = prevVertices[i];
|
||||
deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
|
||||
}
|
||||
}
|
||||
} else if (add) {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, with alpha.
|
||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
float prev = prevVertices[i];
|
||||
deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha;
|
||||
}
|
||||
} else {
|
||||
// Weighted deform offsets, with alpha.
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
float prev = prevVertices[i];
|
||||
deform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Vertex positions or deform offsets, with alpha.
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
float prev = prevVertices[i];
|
||||
deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeformTimeline::setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2,
|
||||
float time2, float value2) {
|
||||
SP_UNUSED(value1);
|
||||
SP_UNUSED(value2);
|
||||
Array<float> &curves = _curves;
|
||||
size_t i = getFrameCount() + bezier * BEZIER_SIZE;
|
||||
if (value == 0) curves[frame] = BEZIER + (float) i;
|
||||
float tmpx = (time1 - cx1 * 2 + cx2) * 0.03f, tmpy = cy2 * 0.03f - cy1 * 0.06f;
|
||||
float dddx = ((cx1 - cx2) * 3 - time1 + time2) * 0.006f, dddy = (cy1 - cy2 + 0.33333333f) * 0.018f;
|
||||
float ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;
|
||||
float dx = (cx1 - time1) * 0.3f + tmpx + dddx * 0.16666667f, dy = cy1 * 0.3f + tmpy + dddy * 0.16666667f;
|
||||
float x = time1 + dx, y = dy;
|
||||
for (size_t n = i + BEZIER_SIZE; i < n; i += 2) {
|
||||
curves[i] = x;
|
||||
curves[i + 1] = y;
|
||||
dx += ddx;
|
||||
dy += ddy;
|
||||
ddx += dddx;
|
||||
ddy += dddy;
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
float DeformTimeline::getCurvePercent(float time, int frame) {
|
||||
Array<float> &curves = _curves;
|
||||
int i = (int) curves[frame];
|
||||
switch (i) {
|
||||
case LINEAR: {
|
||||
float x = _frames[frame];
|
||||
return (time - x) / (_frames[frame + getFrameEntries()] - x);
|
||||
}
|
||||
case STEPPED: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
i -= BEZIER;
|
||||
if (curves[i] > time) {
|
||||
float x = _frames[frame];
|
||||
return curves[i + 1] * (time - x) / (curves[i] - x);
|
||||
}
|
||||
int n = i + BEZIER_SIZE;
|
||||
for (i += 2; i < n; i += 2) {
|
||||
if (curves[i] >= time) {
|
||||
float x = curves[i - 2], y = curves[i - 1];
|
||||
return y + (time - x) / (curves[i] - x) * (curves[i + 1] - y);
|
||||
}
|
||||
}
|
||||
float x = curves[n - 2], y = curves[n - 1];
|
||||
return y + (1 - y) * (time - x) / (_frames[frame + getFrameEntries()] - x);
|
||||
}
|
||||
|
||||
void DeformTimeline::setFrame(int frame, float time, Array<float> &vertices) {
|
||||
_frames[frame] = time;
|
||||
_vertices[frame].clear();
|
||||
_vertices[frame].addAll(vertices);
|
||||
}
|
||||
|
||||
Array<Array<float>> &DeformTimeline::getVertices() {
|
||||
return _vertices;
|
||||
}
|
||||
|
||||
VertexAttachment &DeformTimeline::getAttachment() {
|
||||
return *_attachment;
|
||||
}
|
||||
|
||||
void DeformTimeline::setAttachment(VertexAttachment &inValue) {
|
||||
_attachment = &inValue;
|
||||
}
|
||||
@ -1,116 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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) {
|
||||
Array<PropertyId> ids(slots.size());
|
||||
for (size_t i = 0; i < slots.size(); ++i) ids.add(((PropertyId) Property_DrawOrderFolder << 32) | (PropertyId) slots[i]);
|
||||
setPropertyIds(ids.buffer(), ids.size());
|
||||
|
||||
_slots.addAll(slots);
|
||||
_drawOrders.ensureCapacity(frameCount);
|
||||
_inFolder.setSize(slotCount, false);
|
||||
for (size_t i = 0; i < _slots.size(); ++i) _inFolder[_slots[i]] = true;
|
||||
_instant = 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, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(alpha);
|
||||
SP_UNUSED(add);
|
||||
SP_UNUSED(appliedPose);
|
||||
|
||||
if (out || time < _frames[0]) {
|
||||
if (fromSetup) 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/DrawOrderTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(DrawOrderTimeline, Timeline)
|
||||
|
||||
PropertyId DrawOrderTimeline::getPropertyId() {
|
||||
return ((PropertyId) Property_DrawOrder << 32);
|
||||
}
|
||||
|
||||
DrawOrderTimeline::DrawOrderTimeline(size_t frameCount) : Timeline(frameCount, 1) {
|
||||
PropertyId ids[] = {getPropertyId()};
|
||||
setPropertyIds(ids, 1);
|
||||
_instant = true;
|
||||
|
||||
_drawOrders.ensureCapacity(frameCount);
|
||||
for (size_t i = 0; i < frameCount; ++i) {
|
||||
Array<int> vec;
|
||||
_drawOrders.add(vec);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(appliedPose);
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(alpha);
|
||||
SP_UNUSED(add);
|
||||
|
||||
Array<Slot *> &drawOrder = skeleton._drawOrder;
|
||||
Array<Slot *> &slots = skeleton._slots;
|
||||
if (out || time < _frames[0]) {
|
||||
if (fromSetup) {
|
||||
drawOrder.clear();
|
||||
drawOrder.ensureCapacity(slots.size());
|
||||
for (size_t i = 0, n = slots.size(); i < n; ++i) drawOrder.add(slots[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Array<int> &drawOrderToSetupIndex = _drawOrders[Animation::search(_frames, time)];
|
||||
if (drawOrderToSetupIndex.size() == 0) {
|
||||
drawOrder.clear();
|
||||
drawOrder.ensureCapacity(slots.size());
|
||||
for (size_t i = 0, n = slots.size(); i < n; ++i) drawOrder.add(slots[i]);
|
||||
} else {
|
||||
drawOrder.clear();
|
||||
drawOrder.ensureCapacity(drawOrderToSetupIndex.size());
|
||||
for (size_t i = 0, n = drawOrderToSetupIndex.size(); i < n; ++i) drawOrder.add(slots[drawOrderToSetupIndex[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawOrderTimeline::setFrame(size_t frame, float time, Array<int> *drawOrder) {
|
||||
_frames[frame] = time;
|
||||
_drawOrders[frame].clear();
|
||||
if (drawOrder != NULL) {
|
||||
_drawOrders[frame].addAll(*drawOrder);
|
||||
}
|
||||
}
|
||||
|
||||
size_t DrawOrderTimeline::getFrameCount() {
|
||||
return _frames.size();
|
||||
}
|
||||
|
||||
Array<Array<int>> &DrawOrderTimeline::getDrawOrders() {
|
||||
return _drawOrders;
|
||||
}
|
||||
@ -1,88 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Event.h>
|
||||
|
||||
#include <spine/EventData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
Event::Event(float time, const EventData &data)
|
||||
: _data(data), _time(time), _intValue(data.getInt()), _floatValue(data.getFloat()), _stringValue(data.getString()), _volume(data.getVolume()),
|
||||
_balance(data.getBalance()) {
|
||||
}
|
||||
|
||||
const EventData &Event::getData() {
|
||||
return _data;
|
||||
}
|
||||
|
||||
float Event::getTime() {
|
||||
return _time;
|
||||
}
|
||||
|
||||
int Event::getInt() {
|
||||
return _intValue;
|
||||
}
|
||||
|
||||
void Event::setInt(int inValue) {
|
||||
_intValue = inValue;
|
||||
}
|
||||
|
||||
float Event::getFloat() {
|
||||
return _floatValue;
|
||||
}
|
||||
|
||||
void Event::setFloat(float inValue) {
|
||||
_floatValue = inValue;
|
||||
}
|
||||
|
||||
const String &Event::getString() {
|
||||
return _stringValue;
|
||||
}
|
||||
|
||||
void Event::setString(const String &inValue) {
|
||||
_stringValue = inValue;
|
||||
}
|
||||
|
||||
|
||||
float Event::getVolume() {
|
||||
return _volume;
|
||||
}
|
||||
|
||||
void Event::setVolume(float inValue) {
|
||||
_volume = inValue;
|
||||
}
|
||||
|
||||
float Event::getBalance() {
|
||||
return _balance;
|
||||
}
|
||||
|
||||
void Event::setBalance(float inValue) {
|
||||
_balance = inValue;
|
||||
}
|
||||
@ -1,92 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/EventData.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
EventData::EventData(const String &name) : _name(name), _intValue(0), _floatValue(0), _stringValue(), _audioPath(), _volume(0), _balance(0) {
|
||||
assert(_name.length() > 0);
|
||||
}
|
||||
|
||||
/// The name of the event, which is unique within the skeleton.
|
||||
const String &EventData::getName() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
int EventData::getInt() const {
|
||||
return _intValue;
|
||||
}
|
||||
|
||||
void EventData::setInt(int inValue) {
|
||||
_intValue = inValue;
|
||||
}
|
||||
|
||||
float EventData::getFloat() const {
|
||||
return _floatValue;
|
||||
}
|
||||
|
||||
void EventData::setFloat(float inValue) {
|
||||
_floatValue = inValue;
|
||||
}
|
||||
|
||||
const String &EventData::getString() const {
|
||||
return _stringValue;
|
||||
}
|
||||
|
||||
void EventData::setString(const String &inValue) {
|
||||
this->_stringValue = inValue;
|
||||
}
|
||||
|
||||
const String &EventData::getAudioPath() const {
|
||||
return _audioPath;
|
||||
}
|
||||
|
||||
void EventData::setAudioPath(const String &inValue) {
|
||||
_audioPath = inValue;
|
||||
}
|
||||
|
||||
|
||||
float EventData::getVolume() const {
|
||||
return _volume;
|
||||
}
|
||||
|
||||
void EventData::setVolume(float inValue) {
|
||||
_volume = inValue;
|
||||
}
|
||||
|
||||
float EventData::getBalance() const {
|
||||
return _balance;
|
||||
}
|
||||
|
||||
void EventData::setBalance(float inValue) {
|
||||
_balance = inValue;
|
||||
}
|
||||
@ -1,106 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/EventTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/ArrayUtils.h>
|
||||
#include <spine/EventData.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(EventTimeline, Timeline)
|
||||
|
||||
EventTimeline::EventTimeline(size_t frameCount) : Timeline(frameCount, 1) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Event << 32)};
|
||||
setPropertyIds(ids, 1);
|
||||
_events.setSize(frameCount, NULL);
|
||||
_instant = true;
|
||||
}
|
||||
|
||||
EventTimeline::~EventTimeline() {
|
||||
ArrayUtils::deleteElements(_events);
|
||||
}
|
||||
|
||||
void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *pEvents, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(skeleton);
|
||||
if (pEvents == NULL) return;
|
||||
|
||||
Array<Event *> &events = *pEvents;
|
||||
|
||||
size_t frameCount = _frames.size();
|
||||
|
||||
if (lastTime > time) {
|
||||
// Apply after lastTime for looped animations.
|
||||
apply(skeleton, lastTime, FLT_MAX, pEvents, 0, false, false, false, false);
|
||||
lastTime = -1.0f;
|
||||
} else if (lastTime >= _frames[frameCount - 1]) {
|
||||
// Last time is after last frame.
|
||||
return;
|
||||
}
|
||||
|
||||
if (time < _frames[0]) return;// Time is before first frame.
|
||||
|
||||
int i;
|
||||
if (lastTime < _frames[0]) {
|
||||
i = 0;
|
||||
} else {
|
||||
i = Animation::search(_frames, lastTime) + 1;
|
||||
float frameTime = _frames[i];
|
||||
while (i > 0) {
|
||||
// Fire multiple events with the same frame.
|
||||
if (_frames[i - 1] != frameTime) break;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
for (; (size_t) i < frameCount && time >= _frames[i]; i++) events.add(_events[i]);
|
||||
}
|
||||
|
||||
void EventTimeline::setFrame(size_t frame, Event &event) {
|
||||
_frames[frame] = event.getTime();
|
||||
_events[frame] = &event;
|
||||
}
|
||||
|
||||
size_t EventTimeline::getFrameCount() {
|
||||
return _frames.size();
|
||||
}
|
||||
|
||||
Array<Event *> &EventTimeline::getEvents() {
|
||||
return _events;
|
||||
}
|
||||
@ -1,124 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Extension.h>
|
||||
#include <spine/SpineString.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
SpineExtension *SpineExtension::_instance = NULL;
|
||||
|
||||
void SpineExtension::setInstance(SpineExtension *inValue) {
|
||||
assert(inValue);
|
||||
|
||||
_instance = inValue;
|
||||
}
|
||||
|
||||
SpineExtension *SpineExtension::getInstance() {
|
||||
if (!_instance) _instance = getDefaultExtension();
|
||||
assert(_instance);
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
SpineExtension::~SpineExtension() {
|
||||
}
|
||||
|
||||
SpineExtension::SpineExtension() {
|
||||
}
|
||||
|
||||
DefaultSpineExtension::~DefaultSpineExtension() {
|
||||
}
|
||||
|
||||
void *DefaultSpineExtension::_alloc(size_t size, const char *file, int line) {
|
||||
SP_UNUSED(file);
|
||||
SP_UNUSED(line);
|
||||
|
||||
if (size == 0) return 0;
|
||||
void *ptr = ::malloc(size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *DefaultSpineExtension::_calloc(size_t size, const char *file, int line) {
|
||||
SP_UNUSED(file);
|
||||
SP_UNUSED(line);
|
||||
|
||||
if (size == 0) return 0;
|
||||
|
||||
void *ptr = ::malloc(size);
|
||||
if (ptr) {
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *DefaultSpineExtension::_realloc(void *ptr, size_t size, const char *file, int line) {
|
||||
SP_UNUSED(file);
|
||||
SP_UNUSED(line);
|
||||
|
||||
void *mem = NULL;
|
||||
if (size == 0) return 0;
|
||||
if (ptr == NULL)
|
||||
mem = ::malloc(size);
|
||||
else
|
||||
mem = ::realloc(ptr, size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void DefaultSpineExtension::_free(void *mem, const char *file, int line) {
|
||||
SP_UNUSED(file);
|
||||
SP_UNUSED(line);
|
||||
|
||||
::free(mem);
|
||||
}
|
||||
|
||||
char *DefaultSpineExtension::_readFile(const String &path, int *length) {
|
||||
#if !defined(__EMSCRIPTEN__) && !defined(SPINE_NO_FILE_IO)
|
||||
char *data;
|
||||
FILE *file = fopen(path.buffer(), "rb");
|
||||
if (!file) return 0;
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
*length = (int) ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
data = SpineExtension::alloc<char>(*length, __FILE__, __LINE__);
|
||||
fread(data, 1, *length, file);
|
||||
fclose(file);
|
||||
|
||||
return data;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
DefaultSpineExtension::DefaultSpineExtension() : SpineExtension() {
|
||||
}
|
||||
@ -1,307 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/IkConstraint.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BonePose.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
#include <spine/IkConstraintData.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/BoneData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(IkConstraint, Constraint)
|
||||
|
||||
IkConstraint::IkConstraint(IkConstraintData &data, Skeleton &skeleton) : IkConstraintBase(data), _target(skeleton._bones[data._target->getIndex()]) {
|
||||
|
||||
_bones.ensureCapacity(data._bones.size());
|
||||
for (size_t i = 0; i < data._bones.size(); i++) {
|
||||
BoneData *boneData = data._bones[i];
|
||||
_bones.add(&skeleton._bones[boneData->getIndex()]->_constrained);
|
||||
}
|
||||
}
|
||||
|
||||
IkConstraint &IkConstraint::copy(Skeleton &skeleton) {
|
||||
IkConstraint *copy = new (__FILE__, __LINE__) IkConstraint(_data, skeleton);
|
||||
copy->_pose.set(_pose);
|
||||
return *copy;
|
||||
}
|
||||
|
||||
void IkConstraint::update(Skeleton &skeleton, Physics physics) {
|
||||
IkConstraintPose &p = *_applied;
|
||||
if (p._mix == 0) return;
|
||||
BonePose &target = *_target->_applied;
|
||||
switch (_bones.size()) {
|
||||
case 1: {
|
||||
apply(skeleton, *_bones[0], target._worldX, target._worldY, p._compress, p._stretch, _data._uniform, p._mix);
|
||||
} break;
|
||||
case 2: {
|
||||
apply(skeleton, *_bones[0], *_bones[1], target._worldX, target._worldY, p._bendDirection, p._stretch, _data._uniform, p._softness,
|
||||
p._mix);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void IkConstraint::sort(Skeleton &skeleton) {
|
||||
skeleton.sortBone(_target);
|
||||
Bone *parent = _bones[0]->_bone;
|
||||
skeleton.sortBone(parent);
|
||||
skeleton._updateCache.add(this);
|
||||
parent->_sorted = false;
|
||||
skeleton.sortReset(parent->_children);
|
||||
skeleton.constrained(*parent);
|
||||
if (_bones.size() > 1) skeleton.constrained(*_bones[1]->_bone);
|
||||
}
|
||||
|
||||
Array<BonePose *> &IkConstraint::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
Bone &IkConstraint::getTarget() {
|
||||
return *_target;
|
||||
}
|
||||
|
||||
void IkConstraint::setTarget(Bone &target) {
|
||||
_target = ⌖
|
||||
}
|
||||
|
||||
bool IkConstraint::isSourceActive() {
|
||||
return _target->_active;
|
||||
}
|
||||
|
||||
void IkConstraint::apply(Skeleton &skeleton, BonePose &bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float mix) {
|
||||
bone.modifyLocal(skeleton);
|
||||
BonePose &p = *bone._bone->_parent->_applied;
|
||||
float pa = p._a, pb = p._b, pc = p._c, pd = p._d;
|
||||
float rotationIK = -bone._shearX - bone._rotation, tx, ty;
|
||||
switch (bone._inherit) {
|
||||
case Inherit_OnlyTranslation:
|
||||
tx = (targetX - bone._worldX) * MathUtil::sign(skeleton._scaleX);
|
||||
ty = (targetY - bone._worldY) * MathUtil::sign(skeleton._scaleY);
|
||||
break;
|
||||
case Inherit_NoRotationOrReflection: {
|
||||
float s = MathUtil::abs(pa * pd - pb * pc) / MathUtil::max(0.0001f, pa * pa + pc * pc);
|
||||
float sa = pa / skeleton._scaleX;
|
||||
float sc = pc / skeleton._scaleY;
|
||||
pb = -sc * s * skeleton._scaleX;
|
||||
pd = sa * s * skeleton._scaleY;
|
||||
rotationIK += MathUtil::atan2Deg(sc, sa);
|
||||
// Fall through.
|
||||
}
|
||||
default:
|
||||
float x = targetX - p._worldX, y = targetY - p._worldY;
|
||||
float d = pa * pd - pb * pc;
|
||||
if (MathUtil::abs(d) <= 0.0001f) {
|
||||
tx = 0;
|
||||
ty = 0;
|
||||
} else {
|
||||
tx = (x * pd - y * pb) / d - bone._x;
|
||||
ty = (y * pa - x * pc) / d - bone._y;
|
||||
}
|
||||
}
|
||||
rotationIK += MathUtil::atan2Deg(ty, tx);
|
||||
if (bone._scaleX < 0) rotationIK += 180;
|
||||
if (rotationIK > 180)
|
||||
rotationIK -= 360;
|
||||
else if (rotationIK < -180)//
|
||||
rotationIK += 360;
|
||||
bone._rotation += rotationIK * mix;
|
||||
if (compress || stretch) {
|
||||
switch (bone._inherit) {
|
||||
case Inherit_NoScale:
|
||||
case Inherit_NoScaleOrReflection:
|
||||
tx = targetX - bone._worldX;
|
||||
ty = targetY - bone._worldY;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
float b = bone._bone->_data.getLength() * bone._scaleX;
|
||||
if (b > 0.0001f) {
|
||||
float dd = tx * tx + ty * ty;
|
||||
if ((compress && dd < b * b) || (stretch && dd > b * b)) {
|
||||
float s = (MathUtil::sqrt(dd) / b - 1) * mix + 1;
|
||||
bone._scaleX *= s;
|
||||
if (uniform) bone._scaleY *= s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IkConstraint::apply(Skeleton &skeleton, BonePose &parent, BonePose &child, float targetX, float targetY, int bendDir, bool stretch, bool uniform,
|
||||
float softness, float mix) {
|
||||
if (parent._inherit != Inherit_Normal || child._inherit != Inherit_Normal) return;
|
||||
parent.modifyLocal(skeleton);
|
||||
child.modifyLocal(skeleton);
|
||||
float px = parent._x, py = parent._y, psx = parent._scaleX, psy = parent._scaleY, csx = child._scaleX;
|
||||
int os1, os2, s2;
|
||||
if (psx < 0) {
|
||||
psx = -psx;
|
||||
os1 = 180;
|
||||
s2 = -1;
|
||||
} else {
|
||||
os1 = 0;
|
||||
s2 = 1;
|
||||
}
|
||||
if (psy < 0) {
|
||||
psy = -psy;
|
||||
s2 = -s2;
|
||||
}
|
||||
if (csx < 0) {
|
||||
csx = -csx;
|
||||
os2 = 180;
|
||||
} else
|
||||
os2 = 0;
|
||||
float cwx, cwy, a = parent._a, b = parent._b, c = parent._c, d = parent._d;
|
||||
bool u = MathUtil::abs(psx - psy) <= 0.0001f;
|
||||
if (!u || stretch) {
|
||||
child._y = 0;
|
||||
cwx = a * child._x + parent._worldX;
|
||||
cwy = c * child._x + parent._worldY;
|
||||
} else {
|
||||
cwx = a * child._x + b * child._y + parent._worldX;
|
||||
cwy = c * child._x + d * child._y + parent._worldY;
|
||||
}
|
||||
BonePose &pp = *parent._bone->_parent->_applied;
|
||||
a = pp._a;
|
||||
b = pp._b;
|
||||
c = pp._c;
|
||||
d = pp._d;
|
||||
float id = a * d - b * c, x = cwx - pp._worldX, y = cwy - pp._worldY;
|
||||
id = MathUtil::abs(id) <= 0.0001f ? 0 : 1 / id;
|
||||
float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py;
|
||||
float l1 = MathUtil::sqrt(dx * dx + dy * dy), l2 = child._bone->_data.getLength() * csx, a1, a2;
|
||||
if (l1 < 0.0001f) {
|
||||
apply(skeleton, parent, targetX, targetY, false, stretch, false, mix);
|
||||
child._rotation = 0;
|
||||
return;
|
||||
}
|
||||
x = targetX - pp._worldX;
|
||||
y = targetY - pp._worldY;
|
||||
float tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py;
|
||||
float dd = tx * tx + ty * ty;
|
||||
if (softness != 0) {
|
||||
softness *= psx * (csx + 1) * 0.5f;
|
||||
float td = MathUtil::sqrt(dd), sd = td - l1 - l2 * psx + softness;
|
||||
if (sd > 0) {
|
||||
float p = MathUtil::min(1.0f, sd / (softness * 2)) - 1;
|
||||
p = (sd - softness * (1 - p * p)) / td;
|
||||
tx -= p * tx;
|
||||
ty -= p * ty;
|
||||
dd = tx * tx + ty * ty;
|
||||
}
|
||||
}
|
||||
|
||||
if (u) {
|
||||
l2 *= psx;
|
||||
float cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2);
|
||||
if (cos < -1) {
|
||||
cos = -1;
|
||||
a2 = MathUtil::Pi * bendDir;
|
||||
} else if (cos > 1) {
|
||||
cos = 1;
|
||||
a2 = 0;
|
||||
if (stretch) {
|
||||
a = (MathUtil::sqrt(dd) / (l1 + l2) - 1) * mix + 1;
|
||||
parent._scaleX *= a;
|
||||
if (uniform) parent._scaleY *= a;
|
||||
}
|
||||
} else
|
||||
a2 = MathUtil::acos(cos) * bendDir;
|
||||
a = l1 + l2 * cos;
|
||||
b = l2 * MathUtil::sin(a2);
|
||||
a1 = MathUtil::atan2(ty * a - tx * b, tx * a + ty * b);
|
||||
} else {
|
||||
a = psx * l2;
|
||||
b = psy * l2;
|
||||
float aa = a * a, bb = b * b, ta = MathUtil::atan2(ty, tx);
|
||||
c = bb * l1 * l1 + aa * dd - aa * bb;
|
||||
float c1 = -2 * bb * l1, c2 = bb - aa;
|
||||
d = c1 * c1 - 4 * c2 * c;
|
||||
if (d >= 0) {
|
||||
float q = MathUtil::sqrt(d);
|
||||
if (c1 < 0) q = -q;
|
||||
q = -(c1 + q) * 0.5f;
|
||||
float r0 = q / c2, r1 = c / q;
|
||||
float r = MathUtil::abs(r0) < MathUtil::abs(r1) ? r0 : r1;
|
||||
r0 = dd - r * r;
|
||||
if (r0 >= 0) {
|
||||
y = MathUtil::sqrt(r0) * bendDir;
|
||||
a1 = ta - MathUtil::atan2(y, r);
|
||||
a2 = MathUtil::atan2(y / psy, (r - l1) / psx);
|
||||
goto outer_break;
|
||||
}
|
||||
}
|
||||
float minAngle = MathUtil::Pi, minX = l1 - a, minDist = minX * minX, minY = 0;
|
||||
float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0;
|
||||
c = -a * l1 / (aa - bb);
|
||||
if (c >= -1 && c <= 1) {
|
||||
c = MathUtil::acos(c);
|
||||
x = a * MathUtil::cos(c) + l1;
|
||||
y = b * MathUtil::sin(c);
|
||||
d = x * x + y * y;
|
||||
if (d < minDist) {
|
||||
minAngle = c;
|
||||
minDist = d;
|
||||
minX = x;
|
||||
minY = y;
|
||||
}
|
||||
if (d > maxDist) {
|
||||
maxAngle = c;
|
||||
maxDist = d;
|
||||
maxX = x;
|
||||
maxY = y;
|
||||
}
|
||||
}
|
||||
if (dd <= (minDist + maxDist) * 0.5f) {
|
||||
a1 = ta - MathUtil::atan2(minY * bendDir, minX);
|
||||
a2 = minAngle * bendDir;
|
||||
} else {
|
||||
a1 = ta - MathUtil::atan2(maxY * bendDir, maxX);
|
||||
a2 = maxAngle * bendDir;
|
||||
}
|
||||
}
|
||||
outer_break:
|
||||
float os = MathUtil::atan2(child._y, child._x) * s2;
|
||||
a1 = (a1 - os) * MathUtil::Rad_Deg + os1 - parent._rotation;
|
||||
if (a1 > 180)
|
||||
a1 -= 360;
|
||||
else if (a1 < -180)//
|
||||
a1 += 360;
|
||||
parent._rotation += a1 * mix;
|
||||
a2 = ((a2 + os) * MathUtil::Rad_Deg - child._shearX) * s2 + os2 - child._rotation;
|
||||
if (a2 > 180)
|
||||
a2 -= 360;
|
||||
else if (a2 < -180)//
|
||||
a2 += 360;
|
||||
child._rotation += a2 * mix;
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/IkConstraintData.h>
|
||||
#include <spine/IkConstraint.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(IkConstraintData, ConstraintData)
|
||||
|
||||
IkConstraintData::IkConstraintData(const String &name) : ConstraintDataGeneric<IkConstraint, IkConstraintPose>(name), _target(NULL), _uniform(false) {
|
||||
}
|
||||
|
||||
Array<BoneData *> &IkConstraintData::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
BoneData &IkConstraintData::getTarget() {
|
||||
return *_target;
|
||||
}
|
||||
|
||||
void IkConstraintData::setTarget(BoneData &inValue) {
|
||||
_target = &inValue;
|
||||
}
|
||||
|
||||
bool IkConstraintData::getUniform() {
|
||||
return _uniform;
|
||||
}
|
||||
|
||||
void IkConstraintData::setUniform(bool uniform) {
|
||||
_uniform = uniform;
|
||||
}
|
||||
|
||||
Constraint &IkConstraintData::create(Skeleton &skeleton) {
|
||||
return *(new (__FILE__, __LINE__) IkConstraint(*this, skeleton));
|
||||
}
|
||||
@ -1,86 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/IkConstraintPose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
IkConstraintPose::IkConstraintPose() : _bendDirection(0), _compress(false), _stretch(false), _mix(0), _softness(0) {
|
||||
}
|
||||
|
||||
IkConstraintPose::~IkConstraintPose() {
|
||||
}
|
||||
|
||||
void IkConstraintPose::set(IkConstraintPose &pose) {
|
||||
_mix = pose._mix;
|
||||
_softness = pose._softness;
|
||||
_bendDirection = pose._bendDirection;
|
||||
_compress = pose._compress;
|
||||
_stretch = pose._stretch;
|
||||
}
|
||||
|
||||
float IkConstraintPose::getMix() {
|
||||
return _mix;
|
||||
}
|
||||
|
||||
void IkConstraintPose::setMix(float mix) {
|
||||
_mix = mix;
|
||||
}
|
||||
|
||||
float IkConstraintPose::getSoftness() {
|
||||
return _softness;
|
||||
}
|
||||
|
||||
void IkConstraintPose::setSoftness(float softness) {
|
||||
_softness = softness;
|
||||
}
|
||||
|
||||
int IkConstraintPose::getBendDirection() {
|
||||
return _bendDirection;
|
||||
}
|
||||
|
||||
void IkConstraintPose::setBendDirection(int bendDirection) {
|
||||
_bendDirection = bendDirection;
|
||||
}
|
||||
|
||||
bool IkConstraintPose::getCompress() {
|
||||
return _compress;
|
||||
}
|
||||
|
||||
void IkConstraintPose::setCompress(bool compress) {
|
||||
_compress = compress;
|
||||
}
|
||||
|
||||
bool IkConstraintPose::getStretch() {
|
||||
return _stretch;
|
||||
}
|
||||
|
||||
void IkConstraintPose::setStretch(bool stretch) {
|
||||
_stretch = stretch;
|
||||
}
|
||||
@ -1,126 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/IkConstraintTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/IkConstraint.h>
|
||||
#include <spine/IkConstraintData.h>
|
||||
#include <spine/IkConstraintPose.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_MULTI(IkConstraintTimeline, CurveTimeline, ConstraintTimeline)
|
||||
|
||||
IkConstraintTimeline::IkConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex)
|
||||
: CurveTimeline(frameCount, IkConstraintTimeline::ENTRIES, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_IkConstraint << 32) | constraintIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
IkConstraintTimeline::~IkConstraintTimeline() {
|
||||
}
|
||||
|
||||
void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(add);
|
||||
|
||||
IkConstraint *constraint = (IkConstraint *) skeleton._constraints[_constraintIndex];
|
||||
if (!constraint->isActive()) return;
|
||||
IkConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) {
|
||||
IkConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mix = setup._mix;
|
||||
pose._softness = setup._softness;
|
||||
pose._bendDirection = setup._bendDirection;
|
||||
pose._compress = setup._compress;
|
||||
pose._stretch = setup._stretch;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float mix = 0, softness = 0;
|
||||
int i = Animation::search(_frames, time, ENTRIES);
|
||||
int curveType = (int) _curves[i / ENTRIES];
|
||||
switch (curveType) {
|
||||
case LINEAR: {
|
||||
float before = _frames[i];
|
||||
mix = _frames[i + MIX];
|
||||
softness = _frames[i + SOFTNESS];
|
||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||
mix += (_frames[i + ENTRIES + MIX] - mix) * t;
|
||||
softness += (_frames[i + ENTRIES + SOFTNESS] - softness) * t;
|
||||
break;
|
||||
}
|
||||
case STEPPED: {
|
||||
mix = _frames[i + MIX];
|
||||
softness = _frames[i + SOFTNESS];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
mix = getBezierValue(time, i, MIX, curveType - BEZIER);
|
||||
softness = getBezierValue(time, i, SOFTNESS, curveType + BEZIER_SIZE - BEZIER);
|
||||
}
|
||||
}
|
||||
|
||||
IkConstraintPose &base = fromSetup ? constraint->_data._setup : pose;
|
||||
pose._mix = base._mix + (mix - base._mix) * alpha;
|
||||
pose._softness = base._softness + (softness - base._softness) * alpha;
|
||||
if (out) {
|
||||
if (fromSetup) {
|
||||
pose._bendDirection = base._bendDirection;
|
||||
pose._compress = base._compress;
|
||||
pose._stretch = base._stretch;
|
||||
}
|
||||
} else {
|
||||
pose._bendDirection = (int) _frames[i + BEND_DIRECTION];
|
||||
pose._compress = _frames[i + COMPRESS] != 0;
|
||||
pose._stretch = _frames[i + STRETCH] != 0;
|
||||
}
|
||||
}
|
||||
|
||||
void IkConstraintTimeline::setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, bool stretch) {
|
||||
frame *= ENTRIES;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + MIX] = mix;
|
||||
_frames[frame + SOFTNESS] = softness;
|
||||
_frames[frame + BEND_DIRECTION] = (float) bendDirection;
|
||||
_frames[frame + COMPRESS] = compress ? 1 : 0;
|
||||
_frames[frame + STRETCH] = stretch ? 1 : 0;
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/InheritTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/BoneLocal.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_MULTI(InheritTimeline, Timeline, BoneTimeline)
|
||||
|
||||
InheritTimeline::InheritTimeline(size_t frameCount, int boneIndex) : Timeline(frameCount, ENTRIES), BoneTimeline(boneIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Inherit << 32) | boneIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_instant = true;
|
||||
}
|
||||
|
||||
InheritTimeline::~InheritTimeline() {
|
||||
}
|
||||
|
||||
void InheritTimeline::setFrame(int frame, float time, Inherit inherit) {
|
||||
frame *= ENTRIES;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + INHERIT] = (float) inherit;
|
||||
}
|
||||
|
||||
void InheritTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(alpha);
|
||||
SP_UNUSED(add);
|
||||
|
||||
Bone *bone = skeleton._bones[_boneIndex];
|
||||
if (!bone->isActive()) return;
|
||||
BoneLocal &pose = appliedPose ? *bone->_applied : bone->_pose;
|
||||
|
||||
if (out) {
|
||||
if (fromSetup) pose._inherit = bone->_data._setup._inherit;
|
||||
} else {
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) pose._inherit = bone->_data._setup._inherit;
|
||||
} else {
|
||||
int idx = Animation::search(_frames, time, ENTRIES) + INHERIT;
|
||||
pose._inherit = static_cast<Inherit>((int) _frames[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,555 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2009, Dave Gamble
|
||||
Copyright (c) 2013, Esoteric Software
|
||||
|
||||
Permission is hereby granted, dispose of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Json */
|
||||
/* JSON parser in CPP, from json.c in the spine-c runtime */
|
||||
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
/* Bring strings.h definitions into string.h, where appropriate */
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
|
||||
#ifndef _BSD_SOURCE
|
||||
/* Bring strings.h definitions into string.h, where appropriate */
|
||||
#define _BSD_SOURCE
|
||||
#endif
|
||||
|
||||
#include <spine/Json.h>
|
||||
#include <spine/Extension.h>
|
||||
#include <spine/SpineString.h>
|
||||
#include <spine/Array.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
const int Json::JSON_FALSE = 0;
|
||||
const int Json::JSON_TRUE = 1;
|
||||
const int Json::JSON_NULL = 2;
|
||||
const int Json::JSON_NUMBER = 3;
|
||||
const int Json::JSON_STRING = 4;
|
||||
const int Json::JSON_ARRAY = 5;
|
||||
const int Json::JSON_OBJECT = 6;
|
||||
|
||||
const char *Json::_error = NULL;
|
||||
|
||||
Json *Json::getItem(Json *object, const char *string) {
|
||||
Json *c = object->_child;
|
||||
while (c && json_strcasecmp(c->_name, string)) {
|
||||
c = c->_next;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
Json *Json::getItem(Json *object, int childIndex) {
|
||||
Json *current = object->_child;
|
||||
while (current != NULL && childIndex > 0) {
|
||||
childIndex--;
|
||||
current = current->_next;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
const char *Json::getString(Json *object, const char *name, const char *defaultValue) {
|
||||
object = getItem(object, name);
|
||||
if (object) {
|
||||
return object->_valueString;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
float Json::getFloat(Json *value, const char *name, float defaultValue) {
|
||||
value = getItem(value, name);
|
||||
return value ? value->_valueFloat : defaultValue;
|
||||
}
|
||||
|
||||
int Json::getInt(Json *value, const char *name, int defaultValue) {
|
||||
value = getItem(value, name);
|
||||
return value ? value->_valueInt : defaultValue;
|
||||
}
|
||||
|
||||
bool Json::getBoolean(Json *value, const char *name, bool defaultValue) {
|
||||
value = getItem(value, name);
|
||||
if (value) {
|
||||
if (value->_valueString) return strcmp(value->_valueString, "true") == 0;
|
||||
if (value->_type == JSON_NULL) return false;
|
||||
if (value->_type == JSON_NUMBER) return value->_valueFloat != 0;
|
||||
if (value->_type == JSON_FALSE) return false;
|
||||
if (value->_type == JSON_TRUE) return true;
|
||||
return defaultValue;
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Json::getError() {
|
||||
return _error;
|
||||
}
|
||||
|
||||
Json::Json(const char *value)
|
||||
: _next(NULL),
|
||||
#if SPINE_JSON_HAVE_PREV
|
||||
_prev(NULL),
|
||||
#endif
|
||||
_child(NULL), _type(0), _size(0), _valueString(NULL), _valueInt(0), _valueFloat(0), _name(NULL) {
|
||||
if (value) {
|
||||
value = parseValue(this, skip(value));
|
||||
|
||||
assert(value);
|
||||
}
|
||||
}
|
||||
|
||||
Json::~Json() {
|
||||
Json *curr = NULL;
|
||||
Json *next = _child;
|
||||
do {
|
||||
curr = next;
|
||||
if (curr) {
|
||||
next = curr->_next;
|
||||
}
|
||||
delete curr;
|
||||
} while (next);
|
||||
|
||||
if (_valueString) {
|
||||
SpineExtension::free(_valueString, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
if (_name) {
|
||||
SpineExtension::free(_name, __FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
const char *Json::skip(const char *inValue) {
|
||||
if (!inValue) {
|
||||
/* must propagate NULL since it's often called in skip(f(...)) form */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*inValue && (unsigned char) *inValue <= 32) {
|
||||
inValue++;
|
||||
}
|
||||
|
||||
return inValue;
|
||||
}
|
||||
|
||||
const char *Json::parseValue(Json *item, const char *value) {
|
||||
/* Referenced by constructor, parseArray(), and parseObject(). */
|
||||
/* Always called with the result of skip(). */
|
||||
#ifdef SPINE_JSON_DEBUG /* Checked at entry to graph, constructor, and after every parse call. */
|
||||
if (!value) {
|
||||
/* Fail on null. */
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (*value) {
|
||||
case 'n': {
|
||||
if (!strncmp(value + 1, "ull", 3)) {
|
||||
item->_type = JSON_NULL;
|
||||
return value + 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'f': {
|
||||
if (!strncmp(value + 1, "alse", 4)) {
|
||||
item->_type = JSON_FALSE;
|
||||
/* calloc prevents us needing item->_type = JSON_FALSE or valueInt = 0 here */
|
||||
return value + 5;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 't': {
|
||||
if (!strncmp(value + 1, "rue", 3)) {
|
||||
item->_type = JSON_TRUE;
|
||||
item->_valueInt = 1;
|
||||
return value + 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '\"':
|
||||
return parseString(item, value);
|
||||
case '[':
|
||||
return parseArray(item, value);
|
||||
case '{':
|
||||
return parseObject(item, value);
|
||||
case '-': /* fallthrough */
|
||||
case '0': /* fallthrough */
|
||||
case '1': /* fallthrough */
|
||||
case '2': /* fallthrough */
|
||||
case '3': /* fallthrough */
|
||||
case '4': /* fallthrough */
|
||||
case '5': /* fallthrough */
|
||||
case '6': /* fallthrough */
|
||||
case '7': /* fallthrough */
|
||||
case '8': /* fallthrough */
|
||||
case '9':
|
||||
return parseNumber(item, value);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_error = value;
|
||||
return NULL; /* failure. */
|
||||
}
|
||||
|
||||
static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
|
||||
|
||||
const char *Json::parseString(Json *item, const char *str) {
|
||||
const char *ptr = str + 1;
|
||||
char *ptr2;
|
||||
char *out;
|
||||
int len = 0;
|
||||
unsigned uc, uc2;
|
||||
if (*str != '\"') {
|
||||
/* TODO: don't need this check when called from parseValue, but do need from parseObject */
|
||||
_error = str;
|
||||
return 0;
|
||||
} /* not a string! */
|
||||
|
||||
while (*ptr != '\"' && *ptr && ++len) {
|
||||
if (*ptr++ == '\\') {
|
||||
ptr++; /* Skip escaped quotes. */
|
||||
}
|
||||
}
|
||||
|
||||
out = SpineExtension::alloc<char>(len + 1, __FILE__, __LINE__); /* The length needed for the string, roughly. */
|
||||
if (!out) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ptr = str + 1;
|
||||
ptr2 = out;
|
||||
while (*ptr != '\"' && *ptr) {
|
||||
if (*ptr != '\\') {
|
||||
*ptr2++ = *ptr++;
|
||||
} else {
|
||||
ptr++;
|
||||
switch (*ptr) {
|
||||
case 'b':
|
||||
*ptr2++ = '\b';
|
||||
break;
|
||||
case 'f':
|
||||
*ptr2++ = '\f';
|
||||
break;
|
||||
case 'n':
|
||||
*ptr2++ = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
*ptr2++ = '\r';
|
||||
break;
|
||||
case 't':
|
||||
*ptr2++ = '\t';
|
||||
break;
|
||||
case 'u': {
|
||||
/* transcode utf16 to utf8. */
|
||||
sscanf(ptr + 1, "%4x", &uc);
|
||||
ptr += 4; /* get the unicode char. */
|
||||
|
||||
if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) {
|
||||
break; /* check for invalid. */
|
||||
}
|
||||
|
||||
/* TODO provide an option to ignore surrogates, use unicode replacement character? */
|
||||
if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs. */ {
|
||||
if (ptr[1] != '\\' || ptr[2] != 'u') {
|
||||
break; /* missing second-half of surrogate. */
|
||||
}
|
||||
sscanf(ptr + 3, "%4x", &uc2);
|
||||
ptr += 6;
|
||||
if (uc2 < 0xDC00 || uc2 > 0xDFFF) {
|
||||
break; /* invalid second-half of surrogate. */
|
||||
}
|
||||
uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
|
||||
}
|
||||
|
||||
len = 4;
|
||||
if (uc < 0x80) {
|
||||
len = 1;
|
||||
} else if (uc < 0x800) {
|
||||
len = 2;
|
||||
} else if (uc < 0x10000) {
|
||||
len = 3;
|
||||
}
|
||||
ptr2 += len;
|
||||
|
||||
switch (len) {
|
||||
case 4:
|
||||
*--ptr2 = ((uc | 0x80) & 0xBF);
|
||||
uc >>= 6;
|
||||
/* fallthrough */
|
||||
case 3:
|
||||
*--ptr2 = ((uc | 0x80) & 0xBF);
|
||||
uc >>= 6;
|
||||
/* fallthrough */
|
||||
case 2:
|
||||
*--ptr2 = ((uc | 0x80) & 0xBF);
|
||||
uc >>= 6;
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
*--ptr2 = (uc | firstByteMark[len]);
|
||||
}
|
||||
ptr2 += len;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
*ptr2++ = *ptr;
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
*ptr2 = 0;
|
||||
|
||||
if (*ptr == '\"') {
|
||||
ptr++; /* TODO error handling if not \" or \0 ? */
|
||||
}
|
||||
|
||||
item->_valueString = out;
|
||||
item->_type = JSON_STRING;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
const char *Json::parseNumber(Json *item, const char *num) {
|
||||
double result = 0.0;
|
||||
int negative = 0;
|
||||
char *ptr = (char *) num;
|
||||
|
||||
if (*ptr == '-') {
|
||||
negative = -1;
|
||||
++ptr;
|
||||
}
|
||||
|
||||
while (*ptr >= '0' && *ptr <= '9') {
|
||||
result = result * 10.0 + (*ptr - '0');
|
||||
++ptr;
|
||||
}
|
||||
|
||||
if (*ptr == '.') {
|
||||
double fraction = 0.0;
|
||||
int n = 0;
|
||||
++ptr;
|
||||
|
||||
while (*ptr >= '0' && *ptr <= '9') {
|
||||
fraction = (fraction * 10.0) + (*ptr - '0');
|
||||
++ptr;
|
||||
++n;
|
||||
}
|
||||
result += fraction / pow(10.0, n);
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
result = -result;
|
||||
}
|
||||
|
||||
if (*ptr == 'e' || *ptr == 'E') {
|
||||
double exponent = 0;
|
||||
int expNegative = 0;
|
||||
++ptr;
|
||||
|
||||
if (*ptr == '-') {
|
||||
expNegative = -1;
|
||||
++ptr;
|
||||
} else if (*ptr == '+') {
|
||||
++ptr;
|
||||
}
|
||||
|
||||
while (*ptr >= '0' && *ptr <= '9') {
|
||||
exponent = (exponent * 10.0) + (*ptr - '0');
|
||||
++ptr;
|
||||
}
|
||||
|
||||
if (expNegative) {
|
||||
result = result / pow(10, exponent);
|
||||
} else {
|
||||
result = result * pow(10, exponent);
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr != num) {
|
||||
/* Parse success, number found. */
|
||||
item->_valueFloat = (float) result;
|
||||
item->_valueInt = (int) result;
|
||||
item->_type = JSON_NUMBER;
|
||||
return ptr;
|
||||
} else {
|
||||
/* Parse failure, _error is set. */
|
||||
_error = num;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Json::parseArray(Json *item, const char *value) {
|
||||
Json *child;
|
||||
|
||||
#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */
|
||||
if (*value != '[') {
|
||||
ep = value;
|
||||
return 0;
|
||||
} /* not an array! */
|
||||
#endif
|
||||
|
||||
item->_type = JSON_ARRAY;
|
||||
value = skip(value + 1);
|
||||
if (*value == ']') {
|
||||
return value + 1; /* empty array. */
|
||||
}
|
||||
|
||||
item->_child = child = new (__FILE__, __LINE__) Json(NULL);
|
||||
if (!item->_child) {
|
||||
return NULL; /* memory fail */
|
||||
}
|
||||
|
||||
value = skip(parseValue(child, skip(value))); /* skip any spacing, get the value. */
|
||||
|
||||
if (!value) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item->_size = 1;
|
||||
|
||||
while (*value == ',') {
|
||||
Json *new_item = new (__FILE__, __LINE__) Json(NULL);
|
||||
if (!new_item) {
|
||||
return NULL; /* memory fail */
|
||||
}
|
||||
child->_next = new_item;
|
||||
#if SPINE_JSON_HAVE_PREV
|
||||
new_item->prev = child;
|
||||
#endif
|
||||
child = new_item;
|
||||
value = skip(parseValue(child, skip(value + 1)));
|
||||
if (!value) {
|
||||
return NULL; /* parse fail */
|
||||
}
|
||||
item->_size++;
|
||||
}
|
||||
|
||||
if (*value == ']') {
|
||||
return value + 1; /* end of array */
|
||||
}
|
||||
|
||||
_error = value;
|
||||
|
||||
return NULL; /* malformed. */
|
||||
}
|
||||
|
||||
/* Build an object from the text. */
|
||||
const char *Json::parseObject(Json *item, const char *value) {
|
||||
Json *child;
|
||||
|
||||
#ifdef SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */
|
||||
if (*value != '{') {
|
||||
ep = value;
|
||||
return 0;
|
||||
} /* not an object! */
|
||||
#endif
|
||||
|
||||
item->_type = JSON_OBJECT;
|
||||
value = skip(value + 1);
|
||||
if (*value == '}') {
|
||||
return value + 1; /* empty array. */
|
||||
}
|
||||
|
||||
item->_child = child = new (__FILE__, __LINE__) Json(NULL);
|
||||
if (!item->_child) {
|
||||
return NULL;
|
||||
}
|
||||
value = skip(parseString(child, skip(value)));
|
||||
if (!value) {
|
||||
return NULL;
|
||||
}
|
||||
child->_name = child->_valueString;
|
||||
child->_valueString = 0;
|
||||
if (*value != ':') {
|
||||
_error = value;
|
||||
return NULL;
|
||||
} /* fail! */
|
||||
|
||||
value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */
|
||||
if (!value) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item->_size = 1;
|
||||
|
||||
while (*value == ',') {
|
||||
Json *new_item = new (__FILE__, __LINE__) Json(NULL);
|
||||
if (!new_item) {
|
||||
return NULL; /* memory fail */
|
||||
}
|
||||
child->_next = new_item;
|
||||
#if SPINE_JSON_HAVE_PREV
|
||||
new_item->prev = child;
|
||||
#endif
|
||||
child = new_item;
|
||||
value = skip(parseString(child, skip(value + 1)));
|
||||
if (!value) {
|
||||
return NULL;
|
||||
}
|
||||
child->_name = child->_valueString;
|
||||
child->_valueString = 0;
|
||||
if (*value != ':') {
|
||||
_error = value;
|
||||
return NULL;
|
||||
} /* fail! */
|
||||
|
||||
value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */
|
||||
if (!value) {
|
||||
return NULL;
|
||||
}
|
||||
item->_size++;
|
||||
}
|
||||
|
||||
if (*value == '}') {
|
||||
return value + 1; /* end of array */
|
||||
}
|
||||
|
||||
_error = value;
|
||||
|
||||
return NULL; /* malformed. */
|
||||
}
|
||||
|
||||
int Json::json_strcasecmp(const char *s1, const char *s2) {
|
||||
/* TODO we may be able to elide these NULL checks if we can prove
|
||||
* the graph and input (only callsite is Json_getItem) should not have NULLs
|
||||
*/
|
||||
if (s1 && s2) {
|
||||
#if defined(_WIN32)
|
||||
return _stricmp(s1, s2);
|
||||
#else
|
||||
return strcasecmp(s1, s2);
|
||||
#endif
|
||||
} else {
|
||||
if (s1 < s2) {
|
||||
return -1; /* s1 is null, s2 is not */
|
||||
} else if (s1 == s2) {
|
||||
return 0; /* both are null */
|
||||
} else {
|
||||
return 1; /* s2 is nul s1 is not */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/LinkedMesh.h>
|
||||
|
||||
#include <spine/MeshAttachment.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
LinkedMesh::LinkedMesh(MeshAttachment &mesh, const int skinIndex, size_t slotIndex, const String &parent, bool inheritTimelines)
|
||||
: _mesh(&mesh), _skinIndex(skinIndex), _skin(""), _slotIndex(slotIndex), _parent(parent), _inheritTimelines(inheritTimelines) {
|
||||
}
|
||||
|
||||
LinkedMesh::LinkedMesh(MeshAttachment &mesh, const String &skin, size_t slotIndex, const String &parent, bool inheritTimelines)
|
||||
: _mesh(&mesh), _skinIndex(-1), _skin(skin), _slotIndex(slotIndex), _parent(parent), _inheritTimelines(inheritTimelines) {
|
||||
}
|
||||
@ -1,131 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/MathUtil.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <cmath>
|
||||
|
||||
// Required for division by 0 in _isNaN on MSVC
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4723)
|
||||
#endif
|
||||
|
||||
using namespace spine;
|
||||
|
||||
const float MathUtil::Pi = 3.1415926535897932385f;
|
||||
const float MathUtil::Pi_2 = 3.1415926535897932385f * 2;
|
||||
const float MathUtil::InvPi_2 = 1 / MathUtil::Pi_2;
|
||||
const float MathUtil::Deg_Rad = (3.1415926535897932385f / 180.0f);
|
||||
const float MathUtil::Rad_Deg = (180.0f / 3.1415926535897932385f);
|
||||
|
||||
float MathUtil::abs(float v) {
|
||||
return ((v) < 0 ? -(v) : (v));
|
||||
}
|
||||
|
||||
float MathUtil::sign(float v) {
|
||||
return ((v) < 0 ? -1.0f : (v) > 0 ? 1.0f : 0.0f);
|
||||
}
|
||||
|
||||
float MathUtil::clamp(float x, float min, float max) {
|
||||
return ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)));
|
||||
}
|
||||
|
||||
float MathUtil::fmod(float a, float b) {
|
||||
return (float) ::fmod(a, b);
|
||||
}
|
||||
|
||||
/// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323
|
||||
/// degrees), largest error of 0.00488 radians (0.2796 degrees).
|
||||
float MathUtil::atan2(float y, float x) {
|
||||
return (float) ::atan2(y, x);
|
||||
}
|
||||
|
||||
float MathUtil::atan2Deg(float y, float x) {
|
||||
return MathUtil::atan2(y, x) * MathUtil::Rad_Deg;
|
||||
}
|
||||
|
||||
/// Returns the cosine in radians from a lookup table.
|
||||
float MathUtil::cos(float radians) {
|
||||
return (float) ::cos(radians);
|
||||
}
|
||||
|
||||
/// Returns the sine in radians from a lookup table.
|
||||
float MathUtil::sin(float radians) {
|
||||
return (float) ::sin(radians);
|
||||
}
|
||||
|
||||
float MathUtil::sqrt(float v) {
|
||||
return (float) ::sqrt(v);
|
||||
}
|
||||
|
||||
float MathUtil::acos(float v) {
|
||||
return (float) ::acos(v);
|
||||
}
|
||||
|
||||
/// Returns the sine in radians from a lookup table.
|
||||
float MathUtil::sinDeg(float degrees) {
|
||||
return (float) ::sin(degrees * MathUtil::Deg_Rad);
|
||||
}
|
||||
|
||||
/// Returns the cosine in radians from a lookup table.
|
||||
float MathUtil::cosDeg(float degrees) {
|
||||
return (float) ::cos(degrees * MathUtil::Deg_Rad);
|
||||
}
|
||||
|
||||
bool MathUtil::isNan(float v) {
|
||||
return std::isnan(v);
|
||||
}
|
||||
|
||||
float MathUtil::quietNan() {
|
||||
return std::nan("");
|
||||
}
|
||||
|
||||
float MathUtil::random() {
|
||||
return ::rand() / (float) RAND_MAX;
|
||||
}
|
||||
|
||||
float MathUtil::randomTriangular(float min, float max) {
|
||||
return randomTriangular(min, max, (min + max) * 0.5f);
|
||||
}
|
||||
|
||||
float MathUtil::randomTriangular(float min, float max, float mode) {
|
||||
float u = random();
|
||||
float d = max - min;
|
||||
if (u <= (mode - min) / d) return min + sqrt(u * d * (mode - min));
|
||||
return max - sqrt((1 - u) * d * (max - mode));
|
||||
}
|
||||
|
||||
float MathUtil::pow(float a, float b) {
|
||||
return (float) ::pow(a, b);
|
||||
}
|
||||
|
||||
float MathUtil::ceil(float v) {
|
||||
return ::ceil(v);
|
||||
}
|
||||
@ -1,230 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/MeshAttachment.h>
|
||||
#include <spine/Atlas.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(MeshAttachment, VertexAttachment)
|
||||
|
||||
MeshAttachment::MeshAttachment(const String &name, Sequence *sequence)
|
||||
: VertexAttachment(name), _sequence(sequence), _regionUVs(), _triangles(), _hullLength(0), _path(), _color(1, 1, 1, 1), _parentMesh(NULL),
|
||||
_edges(), _width(0), _height(0) {
|
||||
assert(sequence);
|
||||
}
|
||||
|
||||
MeshAttachment::~MeshAttachment() {
|
||||
delete _sequence;
|
||||
}
|
||||
|
||||
void MeshAttachment::computeWorldVertices(Skeleton &skeleton, Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset,
|
||||
size_t stride) {
|
||||
VertexAttachment::computeWorldVertices(skeleton, slot, start, count, worldVertices, offset, stride);
|
||||
}
|
||||
|
||||
Array<float> &MeshAttachment::getRegionUVs() {
|
||||
return _regionUVs;
|
||||
}
|
||||
|
||||
void MeshAttachment::setRegionUVs(Array<float> &inValue) {
|
||||
_regionUVs.clearAndAddAll(inValue);
|
||||
}
|
||||
|
||||
Array<unsigned short> &MeshAttachment::getTriangles() {
|
||||
return _triangles;
|
||||
}
|
||||
|
||||
void MeshAttachment::setTriangles(Array<unsigned short> &inValue) {
|
||||
_triangles.clearAndAddAll(inValue);
|
||||
}
|
||||
|
||||
int MeshAttachment::getHullLength() {
|
||||
return _hullLength;
|
||||
}
|
||||
|
||||
void MeshAttachment::setHullLength(int inValue) {
|
||||
_hullLength = inValue;
|
||||
}
|
||||
|
||||
Sequence &MeshAttachment::getSequence() {
|
||||
return *_sequence;
|
||||
}
|
||||
|
||||
void MeshAttachment::updateSequence() {
|
||||
_sequence->update(*this);
|
||||
}
|
||||
|
||||
const String &MeshAttachment::getPath() {
|
||||
return _path;
|
||||
}
|
||||
|
||||
void MeshAttachment::setPath(const String &inValue) {
|
||||
_path = inValue;
|
||||
}
|
||||
|
||||
Color &MeshAttachment::getColor() {
|
||||
return _color;
|
||||
}
|
||||
|
||||
MeshAttachment *MeshAttachment::getParentMesh() {
|
||||
return _parentMesh;
|
||||
}
|
||||
|
||||
void MeshAttachment::setParentMesh(MeshAttachment *inValue) {
|
||||
_parentMesh = inValue;
|
||||
if (inValue != NULL) {
|
||||
_bones.clearAndAddAll(inValue->_bones);
|
||||
_vertices.clearAndAddAll(inValue->_vertices);
|
||||
_regionUVs.clearAndAddAll(inValue->_regionUVs);
|
||||
_triangles.clearAndAddAll(inValue->_triangles);
|
||||
_hullLength = inValue->_hullLength;
|
||||
_worldVerticesLength = inValue->_worldVerticesLength;
|
||||
_edges.clearAndAddAll(inValue->_edges);
|
||||
_width = inValue->_width;
|
||||
_height = inValue->_height;
|
||||
}
|
||||
}
|
||||
|
||||
Array<unsigned short> &MeshAttachment::getEdges() {
|
||||
return _edges;
|
||||
}
|
||||
|
||||
void MeshAttachment::setEdges(Array<unsigned short> &inValue) {
|
||||
_edges.clearAndAddAll(inValue);
|
||||
}
|
||||
|
||||
float MeshAttachment::getWidth() {
|
||||
return _width;
|
||||
}
|
||||
|
||||
void MeshAttachment::setWidth(float inValue) {
|
||||
_width = inValue;
|
||||
}
|
||||
|
||||
float MeshAttachment::getHeight() {
|
||||
return _height;
|
||||
}
|
||||
|
||||
void MeshAttachment::setHeight(float inValue) {
|
||||
_height = inValue;
|
||||
}
|
||||
|
||||
Attachment &MeshAttachment::copy() {
|
||||
if (_parentMesh) return newLinkedMesh();
|
||||
|
||||
MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName(), new (__FILE__, __LINE__) Sequence(*_sequence));
|
||||
copy->_path = _path;
|
||||
copy->_color.set(_color);
|
||||
copyTo(*copy);
|
||||
copy->_regionUVs.clearAndAddAll(_regionUVs);
|
||||
copy->_triangles.clearAndAddAll(_triangles);
|
||||
copy->_hullLength = _hullLength;
|
||||
copy->_edges.clearAndAddAll(_edges);
|
||||
copy->_width = _width;
|
||||
copy->_height = _height;
|
||||
return *copy;
|
||||
}
|
||||
|
||||
MeshAttachment &MeshAttachment::newLinkedMesh() {
|
||||
MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName(), new (__FILE__, __LINE__) Sequence(*_sequence));
|
||||
copy->setTimelineAttachment(getTimelineAttachment());
|
||||
copy->_path = _path;
|
||||
copy->_color.set(_color);
|
||||
copy->setParentMesh(_parentMesh != NULL ? _parentMesh : this);
|
||||
copy->updateSequence();
|
||||
return *copy;
|
||||
}
|
||||
|
||||
void MeshAttachment::computeUVs(TextureRegion *region, Array<float> ®ionUVs, Array<float> &uvs) {
|
||||
int n = (int) uvs.size();
|
||||
float u, v, width, height;
|
||||
if (region != NULL && region->getRTTI().instanceOf(AtlasRegion::rtti)) {
|
||||
AtlasRegion *r = static_cast<AtlasRegion *>(region);
|
||||
u = r->_u;
|
||||
v = r->_v;
|
||||
float textureWidth = r->getPage()->width;
|
||||
float textureHeight = r->getPage()->height;
|
||||
switch (r->_degrees) {
|
||||
case 90: {
|
||||
u -= (r->_originalHeight - r->_offsetY - r->_packedWidth) / textureWidth;
|
||||
v -= (r->_originalWidth - r->_offsetX - r->_packedHeight) / textureHeight;
|
||||
width = r->_originalHeight / textureWidth;
|
||||
height = r->_originalWidth / textureHeight;
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
uvs[i] = u + regionUVs[i + 1] * width;
|
||||
uvs[i + 1] = v + (1 - regionUVs[i]) * height;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 180: {
|
||||
u -= (r->_originalWidth - r->_offsetX - r->_packedWidth) / textureWidth;
|
||||
v -= r->_offsetY / textureHeight;
|
||||
width = r->_originalWidth / textureWidth;
|
||||
height = r->_originalHeight / textureHeight;
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
uvs[i] = u + (1 - regionUVs[i]) * width;
|
||||
uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 270: {
|
||||
u -= r->_offsetY / textureWidth;
|
||||
v -= r->_offsetX / textureHeight;
|
||||
width = r->_originalHeight / textureWidth;
|
||||
height = r->_originalWidth / textureHeight;
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
uvs[i] = u + (1 - regionUVs[i + 1]) * width;
|
||||
uvs[i + 1] = v + regionUVs[i] * height;
|
||||
}
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
u -= r->_offsetX / textureWidth;
|
||||
v -= (r->_originalHeight - r->_offsetY - r->_packedHeight) / textureHeight;
|
||||
width = r->_originalWidth / textureWidth;
|
||||
height = r->_originalHeight / textureHeight;
|
||||
}
|
||||
}
|
||||
} else if (region == NULL) {
|
||||
u = v = 0;
|
||||
width = height = 1;
|
||||
} else {
|
||||
u = region->_u;
|
||||
v = region->_v;
|
||||
width = region->_u2 - u;
|
||||
height = region->_v2 - v;
|
||||
}
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
uvs[i] = u + regionUVs[i] * width;
|
||||
uvs[i + 1] = v + regionUVs[i + 1] * height;
|
||||
}
|
||||
}
|
||||
@ -1,74 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PathAttachment.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(PathAttachment, VertexAttachment)
|
||||
|
||||
PathAttachment::PathAttachment(const String &name) : VertexAttachment(name), _closed(false), _constantSpeed(false), _color() {
|
||||
}
|
||||
|
||||
Array<float> &PathAttachment::getLengths() {
|
||||
return _lengths;
|
||||
}
|
||||
|
||||
void PathAttachment::setLengths(Array<float> &inValue) {
|
||||
_lengths.clearAndAddAll(inValue);
|
||||
}
|
||||
|
||||
bool PathAttachment::getClosed() {
|
||||
return _closed;
|
||||
}
|
||||
|
||||
void PathAttachment::setClosed(bool inValue) {
|
||||
_closed = inValue;
|
||||
}
|
||||
|
||||
bool PathAttachment::getConstantSpeed() {
|
||||
return _constantSpeed;
|
||||
}
|
||||
|
||||
void PathAttachment::setConstantSpeed(bool inValue) {
|
||||
_constantSpeed = inValue;
|
||||
}
|
||||
|
||||
Color &PathAttachment::getColor() {
|
||||
return _color;
|
||||
}
|
||||
|
||||
Attachment &PathAttachment::copy() {
|
||||
PathAttachment *copy = new (__FILE__, __LINE__) PathAttachment(getName());
|
||||
copyTo(*copy);
|
||||
copy->_lengths.clearAndAddAll(_lengths);
|
||||
copy->_closed = _closed;
|
||||
copy->_constantSpeed = _constantSpeed;
|
||||
return *copy;
|
||||
}
|
||||
@ -1,552 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PathConstraint.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BonePose.h>
|
||||
#include <spine/PathAttachment.h>
|
||||
#include <spine/PathConstraintData.h>
|
||||
#include <spine/PathConstraintPose.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/MathUtil.h>
|
||||
#include <spine/Skin.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/SkeletonData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(PathConstraint, Constraint)
|
||||
|
||||
const float PathConstraint::epsilon = 0.00001f;
|
||||
const int PathConstraint::NONE = -1;
|
||||
const int PathConstraint::BEFORE = -2;
|
||||
const int PathConstraint::AFTER = -3;
|
||||
|
||||
PathConstraint::PathConstraint(PathConstraintData &data, Skeleton &skeleton) : PathConstraintBase(data) {
|
||||
|
||||
_bones.ensureCapacity(data.getBones().size());
|
||||
for (size_t i = 0; i < data.getBones().size(); i++) {
|
||||
BoneData *boneData = data.getBones()[i];
|
||||
_bones.add(&skeleton._bones[boneData->getIndex()]->_constrained);
|
||||
}
|
||||
|
||||
_slot = skeleton._slots[data._slot->_index];
|
||||
_segments.setSize(10, 0);
|
||||
}
|
||||
|
||||
PathConstraint &PathConstraint::copy(Skeleton &skeleton) {
|
||||
PathConstraint *copy = new (__FILE__, __LINE__) PathConstraint(_data, skeleton);
|
||||
copy->_pose.set(_pose);
|
||||
return *copy;
|
||||
}
|
||||
|
||||
void PathConstraint::update(Skeleton &skeleton, Physics physics) {
|
||||
Attachment *baseAttachment = _slot->_applied->_attachment;
|
||||
if (baseAttachment == NULL || !baseAttachment->getRTTI().instanceOf(PathAttachment::rtti)) {
|
||||
return;
|
||||
}
|
||||
PathAttachment *pathAttachment = static_cast<PathAttachment *>(baseAttachment);
|
||||
|
||||
PathConstraintPose &p = *_applied;
|
||||
float mixRotate = p._mixRotate, mixX = p._mixX, mixY = p._mixY;
|
||||
if (mixRotate == 0 && mixX == 0 && mixY == 0) return;
|
||||
|
||||
PathConstraintData &data = _data;
|
||||
bool tangents = data._rotateMode == RotateMode_Tangent, scale = data._rotateMode == RotateMode_ChainScale;
|
||||
size_t boneCount = _bones.size();
|
||||
size_t spacesCount = tangents ? boneCount : boneCount + 1;
|
||||
BonePose **bones = _bones.buffer();
|
||||
_spaces.setSize(spacesCount, 0);
|
||||
float *spaces = _spaces.buffer();
|
||||
float *lengths = NULL;
|
||||
if (scale) {
|
||||
_lengths.setSize(boneCount, 0);
|
||||
lengths = _lengths.buffer();
|
||||
}
|
||||
float spacing = p._spacing;
|
||||
|
||||
switch (data._spacingMode) {
|
||||
case SpacingMode_Percent: {
|
||||
if (scale) {
|
||||
for (size_t i = 0, n = spacesCount - 1; i < n; i++) {
|
||||
BonePose *bone = bones[i];
|
||||
float setupLength = bone->_bone->getData().getLength();
|
||||
float x = setupLength * bone->_a;
|
||||
float y = setupLength * bone->_c;
|
||||
lengths[i] = MathUtil::sqrt(x * x + y * y);
|
||||
}
|
||||
}
|
||||
for (size_t i = 1; i < spacesCount; i++) {
|
||||
spaces[i] = spacing;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SpacingMode_Proportional: {
|
||||
float sum = 0;
|
||||
for (size_t i = 0, n = spacesCount - 1; i < n;) {
|
||||
BonePose *bone = bones[i];
|
||||
float setupLength = bone->_bone->getData().getLength();
|
||||
if (setupLength < epsilon) {
|
||||
if (scale) lengths[i] = 0;
|
||||
spaces[++i] = spacing;
|
||||
} else {
|
||||
float x = setupLength * bone->_a, y = setupLength * bone->_c;
|
||||
float length = MathUtil::sqrt(x * x + y * y);
|
||||
if (scale) lengths[i] = length;
|
||||
spaces[++i] = length;
|
||||
sum += length;
|
||||
}
|
||||
}
|
||||
if (sum > 0) {
|
||||
sum = spacesCount / sum * spacing;
|
||||
for (size_t i = 1; i < spacesCount; i++) {
|
||||
spaces[i] *= sum;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
bool lengthSpacing = data._spacingMode == SpacingMode_Length;
|
||||
for (size_t i = 0, n = spacesCount - 1; i < n;) {
|
||||
BonePose *bone = bones[i];
|
||||
float setupLength = bone->_bone->getData().getLength();
|
||||
if (setupLength < epsilon) {
|
||||
if (scale) lengths[i] = 0;
|
||||
spaces[++i] = spacing;
|
||||
} else {
|
||||
float x = setupLength * bone->_a, y = setupLength * bone->_c;
|
||||
float length = MathUtil::sqrt(x * x + y * y);
|
||||
if (scale) lengths[i] = length;
|
||||
spaces[++i] = (lengthSpacing ? MathUtil::max(0.0f, setupLength + spacing) : spacing) * length / setupLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Array<float> &positions = computeWorldPositions(skeleton, *pathAttachment, (int) spacesCount, tangents);
|
||||
float *positionsBuffer = positions.buffer();
|
||||
float boneX = positionsBuffer[0], boneY = positionsBuffer[1], offsetRotation = data._offsetRotation;
|
||||
bool tip;
|
||||
if (offsetRotation == 0)
|
||||
tip = data._rotateMode == RotateMode_Chain;
|
||||
else {
|
||||
tip = false;
|
||||
BonePose &bone = _slot->getBone().getAppliedPose();
|
||||
offsetRotation *= bone._a * bone._d - bone._b * bone._c > 0 ? MathUtil::Deg_Rad : -MathUtil::Deg_Rad;
|
||||
}
|
||||
for (size_t i = 0, ip = 3, u = skeleton._update; i < boneCount; i++, ip += 3) {
|
||||
BonePose *bone = bones[i];
|
||||
bone->_worldX += (boneX - bone->_worldX) * mixX;
|
||||
bone->_worldY += (boneY - bone->_worldY) * mixY;
|
||||
float x = positionsBuffer[ip], y = positionsBuffer[ip + 1], dx = x - boneX, dy = y - boneY;
|
||||
if (scale) {
|
||||
float length = lengths[i];
|
||||
if (length >= epsilon) {
|
||||
float s = (MathUtil::sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1;
|
||||
bone->_a *= s;
|
||||
bone->_c *= s;
|
||||
}
|
||||
}
|
||||
boneX = x;
|
||||
boneY = y;
|
||||
if (mixRotate > 0) {
|
||||
float a = bone->_a, b = bone->_b, c = bone->_c, d = bone->_d, r, cos, sin;
|
||||
if (tangents)
|
||||
r = positionsBuffer[ip - 1];
|
||||
else if (spaces[i + 1] < epsilon)
|
||||
r = positionsBuffer[ip + 2];
|
||||
else
|
||||
r = MathUtil::atan2(dy, dx);
|
||||
r -= MathUtil::atan2(c, a);
|
||||
if (tip) {
|
||||
cos = MathUtil::cos(r);
|
||||
sin = MathUtil::sin(r);
|
||||
float length = bone->_bone->getData().getLength();
|
||||
boneX += (length * (cos * a - sin * c) - dx) * mixRotate;
|
||||
boneY += (length * (sin * a + cos * c) - dy) * mixRotate;
|
||||
} else
|
||||
r += offsetRotation;
|
||||
if (r > MathUtil::Pi)
|
||||
r -= MathUtil::Pi_2;
|
||||
else if (r < -MathUtil::Pi)
|
||||
r += MathUtil::Pi_2;
|
||||
r *= mixRotate;
|
||||
cos = MathUtil::cos(r);
|
||||
sin = MathUtil::sin(r);
|
||||
bone->_a = cos * a - sin * c;
|
||||
bone->_b = cos * b - sin * d;
|
||||
bone->_c = sin * a + cos * c;
|
||||
bone->_d = sin * b + cos * d;
|
||||
}
|
||||
bone->modifyWorld((int) u);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PathConstraint::sort(Skeleton &skeleton) {
|
||||
int slotIndex = _slot->getData().getIndex();
|
||||
Bone &slotBone = _slot->getBone();
|
||||
if (skeleton.getSkin() != NULL) sortPathSlot(skeleton, *skeleton.getSkin(), slotIndex, slotBone);
|
||||
if (skeleton.getData().getDefaultSkin() != NULL && skeleton.getData().getDefaultSkin() != skeleton.getSkin())
|
||||
sortPathSlot(skeleton, *skeleton.getData().getDefaultSkin(), slotIndex, slotBone);
|
||||
sortPath(skeleton, _slot->_pose._attachment, slotBone);
|
||||
BonePose **bones = _bones.buffer();
|
||||
size_t boneCount = _bones.size();
|
||||
for (size_t i = 0; i < boneCount; i++) {
|
||||
Bone *bone = bones[i]->_bone;
|
||||
skeleton.sortBone(bone);
|
||||
skeleton.constrained(*bone);
|
||||
}
|
||||
skeleton._updateCache.add(this);
|
||||
for (size_t i = 0; i < boneCount; i++) skeleton.sortReset(bones[i]->_bone->getChildren());
|
||||
for (size_t i = 0; i < boneCount; i++) bones[i]->_bone->_sorted = true;
|
||||
}
|
||||
|
||||
bool PathConstraint::isSourceActive() {
|
||||
return _slot->getBone().isActive();
|
||||
}
|
||||
|
||||
Array<BonePose *> &PathConstraint::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
Slot &PathConstraint::getSlot() {
|
||||
return *_slot;
|
||||
}
|
||||
|
||||
void PathConstraint::setSlot(Slot &slot) {
|
||||
_slot = &slot;
|
||||
}
|
||||
|
||||
Array<float> &PathConstraint::computeWorldPositions(Skeleton &skeleton, PathAttachment &path, int spacesCount, bool tangents) {
|
||||
float position = _applied->_position;
|
||||
float *spaces = _spaces.buffer();
|
||||
_positions.setSize(spacesCount * 3 + 2, 0);
|
||||
Array<float> &out = _positions;
|
||||
Array<float> &world = _world;
|
||||
bool closed = path.getClosed();
|
||||
int verticesLength = (int) path.getWorldVerticesLength();
|
||||
int curveCount = verticesLength / 6;
|
||||
int prevCurve = NONE;
|
||||
|
||||
float pathLength;
|
||||
if (!path.getConstantSpeed()) {
|
||||
Array<float> &lengths = path.getLengths();
|
||||
float *lengthsBuffer = lengths.buffer();
|
||||
curveCount -= closed ? 1 : 2;
|
||||
pathLength = lengthsBuffer[curveCount];
|
||||
if (_data._positionMode == PositionMode_Percent) position *= pathLength;
|
||||
|
||||
float multiplier = 0;
|
||||
switch (_data._spacingMode) {
|
||||
case SpacingMode_Percent:
|
||||
multiplier = pathLength;
|
||||
break;
|
||||
case SpacingMode_Proportional:
|
||||
multiplier = pathLength / spacesCount;
|
||||
break;
|
||||
default:
|
||||
multiplier = 1;
|
||||
}
|
||||
|
||||
world.setSize(8, 0);
|
||||
float *worldBuffer = world.buffer();
|
||||
for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {
|
||||
float space = spaces[i] * multiplier;
|
||||
position += space;
|
||||
float p = position;
|
||||
|
||||
if (closed) {
|
||||
p = MathUtil::fmod(p, pathLength);
|
||||
if (p < 0) p += pathLength;
|
||||
curve = 0;
|
||||
} else if (p < 0) {
|
||||
if (prevCurve != BEFORE) {
|
||||
prevCurve = BEFORE;
|
||||
path.computeWorldVertices(skeleton, *_slot, 2, 4, world, 0, 2);
|
||||
}
|
||||
addBeforePosition(p, world, 0, out, o);
|
||||
continue;
|
||||
} else if (p > pathLength) {
|
||||
if (prevCurve != AFTER) {
|
||||
prevCurve = AFTER;
|
||||
path.computeWorldVertices(skeleton, *_slot, verticesLength - 6, 4, world, 0, 2);
|
||||
}
|
||||
addAfterPosition(p - pathLength, world, 0, out, o);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine curve containing position.
|
||||
for (;; curve++) {
|
||||
float length = lengthsBuffer[curve];
|
||||
if (p > length) continue;
|
||||
if (curve == 0)
|
||||
p /= length;
|
||||
else {
|
||||
float prev = lengthsBuffer[curve - 1];
|
||||
p = (p - prev) / (length - prev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (curve != prevCurve) {
|
||||
prevCurve = curve;
|
||||
if (closed && curve == curveCount) {
|
||||
path.computeWorldVertices(skeleton, *_slot, verticesLength - 4, 4, world, 0, 2);
|
||||
path.computeWorldVertices(skeleton, *_slot, 0, 4, world, 4, 2);
|
||||
} else
|
||||
path.computeWorldVertices(skeleton, *_slot, curve * 6 + 2, 8, world, 0, 2);
|
||||
}
|
||||
addCurvePosition(p, worldBuffer[0], worldBuffer[1], worldBuffer[2], worldBuffer[3], worldBuffer[4], worldBuffer[5], worldBuffer[6],
|
||||
worldBuffer[7], out, o, tangents || (i > 0 && space < epsilon));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// World vertices.
|
||||
if (closed) {
|
||||
verticesLength += 2;
|
||||
world.setSize(verticesLength, 0);
|
||||
float *worldBuffer = world.buffer();
|
||||
path.computeWorldVertices(skeleton, *_slot, 2, verticesLength - 4, world, 0, 2);
|
||||
path.computeWorldVertices(skeleton, *_slot, 0, 2, world, verticesLength - 4, 2);
|
||||
worldBuffer[verticesLength - 2] = worldBuffer[0];
|
||||
worldBuffer[verticesLength - 1] = worldBuffer[1];
|
||||
} else {
|
||||
curveCount--;
|
||||
verticesLength -= 4;
|
||||
world.setSize(verticesLength, 0);
|
||||
path.computeWorldVertices(skeleton, *_slot, 2, verticesLength, world, 0, 2);
|
||||
}
|
||||
float *worldBuffer = world.buffer();
|
||||
|
||||
// Curve lengths.
|
||||
_curves.setSize(curveCount, 0);
|
||||
float *curvesBuffer = _curves.buffer();
|
||||
pathLength = 0;
|
||||
float x1 = worldBuffer[0], y1 = worldBuffer[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0;
|
||||
float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy;
|
||||
for (int i = 0, w = 2; i < curveCount; i++, w += 6) {
|
||||
cx1 = worldBuffer[w];
|
||||
cy1 = worldBuffer[w + 1];
|
||||
cx2 = worldBuffer[w + 2];
|
||||
cy2 = worldBuffer[w + 3];
|
||||
x2 = worldBuffer[w + 4];
|
||||
y2 = worldBuffer[w + 5];
|
||||
tmpx = (x1 - cx1 * 2 + cx2) * 0.1875f;
|
||||
tmpy = (y1 - cy1 * 2 + cy2) * 0.1875f;
|
||||
dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f;
|
||||
dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f;
|
||||
ddfx = tmpx * 2 + dddfx;
|
||||
ddfy = tmpy * 2 + dddfy;
|
||||
dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f;
|
||||
dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f;
|
||||
pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy);
|
||||
dfx += ddfx;
|
||||
dfy += ddfy;
|
||||
ddfx += dddfx;
|
||||
ddfy += dddfy;
|
||||
pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy);
|
||||
dfx += ddfx;
|
||||
dfy += ddfy;
|
||||
pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy);
|
||||
dfx += ddfx + dddfx;
|
||||
dfy += ddfy + dddfy;
|
||||
pathLength += MathUtil::sqrt(dfx * dfx + dfy * dfy);
|
||||
curvesBuffer[i] = pathLength;
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
|
||||
if (_data._positionMode == PositionMode_Percent) position *= pathLength;
|
||||
|
||||
float multiplier = 0;
|
||||
switch (_data._spacingMode) {
|
||||
case SpacingMode_Percent:
|
||||
multiplier = pathLength;
|
||||
break;
|
||||
case SpacingMode_Proportional:
|
||||
multiplier = pathLength / spacesCount;
|
||||
break;
|
||||
default:
|
||||
multiplier = 1;
|
||||
}
|
||||
|
||||
float curveLength = 0;
|
||||
for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) {
|
||||
float space = spaces[i] * multiplier;
|
||||
position += space;
|
||||
float p = position;
|
||||
|
||||
if (closed) {
|
||||
p = MathUtil::fmod(p, pathLength);
|
||||
if (p < 0) p += pathLength;
|
||||
curve = 0;
|
||||
segment = 0;
|
||||
} else if (p < 0) {
|
||||
addBeforePosition(p, world, 0, out, o);
|
||||
continue;
|
||||
} else if (p > pathLength) {
|
||||
addAfterPosition(p - pathLength, world, verticesLength - 4, out, o);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine curve containing position.
|
||||
for (;; curve++) {
|
||||
float length = curvesBuffer[curve];
|
||||
if (p > length) continue;
|
||||
if (curve == 0)
|
||||
p /= length;
|
||||
else {
|
||||
float prev = curvesBuffer[curve - 1];
|
||||
p = (p - prev) / (length - prev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Curve segment lengths.
|
||||
if (curve != prevCurve) {
|
||||
prevCurve = curve;
|
||||
int ii = curve * 6;
|
||||
x1 = worldBuffer[ii];
|
||||
y1 = worldBuffer[ii + 1];
|
||||
cx1 = worldBuffer[ii + 2];
|
||||
cy1 = worldBuffer[ii + 3];
|
||||
cx2 = worldBuffer[ii + 4];
|
||||
cy2 = worldBuffer[ii + 5];
|
||||
x2 = worldBuffer[ii + 6];
|
||||
y2 = worldBuffer[ii + 7];
|
||||
tmpx = (x1 - cx1 * 2 + cx2) * 0.03f;
|
||||
tmpy = (y1 - cy1 * 2 + cy2) * 0.03f;
|
||||
dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f;
|
||||
dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f;
|
||||
ddfx = tmpx * 2 + dddfx;
|
||||
ddfy = tmpy * 2 + dddfy;
|
||||
dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f;
|
||||
dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f;
|
||||
curveLength = MathUtil::sqrt(dfx * dfx + dfy * dfy);
|
||||
_segments[0] = curveLength;
|
||||
for (ii = 1; ii < 8; ii++) {
|
||||
dfx += ddfx;
|
||||
dfy += ddfy;
|
||||
ddfx += dddfx;
|
||||
ddfy += dddfy;
|
||||
curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy);
|
||||
_segments[ii] = curveLength;
|
||||
}
|
||||
dfx += ddfx;
|
||||
dfy += ddfy;
|
||||
curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy);
|
||||
_segments[8] = curveLength;
|
||||
dfx += ddfx + dddfx;
|
||||
dfy += ddfy + dddfy;
|
||||
curveLength += MathUtil::sqrt(dfx * dfx + dfy * dfy);
|
||||
_segments[9] = curveLength;
|
||||
segment = 0;
|
||||
}
|
||||
|
||||
// Weight by segment length.
|
||||
p *= curveLength;
|
||||
for (;; segment++) {
|
||||
float length = _segments[segment];
|
||||
if (p > length) continue;
|
||||
if (segment == 0)
|
||||
p /= length;
|
||||
else {
|
||||
float prev = _segments[segment - 1];
|
||||
p = segment + (p - prev) / (length - prev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space < epsilon));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void PathConstraint::addBeforePosition(float p, Array<float> &temp, int i, Array<float> &output, int o) {
|
||||
float x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = MathUtil::atan2(dy, dx);
|
||||
output[o] = x1 + p * MathUtil::cos(r);
|
||||
output[o + 1] = y1 + p * MathUtil::sin(r);
|
||||
output[o + 2] = r;
|
||||
}
|
||||
|
||||
void PathConstraint::addAfterPosition(float p, Array<float> &temp, int i, Array<float> &output, int o) {
|
||||
float x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = MathUtil::atan2(dy, dx);
|
||||
output[o] = x1 + p * MathUtil::cos(r);
|
||||
output[o + 1] = y1 + p * MathUtil::sin(r);
|
||||
output[o + 2] = r;
|
||||
}
|
||||
|
||||
void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2,
|
||||
Array<float> &output, int o, bool tangents) {
|
||||
if (p < epsilon || MathUtil::isNan(p)) {
|
||||
output[o] = x1;
|
||||
output[o + 1] = y1;
|
||||
output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1);
|
||||
return;
|
||||
}
|
||||
float tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u;
|
||||
float ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p;
|
||||
float x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt;
|
||||
output[o] = x;
|
||||
output[o + 1] = y;
|
||||
if (tangents) {
|
||||
if (p < 0.001f)
|
||||
output[o + 2] = MathUtil::atan2(cy1 - y1, cx1 - x1);
|
||||
else
|
||||
output[o + 2] = MathUtil::atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));
|
||||
}
|
||||
}
|
||||
|
||||
void PathConstraint::sortPathSlot(Skeleton &skeleton, Skin &skin, int slotIndex, Bone &slotBone) {
|
||||
Skin::AttachmentMap::Entries entries = skin.getAttachments();
|
||||
while (entries.hasNext()) {
|
||||
Skin::AttachmentMap::Entry &entry = entries.next();
|
||||
if (entry._slotIndex == (size_t) slotIndex) sortPath(skeleton, entry._attachment, slotBone);
|
||||
}
|
||||
}
|
||||
|
||||
void PathConstraint::sortPath(Skeleton &skeleton, Attachment *attachment, Bone &slotBone) {
|
||||
if (attachment == NULL || !attachment->getRTTI().instanceOf(PathAttachment::rtti)) return;
|
||||
PathAttachment *pathAttachment = static_cast<PathAttachment *>(attachment);
|
||||
Array<int> &pathBones = pathAttachment->getBones();
|
||||
if (pathBones.size() == 0)
|
||||
skeleton.sortBone(&slotBone);
|
||||
else {
|
||||
Array<Bone *> &bones = skeleton._bones;
|
||||
for (size_t i = 0, n = pathBones.size(); i < n;) {
|
||||
int nn = pathBones[i++];
|
||||
nn += i;
|
||||
while (i < (size_t) nn) skeleton.sortBone(bones[pathBones[i++]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,92 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PathConstraintData.h>
|
||||
#include <spine/PathConstraint.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(PathConstraintData, ConstraintData)
|
||||
|
||||
PathConstraintData::PathConstraintData(const String &name)
|
||||
: ConstraintDataGeneric<PathConstraint, PathConstraintPose>(name), _slot(NULL), _positionMode(PositionMode_Fixed),
|
||||
_spacingMode(SpacingMode_Length), _rotateMode(RotateMode_Tangent), _offsetRotation(0) {
|
||||
}
|
||||
|
||||
|
||||
Array<BoneData *> &PathConstraintData::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
SlotData &PathConstraintData::getSlot() {
|
||||
return *_slot;
|
||||
}
|
||||
|
||||
void PathConstraintData::setSlot(SlotData &slot) {
|
||||
_slot = &slot;
|
||||
}
|
||||
|
||||
PositionMode PathConstraintData::getPositionMode() {
|
||||
return _positionMode;
|
||||
}
|
||||
|
||||
void PathConstraintData::setPositionMode(PositionMode positionMode) {
|
||||
_positionMode = positionMode;
|
||||
}
|
||||
|
||||
SpacingMode PathConstraintData::getSpacingMode() {
|
||||
return _spacingMode;
|
||||
}
|
||||
|
||||
void PathConstraintData::setSpacingMode(SpacingMode spacingMode) {
|
||||
_spacingMode = spacingMode;
|
||||
}
|
||||
|
||||
RotateMode PathConstraintData::getRotateMode() {
|
||||
return _rotateMode;
|
||||
}
|
||||
|
||||
void PathConstraintData::setRotateMode(RotateMode rotateMode) {
|
||||
_rotateMode = rotateMode;
|
||||
}
|
||||
|
||||
float PathConstraintData::getOffsetRotation() {
|
||||
return _offsetRotation;
|
||||
}
|
||||
|
||||
void PathConstraintData::setOffsetRotation(float offsetRotation) {
|
||||
_offsetRotation = offsetRotation;
|
||||
}
|
||||
|
||||
Constraint &PathConstraintData::create(Skeleton &skeleton) {
|
||||
return *(new (__FILE__, __LINE__) PathConstraint(*this, skeleton));
|
||||
}
|
||||
@ -1,123 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PathConstraintMixTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/PathConstraint.h>
|
||||
#include <spine/PathConstraintData.h>
|
||||
#include <spine/PathConstraintPose.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_MULTI(PathConstraintMixTimeline, CurveTimeline, ConstraintTimeline)
|
||||
|
||||
PathConstraintMixTimeline::PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int constraintIndex)
|
||||
: CurveTimeline(frameCount, PathConstraintMixTimeline::ENTRIES, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_PathConstraintMix << 32) | constraintIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
PathConstraintMixTimeline::~PathConstraintMixTimeline() {
|
||||
}
|
||||
|
||||
void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(out);
|
||||
|
||||
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
||||
if (!constraint->isActive()) return;
|
||||
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) {
|
||||
PathConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mixRotate = setup._mixRotate;
|
||||
pose._mixX = setup._mixX;
|
||||
pose._mixY = setup._mixY;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float rotate, x, y;
|
||||
int i = Animation::search(_frames, time, PathConstraintMixTimeline::ENTRIES);
|
||||
int curveType = (int) _curves[i >> 2];
|
||||
switch (curveType) {
|
||||
case LINEAR: {
|
||||
float before = _frames[i];
|
||||
rotate = _frames[i + ROTATE];
|
||||
x = _frames[i + X];
|
||||
y = _frames[i + Y];
|
||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||
rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t;
|
||||
x += (_frames[i + ENTRIES + X] - x) * t;
|
||||
y += (_frames[i + ENTRIES + Y] - y) * t;
|
||||
break;
|
||||
}
|
||||
case STEPPED: {
|
||||
rotate = _frames[i + ROTATE];
|
||||
x = _frames[i + X];
|
||||
y = _frames[i + Y];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER);
|
||||
x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER);
|
||||
y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||
}
|
||||
}
|
||||
|
||||
PathConstraintPose &base = fromSetup ? constraint->_data._setup : pose;
|
||||
if (add) {
|
||||
pose._mixRotate = base._mixRotate + rotate * alpha;
|
||||
pose._mixX = base._mixX + x * alpha;
|
||||
pose._mixY = base._mixY + y * alpha;
|
||||
} else {
|
||||
pose._mixRotate = base._mixRotate + (rotate - base._mixRotate) * alpha;
|
||||
pose._mixX = base._mixX + (x - base._mixX) * alpha;
|
||||
pose._mixY = base._mixY + (y - base._mixY) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
void PathConstraintMixTimeline::setFrame(int frame, float time, float mixRotate, float mixX, float mixY) {
|
||||
frame *= ENTRIES;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + ROTATE] = mixRotate;
|
||||
_frames[frame + X] = mixX;
|
||||
_frames[frame + Y] = mixY;
|
||||
}
|
||||
@ -1,86 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PathConstraintPose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
PathConstraintPose::PathConstraintPose() : Pose<PathConstraintPose>(), _position(0), _spacing(0), _mixRotate(0), _mixX(0), _mixY(0) {
|
||||
}
|
||||
|
||||
PathConstraintPose::~PathConstraintPose() {
|
||||
}
|
||||
|
||||
void PathConstraintPose::set(PathConstraintPose &pose) {
|
||||
_position = pose._position;
|
||||
_spacing = pose._spacing;
|
||||
_mixRotate = pose._mixRotate;
|
||||
_mixX = pose._mixX;
|
||||
_mixY = pose._mixY;
|
||||
}
|
||||
|
||||
float PathConstraintPose::getPosition() {
|
||||
return _position;
|
||||
}
|
||||
|
||||
void PathConstraintPose::setPosition(float position) {
|
||||
_position = position;
|
||||
}
|
||||
|
||||
float PathConstraintPose::getSpacing() {
|
||||
return _spacing;
|
||||
}
|
||||
|
||||
void PathConstraintPose::setSpacing(float spacing) {
|
||||
_spacing = spacing;
|
||||
}
|
||||
|
||||
float PathConstraintPose::getMixRotate() {
|
||||
return _mixRotate;
|
||||
}
|
||||
|
||||
void PathConstraintPose::setMixRotate(float mixRotate) {
|
||||
_mixRotate = mixRotate;
|
||||
}
|
||||
|
||||
float PathConstraintPose::getMixX() {
|
||||
return _mixX;
|
||||
}
|
||||
|
||||
void PathConstraintPose::setMixX(float mixX) {
|
||||
_mixX = mixX;
|
||||
}
|
||||
|
||||
float PathConstraintPose::getMixY() {
|
||||
return _mixY;
|
||||
}
|
||||
|
||||
void PathConstraintPose::setMixY(float mixY) {
|
||||
_mixY = mixY;
|
||||
}
|
||||
@ -1,66 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PathConstraintPositionTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/PathConstraint.h>
|
||||
#include <spine/PathConstraintData.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(PathConstraintPositionTimeline, ConstraintTimeline1)
|
||||
|
||||
PathConstraintPositionTimeline::PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int constraintIndex)
|
||||
: ConstraintTimeline1(frameCount, bezierCount, constraintIndex, Property_PathConstraintPosition) {
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
PathConstraintPositionTimeline::~PathConstraintPositionTimeline() {
|
||||
}
|
||||
|
||||
void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup,
|
||||
bool add, bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(out);
|
||||
|
||||
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
||||
if (constraint->isActive()) {
|
||||
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
PathConstraintData &data = constraint->_data;
|
||||
pose._position = getAbsoluteValue(time, alpha, fromSetup, add, pose._position, data._setup._position);
|
||||
}
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PathConstraintSpacingTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/PathConstraint.h>
|
||||
#include <spine/PathConstraintData.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(PathConstraintSpacingTimeline, ConstraintTimeline1)
|
||||
|
||||
PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, int constraintIndex)
|
||||
: ConstraintTimeline1(frameCount, bezierCount, constraintIndex, Property_PathConstraintSpacing) {
|
||||
}
|
||||
|
||||
PathConstraintSpacingTimeline::~PathConstraintSpacingTimeline() {
|
||||
}
|
||||
|
||||
void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup,
|
||||
bool add, bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(out);
|
||||
|
||||
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
||||
if (constraint->isActive()) {
|
||||
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
PathConstraintData &data = constraint->_data;
|
||||
pose._spacing = getAbsoluteValue(time, alpha, fromSetup, false, pose._spacing, data._setup._spacing);
|
||||
}
|
||||
}
|
||||
@ -1,292 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PhysicsConstraint.h>
|
||||
#include <spine/PhysicsConstraintData.h>
|
||||
#include <spine/PhysicsConstraintPose.h>
|
||||
#include <spine/BonePose.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/SkeletonData.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/MathUtil.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(PhysicsConstraint, Constraint)
|
||||
|
||||
PhysicsConstraint::PhysicsConstraint(PhysicsConstraintData &data, Skeleton &skeleton)
|
||||
: PhysicsConstraintBase(data), _reset(true), _ux(0), _uy(0), _cx(0), _cy(0), _tx(0), _ty(0), _xOffset(0), _xLag(0), _xVelocity(0), _yOffset(0),
|
||||
_yLag(0), _yVelocity(0), _rotateOffset(0), _rotateLag(0), _rotateVelocity(0), _scaleOffset(0), _scaleLag(0), _scaleVelocity(0), _remaining(0),
|
||||
_lastTime(0) {
|
||||
|
||||
_bone = &skeleton._bones[(size_t) data._bone->getIndex()]->_constrained;
|
||||
}
|
||||
|
||||
PhysicsConstraint &PhysicsConstraint::copy(Skeleton &skeleton) {
|
||||
PhysicsConstraint *copy = new (__FILE__, __LINE__) PhysicsConstraint(_data, skeleton);
|
||||
copy->_pose.set(_pose);
|
||||
return *copy;
|
||||
}
|
||||
|
||||
void PhysicsConstraint::reset(Skeleton &skeleton) {
|
||||
_remaining = 0;
|
||||
_lastTime = skeleton.getTime();
|
||||
_reset = true;
|
||||
_xOffset = 0;
|
||||
_xLag = 0;
|
||||
_xVelocity = 0;
|
||||
_yOffset = 0;
|
||||
_yLag = 0;
|
||||
_yVelocity = 0;
|
||||
_rotateOffset = 0;
|
||||
_rotateLag = 0;
|
||||
_rotateVelocity = 0;
|
||||
_scaleOffset = 0;
|
||||
_scaleLag = 0;
|
||||
_scaleVelocity = 0;
|
||||
}
|
||||
|
||||
void PhysicsConstraint::translate(float x, float y) {
|
||||
_ux -= x;
|
||||
_uy -= y;
|
||||
_cx -= x;
|
||||
_cy -= y;
|
||||
}
|
||||
|
||||
void PhysicsConstraint::rotate(float x, float y, float degrees) {
|
||||
float r = degrees * MathUtil::Deg_Rad, cosVal = MathUtil::cos(r), sinVal = MathUtil::sin(r);
|
||||
float dx = _cx - x, dy = _cy - y;
|
||||
translate(dx * cosVal - dy * sinVal - dx, dx * sinVal + dy * cosVal - dy);
|
||||
}
|
||||
|
||||
void PhysicsConstraint::update(Skeleton &skeleton, Physics physics) {
|
||||
PhysicsConstraintPose &p = *_applied;
|
||||
float mix = p._mix;
|
||||
if (mix == 0) return;
|
||||
|
||||
bool x = _data._x > 0, y = _data._y > 0, rotateOrShearX = _data._rotate > 0 || _data._shearX > 0, scaleX = _data._scaleX > 0;
|
||||
BonePose *bone = _bone;
|
||||
float l = bone->_bone->_data.getLength(), t = _data._step, z = 0;
|
||||
|
||||
switch (physics) {
|
||||
case Physics_None:
|
||||
return;
|
||||
case Physics_Reset:
|
||||
reset(skeleton);
|
||||
// Fall through.
|
||||
case Physics_Update: {
|
||||
float delta = MathUtil::max(skeleton._time - _lastTime, 0.0f), aa = _remaining;
|
||||
_remaining += delta;
|
||||
_lastTime = skeleton._time;
|
||||
|
||||
float bx = bone->_worldX, by = bone->_worldY;
|
||||
if (_reset) {
|
||||
_reset = false;
|
||||
_ux = bx;
|
||||
_uy = by;
|
||||
} else {
|
||||
float a = _remaining, i = p._inertia, f = skeleton._data.getReferenceScale(), d = -1, m = 0, e = 0, qx = _data._limit * delta,
|
||||
qy = qx * MathUtil::abs(skeleton.getScaleY());
|
||||
qx *= MathUtil::abs(skeleton._scaleX);
|
||||
if (x || y) {
|
||||
if (x) {
|
||||
float u = (_ux - bx) * i;
|
||||
_xOffset += u > qx ? qx : u < -qx ? -qx : u;
|
||||
_ux = bx;
|
||||
}
|
||||
if (y) {
|
||||
float u = (_uy - by) * i;
|
||||
_yOffset += u > qy ? qy : u < -qy ? -qy : u;
|
||||
_uy = by;
|
||||
}
|
||||
if (a >= t) {
|
||||
float xs = _xOffset, ys = _yOffset;
|
||||
d = MathUtil::pow(p._damping, 60 * t);
|
||||
m = t * p._massInverse;
|
||||
e = p._strength;
|
||||
float w = f * p._wind, g = f * p._gravity;
|
||||
float ax = (w * skeleton._windX + g * skeleton._gravityX) * skeleton._scaleX;
|
||||
float ay = (w * skeleton._windY + g * skeleton._gravityY) * skeleton.getScaleY();
|
||||
do {
|
||||
if (x) {
|
||||
_xVelocity += (ax - _xOffset * e) * m;
|
||||
_xOffset += _xVelocity * t;
|
||||
_xVelocity *= d;
|
||||
}
|
||||
if (y) {
|
||||
_yVelocity -= (ay + _yOffset * e) * m;
|
||||
_yOffset += _yVelocity * t;
|
||||
_yVelocity *= d;
|
||||
}
|
||||
a -= t;
|
||||
} while (a >= t);
|
||||
_xLag = _xOffset - xs;
|
||||
_yLag = _yOffset - ys;
|
||||
}
|
||||
z = MathUtil::max(0.0f, 1 - a / t);
|
||||
if (x) bone->_worldX += (_xOffset - _xLag * z) * mix * _data._x;
|
||||
if (y) bone->_worldY += (_yOffset - _yLag * z) * mix * _data._y;
|
||||
}
|
||||
if (rotateOrShearX || scaleX) {
|
||||
float ca = MathUtil::atan2(bone->_c, bone->_a), c, s, mr = 0, dx = _cx - bone->_worldX, dy = _cy - bone->_worldY;
|
||||
if (dx > qx)
|
||||
dx = qx;
|
||||
else if (dx < -qx)
|
||||
dx = -qx;
|
||||
if (dy > qy)
|
||||
dy = qy;
|
||||
else if (dy < -qy)
|
||||
dy = -qy;
|
||||
if (rotateOrShearX) {
|
||||
mr = (_data._rotate + _data._shearX) * mix;
|
||||
z = _rotateLag * MathUtil::max(0.0f, 1 - aa / t);
|
||||
float r = MathUtil::atan2(dy + _ty, dx + _tx) - ca - (_rotateOffset - z) * mr;
|
||||
_rotateOffset += (r - MathUtil::ceil(r * MathUtil::InvPi_2 - 0.5f) * MathUtil::Pi_2) * i;
|
||||
r = (_rotateOffset - z) * mr + ca;
|
||||
c = MathUtil::cos(r);
|
||||
s = MathUtil::sin(r);
|
||||
if (scaleX) {
|
||||
r = l * bone->getWorldScaleX();
|
||||
if (r > 0) _scaleOffset += (dx * c + dy * s) * i / r;
|
||||
}
|
||||
} else {
|
||||
c = MathUtil::cos(ca);
|
||||
s = MathUtil::sin(ca);
|
||||
float r = l * bone->getWorldScaleX() - _scaleLag * MathUtil::max(0.0f, 1 - aa / t);
|
||||
if (r > 0) _scaleOffset += (dx * c + dy * s) * i / r;
|
||||
}
|
||||
a = _remaining;
|
||||
if (a >= t) {
|
||||
if (d == -1) {
|
||||
d = MathUtil::pow(p._damping, 60 * t);
|
||||
m = t * p._massInverse;
|
||||
e = p._strength;
|
||||
}
|
||||
float ax = p._wind * skeleton._windX + p._gravity * skeleton._gravityX;
|
||||
float ay = p._wind * skeleton._windY + p._gravity * skeleton._gravityY;
|
||||
float rs = _rotateOffset, ss = _scaleOffset, h = l / f;
|
||||
while (true) {
|
||||
a -= t;
|
||||
if (scaleX) {
|
||||
_scaleVelocity += (ax * c - ay * s - _scaleOffset * e) * m;
|
||||
_scaleOffset += _scaleVelocity * t;
|
||||
_scaleVelocity *= d;
|
||||
}
|
||||
if (rotateOrShearX) {
|
||||
_rotateVelocity -= ((ax * s + ay * c) * h + _rotateOffset * e) * m;
|
||||
_rotateOffset += _rotateVelocity * t;
|
||||
_rotateVelocity *= d;
|
||||
if (a < t) break;
|
||||
float r = _rotateOffset * mr + ca;
|
||||
c = MathUtil::cos(r);
|
||||
s = MathUtil::sin(r);
|
||||
} else if (a < t)
|
||||
break;
|
||||
}
|
||||
_rotateLag = _rotateOffset - rs;
|
||||
_scaleLag = _scaleOffset - ss;
|
||||
}
|
||||
z = MathUtil::max(0.0f, 1 - a / t);
|
||||
}
|
||||
_remaining = a;
|
||||
}
|
||||
_cx = bone->_worldX;
|
||||
_cy = bone->_worldY;
|
||||
break;
|
||||
}
|
||||
case Physics_Pose: {
|
||||
z = MathUtil::max(0.0f, 1 - _remaining / t);
|
||||
if (x) bone->_worldX += (_xOffset - _xLag * z) * mix * _data._x;
|
||||
if (y) bone->_worldY += (_yOffset - _yLag * z) * mix * _data._y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rotateOrShearX) {
|
||||
float o = (_rotateOffset - _rotateLag * z) * mix, s, c, a;
|
||||
if (_data._shearX > 0) {
|
||||
float r = 0;
|
||||
if (_data._rotate > 0) {
|
||||
r = o * _data._rotate;
|
||||
s = MathUtil::sin(r);
|
||||
c = MathUtil::cos(r);
|
||||
a = bone->_b;
|
||||
bone->_b = c * a - s * bone->_d;
|
||||
bone->_d = s * a + c * bone->_d;
|
||||
}
|
||||
r += o * _data._shearX;
|
||||
s = MathUtil::sin(r);
|
||||
c = MathUtil::cos(r);
|
||||
a = bone->_a;
|
||||
bone->_a = c * a - s * bone->_c;
|
||||
bone->_c = s * a + c * bone->_c;
|
||||
} else {
|
||||
o *= _data._rotate;
|
||||
s = MathUtil::sin(o);
|
||||
c = MathUtil::cos(o);
|
||||
a = bone->_a;
|
||||
bone->_a = c * a - s * bone->_c;
|
||||
bone->_c = s * a + c * bone->_c;
|
||||
a = bone->_b;
|
||||
bone->_b = c * a - s * bone->_d;
|
||||
bone->_d = s * a + c * bone->_d;
|
||||
}
|
||||
}
|
||||
if (scaleX) {
|
||||
float s = 1 + (_scaleOffset - _scaleLag * z) * mix * _data._scaleX;
|
||||
bone->_a *= s;
|
||||
bone->_c *= s;
|
||||
}
|
||||
if (physics != Physics_Pose) {
|
||||
_tx = l * bone->_a;
|
||||
_ty = l * bone->_c;
|
||||
}
|
||||
bone->modifyWorld(skeleton._update);
|
||||
}
|
||||
|
||||
void PhysicsConstraint::sort(Skeleton &skeleton) {
|
||||
Bone *bone = _bone->_bone;
|
||||
skeleton.sortBone(bone);
|
||||
skeleton._updateCache.add(this);
|
||||
skeleton.sortReset(bone->_children);
|
||||
skeleton.constrained(*bone);
|
||||
}
|
||||
|
||||
bool PhysicsConstraint::isSourceActive() {
|
||||
return _bone->_bone->isActive();
|
||||
}
|
||||
|
||||
BonePose &PhysicsConstraint::getBone() {
|
||||
return *_bone;
|
||||
}
|
||||
|
||||
void PhysicsConstraint::setBone(BonePose &bone) {
|
||||
_bone = &bone;
|
||||
}
|
||||
@ -1,167 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PhysicsConstraintData.h>
|
||||
#include <spine/PhysicsConstraint.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(PhysicsConstraintData, ConstraintData)
|
||||
|
||||
PhysicsConstraintData::PhysicsConstraintData(const String &name)
|
||||
: ConstraintDataGeneric<PhysicsConstraint, PhysicsConstraintPose>(name), _bone(NULL), _x(0), _y(0), _rotate(0), _scaleX(0), _shearX(0), _limit(0),
|
||||
_step(0), _inertiaGlobal(false), _strengthGlobal(false), _dampingGlobal(false), _massGlobal(false), _windGlobal(false), _gravityGlobal(false),
|
||||
_mixGlobal(false) {
|
||||
}
|
||||
|
||||
BoneData &PhysicsConstraintData::getBone() {
|
||||
return *_bone;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setBone(BoneData &bone) {
|
||||
_bone = &bone;
|
||||
}
|
||||
|
||||
float PhysicsConstraintData::getStep() {
|
||||
return _step;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setStep(float step) {
|
||||
_step = step;
|
||||
}
|
||||
|
||||
float PhysicsConstraintData::getX() {
|
||||
return _x;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setX(float x) {
|
||||
_x = x;
|
||||
}
|
||||
|
||||
float PhysicsConstraintData::getY() {
|
||||
return _y;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setY(float y) {
|
||||
_y = y;
|
||||
}
|
||||
|
||||
float PhysicsConstraintData::getRotate() {
|
||||
return _rotate;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setRotate(float rotate) {
|
||||
_rotate = rotate;
|
||||
}
|
||||
|
||||
float PhysicsConstraintData::getScaleX() {
|
||||
return _scaleX;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setScaleX(float scaleX) {
|
||||
_scaleX = scaleX;
|
||||
}
|
||||
|
||||
float PhysicsConstraintData::getShearX() {
|
||||
return _shearX;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setShearX(float shearX) {
|
||||
_shearX = shearX;
|
||||
}
|
||||
|
||||
float PhysicsConstraintData::getLimit() {
|
||||
return _limit;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setLimit(float limit) {
|
||||
_limit = limit;
|
||||
}
|
||||
|
||||
bool PhysicsConstraintData::getInertiaGlobal() {
|
||||
return _inertiaGlobal;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setInertiaGlobal(bool inertiaGlobal) {
|
||||
_inertiaGlobal = inertiaGlobal;
|
||||
}
|
||||
|
||||
bool PhysicsConstraintData::getStrengthGlobal() {
|
||||
return _strengthGlobal;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setStrengthGlobal(bool strengthGlobal) {
|
||||
_strengthGlobal = strengthGlobal;
|
||||
}
|
||||
|
||||
bool PhysicsConstraintData::getDampingGlobal() {
|
||||
return _dampingGlobal;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setDampingGlobal(bool dampingGlobal) {
|
||||
_dampingGlobal = dampingGlobal;
|
||||
}
|
||||
|
||||
bool PhysicsConstraintData::getMassGlobal() {
|
||||
return _massGlobal;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setMassGlobal(bool massGlobal) {
|
||||
_massGlobal = massGlobal;
|
||||
}
|
||||
|
||||
bool PhysicsConstraintData::getWindGlobal() {
|
||||
return _windGlobal;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setWindGlobal(bool windGlobal) {
|
||||
_windGlobal = windGlobal;
|
||||
}
|
||||
|
||||
bool PhysicsConstraintData::getGravityGlobal() {
|
||||
return _gravityGlobal;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setGravityGlobal(bool gravityGlobal) {
|
||||
_gravityGlobal = gravityGlobal;
|
||||
}
|
||||
|
||||
bool PhysicsConstraintData::getMixGlobal() {
|
||||
return _mixGlobal;
|
||||
}
|
||||
|
||||
void PhysicsConstraintData::setMixGlobal(bool mixGlobal) {
|
||||
_mixGlobal = mixGlobal;
|
||||
}
|
||||
|
||||
Constraint &PhysicsConstraintData::create(Skeleton &skeleton) {
|
||||
return *(new (__FILE__, __LINE__) PhysicsConstraint(*this, skeleton));
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PhysicsConstraintPose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
PhysicsConstraintPose::PhysicsConstraintPose()
|
||||
: Pose<PhysicsConstraintPose>(), _inertia(0), _strength(0), _damping(0), _massInverse(0), _wind(0), _gravity(0), _mix(0) {
|
||||
}
|
||||
|
||||
PhysicsConstraintPose::~PhysicsConstraintPose() {
|
||||
}
|
||||
|
||||
void PhysicsConstraintPose::set(PhysicsConstraintPose &pose) {
|
||||
_inertia = pose._inertia;
|
||||
_strength = pose._strength;
|
||||
_damping = pose._damping;
|
||||
_massInverse = pose._massInverse;
|
||||
_wind = pose._wind;
|
||||
_gravity = pose._gravity;
|
||||
_mix = pose._mix;
|
||||
}
|
||||
|
||||
float PhysicsConstraintPose::getInertia() {
|
||||
return _inertia;
|
||||
}
|
||||
|
||||
void PhysicsConstraintPose::setInertia(float inertia) {
|
||||
_inertia = inertia;
|
||||
}
|
||||
|
||||
float PhysicsConstraintPose::getStrength() {
|
||||
return _strength;
|
||||
}
|
||||
|
||||
void PhysicsConstraintPose::setStrength(float strength) {
|
||||
_strength = strength;
|
||||
}
|
||||
|
||||
float PhysicsConstraintPose::getDamping() {
|
||||
return _damping;
|
||||
}
|
||||
|
||||
void PhysicsConstraintPose::setDamping(float damping) {
|
||||
_damping = damping;
|
||||
}
|
||||
|
||||
float PhysicsConstraintPose::getMassInverse() {
|
||||
return _massInverse;
|
||||
}
|
||||
|
||||
void PhysicsConstraintPose::setMassInverse(float massInverse) {
|
||||
_massInverse = massInverse;
|
||||
}
|
||||
|
||||
float PhysicsConstraintPose::getWind() {
|
||||
return _wind;
|
||||
}
|
||||
|
||||
void PhysicsConstraintPose::setWind(float wind) {
|
||||
_wind = wind;
|
||||
}
|
||||
|
||||
float PhysicsConstraintPose::getGravity() {
|
||||
return _gravity;
|
||||
}
|
||||
|
||||
void PhysicsConstraintPose::setGravity(float gravity) {
|
||||
_gravity = gravity;
|
||||
}
|
||||
|
||||
float PhysicsConstraintPose::getMix() {
|
||||
return _mix;
|
||||
}
|
||||
|
||||
void PhysicsConstraintPose::setMix(float mix) {
|
||||
_mix = mix;
|
||||
}
|
||||
@ -1,110 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PhysicsConstraintTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/PhysicsConstraint.h>
|
||||
#include <cfloat>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_MULTI(PhysicsConstraintTimeline, CurveTimeline, ConstraintTimeline)
|
||||
RTTI_IMPL(PhysicsConstraintInertiaTimeline, PhysicsConstraintTimeline)
|
||||
RTTI_IMPL(PhysicsConstraintStrengthTimeline, PhysicsConstraintTimeline)
|
||||
RTTI_IMPL(PhysicsConstraintDampingTimeline, PhysicsConstraintTimeline)
|
||||
RTTI_IMPL(PhysicsConstraintMassTimeline, PhysicsConstraintTimeline)
|
||||
RTTI_IMPL(PhysicsConstraintWindTimeline, PhysicsConstraintTimeline)
|
||||
RTTI_IMPL(PhysicsConstraintGravityTimeline, PhysicsConstraintTimeline)
|
||||
RTTI_IMPL(PhysicsConstraintMixTimeline, PhysicsConstraintTimeline)
|
||||
RTTI_IMPL_MULTI(PhysicsConstraintResetTimeline, Timeline, ConstraintTimeline)
|
||||
|
||||
PhysicsConstraintTimeline::PhysicsConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex, Property property)
|
||||
: CurveTimeline1(frameCount, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) {
|
||||
PropertyId ids[] = {((PropertyId) property << 32) | constraintIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
void PhysicsConstraintTimeline::apply(Skeleton &skeleton, float, float time, Array<Event *> *, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(out);
|
||||
if (add && !_additive) add = false;
|
||||
if (_constraintIndex == -1) {
|
||||
float value = time >= _frames[0] ? getCurveValue(time) : 0;
|
||||
|
||||
Array<PhysicsConstraint *> &physicsConstraints = skeleton.getPhysicsConstraints();
|
||||
for (size_t i = 0; i < physicsConstraints.size(); i++) {
|
||||
PhysicsConstraint *constraint = physicsConstraints[i];
|
||||
if (constraint->isActive() && global(constraint->_data)) {
|
||||
PhysicsConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
set(pose, getAbsoluteValue(time, alpha, fromSetup, add, get(pose), get(constraint->_data._setup), value));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PhysicsConstraint *constraint = static_cast<PhysicsConstraint *>(skeleton.getConstraints()[_constraintIndex]);
|
||||
if (constraint->isActive()) {
|
||||
PhysicsConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
set(pose, getAbsoluteValue(time, alpha, fromSetup, add, get(pose), get(constraint->_data._setup)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsConstraintResetTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
PhysicsConstraint *constraint = nullptr;
|
||||
if (_constraintIndex != -1) {
|
||||
constraint = static_cast<PhysicsConstraint *>(skeleton.getConstraints()[_constraintIndex]);
|
||||
if (!constraint->isActive()) return;
|
||||
}
|
||||
|
||||
if (lastTime > time) {// Apply after lastTime for looped animations.
|
||||
apply(skeleton, lastTime, FLT_MAX, nullptr, alpha, false, false, false, false);
|
||||
lastTime = -1;
|
||||
} else if (lastTime >= _frames[_frames.size() - 1])// Last time is after last frame.
|
||||
return;
|
||||
if (time < _frames[0]) return;
|
||||
|
||||
if (lastTime < _frames[0] || time >= _frames[Animation::search(_frames, lastTime) + 1]) {
|
||||
if (constraint != nullptr)
|
||||
constraint->reset(skeleton);
|
||||
else {
|
||||
Array<PhysicsConstraint *> &physicsConstraints = skeleton.getPhysicsConstraints();
|
||||
for (size_t i = 0; i < physicsConstraints.size(); i++) {
|
||||
constraint = physicsConstraints[i];
|
||||
if (constraint->isActive()) constraint->reset(skeleton);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,90 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/PointAttachment.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
|
||||
#include <spine/MathUtil.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(PointAttachment, Attachment)
|
||||
|
||||
PointAttachment::PointAttachment(const String &name) : Attachment(name), _x(0), _y(0), _rotation(0), _color(0.9451f, 0.9451f, 0, 1) {
|
||||
}
|
||||
|
||||
float PointAttachment::getX() {
|
||||
return _x;
|
||||
}
|
||||
|
||||
void PointAttachment::setX(float inValue) {
|
||||
_x = inValue;
|
||||
}
|
||||
|
||||
float PointAttachment::getY() {
|
||||
return _y;
|
||||
}
|
||||
|
||||
void PointAttachment::setY(float inValue) {
|
||||
_y = inValue;
|
||||
}
|
||||
|
||||
float PointAttachment::getRotation() {
|
||||
return _rotation;
|
||||
}
|
||||
|
||||
void PointAttachment::setRotation(float inValue) {
|
||||
_rotation = inValue;
|
||||
}
|
||||
|
||||
Color &PointAttachment::getColor() {
|
||||
return _color;
|
||||
}
|
||||
|
||||
void PointAttachment::computeWorldPosition(BonePose &bone, float &ox, float &oy) {
|
||||
ox = _x * bone.getA() + _y * bone.getB() + bone.getWorldX();
|
||||
oy = _x * bone.getC() + _y * bone.getD() + bone.getWorldY();
|
||||
}
|
||||
|
||||
float PointAttachment::computeWorldRotation(BonePose &bone) {
|
||||
float r = _rotation * MathUtil::Deg_Rad, cosine = MathUtil::cos(r), sine = MathUtil::sin(r);
|
||||
float x = cosine * bone.getA() + sine * bone.getB();
|
||||
float y = cosine * bone.getC() + sine * bone.getD();
|
||||
return MathUtil::atan2Deg(y, x);
|
||||
}
|
||||
|
||||
Attachment &PointAttachment::copy() {
|
||||
PointAttachment *copy = new (__FILE__, __LINE__) PointAttachment(getName());
|
||||
copy->_x = _x;
|
||||
copy->_y = _y;
|
||||
copy->_rotation = _rotation;
|
||||
copy->_color.set(_color);
|
||||
return *copy;
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/RTTI.h>
|
||||
#include <spine/SpineString.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI::RTTI(const char *className) : _className(className), _pBaseRTTI(NULL), _interfaceCount(0) {
|
||||
_interfaces[0] = NULL;
|
||||
_interfaces[1] = NULL;
|
||||
_interfaces[2] = NULL;
|
||||
}
|
||||
|
||||
RTTI::RTTI(const char *className, const RTTI &baseRTTI) : _className(className), _pBaseRTTI(&baseRTTI), _interfaceCount(0) {
|
||||
_interfaces[0] = NULL;
|
||||
_interfaces[1] = NULL;
|
||||
_interfaces[2] = NULL;
|
||||
}
|
||||
|
||||
RTTI::RTTI(const char *className, const RTTI &baseRTTI, const RTTI *interface1, const RTTI *interface2, const RTTI *interface3)
|
||||
: _className(className), _pBaseRTTI(&baseRTTI), _interfaceCount(0) {
|
||||
_interfaces[0] = interface1;
|
||||
_interfaces[1] = interface2;
|
||||
_interfaces[2] = interface3;
|
||||
|
||||
if (interface1) _interfaceCount++;
|
||||
if (interface2) _interfaceCount++;
|
||||
if (interface3) _interfaceCount++;
|
||||
}
|
||||
|
||||
const char *RTTI::getClassName() const {
|
||||
return _className;
|
||||
}
|
||||
|
||||
bool RTTI::isExactly(const RTTI &rtti) const {
|
||||
return !strcmp(this->_className, rtti._className);
|
||||
}
|
||||
|
||||
bool RTTI::instanceOf(const RTTI &rtti) const {
|
||||
// Check the main inheritance chain
|
||||
const RTTI *pCompare = this;
|
||||
while (pCompare) {
|
||||
if (!strcmp(pCompare->_className, rtti._className)) return true;
|
||||
|
||||
// Check interfaces at this level of the hierarchy
|
||||
for (int i = 0; i < pCompare->_interfaceCount; i++) {
|
||||
if (pCompare->_interfaces[i] && !strcmp(pCompare->_interfaces[i]->_className, rtti._className)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
pCompare = pCompare->_pBaseRTTI;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -1,257 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/RegionAttachment.h>
|
||||
|
||||
#include <spine/Atlas.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/MathUtil.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotPose.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(RegionAttachment, Attachment)
|
||||
|
||||
const int RegionAttachment::BLX = 0;
|
||||
const int RegionAttachment::BLY = 1;
|
||||
const int RegionAttachment::ULX = 2;
|
||||
const int RegionAttachment::ULY = 3;
|
||||
const int RegionAttachment::URX = 4;
|
||||
const int RegionAttachment::URY = 5;
|
||||
const int RegionAttachment::BRX = 6;
|
||||
const int RegionAttachment::BRY = 7;
|
||||
|
||||
RegionAttachment::RegionAttachment(const String &name, Sequence *sequence)
|
||||
: Attachment(name), _sequence(sequence), _x(0), _y(0), _scaleX(1), _scaleY(1), _rotation(0), _width(0), _height(0), _path(), _color(1, 1, 1, 1) {
|
||||
assert(sequence);
|
||||
}
|
||||
|
||||
RegionAttachment::~RegionAttachment() {
|
||||
delete _sequence;
|
||||
}
|
||||
|
||||
void RegionAttachment::computeWorldVertices(Slot &slot, Array<float> &vertexOffsets, Array<float> &worldVertices, size_t offset, size_t stride) {
|
||||
assert(worldVertices.size() >= (offset + 8));
|
||||
computeWorldVertices(slot, vertexOffsets.buffer(), worldVertices.buffer(), offset, stride);
|
||||
}
|
||||
|
||||
void RegionAttachment::computeWorldVertices(Slot &slot, float *vertexOffsets, float *worldVertices, size_t offset, size_t stride) {
|
||||
BonePose &bone = slot.getBone().getAppliedPose();
|
||||
float x = bone.getWorldX(), y = bone.getWorldY();
|
||||
float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD();
|
||||
|
||||
float offsetX = vertexOffsets[BRX];
|
||||
float offsetY = vertexOffsets[BRY];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x;
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
offset += stride;
|
||||
|
||||
offsetX = vertexOffsets[BLX];
|
||||
offsetY = vertexOffsets[BLY];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x;
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
offset += stride;
|
||||
|
||||
offsetX = vertexOffsets[ULX];
|
||||
offsetY = vertexOffsets[ULY];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x;
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
offset += stride;
|
||||
|
||||
offsetX = vertexOffsets[URX];
|
||||
offsetY = vertexOffsets[URY];
|
||||
worldVertices[offset] = offsetX * a + offsetY * b + x;
|
||||
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
||||
}
|
||||
|
||||
Array<float> &RegionAttachment::getOffsets(SlotPose &pose) {
|
||||
return _sequence->getOffsets(_sequence->resolveIndex(pose));
|
||||
}
|
||||
|
||||
float RegionAttachment::getX() {
|
||||
return _x;
|
||||
}
|
||||
|
||||
void RegionAttachment::setX(float inValue) {
|
||||
_x = inValue;
|
||||
}
|
||||
|
||||
float RegionAttachment::getY() {
|
||||
return _y;
|
||||
}
|
||||
|
||||
void RegionAttachment::setY(float inValue) {
|
||||
_y = inValue;
|
||||
}
|
||||
|
||||
float RegionAttachment::getScaleX() {
|
||||
return _scaleX;
|
||||
}
|
||||
|
||||
void RegionAttachment::setScaleX(float inValue) {
|
||||
_scaleX = inValue;
|
||||
}
|
||||
|
||||
float RegionAttachment::getScaleY() {
|
||||
return _scaleY;
|
||||
}
|
||||
|
||||
void RegionAttachment::setScaleY(float inValue) {
|
||||
_scaleY = inValue;
|
||||
}
|
||||
|
||||
float RegionAttachment::getRotation() {
|
||||
return _rotation;
|
||||
}
|
||||
|
||||
void RegionAttachment::setRotation(float inValue) {
|
||||
_rotation = inValue;
|
||||
}
|
||||
|
||||
float RegionAttachment::getWidth() {
|
||||
return _width;
|
||||
}
|
||||
|
||||
void RegionAttachment::setWidth(float inValue) {
|
||||
_width = inValue;
|
||||
}
|
||||
|
||||
float RegionAttachment::getHeight() {
|
||||
return _height;
|
||||
}
|
||||
|
||||
void RegionAttachment::setHeight(float inValue) {
|
||||
_height = inValue;
|
||||
}
|
||||
|
||||
Sequence &RegionAttachment::getSequence() {
|
||||
return *_sequence;
|
||||
}
|
||||
|
||||
void RegionAttachment::updateSequence() {
|
||||
_sequence->update(*this);
|
||||
}
|
||||
|
||||
const String &RegionAttachment::getPath() {
|
||||
return _path;
|
||||
}
|
||||
|
||||
void RegionAttachment::setPath(const String &inValue) {
|
||||
_path = inValue;
|
||||
}
|
||||
|
||||
Color &RegionAttachment::getColor() {
|
||||
return _color;
|
||||
}
|
||||
|
||||
Attachment &RegionAttachment::copy() {
|
||||
RegionAttachment *copy = new (__FILE__, __LINE__) RegionAttachment(getName(), new (__FILE__, __LINE__) Sequence(*_sequence));
|
||||
copy->setTimelineAttachment(getTimelineAttachment());
|
||||
copy->_path = _path;
|
||||
copy->_x = _x;
|
||||
copy->_y = _y;
|
||||
copy->_scaleX = _scaleX;
|
||||
copy->_scaleY = _scaleY;
|
||||
copy->_rotation = _rotation;
|
||||
copy->_width = _width;
|
||||
copy->_height = _height;
|
||||
copy->_color.set(_color);
|
||||
return *copy;
|
||||
}
|
||||
|
||||
void RegionAttachment::computeUVs(TextureRegion *region, float x, float y, float scaleX, float scaleY, float rotation, float width, float height,
|
||||
Array<float> &offset, Array<float> &uvs) {
|
||||
float localX2 = width / 2, localY2 = height / 2;
|
||||
float localX = -localX2, localY = -localY2;
|
||||
bool rotated = false;
|
||||
if (region != NULL && region->getRTTI().instanceOf(AtlasRegion::rtti)) {
|
||||
AtlasRegion *r = static_cast<AtlasRegion *>(region);
|
||||
localX += r->_offsetX / r->_originalWidth * width;
|
||||
localY += r->_offsetY / r->_originalHeight * height;
|
||||
if (r->_degrees == 90) {
|
||||
rotated = true;
|
||||
localX2 -= (r->_originalWidth - r->_offsetX - r->_packedHeight) / r->_originalWidth * width;
|
||||
localY2 -= (r->_originalHeight - r->_offsetY - r->_packedWidth) / r->_originalHeight * height;
|
||||
} else {
|
||||
localX2 -= (r->_originalWidth - r->_offsetX - r->_packedWidth) / r->_originalWidth * width;
|
||||
localY2 -= (r->_originalHeight - r->_offsetY - r->_packedHeight) / r->_originalHeight * height;
|
||||
}
|
||||
}
|
||||
localX *= scaleX;
|
||||
localY *= scaleY;
|
||||
localX2 *= scaleX;
|
||||
localY2 *= scaleY;
|
||||
float cos = MathUtil::cosDeg(rotation);
|
||||
float sin = MathUtil::sinDeg(rotation);
|
||||
float localXCos = localX * cos + x;
|
||||
float localXSin = localX * sin;
|
||||
float localYCos = localY * cos + y;
|
||||
float localYSin = localY * sin;
|
||||
float localX2Cos = localX2 * cos + x;
|
||||
float localX2Sin = localX2 * sin;
|
||||
float localY2Cos = localY2 * cos + y;
|
||||
float localY2Sin = localY2 * sin;
|
||||
offset[BLX] = localXCos - localYSin;
|
||||
offset[BLY] = localYCos + localXSin;
|
||||
offset[ULX] = localXCos - localY2Sin;
|
||||
offset[ULY] = localY2Cos + localXSin;
|
||||
offset[URX] = localX2Cos - localY2Sin;
|
||||
offset[URY] = localY2Cos + localX2Sin;
|
||||
offset[BRX] = localX2Cos - localYSin;
|
||||
offset[BRY] = localYCos + localX2Sin;
|
||||
if (region == NULL) {
|
||||
uvs[BLX] = 0;
|
||||
uvs[BLY] = 0;
|
||||
uvs[ULX] = 0;
|
||||
uvs[ULY] = 1;
|
||||
uvs[URX] = 1;
|
||||
uvs[URY] = 1;
|
||||
uvs[BRX] = 1;
|
||||
uvs[BRY] = 0;
|
||||
} else {
|
||||
uvs[BLX] = region->_u2;
|
||||
uvs[ULY] = region->_v2;
|
||||
uvs[URX] = region->_u;
|
||||
uvs[BRY] = region->_v;
|
||||
if (rotated) {
|
||||
uvs[BLY] = region->_v;
|
||||
uvs[ULX] = region->_u2;
|
||||
uvs[URY] = region->_v2;
|
||||
uvs[BRX] = region->_u;
|
||||
} else {
|
||||
uvs[BLY] = region->_v2;
|
||||
uvs[ULX] = region->_u;
|
||||
uvs[URY] = region->_v;
|
||||
uvs[BRX] = region->_u2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/RotateTimeline.h>
|
||||
|
||||
#include <spine/BoneLocal.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(RotateTimeline, BoneTimeline1)
|
||||
|
||||
RotateTimeline::RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex)
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Rotate) {
|
||||
}
|
||||
|
||||
void RotateTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
SP_UNUSED(out);
|
||||
pose._rotation = getRelativeValue(time, alpha, fromSetup, add, pose._rotation, setup._rotation);
|
||||
}
|
||||
@ -1,129 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/ScaleTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Animation.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(ScaleTimeline, BoneTimeline2)
|
||||
|
||||
ScaleTimeline::ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex)
|
||||
: BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ScaleX, Property_ScaleY) {
|
||||
}
|
||||
|
||||
void ScaleTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) {
|
||||
pose._scaleX = setup._scaleX;
|
||||
pose._scaleY = setup._scaleY;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float x, y;
|
||||
int i = Animation::search(_frames, time, BoneTimeline2::ENTRIES);
|
||||
int curveType = (int) _curves[i / BoneTimeline2::ENTRIES];
|
||||
switch (curveType) {
|
||||
case CurveTimeline::LINEAR: {
|
||||
float before = _frames[i];
|
||||
x = _frames[i + BoneTimeline2::VALUE1];
|
||||
y = _frames[i + BoneTimeline2::VALUE2];
|
||||
float t = (time - before) / (_frames[i + BoneTimeline2::ENTRIES] - before);
|
||||
x += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE1] - x) * t;
|
||||
y += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE2] - y) * t;
|
||||
break;
|
||||
}
|
||||
case CurveTimeline::STEPPED: {
|
||||
x = _frames[i + BoneTimeline2::VALUE1];
|
||||
y = _frames[i + BoneTimeline2::VALUE2];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
x = getBezierValue(time, i, BoneTimeline2::VALUE1, curveType - BoneTimeline2::BEZIER);
|
||||
y = getBezierValue(time, i, BoneTimeline2::VALUE2, curveType + BoneTimeline2::BEZIER_SIZE - BoneTimeline2::BEZIER);
|
||||
}
|
||||
}
|
||||
x *= setup._scaleX;
|
||||
y *= setup._scaleY;
|
||||
|
||||
if (alpha == 1 && !add) {
|
||||
pose._scaleX = x;
|
||||
pose._scaleY = y;
|
||||
} else {
|
||||
float bx, by;
|
||||
if (fromSetup) {
|
||||
bx = setup._scaleX;
|
||||
by = setup._scaleY;
|
||||
} else {
|
||||
bx = pose._scaleX;
|
||||
by = pose._scaleY;
|
||||
}
|
||||
if (add) {
|
||||
pose._scaleX = bx + (x - setup._scaleX) * alpha;
|
||||
pose._scaleY = by + (y - setup._scaleY) * alpha;
|
||||
} else if (out) {
|
||||
pose._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
|
||||
pose._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
|
||||
} else {
|
||||
bx = MathUtil::abs(bx) * MathUtil::sign(x);
|
||||
by = MathUtil::abs(by) * MathUtil::sign(y);
|
||||
pose._scaleX = bx + (x - bx) * alpha;
|
||||
pose._scaleY = by + (y - by) * alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RTTI_IMPL(ScaleXTimeline, BoneTimeline1)
|
||||
|
||||
ScaleXTimeline::ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex)
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleX) {
|
||||
}
|
||||
|
||||
void ScaleXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
pose._scaleX = getScaleValue(time, alpha, fromSetup, add, out, pose._scaleX, setup._scaleX);
|
||||
}
|
||||
|
||||
RTTI_IMPL(ScaleYTimeline, BoneTimeline1)
|
||||
|
||||
ScaleYTimeline::ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex)
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleY) {
|
||||
}
|
||||
|
||||
void ScaleYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
pose._scaleY = getScaleValue(time, alpha, fromSetup, add, out, pose._scaleY, setup._scaleY);
|
||||
}
|
||||
@ -1,110 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Sequence.h>
|
||||
#include <spine/MeshAttachment.h>
|
||||
#include <spine/RegionAttachment.h>
|
||||
#include <spine/SlotPose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
int Sequence::_nextID = 0;
|
||||
|
||||
Sequence::Sequence(int count, bool pathSuffix)
|
||||
: _id(nextID()), _regions(count), _pathSuffix(pathSuffix), _uvs(), _offsets(), _start(0), _digits(0), _setupIndex(0) {
|
||||
_regions.setSize(count, NULL);
|
||||
}
|
||||
|
||||
Sequence::Sequence(const Sequence &other)
|
||||
: _id(nextID()), _regions(other._regions), _pathSuffix(other._pathSuffix), _uvs(other._uvs), _offsets(other._offsets), _start(other._start),
|
||||
_digits(other._digits), _setupIndex(other._setupIndex) {
|
||||
}
|
||||
|
||||
Sequence::~Sequence() {
|
||||
}
|
||||
|
||||
void Sequence::update(RegionAttachment &attachment) {
|
||||
int regionCount = (int) _regions.size();
|
||||
Array<float> empty;
|
||||
_uvs.setSize(regionCount, empty);
|
||||
_offsets.setSize(regionCount, empty);
|
||||
for (int i = 0; i < regionCount; i++) {
|
||||
_uvs[i].setSize(8, 0);
|
||||
_offsets[i].setSize(8, 0);
|
||||
RegionAttachment::computeUVs(_regions[i], attachment.getX(), attachment.getY(), attachment.getScaleX(), attachment.getScaleY(),
|
||||
attachment.getRotation(), attachment.getWidth(), attachment.getHeight(), _offsets[i], _uvs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Sequence::update(MeshAttachment &attachment) {
|
||||
int regionCount = (int) _regions.size();
|
||||
Array<float> empty;
|
||||
_uvs.setSize(regionCount, empty);
|
||||
_offsets.clear();
|
||||
for (int i = 0; i < regionCount; i++) {
|
||||
_uvs[i].setSize(attachment.getRegionUVs().size(), 0);
|
||||
MeshAttachment::computeUVs(_regions[i], attachment.getRegionUVs(), _uvs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int Sequence::resolveIndex(SlotPose &pose) {
|
||||
int index = pose.getSequenceIndex();
|
||||
if (index == -1) index = _setupIndex;
|
||||
if (index >= (int) _regions.size()) index = (int) _regions.size() - 1;
|
||||
return index;
|
||||
}
|
||||
|
||||
TextureRegion *Sequence::getRegion(int index) {
|
||||
return _regions[index];
|
||||
}
|
||||
|
||||
Array<float> &Sequence::getUVs(int index) {
|
||||
return _uvs[index];
|
||||
}
|
||||
|
||||
Array<float> &Sequence::getOffsets(int index) {
|
||||
return _offsets[index];
|
||||
}
|
||||
|
||||
String &Sequence::getPath(const String &basePath, int index) {
|
||||
if (!_pathSuffix) {
|
||||
_tmpPath = basePath;
|
||||
return _tmpPath;
|
||||
}
|
||||
_tmpPath = basePath;
|
||||
String frame;
|
||||
frame.append(_start + index);
|
||||
for (int i = _digits - (int) frame.length(); i > 0; i--) _tmpPath.append("0");
|
||||
_tmpPath.append(frame);
|
||||
return _tmpPath;
|
||||
}
|
||||
|
||||
int Sequence::nextID() {
|
||||
return _nextID++;
|
||||
}
|
||||
@ -1,143 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SequenceTimeline.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/RegionAttachment.h>
|
||||
#include <spine/MeshAttachment.h>
|
||||
#include <spine/VertexAttachment.h>
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Attachment.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/MathUtil.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_MULTI(SequenceTimeline, Timeline, SlotTimeline)
|
||||
|
||||
SequenceTimeline::SequenceTimeline(size_t frameCount, int slotIndex, Attachment &attachment)
|
||||
: Timeline(frameCount, ENTRIES), SlotTimeline(), _slotIndex(slotIndex), _attachment((HasTextureRegion *) &attachment) {
|
||||
_instant = true;
|
||||
int sequenceId = 0;
|
||||
if (attachment.getRTTI().instanceOf(RegionAttachment::rtti)) sequenceId = ((RegionAttachment *) &attachment)->getSequence().getId();
|
||||
if (attachment.getRTTI().instanceOf(MeshAttachment::rtti)) sequenceId = ((MeshAttachment *) &attachment)->getSequence().getId();
|
||||
PropertyId ids[] = {((PropertyId) Property_Sequence << 32) | ((slotIndex << 16 | sequenceId) & 0xffffffff)};
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
SequenceTimeline::~SequenceTimeline() {
|
||||
}
|
||||
|
||||
void SequenceTimeline::setFrame(int frame, float time, SequenceMode mode, int index, float delay) {
|
||||
Array<float> &frames = this->_frames;
|
||||
frame *= ENTRIES;
|
||||
frames[frame] = time;
|
||||
frames[frame + MODE] = mode | (index << 4);
|
||||
frames[frame + DELAY] = delay;
|
||||
}
|
||||
|
||||
int SequenceTimeline::getSlotIndex() {
|
||||
return _slotIndex;
|
||||
}
|
||||
|
||||
void SequenceTimeline::setSlotIndex(int inValue) {
|
||||
_slotIndex = inValue;
|
||||
}
|
||||
|
||||
void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(alpha);
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(add);
|
||||
|
||||
Slot *slot = skeleton.getSlots()[getSlotIndex()];
|
||||
if (!slot->getBone().isActive()) return;
|
||||
SlotPose &pose = appliedPose ? slot->getAppliedPose() : slot->getPose();
|
||||
|
||||
Attachment *slotAttachment = pose.getAttachment();
|
||||
if (slotAttachment != (Attachment *) _attachment) {
|
||||
if (slotAttachment == NULL || slotAttachment->getTimelineAttachment() != (Attachment *) _attachment) return;
|
||||
}
|
||||
Sequence *sequence = NULL;
|
||||
if (((Attachment *) _attachment)->getRTTI().instanceOf(RegionAttachment::rtti)) sequence = &((RegionAttachment *) _attachment)->getSequence();
|
||||
if (((Attachment *) _attachment)->getRTTI().instanceOf(MeshAttachment::rtti)) sequence = &((MeshAttachment *) _attachment)->getSequence();
|
||||
if (!sequence) return;
|
||||
|
||||
if (out) {
|
||||
if (fromSetup) pose.setSequenceIndex(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
Array<float> &frames = this->_frames;
|
||||
if (time < frames[0]) {
|
||||
if (fromSetup) pose.setSequenceIndex(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
int i = Animation::search(frames, time, ENTRIES);
|
||||
float before = frames[i];
|
||||
int modeAndIndex = (int) frames[i + MODE];
|
||||
float delay = frames[i + DELAY];
|
||||
|
||||
int index = modeAndIndex >> 4, count = (int) sequence->getRegions().size();
|
||||
int mode = modeAndIndex & 0xf;
|
||||
if (mode != SequenceMode_hold) {
|
||||
index += (int) (((time - before) / delay + 0.0001));
|
||||
switch (mode) {
|
||||
case SequenceMode_once:
|
||||
index = MathUtil::min(count - 1, index);
|
||||
break;
|
||||
case SequenceMode_loop:
|
||||
index %= count;
|
||||
break;
|
||||
case SequenceMode_pingpong: {
|
||||
int n = (count << 1) - 2;
|
||||
index = n == 0 ? 0 : index % n;
|
||||
if (index >= count) index = n - index;
|
||||
break;
|
||||
}
|
||||
case SequenceMode_onceReverse:
|
||||
index = MathUtil::max(count - 1 - index, 0);
|
||||
break;
|
||||
case SequenceMode_loopReverse:
|
||||
index = count - 1 - (index % count);
|
||||
break;
|
||||
case SequenceMode_pingpongReverse: {
|
||||
int n = (count << 1) - 2;
|
||||
index = n == 0 ? 0 : (index + count - 1) % n;
|
||||
if (index >= count) index = n - index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pose.setSequenceIndex(index);
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/ShearTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Animation.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(ShearTimeline, BoneTimeline2)
|
||||
|
||||
ShearTimeline::ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex)
|
||||
: BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ShearX, Property_ShearY) {
|
||||
}
|
||||
|
||||
void ShearTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
SP_UNUSED(out);
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) {
|
||||
pose._shearX = setup._shearX;
|
||||
pose._shearY = setup._shearY;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float x, y;
|
||||
int i = Animation::search(_frames, time, BoneTimeline2::ENTRIES);
|
||||
int curveType = (int) _curves[i / BoneTimeline2::ENTRIES];
|
||||
switch (curveType) {
|
||||
case CurveTimeline::LINEAR: {
|
||||
float before = _frames[i];
|
||||
x = _frames[i + BoneTimeline2::VALUE1];
|
||||
y = _frames[i + BoneTimeline2::VALUE2];
|
||||
float t = (time - before) / (_frames[i + BoneTimeline2::ENTRIES] - before);
|
||||
x += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE1] - x) * t;
|
||||
y += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE2] - y) * t;
|
||||
break;
|
||||
}
|
||||
case CurveTimeline::STEPPED: {
|
||||
x = _frames[i + BoneTimeline2::VALUE1];
|
||||
y = _frames[i + BoneTimeline2::VALUE2];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
x = getBezierValue(time, i, BoneTimeline2::VALUE1, curveType - BoneTimeline2::BEZIER);
|
||||
y = getBezierValue(time, i, BoneTimeline2::VALUE2, curveType + BoneTimeline2::BEZIER_SIZE - BoneTimeline2::BEZIER);
|
||||
}
|
||||
}
|
||||
|
||||
if (fromSetup) {
|
||||
pose._shearX = setup._shearX + x * alpha;
|
||||
pose._shearY = setup._shearY + y * alpha;
|
||||
} else if (add) {
|
||||
pose._shearX += x * alpha;
|
||||
pose._shearY += y * alpha;
|
||||
} else {
|
||||
pose._shearX += (setup._shearX + x - pose._shearX) * alpha;
|
||||
pose._shearY += (setup._shearY + y - pose._shearY) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
RTTI_IMPL(ShearXTimeline, BoneTimeline1)
|
||||
|
||||
ShearXTimeline::ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex)
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearX) {
|
||||
}
|
||||
|
||||
void ShearXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
SP_UNUSED(out);
|
||||
pose._shearX = getRelativeValue(time, alpha, fromSetup, add, pose._shearX, setup._shearX);
|
||||
}
|
||||
|
||||
RTTI_IMPL(ShearYTimeline, BoneTimeline1)
|
||||
|
||||
ShearYTimeline::ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex)
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearY) {
|
||||
}
|
||||
|
||||
void ShearYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
SP_UNUSED(out);
|
||||
pose._shearY = getRelativeValue(time, alpha, fromSetup, add, pose._shearY, setup._shearY);
|
||||
}
|
||||
@ -1,553 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Skeleton.h>
|
||||
|
||||
#include <spine/Attachment.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BonePose.h>
|
||||
#include <spine/IkConstraint.h>
|
||||
#include <spine/PathConstraint.h>
|
||||
#include <spine/PhysicsConstraint.h>
|
||||
#include <spine/SkeletonData.h>
|
||||
#include <spine/Skin.h>
|
||||
#include <spine/Slider.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/TransformConstraint.h>
|
||||
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/ClippingAttachment.h>
|
||||
#include <spine/IkConstraintData.h>
|
||||
#include <spine/MeshAttachment.h>
|
||||
#include <spine/PathAttachment.h>
|
||||
#include <spine/PathConstraintData.h>
|
||||
#include <spine/PhysicsConstraintData.h>
|
||||
#include <spine/RegionAttachment.h>
|
||||
#include <spine/SkeletonClipping.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/TransformConstraintData.h>
|
||||
|
||||
#include <spine/ArrayUtils.h>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
Skeleton::Skeleton(SkeletonData &skeletonData)
|
||||
: _data(skeletonData), _skin(NULL), _color(1, 1, 1, 1), _x(0), _y(0), _scaleX(1), _scaleY(1), _windX(1), _windY(0), _gravityX(0), _gravityY(1),
|
||||
_time(0), _update(0) {
|
||||
|
||||
_bones.ensureCapacity(_data.getBones().size());
|
||||
for (size_t i = 0; i < _data.getBones().size(); ++i) {
|
||||
BoneData *data = _data.getBones()[i];
|
||||
|
||||
Bone *bone;
|
||||
if (data->getParent() == NULL) {
|
||||
bone = new (__FILE__, __LINE__) Bone(*data, NULL);
|
||||
} else {
|
||||
Bone *parent = _bones[data->getParent()->getIndex()];
|
||||
bone = new (__FILE__, __LINE__) Bone(*data, parent);
|
||||
parent->getChildren().add(bone);
|
||||
}
|
||||
|
||||
_bones.add(bone);
|
||||
}
|
||||
|
||||
_slots.ensureCapacity(_data.getSlots().size());
|
||||
_drawOrder.ensureCapacity(_data.getSlots().size());
|
||||
for (size_t i = 0; i < _data.getSlots().size(); ++i) {
|
||||
SlotData *data = _data.getSlots()[i];
|
||||
Slot *slot = new (__FILE__, __LINE__) Slot(*data, *this);
|
||||
_slots.add(slot);
|
||||
_drawOrder.add(slot);
|
||||
}
|
||||
|
||||
_physics.ensureCapacity(8);
|
||||
_constraints.ensureCapacity(_data.getConstraints().size());
|
||||
for (size_t i = 0; i < _data.getConstraints().size(); ++i) {
|
||||
ConstraintData *constraintData = _data.getConstraints()[i];
|
||||
Constraint *constraint = &constraintData->create(*this);
|
||||
if (constraint->getRTTI().instanceOf(PhysicsConstraint::rtti)) {
|
||||
_physics.add(static_cast<PhysicsConstraint *>(constraint));
|
||||
}
|
||||
_constraints.add(constraint);
|
||||
}
|
||||
|
||||
updateCache();
|
||||
}
|
||||
|
||||
Skeleton::~Skeleton() {
|
||||
ArrayUtils::deleteElements(_bones);
|
||||
ArrayUtils::deleteElements(_slots);
|
||||
ArrayUtils::deleteElements(_constraints);
|
||||
}
|
||||
|
||||
void Skeleton::updateCache() {
|
||||
_updateCache.clear();
|
||||
_resetCache.clear();
|
||||
|
||||
Slot **slots = _slots.buffer();
|
||||
for (size_t i = 0, n = _slots.size(); i < n; i++) {
|
||||
slots[i]->pose();
|
||||
}
|
||||
|
||||
size_t boneCount = _bones.size();
|
||||
Bone **bones = _bones.buffer();
|
||||
for (size_t i = 0; i < boneCount; i++) {
|
||||
Bone *bone = bones[i];
|
||||
bone->_sorted = bone->_data.getSkinRequired();
|
||||
bone->_active = !bone->_sorted;
|
||||
bone->pose();
|
||||
}
|
||||
|
||||
if (_skin) {
|
||||
Array<BoneData *> &skinBones = _skin->getBones();
|
||||
for (size_t i = 0, n = skinBones.size(); i < n; i++) {
|
||||
Bone *bone = _bones[skinBones[i]->getIndex()];
|
||||
do {
|
||||
bone->_sorted = false;
|
||||
bone->_active = true;
|
||||
bone = bone->_parent;
|
||||
} while (bone);
|
||||
}
|
||||
}
|
||||
|
||||
Constraint **constraints = _constraints.buffer();
|
||||
size_t n = _constraints.size();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
constraints[i]->pose();
|
||||
}
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
Constraint *constraint = constraints[i];
|
||||
constraint->_active = constraint->isSourceActive() &&
|
||||
((!constraint->getData().getSkinRequired()) || (_skin && _skin->_constraints.contains(&constraint->getData())));
|
||||
if (constraint->_active) constraint->sort(*this);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < boneCount; i++) {
|
||||
sortBone(bones[i]);
|
||||
}
|
||||
|
||||
Update **updateCache = _updateCache.buffer();
|
||||
n = _updateCache.size();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
const RTTI &rtti = updateCache[i]->getRTTI();
|
||||
if (rtti.instanceOf(Bone::rtti)) {
|
||||
Bone *bone = (Bone *) (updateCache[i]);
|
||||
updateCache[i] = bone->_applied;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::printUpdateCache() {
|
||||
for (size_t i = 0; i < _updateCache.size(); i++) {
|
||||
Update *updatable = _updateCache[i];
|
||||
if (updatable->getRTTI().isExactly(Bone::rtti)) {
|
||||
printf("bone %s\n", ((Bone *) updatable)->getData().getName().buffer());
|
||||
} else if (updatable->getRTTI().isExactly(TransformConstraint::rtti)) {
|
||||
printf("transform constraint %s\n", ((TransformConstraint *) updatable)->getData().getName().buffer());
|
||||
} else if (updatable->getRTTI().isExactly(IkConstraint::rtti)) {
|
||||
printf("ik constraint %s\n", ((IkConstraint *) updatable)->getData().getName().buffer());
|
||||
} else if (updatable->getRTTI().isExactly(PathConstraint::rtti)) {
|
||||
printf("path constraint %s\n", ((PathConstraint *) updatable)->getData().getName().buffer());
|
||||
} else if (updatable->getRTTI().isExactly(PhysicsConstraint::rtti)) {
|
||||
printf("physics constraint %s\n", ((PhysicsConstraint *) updatable)->getData().getName().buffer());
|
||||
} else if (updatable->getRTTI().isExactly(Slider::rtti)) {
|
||||
printf("slider %s\n", ((Slider *) updatable)->getData().getName().buffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::constrained(Posed &object) {
|
||||
if (object.isPoseEqualToApplied()) {
|
||||
object.constrained();
|
||||
_resetCache.add(&object);
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::sortBone(Bone *bone) {
|
||||
if (bone->_sorted || !bone->_active) return;
|
||||
Bone *parent = bone->_parent;
|
||||
if (parent != NULL) sortBone(parent);
|
||||
bone->_sorted = true;
|
||||
_updateCache.add((Update *) bone);
|
||||
}
|
||||
|
||||
void Skeleton::sortReset(Array<Bone *> &bones) {
|
||||
Bone **items = bones.buffer();
|
||||
for (size_t i = 0, n = bones.size(); i < n; i++) {
|
||||
Bone *bone = items[i];
|
||||
if (bone->_active) {
|
||||
if (bone->_sorted) sortReset(bone->getChildren());
|
||||
bone->_sorted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::updateWorldTransform(Physics physics) {
|
||||
_update++;
|
||||
|
||||
Posed **resetCache = _resetCache.buffer();
|
||||
for (size_t i = 0, n = _resetCache.size(); i < n; i++) {
|
||||
resetCache[i]->resetConstrained();
|
||||
}
|
||||
|
||||
Update **updateCache = _updateCache.buffer();
|
||||
for (size_t i = 0, n = _updateCache.size(); i < n; i++) {
|
||||
updateCache[i]->update(*this, physics);
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::setupPose() {
|
||||
setupPoseBones();
|
||||
setupPoseSlots();
|
||||
}
|
||||
|
||||
void Skeleton::setupPoseBones() {
|
||||
Bone **bones = _bones.buffer();
|
||||
for (size_t i = 0, n = _bones.size(); i < n; ++i) {
|
||||
bones[i]->setupPose();
|
||||
}
|
||||
|
||||
Constraint **constraints = _constraints.buffer();
|
||||
for (size_t i = 0, n = _constraints.size(); i < n; ++i) {
|
||||
constraints[i]->setupPose();
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::setupPoseSlots() {
|
||||
Slot **slots = _slots.buffer();
|
||||
size_t n = _slots.size();
|
||||
_drawOrder.clear();
|
||||
_drawOrder.setSize(n, 0);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
_drawOrder[i] = _slots[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
slots[i]->setupPose();
|
||||
}
|
||||
}
|
||||
|
||||
SkeletonData &Skeleton::getData() {
|
||||
return _data;
|
||||
}
|
||||
|
||||
Array<Bone *> &Skeleton::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
Array<Update *> &Skeleton::getUpdateCache() {
|
||||
return _updateCache;
|
||||
}
|
||||
|
||||
Bone *Skeleton::getRootBone() {
|
||||
return _bones.size() == 0 ? NULL : _bones[0];
|
||||
}
|
||||
|
||||
Bone *Skeleton::findBone(const String &boneName) {
|
||||
if (boneName.isEmpty()) return NULL;
|
||||
Bone **bones = _bones.buffer();
|
||||
for (size_t i = 0, n = _bones.size(); i < n; i++) {
|
||||
if (bones[i]->_data.getName() == boneName) return bones[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Array<Slot *> &Skeleton::getSlots() {
|
||||
return _slots;
|
||||
}
|
||||
|
||||
Slot *Skeleton::findSlot(const String &slotName) {
|
||||
if (slotName.isEmpty()) return NULL;
|
||||
Slot **slots = _slots.buffer();
|
||||
for (size_t i = 0, n = _slots.size(); i < n; i++) {
|
||||
if (slots[i]->_data.getName() == slotName) return slots[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Array<Slot *> &Skeleton::getDrawOrder() {
|
||||
return _drawOrder;
|
||||
}
|
||||
|
||||
Skin *Skeleton::getSkin() {
|
||||
return _skin;
|
||||
}
|
||||
|
||||
void Skeleton::setSkin(const String &skinName) {
|
||||
Skin *skin = skinName.isEmpty() ? NULL : _data.findSkin(skinName);
|
||||
if (skin == NULL) return;
|
||||
setSkin(skin);
|
||||
}
|
||||
|
||||
void Skeleton::setSkin(Skin *newSkin) {
|
||||
if (_skin == newSkin) return;
|
||||
if (newSkin != NULL) {
|
||||
if (_skin != NULL) {
|
||||
newSkin->attachAll(*this, *_skin);
|
||||
} else {
|
||||
Slot **slots = _slots.buffer();
|
||||
for (size_t i = 0, n = _slots.size(); i < n; ++i) {
|
||||
Slot *slot = slots[i];
|
||||
const String &name = slot->_data.getAttachmentName();
|
||||
if (name.length() > 0) {
|
||||
Attachment *attachment = newSkin->getAttachment(i, name);
|
||||
if (attachment != NULL) {
|
||||
slot->_pose.setAttachment(attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_skin = newSkin;
|
||||
updateCache();
|
||||
}
|
||||
|
||||
Attachment *Skeleton::getAttachment(const String &slotName, const String &attachmentName) {
|
||||
SlotData *slot = _data.findSlot(slotName);
|
||||
if (slot == NULL) return NULL;
|
||||
return getAttachment(slot->getIndex(), attachmentName);
|
||||
}
|
||||
|
||||
Attachment *Skeleton::getAttachment(int slotIndex, const String &attachmentName) {
|
||||
if (attachmentName.isEmpty()) return NULL;
|
||||
if (_skin != NULL) {
|
||||
Attachment *attachment = _skin->getAttachment(slotIndex, attachmentName);
|
||||
if (attachment != NULL) return attachment;
|
||||
}
|
||||
if (_data.getDefaultSkin() != NULL) return _data.getDefaultSkin()->getAttachment(slotIndex, attachmentName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Skeleton::setAttachment(const String &slotName, const String &attachmentName) {
|
||||
if (slotName.isEmpty()) return;
|
||||
Slot *slot = findSlot(slotName);
|
||||
if (slot == NULL) return;
|
||||
Attachment *attachment = NULL;
|
||||
if (!attachmentName.isEmpty()) {
|
||||
attachment = getAttachment(slot->_data.getIndex(), attachmentName);
|
||||
if (attachment == NULL) return;
|
||||
}
|
||||
slot->_pose.setAttachment(attachment);
|
||||
}
|
||||
|
||||
Array<Constraint *> &Skeleton::getConstraints() {
|
||||
return _constraints;
|
||||
}
|
||||
|
||||
Array<PhysicsConstraint *> &Skeleton::getPhysicsConstraints() {
|
||||
return _physics;
|
||||
}
|
||||
|
||||
void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight) {
|
||||
Array<float> outVertexBuffer;
|
||||
getBounds(outX, outY, outWidth, outHeight, outVertexBuffer, NULL);
|
||||
}
|
||||
|
||||
void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Array<float> &outVertexBuffer, SkeletonClipping *clipper) {
|
||||
static unsigned short quadIndices[] = {0, 1, 2, 2, 3, 0};
|
||||
float minX = FLT_MAX;
|
||||
float minY = FLT_MAX;
|
||||
float maxX = -FLT_MAX;
|
||||
float maxY = -FLT_MAX;
|
||||
|
||||
Slot **drawOrder = _drawOrder.buffer();
|
||||
for (size_t i = 0, n = _drawOrder.size(); i < n; ++i) {
|
||||
Slot *slot = drawOrder[i];
|
||||
if (!slot->_bone._active) continue;
|
||||
size_t verticesLength = 0;
|
||||
float *vertices = NULL;
|
||||
unsigned short *triangles = NULL;
|
||||
size_t trianglesLength = 0;
|
||||
Attachment *attachment = slot->_pose.getAttachment();
|
||||
|
||||
if (attachment != NULL) {
|
||||
if (attachment->getRTTI().instanceOf(RegionAttachment::rtti)) {
|
||||
RegionAttachment *regionAttachment = static_cast<RegionAttachment *>(attachment);
|
||||
verticesLength = 8;
|
||||
outVertexBuffer.setSize(8, 0);
|
||||
regionAttachment->computeWorldVertices(*slot, regionAttachment->getOffsets(slot->getAppliedPose()), outVertexBuffer, 0, 2);
|
||||
vertices = outVertexBuffer.buffer();
|
||||
triangles = quadIndices;
|
||||
trianglesLength = 6;
|
||||
} else if (attachment->getRTTI().instanceOf(MeshAttachment::rtti)) {
|
||||
MeshAttachment *mesh = static_cast<MeshAttachment *>(attachment);
|
||||
verticesLength = mesh->getWorldVerticesLength();
|
||||
outVertexBuffer.setSize(verticesLength, 0);
|
||||
mesh->computeWorldVertices(*this, *slot, 0, verticesLength, outVertexBuffer.buffer(), 0, 2);
|
||||
vertices = outVertexBuffer.buffer();
|
||||
triangles = mesh->getTriangles().buffer();
|
||||
trianglesLength = mesh->getTriangles().size();
|
||||
} else if (attachment->getRTTI().instanceOf(ClippingAttachment::rtti) && clipper != NULL) {
|
||||
clipper->clipEnd(*slot);
|
||||
clipper->clipStart(*this, *slot, static_cast<ClippingAttachment *>(attachment));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vertices != NULL) {
|
||||
if (clipper != NULL && clipper->isClipping() && clipper->clipTriangles(vertices, triangles, trianglesLength)) {
|
||||
vertices = clipper->getClippedVertices().buffer();
|
||||
verticesLength = clipper->getClippedVertices().size();
|
||||
}
|
||||
for (size_t ii = 0; ii < verticesLength; ii += 2) {
|
||||
float x = vertices[ii], y = vertices[ii + 1];
|
||||
minX = MathUtil::min(minX, x);
|
||||
minY = MathUtil::min(minY, y);
|
||||
maxX = MathUtil::max(maxX, x);
|
||||
maxY = MathUtil::max(maxY, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clipper != NULL) clipper->clipEnd(*slot);
|
||||
}
|
||||
if (clipper != NULL) clipper->clipEnd();
|
||||
|
||||
outX = minX;
|
||||
outY = minY;
|
||||
outWidth = maxX - minX;
|
||||
outHeight = maxY - minY;
|
||||
}
|
||||
|
||||
Color &Skeleton::getColor() {
|
||||
return _color;
|
||||
}
|
||||
|
||||
void Skeleton::setColor(Color &color) {
|
||||
_color.set(color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
void Skeleton::setColor(float r, float g, float b, float a) {
|
||||
_color.set(r, g, b, a);
|
||||
}
|
||||
|
||||
float Skeleton::getScaleX() {
|
||||
return _scaleX;
|
||||
}
|
||||
|
||||
void Skeleton::setScaleX(float inValue) {
|
||||
_scaleX = inValue;
|
||||
}
|
||||
|
||||
float Skeleton::getScaleY() {
|
||||
return _scaleY * (Bone::isYDown() ? -1 : 1);
|
||||
}
|
||||
|
||||
void Skeleton::setScaleY(float inValue) {
|
||||
_scaleY = inValue;
|
||||
}
|
||||
|
||||
void Skeleton::setScale(float scaleX, float scaleY) {
|
||||
_scaleX = scaleX;
|
||||
_scaleY = scaleY;
|
||||
}
|
||||
|
||||
float Skeleton::getX() {
|
||||
return _x;
|
||||
}
|
||||
|
||||
void Skeleton::setX(float inValue) {
|
||||
_x = inValue;
|
||||
}
|
||||
|
||||
float Skeleton::getY() {
|
||||
return _y;
|
||||
}
|
||||
|
||||
void Skeleton::setY(float inValue) {
|
||||
_y = inValue;
|
||||
}
|
||||
|
||||
void Skeleton::setPosition(float x, float y) {
|
||||
_x = x;
|
||||
_y = y;
|
||||
}
|
||||
|
||||
void Skeleton::getPosition(float &x, float &y) {
|
||||
x = _x;
|
||||
y = _y;
|
||||
}
|
||||
|
||||
float Skeleton::getWindX() {
|
||||
return _windX;
|
||||
}
|
||||
|
||||
void Skeleton::setWindX(float windX) {
|
||||
_windX = windX;
|
||||
}
|
||||
|
||||
float Skeleton::getWindY() {
|
||||
return _windY;
|
||||
}
|
||||
|
||||
void Skeleton::setWindY(float windY) {
|
||||
_windY = windY;
|
||||
}
|
||||
|
||||
float Skeleton::getGravityX() {
|
||||
return _gravityX;
|
||||
}
|
||||
|
||||
void Skeleton::setGravityX(float gravityX) {
|
||||
_gravityX = gravityX;
|
||||
}
|
||||
|
||||
float Skeleton::getGravityY() {
|
||||
return _gravityY;
|
||||
}
|
||||
|
||||
void Skeleton::setGravityY(float gravityY) {
|
||||
_gravityY = gravityY;
|
||||
}
|
||||
|
||||
void Skeleton::physicsTranslate(float x, float y) {
|
||||
PhysicsConstraint **constraints = _physics.buffer();
|
||||
for (size_t i = 0, n = _physics.size(); i < n; i++) {
|
||||
constraints[i]->translate(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::physicsRotate(float x, float y, float degrees) {
|
||||
PhysicsConstraint **constraints = _physics.buffer();
|
||||
for (size_t i = 0, n = _physics.size(); i < n; i++) {
|
||||
constraints[i]->rotate(x, y, degrees);
|
||||
}
|
||||
}
|
||||
|
||||
float Skeleton::getTime() {
|
||||
return _time;
|
||||
}
|
||||
|
||||
void Skeleton::setTime(float time) {
|
||||
_time = time;
|
||||
}
|
||||
|
||||
void Skeleton::update(float delta) {
|
||||
_time += delta;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,245 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SkeletonBounds.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BoundingBoxAttachment.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Slot.h>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0) {
|
||||
}
|
||||
|
||||
SkeletonBounds::~SkeletonBounds() {
|
||||
for (size_t i = 0, n = _polygons.size(); i < n; i++) _polygonPool.free(_polygons[i]);
|
||||
_polygons.clear();
|
||||
}
|
||||
|
||||
void SkeletonBounds::update(Skeleton &skeleton, bool updateAabb) {
|
||||
Array<Slot *> &slots = skeleton.getSlots();
|
||||
size_t slotCount = slots.size();
|
||||
|
||||
_boundingBoxes.clear();
|
||||
for (size_t i = 0, n = _polygons.size(); i < n; ++i) {
|
||||
_polygonPool.free(_polygons[i]);
|
||||
}
|
||||
|
||||
_polygons.clear();
|
||||
|
||||
for (size_t i = 0; i < slotCount; i++) {
|
||||
Slot *slot = slots[i];
|
||||
if (!slot->getBone().isActive()) continue;
|
||||
|
||||
Attachment *attachment = slot->_applied->getAttachment();
|
||||
if (attachment == NULL || !attachment->getRTTI().instanceOf(BoundingBoxAttachment::rtti)) continue;
|
||||
BoundingBoxAttachment *boundingBox = static_cast<BoundingBoxAttachment *>(attachment);
|
||||
_boundingBoxes.add(boundingBox);
|
||||
|
||||
Polygon *polygonP = _polygonPool.obtain();
|
||||
_polygons.add(polygonP);
|
||||
|
||||
Polygon &polygon = *polygonP;
|
||||
|
||||
size_t count = boundingBox->getWorldVerticesLength();
|
||||
polygon._count = (int) count;
|
||||
if (polygon._vertices.size() < count) {
|
||||
polygon._vertices.setSize(count, 0);
|
||||
}
|
||||
boundingBox->computeWorldVertices(skeleton, *slot, 0, count, polygon._vertices, 0, 2);
|
||||
}
|
||||
|
||||
if (updateAabb)
|
||||
aabbCompute();
|
||||
else {
|
||||
_minX = FLT_MIN;
|
||||
_minY = FLT_MIN;
|
||||
_maxX = FLT_MAX;
|
||||
_maxY = FLT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
bool SkeletonBounds::aabbContainsPoint(float x, float y) {
|
||||
return x >= _minX && x <= _maxX && y >= _minY && y <= _maxY;
|
||||
}
|
||||
|
||||
bool SkeletonBounds::aabbIntersectsSegment(float x1, float y1, float x2, float y2) {
|
||||
float minX = _minX;
|
||||
float minY = _minY;
|
||||
float maxX = _maxX;
|
||||
float maxY = _maxY;
|
||||
|
||||
if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float m = (y2 - y1) / (x2 - x1);
|
||||
float y = m * (minX - x1) + y1;
|
||||
if (y > minY && y < maxY) return true;
|
||||
y = m * (maxX - x1) + y1;
|
||||
if (y > minY && y < maxY) return true;
|
||||
float x = (minY - y1) / m + x1;
|
||||
if (x > minX && x < maxX) return true;
|
||||
x = (maxY - y1) / m + x1;
|
||||
if (x > minX && x < maxX) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkeletonBounds::aabbIntersectsSkeleton(SkeletonBounds &bounds) {
|
||||
return _minX < bounds._maxX && _maxX > bounds._minX && _minY < bounds._maxY && _maxY > bounds._minY;
|
||||
}
|
||||
|
||||
bool SkeletonBounds::containsPoint(Polygon &polygon, float x, float y) {
|
||||
Array<float> &vertices = polygon._vertices;
|
||||
int nn = polygon._count;
|
||||
|
||||
int prevIndex = nn - 2;
|
||||
bool inside = false;
|
||||
for (int ii = 0; ii < nn; ii += 2) {
|
||||
float vertexY = vertices[ii + 1];
|
||||
float prevY = vertices[prevIndex + 1];
|
||||
if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {
|
||||
float vertexX = vertices[ii];
|
||||
if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) {
|
||||
inside = !inside;
|
||||
}
|
||||
}
|
||||
prevIndex = ii;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
|
||||
BoundingBoxAttachment *SkeletonBounds::containsPoint(float x, float y) {
|
||||
for (size_t i = 0, n = _polygons.size(); i < n; ++i)
|
||||
if (containsPoint(*_polygons[i], x, y)) return _boundingBoxes[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BoundingBoxAttachment *SkeletonBounds::intersectsSegment(float x1, float y1, float x2, float y2) {
|
||||
for (size_t i = 0, n = _polygons.size(); i < n; ++i)
|
||||
if (intersectsSegment(*_polygons[i], x1, y1, x2, y2)) return _boundingBoxes[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool SkeletonBounds::intersectsSegment(Polygon &polygon, float x1, float y1, float x2, float y2) {
|
||||
Array<float> &vertices = polygon._vertices;
|
||||
size_t nn = polygon._count;
|
||||
|
||||
float width12 = x1 - x2, height12 = y1 - y2;
|
||||
float det1 = x1 * y2 - y1 * x2;
|
||||
float x3 = vertices[nn - 2], y3 = vertices[nn - 1];
|
||||
for (size_t ii = 0; ii < nn; ii += 2) {
|
||||
float x4 = vertices[ii], y4 = vertices[ii + 1];
|
||||
float det2 = x3 * y4 - y3 * x4;
|
||||
float width34 = x3 - x4, height34 = y3 - y4;
|
||||
float det3 = width12 * height34 - height12 * width34;
|
||||
float x = (det1 * width34 - width12 * det2) / det3;
|
||||
if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) {
|
||||
float y = (det1 * height34 - height12 * det2) / det3;
|
||||
if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
x3 = x4;
|
||||
y3 = y4;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
spine::Polygon *SkeletonBounds::getPolygon(BoundingBoxAttachment *attachment) {
|
||||
int index = _boundingBoxes.indexOf(attachment);
|
||||
return index == -1 ? NULL : _polygons[index];
|
||||
}
|
||||
|
||||
BoundingBoxAttachment *SkeletonBounds::getBoundingBox(spine::Polygon *polygon) {
|
||||
int index = _polygons.indexOf(polygon);
|
||||
return index == -1 ? NULL : _boundingBoxes[index];
|
||||
}
|
||||
|
||||
Array<spine::Polygon *> &SkeletonBounds::getPolygons() {
|
||||
return _polygons;
|
||||
}
|
||||
|
||||
Array<BoundingBoxAttachment *> &SkeletonBounds::getBoundingBoxes() {
|
||||
return _boundingBoxes;
|
||||
}
|
||||
|
||||
float SkeletonBounds::getMinX() {
|
||||
return _minX;
|
||||
}
|
||||
|
||||
float SkeletonBounds::getMinY() {
|
||||
return _minY;
|
||||
}
|
||||
|
||||
float SkeletonBounds::getMaxX() {
|
||||
return _maxX;
|
||||
}
|
||||
|
||||
float SkeletonBounds::getMaxY() {
|
||||
return _maxY;
|
||||
}
|
||||
|
||||
float SkeletonBounds::getWidth() {
|
||||
return _maxX - _minX;
|
||||
}
|
||||
|
||||
float SkeletonBounds::getHeight() {
|
||||
return _maxY - _minY;
|
||||
}
|
||||
|
||||
void SkeletonBounds::aabbCompute() {
|
||||
float minX = FLT_MAX;
|
||||
float minY = FLT_MAX;
|
||||
float maxX = FLT_MIN;
|
||||
float maxY = FLT_MIN;
|
||||
|
||||
for (size_t i = 0, n = _polygons.size(); i < n; ++i) {
|
||||
Polygon *polygon = _polygons[i];
|
||||
Array<float> &vertices = polygon->_vertices;
|
||||
for (int ii = 0, nn = polygon->_count; ii < nn; ii += 2) {
|
||||
float x = vertices[ii];
|
||||
float y = vertices[ii + 1];
|
||||
minX = MathUtil::min(minX, x);
|
||||
minY = MathUtil::min(minY, y);
|
||||
maxX = MathUtil::max(maxX, x);
|
||||
maxY = MathUtil::max(maxY, y);
|
||||
}
|
||||
}
|
||||
_minX = minX;
|
||||
_minY = minY;
|
||||
_maxX = maxX;
|
||||
_maxY = maxY;
|
||||
}
|
||||
@ -1,397 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SkeletonClipping.h>
|
||||
|
||||
#include <spine/ClippingAttachment.h>
|
||||
#include <spine/Slot.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL) {
|
||||
_clipOutput.ensureCapacity(128);
|
||||
_clippedVertices.ensureCapacity(128);
|
||||
_clippedTriangles.ensureCapacity(128);
|
||||
_clippedUVs.ensureCapacity(128);
|
||||
}
|
||||
|
||||
size_t SkeletonClipping::clipStart(Skeleton &skeleton, Slot &slot, ClippingAttachment *clip) {
|
||||
if (_clipAttachment != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_clipAttachment = clip;
|
||||
|
||||
int n = (int) clip->getWorldVerticesLength();
|
||||
if (n < 6) {
|
||||
return 0;
|
||||
}
|
||||
_clippingPolygon.setSize(n, 0);
|
||||
clip->computeWorldVertices(skeleton, slot, 0, n, _clippingPolygon.buffer(), 0, 2);
|
||||
makeClockwise(_clippingPolygon);
|
||||
_clippingPolygons = &_triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon));
|
||||
|
||||
for (size_t i = 0; i < _clippingPolygons->size(); ++i) {
|
||||
Array<float> *polygonP = (*_clippingPolygons)[i];
|
||||
Array<float> &polygon = *polygonP;
|
||||
makeClockwise(polygon);
|
||||
polygon.add(polygon[0]);
|
||||
polygon.add(polygon[1]);
|
||||
}
|
||||
|
||||
return (*_clippingPolygons).size();
|
||||
}
|
||||
|
||||
void SkeletonClipping::clipEnd(Slot &slot) {
|
||||
if (_clipAttachment != NULL && _clipAttachment->_endSlot == &slot._data) {
|
||||
clipEnd();
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonClipping::clipEnd() {
|
||||
if (_clipAttachment == NULL) return;
|
||||
|
||||
_clipAttachment = NULL;
|
||||
_clippingPolygons = NULL;
|
||||
_clippedVertices.clear();
|
||||
_clippedUVs.clear();
|
||||
_clippedTriangles.clear();
|
||||
_clippingPolygon.clear();
|
||||
}
|
||||
|
||||
bool SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength) {
|
||||
Array<float> &clipOutput = _clipOutput;
|
||||
Array<float> &clippedVertices = _clippedVertices;
|
||||
Array<unsigned short> &clippedTriangles = _clippedTriangles;
|
||||
Array<Array<float> *> &polygons = *_clippingPolygons;
|
||||
size_t polygonsCount = (*_clippingPolygons).size();
|
||||
|
||||
size_t index = 0;
|
||||
clippedVertices.clear();
|
||||
_clippedUVs.clear();
|
||||
clippedTriangles.clear();
|
||||
bool clipped = false;
|
||||
|
||||
int stride = 2;
|
||||
|
||||
for (size_t i = 0; i < trianglesLength; i += 3) {
|
||||
int vertexOffset = triangles[i] * stride;
|
||||
float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
|
||||
|
||||
vertexOffset = triangles[i + 1] * stride;
|
||||
float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
|
||||
|
||||
vertexOffset = triangles[i + 2] * stride;
|
||||
float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
|
||||
|
||||
for (size_t p = 0; p < polygonsCount; p++) {
|
||||
size_t s = clippedVertices.size();
|
||||
if (clip(x1, y1, x2, y2, x3, y3, &(*polygons[p]), &clipOutput)) {
|
||||
size_t clipOutputLength = clipOutput.size();
|
||||
if (clipOutputLength == 0) continue;
|
||||
clipped = true;
|
||||
|
||||
size_t clipOutputCount = clipOutputLength >> 1;
|
||||
clippedVertices.setSize(s + clipOutputCount * 2, 0);
|
||||
for (size_t ii = 0; ii < clipOutputLength; ii += 2) {
|
||||
float x = clipOutput[ii], y = clipOutput[ii + 1];
|
||||
clippedVertices[s] = x;
|
||||
clippedVertices[s + 1] = y;
|
||||
s += 2;
|
||||
}
|
||||
|
||||
s = clippedTriangles.size();
|
||||
clippedTriangles.setSize(s + 3 * (clipOutputCount - 2), 0);
|
||||
clipOutputCount--;
|
||||
for (size_t ii = 1; ii < clipOutputCount; ii++) {
|
||||
clippedTriangles[s] = (unsigned short) (index);
|
||||
clippedTriangles[s + 1] = (unsigned short) (index + ii);
|
||||
clippedTriangles[s + 2] = (unsigned short) (index + ii + 1);
|
||||
s += 3;
|
||||
}
|
||||
index += clipOutputCount + 1;
|
||||
} else {
|
||||
clippedVertices.setSize(s + 3 * 2, 0);
|
||||
clippedVertices[s] = x1;
|
||||
clippedVertices[s + 1] = y1;
|
||||
clippedVertices[s + 2] = x2;
|
||||
clippedVertices[s + 3] = y2;
|
||||
clippedVertices[s + 4] = x3;
|
||||
clippedVertices[s + 5] = y3;
|
||||
|
||||
s = clippedTriangles.size();
|
||||
clippedTriangles.setSize(s + 3, 0);
|
||||
clippedTriangles[s] = (unsigned short) index;
|
||||
clippedTriangles[s + 1] = (unsigned short) (index + 1);
|
||||
clippedTriangles[s + 2] = (unsigned short) (index + 2);
|
||||
index += 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return clipped;
|
||||
}
|
||||
|
||||
bool SkeletonClipping::clipTriangles(Array<float> &vertices, Array<unsigned short> &triangles, Array<float> &uvs, size_t stride) {
|
||||
return clipTriangles(vertices.buffer(), triangles.buffer(), triangles.size(), uvs.buffer(), stride);
|
||||
}
|
||||
|
||||
bool SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength, float *uvs, size_t stride) {
|
||||
Array<float> &clipOutput = _clipOutput;
|
||||
Array<float> &clippedVertices = _clippedVertices;
|
||||
Array<unsigned short> &clippedTriangles = _clippedTriangles;
|
||||
Array<Array<float> *> &polygons = *_clippingPolygons;
|
||||
size_t polygonsCount = (*_clippingPolygons).size();
|
||||
|
||||
size_t index = 0;
|
||||
clippedVertices.clear();
|
||||
_clippedUVs.clear();
|
||||
clippedTriangles.clear();
|
||||
bool clipped = false;
|
||||
|
||||
for (size_t i = 0; i < trianglesLength; i += 3) {
|
||||
int vertexOffset = triangles[i] * (int) stride;
|
||||
float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
|
||||
float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
|
||||
|
||||
vertexOffset = triangles[i + 1] * (int) stride;
|
||||
float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
|
||||
float u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
|
||||
|
||||
vertexOffset = triangles[i + 2] * (int) stride;
|
||||
float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
|
||||
float u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
|
||||
|
||||
for (size_t p = 0; p < polygonsCount; p++) {
|
||||
size_t s = clippedVertices.size();
|
||||
if (clip(x1, y1, x2, y2, x3, y3, &(*polygons[p]), &clipOutput)) {
|
||||
size_t clipOutputLength = clipOutput.size();
|
||||
if (clipOutputLength == 0) continue;
|
||||
clipped = true;
|
||||
float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
|
||||
float d = 1 / (d0 * d2 + d1 * (y1 - y3));
|
||||
|
||||
size_t clipOutputCount = clipOutputLength >> 1;
|
||||
clippedVertices.setSize(s + clipOutputCount * 2, 0);
|
||||
_clippedUVs.setSize(s + clipOutputCount * 2, 0);
|
||||
for (size_t ii = 0; ii < clipOutputLength; ii += 2) {
|
||||
float x = clipOutput[ii], y = clipOutput[ii + 1];
|
||||
clippedVertices[s] = x;
|
||||
clippedVertices[s + 1] = y;
|
||||
float c0 = x - x3, c1 = y - y3;
|
||||
float a = (d0 * c0 + d1 * c1) * d;
|
||||
float b = (d4 * c0 + d2 * c1) * d;
|
||||
float c = 1 - a - b;
|
||||
_clippedUVs[s] = u1 * a + u2 * b + u3 * c;
|
||||
_clippedUVs[s + 1] = v1 * a + v2 * b + v3 * c;
|
||||
s += 2;
|
||||
}
|
||||
|
||||
s = clippedTriangles.size();
|
||||
clippedTriangles.setSize(s + 3 * (clipOutputCount - 2), 0);
|
||||
clipOutputCount--;
|
||||
for (size_t ii = 1; ii < clipOutputCount; ii++) {
|
||||
clippedTriangles[s] = (unsigned short) (index);
|
||||
clippedTriangles[s + 1] = (unsigned short) (index + ii);
|
||||
clippedTriangles[s + 2] = (unsigned short) (index + ii + 1);
|
||||
s += 3;
|
||||
}
|
||||
index += clipOutputCount + 1;
|
||||
} else {
|
||||
clippedVertices.setSize(s + 3 * 2, 0);
|
||||
_clippedUVs.setSize(s + 3 * 2, 0);
|
||||
clippedVertices[s] = x1;
|
||||
clippedVertices[s + 1] = y1;
|
||||
clippedVertices[s + 2] = x2;
|
||||
clippedVertices[s + 3] = y2;
|
||||
clippedVertices[s + 4] = x3;
|
||||
clippedVertices[s + 5] = y3;
|
||||
|
||||
_clippedUVs[s] = u1;
|
||||
_clippedUVs[s + 1] = v1;
|
||||
_clippedUVs[s + 2] = u2;
|
||||
_clippedUVs[s + 3] = v2;
|
||||
_clippedUVs[s + 4] = u3;
|
||||
_clippedUVs[s + 5] = v3;
|
||||
|
||||
s = clippedTriangles.size();
|
||||
clippedTriangles.setSize(s + 3, 0);
|
||||
clippedTriangles[s] = (unsigned short) index;
|
||||
clippedTriangles[s + 1] = (unsigned short) (index + 1);
|
||||
clippedTriangles[s + 2] = (unsigned short) (index + 2);
|
||||
index += 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return clipped;
|
||||
}
|
||||
|
||||
bool SkeletonClipping::isClipping() {
|
||||
return _clipAttachment != NULL;
|
||||
}
|
||||
|
||||
Array<float> &SkeletonClipping::getClippedVertices() {
|
||||
return _clippedVertices;
|
||||
}
|
||||
|
||||
Array<unsigned short> &SkeletonClipping::getClippedTriangles() {
|
||||
return _clippedTriangles;
|
||||
}
|
||||
|
||||
Array<float> &SkeletonClipping::getClippedUVs() {
|
||||
return _clippedUVs;
|
||||
}
|
||||
|
||||
bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Array<float> *clippingArea, Array<float> *output) {
|
||||
Array<float> *originalOutput = output;
|
||||
bool clipped = false;
|
||||
|
||||
// Avoid copy at the end.
|
||||
Array<float> *input;
|
||||
if (clippingArea->size() % 4 >= 2) {
|
||||
input = output;
|
||||
output = &_scratch;
|
||||
} else
|
||||
input = &_scratch;
|
||||
|
||||
input->clear();
|
||||
input->add(x1);
|
||||
input->add(y1);
|
||||
input->add(x2);
|
||||
input->add(y2);
|
||||
input->add(x3);
|
||||
input->add(y3);
|
||||
input->add(x1);
|
||||
input->add(y1);
|
||||
output->clear();
|
||||
|
||||
size_t clippingVerticesLast = clippingArea->size() - 4;
|
||||
Array<float> &clippingVertices = *clippingArea;
|
||||
for (size_t i = 0;; i += 2) {
|
||||
float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
|
||||
float ex = edgeX - clippingVertices[i + 2], ey = edgeY - clippingVertices[i + 3];
|
||||
|
||||
size_t outputStart = output->size();
|
||||
Array<float> &inputVertices = *input;
|
||||
for (size_t ii = 0, nn = input->size() - 2; ii < nn;) {
|
||||
float inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
|
||||
ii += 2;
|
||||
float inputX2 = inputVertices[ii], inputY2 = inputVertices[ii + 1];
|
||||
bool s2 = ey * (edgeX - inputX2) > ex * (edgeY - inputY2);
|
||||
float s1 = ey * (edgeX - inputX) - ex * (edgeY - inputY);
|
||||
if (s1 > 0) {
|
||||
if (s2) {// v1 inside, v2 inside
|
||||
output->add(inputX2);
|
||||
output->add(inputY2);
|
||||
continue;
|
||||
}
|
||||
// v1 inside, v2 outside
|
||||
float ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex);
|
||||
if (t >= 0 && t <= 1) {
|
||||
output->add(inputX + ix * t);
|
||||
output->add(inputY + iy * t);
|
||||
} else {
|
||||
output->add(inputX2);
|
||||
output->add(inputY2);
|
||||
continue;
|
||||
}
|
||||
} else if (s2) {// v1 outside, v2 inside
|
||||
float ix = inputX2 - inputX, iy = inputY2 - inputY, t = s1 / (ix * ey - iy * ex);
|
||||
if (t >= 0 && t <= 1) {
|
||||
output->add(inputX + ix * t);
|
||||
output->add(inputY + iy * t);
|
||||
output->add(inputX2);
|
||||
output->add(inputY2);
|
||||
} else {
|
||||
output->add(inputX2);
|
||||
output->add(inputY2);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
clipped = true;
|
||||
}
|
||||
|
||||
|
||||
if (outputStart == output->size()) {
|
||||
// All edges outside.
|
||||
originalOutput->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
output->add((*output)[0]);
|
||||
output->add((*output)[1]);
|
||||
|
||||
if (i == clippingVerticesLast) {
|
||||
break;
|
||||
}
|
||||
Array<float> *temp = output;
|
||||
output = input;
|
||||
output->clear();
|
||||
input = temp;
|
||||
}
|
||||
|
||||
if (originalOutput != output) {
|
||||
originalOutput->clear();
|
||||
for (size_t i = 0, n = output->size() - 2; i < n; ++i) originalOutput->add((*output)[i]);
|
||||
} else
|
||||
originalOutput->setSize(originalOutput->size() - 2, 0);
|
||||
|
||||
if (originalOutput->size() < 6) {
|
||||
originalOutput->clear();
|
||||
return false;
|
||||
}
|
||||
return clipped;
|
||||
}
|
||||
|
||||
void SkeletonClipping::makeClockwise(Array<float> &polygon) {
|
||||
size_t verticeslength = polygon.size();
|
||||
|
||||
float area = polygon[verticeslength - 2] * polygon[1] - polygon[0] * polygon[verticeslength - 1];
|
||||
float p1x, p1y, p2x, p2y;
|
||||
|
||||
for (size_t i = 0, n = verticeslength - 3; i < n; i += 2) {
|
||||
p1x = polygon[i];
|
||||
p1y = polygon[i + 1];
|
||||
p2x = polygon[i + 2];
|
||||
p2y = polygon[i + 3];
|
||||
area += p1x * p2y - p2x * p1y;
|
||||
}
|
||||
|
||||
if (area < 0) return;
|
||||
|
||||
for (size_t i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
|
||||
float x = polygon[i], y = polygon[i + 1];
|
||||
int other = (int) (lastX - i);
|
||||
polygon[i] = polygon[other];
|
||||
polygon[i + 1] = polygon[other + 1];
|
||||
polygon[other] = x;
|
||||
polygon[other + 1] = y;
|
||||
}
|
||||
}
|
||||
@ -1,218 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SkeletonData.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/ConstraintData.h>
|
||||
#include <spine/EventData.h>
|
||||
#include <spine/IkConstraintData.h>
|
||||
#include <spine/PathConstraintData.h>
|
||||
#include <spine/PhysicsConstraintData.h>
|
||||
#include <spine/Skin.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/TransformConstraintData.h>
|
||||
#include <spine/SliderData.h>
|
||||
|
||||
#include <spine/ArrayUtils.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
SkeletonData::SkeletonData()
|
||||
: _name(), _defaultSkin(NULL), _x(0), _y(0), _width(0), _height(0), _referenceScale(100), _version(), _hash(), _fps(30), _imagesPath(),
|
||||
_audioPath() {
|
||||
}
|
||||
|
||||
SkeletonData::~SkeletonData() {
|
||||
ArrayUtils::deleteElements(_bones);
|
||||
ArrayUtils::deleteElements(_slots);
|
||||
ArrayUtils::deleteElements(_skins);
|
||||
|
||||
_defaultSkin = NULL;
|
||||
|
||||
ArrayUtils::deleteElements(_events);
|
||||
ArrayUtils::deleteElements(_animations);
|
||||
ArrayUtils::deleteElements(_constraints);
|
||||
for (size_t i = 0; i < _strings.size(); i++) {
|
||||
SpineExtension::free(_strings[i], __FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
BoneData *SkeletonData::findBone(const String &boneName) {
|
||||
return ArrayUtils::findWithName(_bones, boneName);
|
||||
}
|
||||
|
||||
SlotData *SkeletonData::findSlot(const String &slotName) {
|
||||
return ArrayUtils::findWithName(_slots, slotName);
|
||||
}
|
||||
|
||||
Skin *SkeletonData::findSkin(const String &skinName) {
|
||||
return ArrayUtils::findWithName(_skins, skinName);
|
||||
}
|
||||
|
||||
EventData *SkeletonData::findEvent(const String &eventDataName) {
|
||||
return ArrayUtils::findWithName(_events, eventDataName);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void SkeletonData::setName(const String &inValue) {
|
||||
_name = inValue;
|
||||
}
|
||||
|
||||
Array<BoneData *> &SkeletonData::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
Array<SlotData *> &SkeletonData::getSlots() {
|
||||
return _slots;
|
||||
}
|
||||
|
||||
Array<Skin *> &SkeletonData::getSkins() {
|
||||
return _skins;
|
||||
}
|
||||
|
||||
Skin *SkeletonData::getDefaultSkin() {
|
||||
return _defaultSkin;
|
||||
}
|
||||
|
||||
void SkeletonData::setDefaultSkin(Skin *inValue) {
|
||||
_defaultSkin = inValue;
|
||||
}
|
||||
|
||||
Array<EventData *> &SkeletonData::getEvents() {
|
||||
return _events;
|
||||
}
|
||||
|
||||
Array<Animation *> &SkeletonData::getAnimations() {
|
||||
return _animations;
|
||||
}
|
||||
|
||||
float SkeletonData::getX() {
|
||||
return _x;
|
||||
}
|
||||
|
||||
void SkeletonData::setX(float inValue) {
|
||||
_x = inValue;
|
||||
}
|
||||
|
||||
float SkeletonData::getY() {
|
||||
return _y;
|
||||
}
|
||||
|
||||
void SkeletonData::setY(float inValue) {
|
||||
_y = inValue;
|
||||
}
|
||||
|
||||
float SkeletonData::getWidth() {
|
||||
return _width;
|
||||
}
|
||||
|
||||
void SkeletonData::setWidth(float inValue) {
|
||||
_width = inValue;
|
||||
}
|
||||
|
||||
float SkeletonData::getHeight() {
|
||||
return _height;
|
||||
}
|
||||
|
||||
void SkeletonData::setHeight(float inValue) {
|
||||
_height = inValue;
|
||||
}
|
||||
|
||||
float SkeletonData::getReferenceScale() {
|
||||
return _referenceScale;
|
||||
}
|
||||
|
||||
void SkeletonData::setReferenceScale(float inValue) {
|
||||
_referenceScale = inValue;
|
||||
}
|
||||
|
||||
const String &SkeletonData::getVersion() {
|
||||
return _version;
|
||||
}
|
||||
|
||||
void SkeletonData::setVersion(const String &inValue) {
|
||||
_version = inValue;
|
||||
}
|
||||
|
||||
const String &SkeletonData::getHash() {
|
||||
return _hash;
|
||||
}
|
||||
|
||||
void SkeletonData::setHash(const String &inValue) {
|
||||
_hash = inValue;
|
||||
}
|
||||
|
||||
const String &SkeletonData::getImagesPath() {
|
||||
return _imagesPath;
|
||||
}
|
||||
|
||||
void SkeletonData::setImagesPath(const String &inValue) {
|
||||
_imagesPath = inValue;
|
||||
}
|
||||
|
||||
|
||||
const String &SkeletonData::getAudioPath() {
|
||||
return _audioPath;
|
||||
}
|
||||
|
||||
void SkeletonData::setAudioPath(const String &inValue) {
|
||||
_audioPath = inValue;
|
||||
}
|
||||
|
||||
float SkeletonData::getFps() {
|
||||
return _fps;
|
||||
}
|
||||
|
||||
void SkeletonData::setFps(float inValue) {
|
||||
_fps = inValue;
|
||||
}
|
||||
|
||||
Array<ConstraintData *> &SkeletonData::getConstraints() {
|
||||
return _constraints;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,248 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SkeletonRenderer.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/RegionAttachment.h>
|
||||
#include <spine/MeshAttachment.h>
|
||||
#include <spine/ClippingAttachment.h>
|
||||
#include <spine/Bone.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
SkeletonRenderer::SkeletonRenderer() : _allocator(4096), _worldVertices(), _quadIndices(), _clipping(), _renderCommands() {
|
||||
_quadIndices.add(0);
|
||||
_quadIndices.add(1);
|
||||
_quadIndices.add(2);
|
||||
_quadIndices.add(2);
|
||||
_quadIndices.add(3);
|
||||
_quadIndices.add(0);
|
||||
}
|
||||
|
||||
SkeletonRenderer::~SkeletonRenderer() {
|
||||
}
|
||||
|
||||
static RenderCommand *createRenderCommand(BlockAllocator &allocator, int numVertices, int32_t numIndices, BlendMode blendMode, void *texture) {
|
||||
RenderCommand *cmd = allocator.allocate<RenderCommand>(1);
|
||||
cmd->positions = allocator.allocate<float>(numVertices << 1);
|
||||
cmd->uvs = allocator.allocate<float>(numVertices << 1);
|
||||
cmd->colors = allocator.allocate<uint32_t>(numVertices);
|
||||
cmd->darkColors = allocator.allocate<uint32_t>(numVertices);
|
||||
cmd->numVertices = numVertices;
|
||||
cmd->indices = allocator.allocate<uint16_t>(numIndices);
|
||||
cmd->numIndices = numIndices;
|
||||
cmd->blendMode = blendMode;
|
||||
cmd->texture = texture;
|
||||
cmd->next = nullptr;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static RenderCommand *batchSubCommands(BlockAllocator &allocator, Array<RenderCommand *> &commands, int first, int last, int numVertices,
|
||||
int numIndices) {
|
||||
RenderCommand *batched = createRenderCommand(allocator, numVertices, numIndices, commands[first]->blendMode, commands[first]->texture);
|
||||
float *positions = batched->positions;
|
||||
float *uvs = batched->uvs;
|
||||
uint32_t *colors = batched->colors;
|
||||
uint32_t *darkColors = batched->darkColors;
|
||||
uint16_t *indices = batched->indices;
|
||||
int indicesOffset = 0;
|
||||
for (int i = first; i <= last; i++) {
|
||||
RenderCommand *cmd = commands[i];
|
||||
memcpy(positions, cmd->positions, sizeof(float) * 2 * cmd->numVertices);
|
||||
memcpy(uvs, cmd->uvs, sizeof(float) * 2 * cmd->numVertices);
|
||||
memcpy(colors, cmd->colors, sizeof(int32_t) * cmd->numVertices);
|
||||
memcpy(darkColors, cmd->darkColors, sizeof(int32_t) * cmd->numVertices);
|
||||
for (int ii = 0; ii < cmd->numIndices; ii++) indices[ii] = cmd->indices[ii] + indicesOffset;
|
||||
indicesOffset += cmd->numVertices;
|
||||
positions += 2 * cmd->numVertices;
|
||||
uvs += 2 * cmd->numVertices;
|
||||
colors += cmd->numVertices;
|
||||
darkColors += cmd->numVertices;
|
||||
indices += cmd->numIndices;
|
||||
}
|
||||
return batched;
|
||||
}
|
||||
|
||||
static RenderCommand *batchCommands(BlockAllocator &allocator, Array<RenderCommand *> &commands) {
|
||||
if (commands.size() == 0) return nullptr;
|
||||
|
||||
RenderCommand *root = nullptr;
|
||||
RenderCommand *last = nullptr;
|
||||
|
||||
RenderCommand *first = commands[0];
|
||||
int startIndex = 0;
|
||||
int i = 1;
|
||||
int numVertices = first->numVertices;
|
||||
int numIndices = first->numIndices;
|
||||
while (i <= (int) commands.size()) {
|
||||
RenderCommand *cmd = i < (int) commands.size() ? commands[i] : nullptr;
|
||||
|
||||
if (cmd && cmd->numVertices == 0 && cmd->numIndices == 0) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cmd != nullptr && cmd->texture == first->texture && cmd->blendMode == first->blendMode && cmd->colors[0] == first->colors[0] &&
|
||||
cmd->darkColors[0] == first->darkColors[0] && numIndices + cmd->numIndices < 0xffff) {
|
||||
numVertices += cmd->numVertices;
|
||||
numIndices += cmd->numIndices;
|
||||
} else {
|
||||
RenderCommand *batched = batchSubCommands(allocator, commands, startIndex, i - 1, numVertices, numIndices);
|
||||
if (!last) {
|
||||
root = last = batched;
|
||||
} else {
|
||||
last->next = batched;
|
||||
last = batched;
|
||||
}
|
||||
if (i == (int) commands.size()) break;
|
||||
first = commands[i];
|
||||
startIndex = i;
|
||||
numVertices = first->numVertices;
|
||||
numIndices = first->numIndices;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
RenderCommand *SkeletonRenderer::render(Skeleton &skeleton) {
|
||||
_allocator.compress();
|
||||
_renderCommands.clear();
|
||||
|
||||
SkeletonClipping &clipper = _clipping;
|
||||
|
||||
for (unsigned i = 0; i < skeleton.getSlots().size(); ++i) {
|
||||
Slot &slot = *skeleton.getDrawOrder()[i];
|
||||
Attachment *attachment = slot.getAppliedPose().getAttachment();
|
||||
if (!attachment) {
|
||||
clipper.clipEnd(slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Early out if the slot color is 0 or the bone is not active
|
||||
if ((slot.getAppliedPose().getColor().a == 0 || !slot.getBone().isActive()) && !attachment->getRTTI().isExactly(ClippingAttachment::rtti)) {
|
||||
clipper.clipEnd(slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
Array<float> *worldVertices = &_worldVertices;
|
||||
Array<unsigned short> *quadIndices = &_quadIndices;
|
||||
Array<float> *vertices = worldVertices;
|
||||
int32_t verticesCount;
|
||||
Array<float> *uvs;
|
||||
Array<unsigned short> *indices;
|
||||
int32_t indicesCount;
|
||||
Color *attachmentColor;
|
||||
void *texture;
|
||||
|
||||
if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) {
|
||||
RegionAttachment *regionAttachment = (RegionAttachment *) attachment;
|
||||
attachmentColor = ®ionAttachment->getColor();
|
||||
|
||||
if (attachmentColor->a == 0) {
|
||||
clipper.clipEnd(slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
Sequence &sequence = regionAttachment->getSequence();
|
||||
int sequenceIndex = sequence.resolveIndex(slot.getAppliedPose());
|
||||
TextureRegion *region = sequence.getRegion(sequenceIndex);
|
||||
worldVertices->setSize(8, 0);
|
||||
regionAttachment->computeWorldVertices(slot, regionAttachment->getOffsets(slot.getAppliedPose()), *worldVertices, 0, 2);
|
||||
verticesCount = 4;
|
||||
uvs = &sequence.getUVs(sequenceIndex);
|
||||
indices = quadIndices;
|
||||
indicesCount = 6;
|
||||
texture = region->_rendererObject;
|
||||
|
||||
} else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) {
|
||||
MeshAttachment *mesh = (MeshAttachment *) attachment;
|
||||
attachmentColor = &mesh->getColor();
|
||||
|
||||
if (attachmentColor->a == 0) {
|
||||
clipper.clipEnd(slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
Sequence &sequence = mesh->getSequence();
|
||||
int sequenceIndex = sequence.resolveIndex(slot.getAppliedPose());
|
||||
TextureRegion *region = sequence.getRegion(sequenceIndex);
|
||||
worldVertices->setSize(mesh->getWorldVerticesLength(), 0);
|
||||
mesh->computeWorldVertices(skeleton, slot, 0, mesh->getWorldVerticesLength(), worldVertices->buffer(), 0, 2);
|
||||
verticesCount = (int32_t) (mesh->getWorldVerticesLength() >> 1);
|
||||
uvs = &sequence.getUVs(sequenceIndex);
|
||||
indices = &mesh->getTriangles();
|
||||
indicesCount = (int32_t) indices->size();
|
||||
texture = region->_rendererObject;
|
||||
|
||||
} else if (attachment->getRTTI().isExactly(ClippingAttachment::rtti)) {
|
||||
ClippingAttachment *clip = (ClippingAttachment *) slot.getAppliedPose().getAttachment();
|
||||
clipper.clipStart(skeleton, slot, clip);
|
||||
continue;
|
||||
} else
|
||||
continue;
|
||||
|
||||
uint8_t r = static_cast<uint8_t>(skeleton.getColor().r * slot.getAppliedPose().getColor().r * attachmentColor->r * 255);
|
||||
uint8_t g = static_cast<uint8_t>(skeleton.getColor().g * slot.getAppliedPose().getColor().g * attachmentColor->g * 255);
|
||||
uint8_t b = static_cast<uint8_t>(skeleton.getColor().b * slot.getAppliedPose().getColor().b * attachmentColor->b * 255);
|
||||
uint8_t a = static_cast<uint8_t>(skeleton.getColor().a * slot.getAppliedPose().getColor().a * attachmentColor->a * 255);
|
||||
uint32_t color = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
uint32_t darkColor = 0xff000000;
|
||||
if (slot.getAppliedPose().hasDarkColor()) {
|
||||
Color &slotDarkColor = slot.getAppliedPose().getDarkColor();
|
||||
darkColor = 0xff000000 | (static_cast<uint8_t>(slotDarkColor.r * 255) << 16) | (static_cast<uint8_t>(slotDarkColor.g * 255) << 8) |
|
||||
static_cast<uint8_t>(slotDarkColor.b * 255);
|
||||
}
|
||||
|
||||
if (clipper.isClipping()) {
|
||||
clipper.clipTriangles(*worldVertices, *indices, *uvs, 2);
|
||||
vertices = &clipper.getClippedVertices();
|
||||
verticesCount = (int32_t) (clipper.getClippedVertices().size() >> 1);
|
||||
uvs = &clipper.getClippedUVs();
|
||||
indices = &clipper.getClippedTriangles();
|
||||
indicesCount = (int32_t) (clipper.getClippedTriangles().size());
|
||||
}
|
||||
|
||||
RenderCommand *cmd = createRenderCommand(_allocator, verticesCount, indicesCount, slot.getData().getBlendMode(), texture);
|
||||
_renderCommands.add(cmd);
|
||||
memcpy(cmd->positions, vertices->buffer(), (verticesCount << 1) * sizeof(float));
|
||||
memcpy(cmd->uvs, uvs->buffer(), (verticesCount << 1) * sizeof(float));
|
||||
for (int ii = 0; ii < verticesCount; ii++) {
|
||||
cmd->colors[ii] = color;
|
||||
cmd->darkColors[ii] = darkColor;
|
||||
}
|
||||
memcpy(cmd->indices, indices->buffer(), indices->size() * sizeof(uint16_t));
|
||||
clipper.clipEnd(slot);
|
||||
}
|
||||
clipper.clipEnd();
|
||||
|
||||
return batchCommands(_allocator, _renderCommands);
|
||||
}
|
||||
@ -1,192 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Skin.h>
|
||||
|
||||
#include <spine/Attachment.h>
|
||||
#include <spine/MeshAttachment.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/ConstraintData.h>
|
||||
#include <spine/Slot.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
Skin::AttachmentMap::AttachmentMap() {
|
||||
}
|
||||
|
||||
static void disposeAttachment(Attachment *attachment) {
|
||||
if (!attachment) return;
|
||||
attachment->dereference();
|
||||
if (attachment->getRefCount() == 0) delete attachment;
|
||||
}
|
||||
|
||||
void Skin::AttachmentMap::put(size_t slotIndex, const String &placeholderName, Attachment *attachment) {
|
||||
if (slotIndex >= _buckets.size()) _buckets.setSize(slotIndex + 1, Array<Entry>());
|
||||
Array<Entry> &bucket = _buckets[slotIndex];
|
||||
int existing = findInBucket(bucket, placeholderName);
|
||||
attachment->reference();
|
||||
if (existing >= 0) {
|
||||
disposeAttachment(bucket[existing]._attachment);
|
||||
bucket[existing]._attachment = attachment;
|
||||
} else {
|
||||
bucket.add(Entry(slotIndex, placeholderName, attachment));
|
||||
}
|
||||
}
|
||||
|
||||
Attachment *Skin::AttachmentMap::get(size_t slotIndex, const String &placeholderName) {
|
||||
if (slotIndex >= _buckets.size()) return NULL;
|
||||
int existing = findInBucket(_buckets[slotIndex], placeholderName);
|
||||
return existing >= 0 ? _buckets[slotIndex][existing]._attachment : NULL;
|
||||
}
|
||||
|
||||
void Skin::AttachmentMap::remove(size_t slotIndex, const String &placeholderName) {
|
||||
if (slotIndex >= _buckets.size()) return;
|
||||
int existing = findInBucket(_buckets[slotIndex], placeholderName);
|
||||
if (existing >= 0) {
|
||||
disposeAttachment(_buckets[slotIndex][existing]._attachment);
|
||||
_buckets[slotIndex].removeAt(existing);
|
||||
}
|
||||
}
|
||||
|
||||
int Skin::AttachmentMap::findInBucket(Array<Entry> &bucket, const String &placeholderName) {
|
||||
for (size_t i = 0; i < bucket.size(); i++)
|
||||
if (bucket[i]._placeholderName == placeholderName) return (int) i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Skin::AttachmentMap::Entries Skin::AttachmentMap::getEntries() {
|
||||
return Skin::AttachmentMap::Entries(_buckets);
|
||||
}
|
||||
|
||||
Skin::Skin(const String &name) : _name(name), _attachments(), _color(0.99607843f, 0.61960787f, 0.30980393f, 1) {
|
||||
assert(_name.length() > 0);
|
||||
}
|
||||
|
||||
Skin::~Skin() {
|
||||
Skin::AttachmentMap::Entries entries = _attachments.getEntries();
|
||||
while (entries.hasNext()) {
|
||||
Skin::AttachmentMap::Entry entry = entries.next();
|
||||
disposeAttachment(entry._attachment);
|
||||
}
|
||||
}
|
||||
|
||||
void Skin::setAttachment(size_t slotIndex, const String &placeholderName, Attachment *attachment) {
|
||||
_attachments.put(slotIndex, placeholderName, attachment);
|
||||
}
|
||||
|
||||
Attachment *Skin::getAttachment(size_t slotIndex, const String &placeholderName) {
|
||||
return _attachments.get(slotIndex, placeholderName);
|
||||
}
|
||||
|
||||
void Skin::removeAttachment(size_t slotIndex, const String &placeholderName) {
|
||||
_attachments.remove(slotIndex, placeholderName);
|
||||
}
|
||||
|
||||
void Skin::findNamesForSlot(size_t slotIndex, Array<String> &names) {
|
||||
Skin::AttachmentMap::Entries entries = _attachments.getEntries();
|
||||
while (entries.hasNext()) {
|
||||
Skin::AttachmentMap::Entry &entry = entries.next();
|
||||
if (entry._slotIndex == slotIndex) {
|
||||
names.add(entry._placeholderName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Skin::findAttachmentsForSlot(size_t slotIndex, Array<Attachment *> &attachments) {
|
||||
Skin::AttachmentMap::Entries entries = _attachments.getEntries();
|
||||
while (entries.hasNext()) {
|
||||
Skin::AttachmentMap::Entry &entry = entries.next();
|
||||
if (entry._slotIndex == slotIndex) attachments.add(entry._attachment);
|
||||
}
|
||||
}
|
||||
|
||||
const String &Skin::getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
Skin::AttachmentMap::Entries Skin::getAttachments() {
|
||||
return _attachments.getEntries();
|
||||
}
|
||||
|
||||
void Skin::attachAll(Skeleton &skeleton, Skin &oldSkin) {
|
||||
Array<Slot *> &slots = skeleton.getSlots();
|
||||
Skin::AttachmentMap::Entries entries = oldSkin.getAttachments();
|
||||
while (entries.hasNext()) {
|
||||
Skin::AttachmentMap::Entry &entry = entries.next();
|
||||
int slotIndex = (int) entry._slotIndex;
|
||||
Slot *slot = slots[slotIndex];
|
||||
|
||||
if (slot->getPose().getAttachment() == entry._attachment) {
|
||||
Attachment *attachment = getAttachment(slotIndex, entry._placeholderName);
|
||||
if (attachment) slot->getPose().setAttachment(attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Skin::addSkin(Skin &other) {
|
||||
for (size_t i = 0; i < other.getBones().size(); i++)
|
||||
if (!_bones.contains(other.getBones()[i])) _bones.add(other.getBones()[i]);
|
||||
|
||||
for (size_t i = 0; i < other.getConstraints().size(); i++)
|
||||
if (!_constraints.contains(other.getConstraints()[i])) _constraints.add(other.getConstraints()[i]);
|
||||
|
||||
AttachmentMap::Entries entries = other.getAttachments();
|
||||
while (entries.hasNext()) {
|
||||
AttachmentMap::Entry &entry = entries.next();
|
||||
setAttachment(entry._slotIndex, entry._placeholderName, entry._attachment);
|
||||
}
|
||||
}
|
||||
|
||||
void Skin::copySkin(Skin &other) {
|
||||
for (size_t i = 0; i < other.getBones().size(); i++)
|
||||
if (!_bones.contains(other.getBones()[i])) _bones.add(other.getBones()[i]);
|
||||
|
||||
for (size_t i = 0; i < other.getConstraints().size(); i++)
|
||||
if (!_constraints.contains(other.getConstraints()[i])) _constraints.add(other.getConstraints()[i]);
|
||||
|
||||
AttachmentMap::Entries entries = other.getAttachments();
|
||||
while (entries.hasNext()) {
|
||||
AttachmentMap::Entry &entry = entries.next();
|
||||
if (entry._attachment->getRTTI().isExactly(MeshAttachment::rtti))
|
||||
setAttachment(entry._slotIndex, entry._placeholderName, &static_cast<MeshAttachment *>(entry._attachment)->newLinkedMesh());
|
||||
else
|
||||
setAttachment(entry._slotIndex, entry._placeholderName, &entry._attachment->copy());
|
||||
}
|
||||
}
|
||||
|
||||
Array<ConstraintData *> &Skin::getConstraints() {
|
||||
return _constraints;
|
||||
}
|
||||
|
||||
Array<BoneData *> &Skin::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
@ -1,136 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Slider.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/BonePose.h>
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Timeline.h>
|
||||
#include <spine/SlotTimeline.h>
|
||||
#include <spine/ConstraintTimeline.h>
|
||||
#include <spine/PhysicsConstraintTimeline.h>
|
||||
#include <spine/SliderData.h>
|
||||
#include <spine/SliderPose.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/PhysicsConstraint.h>
|
||||
#include <spine/TransformConstraintData.h>
|
||||
#include <spine/MathUtil.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(Slider, Constraint)
|
||||
|
||||
float Slider::_offsets[6];
|
||||
|
||||
Slider::Slider(SliderData &data, Skeleton &skeleton) : SliderBase(data), _bone(NULL) {
|
||||
if (data._bone != NULL) {
|
||||
_bone = skeleton._bones[data._bone->getIndex()];
|
||||
}
|
||||
}
|
||||
|
||||
Slider &Slider::copy(Skeleton &skeleton) {
|
||||
Slider *copy = new (__FILE__, __LINE__) Slider(_data, skeleton);
|
||||
copy->_pose.set(_pose);
|
||||
return *copy;
|
||||
}
|
||||
|
||||
void Slider::update(Skeleton &skeleton, Physics physics) {
|
||||
SliderPose &p = *_applied;
|
||||
if (p._mix == 0) return;
|
||||
|
||||
Animation *animation = _data._animation;
|
||||
if (_bone != NULL) {
|
||||
if (!_bone->isActive()) return;
|
||||
if (_data._local) _bone->_applied->validateLocalTransform(skeleton);
|
||||
p._time = _data._offset +
|
||||
(_data._property->value(skeleton, *_bone->_applied, _data._local, _offsets) - _data._property->_offset) * _data._scale;
|
||||
if (_data._loop)
|
||||
p._time = animation->getDuration() + MathUtil::fmod(p._time, animation->getDuration());
|
||||
else
|
||||
p._time = MathUtil::max(0.0f, p._time);
|
||||
}
|
||||
|
||||
Array<Bone *> &bones = skeleton._bones;
|
||||
const Array<int> &indices = animation->getBones();
|
||||
for (size_t i = 0, n = indices.size(); i < n; i++) bones[indices[i]]->_applied->modifyLocal(skeleton);
|
||||
|
||||
animation->apply(skeleton, p._time, p._time, _data._loop, NULL, p._mix, false, _data._additive, false, true);
|
||||
}
|
||||
|
||||
void Slider::sort(Skeleton &skeleton) {
|
||||
if (_bone != NULL && !_data._local) skeleton.sortBone(_bone);
|
||||
skeleton._updateCache.add(this);
|
||||
|
||||
Array<Bone *> &bones = skeleton._bones;
|
||||
const Array<int> &indices = _data._animation->getBones();
|
||||
for (size_t i = 0, n = indices.size(); i < n; i++) {
|
||||
Bone *bone = bones[indices[i]];
|
||||
bone->_sorted = false;
|
||||
skeleton.sortReset(bone->getChildren());
|
||||
skeleton.constrained(*bone);
|
||||
}
|
||||
|
||||
Array<Timeline *> &timelines = _data._animation->getTimelines();
|
||||
Array<Slot *> &slots = skeleton._slots;
|
||||
Array<Constraint *> &constraints = skeleton._constraints;
|
||||
Array<PhysicsConstraint *> &physics = skeleton._physics;
|
||||
size_t physicsCount = physics.size();
|
||||
for (size_t i = 0, n = timelines.size(); i < n; i++) {
|
||||
Timeline *t = timelines[i];
|
||||
|
||||
if (t->getRTTI().instanceOf(SlotTimeline::rtti)) {
|
||||
SlotTimeline *timeline = (SlotTimeline *) t;
|
||||
skeleton.constrained(*slots[timeline->getSlotIndex()]);
|
||||
} else if (t->getRTTI().instanceOf(PhysicsConstraintTimeline::rtti)) {
|
||||
PhysicsConstraintTimeline *timeline = (PhysicsConstraintTimeline *) t;
|
||||
if (timeline->getConstraintIndex() == -1) {
|
||||
for (size_t ii = 0; ii < physicsCount; ii++) skeleton.constrained(*physics[ii]);
|
||||
} else
|
||||
skeleton.constrained((Posed &) *constraints[timeline->getConstraintIndex()]);
|
||||
} else if (t->getRTTI().instanceOf(ConstraintTimeline::rtti)) {
|
||||
ConstraintTimeline *timeline = (ConstraintTimeline *) t;
|
||||
int index = timeline->getConstraintIndex();
|
||||
if (index != -1) skeleton.constrained((Posed &) *constraints[timeline->getConstraintIndex()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Slider::isSourceActive() {
|
||||
return _bone == NULL || _bone->isActive();
|
||||
}
|
||||
|
||||
Bone &Slider::getBone() {
|
||||
return *_bone;
|
||||
}
|
||||
|
||||
void Slider::setBone(Bone &bone) {
|
||||
_bone = &bone;
|
||||
}
|
||||
@ -1,109 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SliderData.h>
|
||||
#include <spine/Slider.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(SliderData, ConstraintData)
|
||||
|
||||
SliderData::SliderData(const String &name)
|
||||
: ConstraintDataGeneric<Slider, SliderPose>(name), _animation(NULL), _additive(false), _loop(false), _bone(NULL), _property(NULL), _offset(0.0f),
|
||||
_scale(0.0f), _local(false) {
|
||||
}
|
||||
|
||||
Constraint &SliderData::create(Skeleton &skeleton) {
|
||||
return *(new (__FILE__, __LINE__) Slider(*this, skeleton));
|
||||
}
|
||||
|
||||
Animation &SliderData::getAnimation() {
|
||||
return *_animation;
|
||||
}
|
||||
|
||||
void SliderData::setAnimation(Animation &animation) {
|
||||
_animation = &animation;
|
||||
}
|
||||
|
||||
bool SliderData::getAdditive() {
|
||||
return _additive;
|
||||
}
|
||||
|
||||
void SliderData::setAdditive(bool additive) {
|
||||
_additive = additive;
|
||||
}
|
||||
|
||||
bool SliderData::getLoop() {
|
||||
return _loop;
|
||||
}
|
||||
|
||||
void SliderData::setLoop(bool loop) {
|
||||
_loop = loop;
|
||||
}
|
||||
|
||||
BoneData *SliderData::getBone() {
|
||||
return _bone;
|
||||
}
|
||||
|
||||
void SliderData::setBone(BoneData *bone) {
|
||||
_bone = bone;
|
||||
}
|
||||
|
||||
FromProperty *SliderData::getProperty() {
|
||||
return _property;
|
||||
}
|
||||
|
||||
void SliderData::setProperty(FromProperty *property) {
|
||||
_property = property;
|
||||
}
|
||||
|
||||
float SliderData::getScale() {
|
||||
return _scale;
|
||||
}
|
||||
|
||||
void SliderData::setScale(float scale) {
|
||||
_scale = scale;
|
||||
}
|
||||
|
||||
float SliderData::getOffset() {
|
||||
return _offset;
|
||||
}
|
||||
|
||||
void SliderData::setOffset(float offset) {
|
||||
_offset = offset;
|
||||
}
|
||||
|
||||
bool SliderData::getLocal() {
|
||||
return _local;
|
||||
}
|
||||
|
||||
void SliderData::setLocal(bool local) {
|
||||
_local = local;
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SliderMixTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Slider.h>
|
||||
#include <spine/SliderData.h>
|
||||
#include <spine/SliderPose.h>
|
||||
#include <spine/Property.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(SliderMixTimeline, ConstraintTimeline1)
|
||||
|
||||
SliderMixTimeline::SliderMixTimeline(size_t frameCount, size_t bezierCount, int sliderIndex)
|
||||
: ConstraintTimeline1(frameCount, bezierCount, sliderIndex, Property_SliderMix) {
|
||||
PropertyId ids[] = {((PropertyId) Property_SliderMix << 32) | sliderIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
SliderMixTimeline::~SliderMixTimeline() {
|
||||
}
|
||||
|
||||
void SliderMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(out);
|
||||
|
||||
Slider *constraint = (Slider *) skeleton._constraints[_constraintIndex];
|
||||
if (constraint->isActive()) {
|
||||
SliderPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
SliderData &data = constraint->_data;
|
||||
pose._mix = getAbsoluteValue(time, alpha, fromSetup, add, pose._mix, data._setup._mix);
|
||||
}
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SliderPose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
SliderPose::SliderPose() : _time(0), _mix(0) {
|
||||
}
|
||||
|
||||
SliderPose::~SliderPose() {
|
||||
}
|
||||
|
||||
void SliderPose::set(SliderPose &pose) {
|
||||
_time = pose._time;
|
||||
_mix = pose._mix;
|
||||
}
|
||||
|
||||
float SliderPose::getTime() {
|
||||
return _time;
|
||||
}
|
||||
|
||||
void SliderPose::setTime(float time) {
|
||||
this->_time = time;
|
||||
}
|
||||
|
||||
float SliderPose::getMix() {
|
||||
return _mix;
|
||||
}
|
||||
|
||||
void SliderPose::setMix(float mix) {
|
||||
this->_mix = mix;
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SliderTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Slider.h>
|
||||
#include <spine/SliderData.h>
|
||||
#include <spine/SliderPose.h>
|
||||
#include <spine/Property.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(SliderTimeline, ConstraintTimeline1)
|
||||
|
||||
SliderTimeline::SliderTimeline(size_t frameCount, size_t bezierCount, int sliderIndex)
|
||||
: ConstraintTimeline1(frameCount, bezierCount, sliderIndex, Property_SliderTime) {
|
||||
PropertyId ids[] = {((PropertyId) Property_SliderTime << 32) | sliderIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
SliderTimeline::~SliderTimeline() {
|
||||
}
|
||||
|
||||
void SliderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(out);
|
||||
|
||||
Slider *constraint = (Slider *) skeleton._constraints[_constraintIndex];
|
||||
if (constraint->isActive()) {
|
||||
SliderPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
SliderData &data = constraint->_data;
|
||||
pose._time = getAbsoluteValue(time, alpha, fromSetup, add, pose._time, data._setup._time);
|
||||
}
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Slot.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/SlotPose.h>
|
||||
#include <spine/Color.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
Slot::Slot(SlotData &data, Skeleton &skeleton)
|
||||
: PosedGeneric<SlotData, SlotPose, SlotPose>(data), _skeleton(skeleton), _bone(*skeleton.getBones()[data._boneData._index]), _attachmentState(0) {
|
||||
|
||||
if (data.getSetupPose().hasDarkColor()) {
|
||||
_pose._hasDarkColor = true;
|
||||
_constrained._hasDarkColor = true;
|
||||
}
|
||||
setupPose();
|
||||
}
|
||||
|
||||
Bone &Slot::getBone() {
|
||||
return _bone;
|
||||
}
|
||||
|
||||
void Slot::setupPose() {
|
||||
_pose._color.set(_data._setup._color);
|
||||
if (_pose._hasDarkColor) _pose._darkColor.set(_data._setup._darkColor);
|
||||
_pose._sequenceIndex = _data._setup._sequenceIndex;
|
||||
if (_data._attachmentName.isEmpty())
|
||||
_pose.setAttachment(NULL);
|
||||
else {
|
||||
_pose._attachment = NULL;
|
||||
_pose.setAttachment(_skeleton.getAttachment(_data._index, _data._attachmentName));
|
||||
}
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SlotCurveTimeline.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotPose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_MULTI(SlotCurveTimeline, CurveTimeline, SlotTimeline)
|
||||
|
||||
SlotCurveTimeline::SlotCurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount, int slotIndex)
|
||||
: CurveTimeline(frameCount, frameEntries, bezierCount), SlotTimeline(), _slotIndex(slotIndex) {
|
||||
}
|
||||
|
||||
SlotCurveTimeline::~SlotCurveTimeline() {
|
||||
}
|
||||
|
||||
int SlotCurveTimeline::getSlotIndex() {
|
||||
return _slotIndex;
|
||||
}
|
||||
|
||||
void SlotCurveTimeline::setSlotIndex(int inValue) {
|
||||
_slotIndex = inValue;
|
||||
}
|
||||
|
||||
void SlotCurveTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(out);
|
||||
|
||||
Slot *slot = skeleton._slots[_slotIndex];
|
||||
if (slot->_bone.isActive()) _apply(*slot, appliedPose ? *slot->_applied : slot->_pose, time, alpha, fromSetup, add);
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SlotData.h>
|
||||
#include <spine/SlotPose.h>
|
||||
#include <spine/BoneData.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
SlotData::SlotData(int index, const String &name, BoneData &boneData)
|
||||
: PosedDataGeneric<SlotPose>(name), _index(index), _boneData(boneData), _attachmentName(), _blendMode(BlendMode_Normal), _visible(true) {
|
||||
assert(index >= 0);
|
||||
}
|
||||
|
||||
int SlotData::getIndex() {
|
||||
return _index;
|
||||
}
|
||||
|
||||
BoneData &SlotData::getBoneData() {
|
||||
return _boneData;
|
||||
}
|
||||
|
||||
void SlotData::setAttachmentName(const String &attachmentName) {
|
||||
_attachmentName = attachmentName;
|
||||
}
|
||||
|
||||
const String &SlotData::getAttachmentName() {
|
||||
return _attachmentName;
|
||||
}
|
||||
|
||||
BlendMode SlotData::getBlendMode() {
|
||||
return _blendMode;
|
||||
}
|
||||
|
||||
void SlotData::setBlendMode(BlendMode blendMode) {
|
||||
_blendMode = blendMode;
|
||||
}
|
||||
|
||||
bool SlotData::getVisible() {
|
||||
return _visible;
|
||||
}
|
||||
|
||||
void SlotData::setVisible(bool visible) {
|
||||
_visible = visible;
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SlotPose.h>
|
||||
#include <spine/Attachment.h>
|
||||
#include <spine/VertexAttachment.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
SlotPose::SlotPose() : _color(1, 1, 1, 1), _darkColor(0, 0, 0, 0), _hasDarkColor(false), _attachment(nullptr), _sequenceIndex(0) {
|
||||
}
|
||||
|
||||
SlotPose::~SlotPose() {
|
||||
}
|
||||
|
||||
void SlotPose::set(SlotPose &pose) {
|
||||
_color.set(pose._color);
|
||||
if (pose._hasDarkColor) _darkColor.set(pose._darkColor);
|
||||
_hasDarkColor = pose._hasDarkColor;
|
||||
_attachment = pose._attachment;
|
||||
_sequenceIndex = pose._sequenceIndex;
|
||||
_deform.clear();
|
||||
_deform.addAll(pose._deform);
|
||||
}
|
||||
|
||||
Color &SlotPose::getColor() {
|
||||
return _color;
|
||||
}
|
||||
|
||||
Color &SlotPose::getDarkColor() {
|
||||
return _darkColor;
|
||||
}
|
||||
|
||||
bool SlotPose::hasDarkColor() {
|
||||
return _hasDarkColor;
|
||||
}
|
||||
|
||||
void SlotPose::setHasDarkColor(bool hasDarkColor) {
|
||||
_hasDarkColor = hasDarkColor;
|
||||
}
|
||||
|
||||
Attachment *SlotPose::getAttachment() {
|
||||
return _attachment;
|
||||
}
|
||||
|
||||
void SlotPose::setAttachment(Attachment *attachment) {
|
||||
if (_attachment == attachment) return;
|
||||
|
||||
// Check if we need to clear deform based on timeline attachment.
|
||||
if (!attachment || !_attachment || attachment->getTimelineAttachment() != _attachment->getTimelineAttachment()) _deform.clear();
|
||||
_attachment = attachment;
|
||||
_sequenceIndex = -1;
|
||||
}
|
||||
|
||||
int SlotPose::getSequenceIndex() {
|
||||
return _sequenceIndex;
|
||||
}
|
||||
|
||||
void SlotPose::setSequenceIndex(int sequenceIndex) {
|
||||
_sequenceIndex = sequenceIndex;
|
||||
}
|
||||
|
||||
Array<float> &SlotPose::getDeform() {
|
||||
return _deform;
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SlotTimeline.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_NOPARENT(SlotTimeline)
|
||||
|
||||
SlotTimeline::SlotTimeline() {
|
||||
}
|
||||
|
||||
SlotTimeline::~SlotTimeline() {
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/SpineObject.h>
|
||||
#include <spine/Extension.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
void *SpineObject::operator new(size_t sz) {
|
||||
return SpineExtension::getInstance()->_calloc(sz, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void *SpineObject::operator new(size_t sz, const char *file, int line) {
|
||||
return SpineExtension::getInstance()->_calloc(sz, file, line);
|
||||
}
|
||||
|
||||
void *SpineObject::operator new(size_t sz, void *ptr) {
|
||||
SP_UNUSED(sz);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void SpineObject::operator delete(void *p, const char *file, int line) {
|
||||
SpineExtension::free(p, file, line);
|
||||
}
|
||||
|
||||
void SpineObject::operator delete(void *p, void *mem) {
|
||||
SP_UNUSED(mem);
|
||||
SpineExtension::free(p, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void SpineObject::operator delete(void *p) {
|
||||
SpineExtension::free(p, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
SpineObject::~SpineObject() {
|
||||
SpineExtension::beforeFree(this);
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/TextureLoader.h>
|
||||
|
||||
namespace spine {
|
||||
TextureLoader::TextureLoader() {
|
||||
}
|
||||
|
||||
TextureLoader::~TextureLoader() {
|
||||
}
|
||||
}// namespace spine
|
||||
@ -1,34 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/TextureRegion.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_NOPARENT(TextureRegion)
|
||||
@ -1,73 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Timeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_NOPARENT(Timeline)
|
||||
|
||||
Timeline::Timeline(size_t frameCount, size_t frameEntries)
|
||||
: _propertyIds(), _frames(), _frameEntries(frameEntries), _additive(false), _instant(false) {
|
||||
_frames.setSize(frameCount * frameEntries, 0);
|
||||
}
|
||||
|
||||
Timeline::~Timeline() {
|
||||
}
|
||||
|
||||
Array<PropertyId> &Timeline::getPropertyIds() {
|
||||
return _propertyIds;
|
||||
}
|
||||
|
||||
void Timeline::setPropertyIds(PropertyId propertyIds[], size_t propertyIdsCount) {
|
||||
_propertyIds.clear();
|
||||
_propertyIds.ensureCapacity(propertyIdsCount);
|
||||
for (size_t i = 0; i < propertyIdsCount; i++) {
|
||||
_propertyIds.add(propertyIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Timeline::getFrameCount() {
|
||||
return _frames.size() / _frameEntries;
|
||||
}
|
||||
|
||||
Array<float> &Timeline::getFrames() {
|
||||
return _frames;
|
||||
}
|
||||
|
||||
size_t Timeline::getFrameEntries() {
|
||||
return _frameEntries;
|
||||
}
|
||||
|
||||
float Timeline::getDuration() {
|
||||
return _frames[_frames.size() - getFrameEntries()];
|
||||
}
|
||||
@ -1,139 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/TransformConstraint.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BonePose.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/TransformConstraintData.h>
|
||||
#include <spine/MathUtil.h>
|
||||
|
||||
#include <spine/BoneData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(TransformConstraint, Constraint)
|
||||
|
||||
TransformConstraint::TransformConstraint(TransformConstraintData &data, Skeleton &skeleton) : TransformConstraintBase(data) {
|
||||
|
||||
_bones.ensureCapacity(data.getBones().size());
|
||||
for (size_t i = 0; i < data.getBones().size(); i++) {
|
||||
BoneData *boneData = data.getBones()[i];
|
||||
_bones.add(&skeleton._bones[boneData->getIndex()]->_constrained);
|
||||
}
|
||||
|
||||
_source = skeleton._bones[data._source->getIndex()];
|
||||
}
|
||||
|
||||
TransformConstraint &TransformConstraint::copy(Skeleton &skeleton) {
|
||||
TransformConstraint *copy = new (__FILE__, __LINE__) TransformConstraint(_data, skeleton);
|
||||
copy->_pose.set(_pose);
|
||||
return *copy;
|
||||
}
|
||||
|
||||
/// Applies the constraint to the constrained bones.
|
||||
void TransformConstraint::update(Skeleton &skeleton, Physics physics) {
|
||||
TransformConstraintPose &p = *_applied;
|
||||
if (p._mixRotate == 0 && p._mixX == 0 && p._mixY == 0 && p._mixScaleX == 0 && p._mixScaleY == 0 && p._mixShearY == 0) return;
|
||||
|
||||
TransformConstraintData &data = _data;
|
||||
bool localSource = data._localSource, localTarget = data._localTarget, additive = data._additive, clamp = data._clamp;
|
||||
float *offsets = data._offsets;
|
||||
BonePose &source = *_source->_applied;
|
||||
if (localSource) {
|
||||
source.validateLocalTransform(skeleton);
|
||||
}
|
||||
FromProperty **fromItems = data._properties.buffer();
|
||||
size_t fn = data._properties.size();
|
||||
int update = skeleton._update;
|
||||
BonePose **bones = _bones.buffer();
|
||||
for (size_t i = 0, n = _bones.size(); i < n; i++) {
|
||||
BonePose *bone = bones[i];
|
||||
if (localTarget) {
|
||||
bone->modifyLocal(skeleton);
|
||||
} else {
|
||||
bone->modifyWorld(update);
|
||||
}
|
||||
for (size_t f = 0; f < fn; f++) {
|
||||
FromProperty *from = fromItems[f];
|
||||
float value = from->value(skeleton, source, localSource, offsets) - from->_offset;
|
||||
Array<ToProperty *> &toProps = from->_to;
|
||||
ToProperty **toItems = toProps.buffer();
|
||||
for (size_t t = 0, tn = toProps.size(); t < tn; t++) {
|
||||
ToProperty *to = toItems[t];
|
||||
if (to->mix(p) != 0) {
|
||||
float clamped = to->_offset + value * to->_scale;
|
||||
if (clamp) {
|
||||
if (to->_offset < to->_max)
|
||||
clamped = MathUtil::clamp(clamped, to->_offset, to->_max);
|
||||
else
|
||||
clamped = MathUtil::clamp(clamped, to->_max, to->_offset);
|
||||
}
|
||||
to->apply(skeleton, p, *bone, clamped, localTarget, additive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransformConstraint::sort(Skeleton &skeleton) {
|
||||
if (!_data._localSource) skeleton.sortBone(_source);
|
||||
BonePose **bones = _bones.buffer();
|
||||
size_t boneCount = _bones.size();
|
||||
bool worldTarget = !_data._localTarget;
|
||||
if (worldTarget) {
|
||||
for (size_t i = 0; i < boneCount; i++) skeleton.sortBone(bones[i]->_bone);
|
||||
}
|
||||
skeleton._updateCache.add(this);
|
||||
for (size_t i = 0; i < boneCount; i++) {
|
||||
Bone *bone = bones[i]->_bone;
|
||||
skeleton.sortReset(bone->_children);
|
||||
skeleton.constrained(*bone);
|
||||
}
|
||||
for (size_t i = 0; i < boneCount; i++) bones[i]->_bone->_sorted = worldTarget;
|
||||
}
|
||||
|
||||
bool TransformConstraint::isSourceActive() {
|
||||
return _source->_active;
|
||||
}
|
||||
|
||||
/// The bones that will be modified by this transform constraint.
|
||||
Array<BonePose *> &TransformConstraint::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
/// The bone whose world transform will be copied to the constrained bones.
|
||||
Bone &TransformConstraint::getSource() {
|
||||
return *_source;
|
||||
}
|
||||
|
||||
void TransformConstraint::setSource(Bone &source) {
|
||||
_source = &source;
|
||||
}
|
||||
@ -1,363 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/TransformConstraintData.h>
|
||||
#include <spine/TransformConstraint.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/BonePose.h>
|
||||
#include <spine/TransformConstraintPose.h>
|
||||
#include <spine/MathUtil.h>
|
||||
#include <spine/ArrayUtils.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
// Define static constants for TransformConstraintData
|
||||
const int TransformConstraintData::ROTATION = 0;
|
||||
const int TransformConstraintData::X = 1;
|
||||
const int TransformConstraintData::Y = 2;
|
||||
const int TransformConstraintData::SCALEX = 3;
|
||||
const int TransformConstraintData::SCALEY = 4;
|
||||
const int TransformConstraintData::SHEARY = 5;
|
||||
|
||||
RTTI_IMPL(TransformConstraintData, ConstraintData)
|
||||
RTTI_IMPL_NOPARENT(FromProperty)
|
||||
RTTI_IMPL_NOPARENT(ToProperty)
|
||||
RTTI_IMPL(FromRotate, FromProperty)
|
||||
RTTI_IMPL(ToRotate, ToProperty)
|
||||
RTTI_IMPL(FromX, FromProperty)
|
||||
RTTI_IMPL(ToX, ToProperty)
|
||||
RTTI_IMPL(FromY, FromProperty)
|
||||
RTTI_IMPL(ToY, ToProperty)
|
||||
RTTI_IMPL(FromScaleX, FromProperty)
|
||||
RTTI_IMPL(ToScaleX, ToProperty)
|
||||
RTTI_IMPL(FromScaleY, FromProperty)
|
||||
RTTI_IMPL(ToScaleY, ToProperty)
|
||||
RTTI_IMPL(FromShearY, FromProperty)
|
||||
RTTI_IMPL(ToShearY, ToProperty)
|
||||
|
||||
TransformConstraintData::TransformConstraintData(const String &name)
|
||||
: ConstraintDataGeneric<TransformConstraint, TransformConstraintPose>(name), _source(NULL), _localSource(false), _localTarget(false),
|
||||
_additive(false), _clamp(false) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
_offsets[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Array<BoneData *> &TransformConstraintData::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
BoneData &TransformConstraintData::getSource() {
|
||||
return *_source;
|
||||
}
|
||||
|
||||
void TransformConstraintData::setSource(BoneData &source) {
|
||||
_source = &source;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getOffsetRotation() {
|
||||
return _offsets[ROTATION];
|
||||
}
|
||||
|
||||
void TransformConstraintData::setOffsetRotation(float offsetRotation) {
|
||||
_offsets[ROTATION] = offsetRotation;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getOffsetX() {
|
||||
return _offsets[X];
|
||||
}
|
||||
|
||||
void TransformConstraintData::setOffsetX(float offsetX) {
|
||||
_offsets[X] = offsetX;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getOffsetY() {
|
||||
return _offsets[Y];
|
||||
}
|
||||
|
||||
void TransformConstraintData::setOffsetY(float offsetY) {
|
||||
_offsets[Y] = offsetY;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getOffsetScaleX() {
|
||||
return _offsets[SCALEX];
|
||||
}
|
||||
|
||||
void TransformConstraintData::setOffsetScaleX(float offsetScaleX) {
|
||||
_offsets[SCALEX] = offsetScaleX;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getOffsetScaleY() {
|
||||
return _offsets[SCALEY];
|
||||
}
|
||||
|
||||
void TransformConstraintData::setOffsetScaleY(float offsetScaleY) {
|
||||
_offsets[SCALEY] = offsetScaleY;
|
||||
}
|
||||
|
||||
float TransformConstraintData::getOffsetShearY() {
|
||||
return _offsets[SHEARY];
|
||||
}
|
||||
|
||||
void TransformConstraintData::setOffsetShearY(float offsetShearY) {
|
||||
_offsets[SHEARY] = offsetShearY;
|
||||
}
|
||||
|
||||
bool TransformConstraintData::getLocalSource() {
|
||||
return _localSource;
|
||||
}
|
||||
|
||||
void TransformConstraintData::setLocalSource(bool localSource) {
|
||||
_localSource = localSource;
|
||||
}
|
||||
|
||||
bool TransformConstraintData::getLocalTarget() {
|
||||
return _localTarget;
|
||||
}
|
||||
|
||||
void TransformConstraintData::setLocalTarget(bool localTarget) {
|
||||
_localTarget = localTarget;
|
||||
}
|
||||
|
||||
bool TransformConstraintData::getAdditive() {
|
||||
return _additive;
|
||||
}
|
||||
|
||||
void TransformConstraintData::setAdditive(bool additive) {
|
||||
_additive = additive;
|
||||
}
|
||||
|
||||
bool TransformConstraintData::getClamp() {
|
||||
return _clamp;
|
||||
}
|
||||
|
||||
void TransformConstraintData::setClamp(bool clamp) {
|
||||
_clamp = clamp;
|
||||
}
|
||||
|
||||
Array<FromProperty *> &TransformConstraintData::getProperties() {
|
||||
return _properties;
|
||||
}
|
||||
|
||||
FromProperty::FromProperty() : SpineObject(), _offset(0) {
|
||||
}
|
||||
|
||||
FromProperty::~FromProperty() {
|
||||
}
|
||||
|
||||
ToProperty::ToProperty() : SpineObject(), _offset(0), _max(0), _scale(1) {
|
||||
}
|
||||
|
||||
ToProperty::~ToProperty() {
|
||||
}
|
||||
|
||||
float FromRotate::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) {
|
||||
if (local) return source._rotation + offsets[TransformConstraintData::ROTATION];
|
||||
float sx = skeleton.getScaleX(), sy = skeleton.getScaleY();
|
||||
float value = MathUtil::atan2(source._c / sy, source._a / sx) * MathUtil::Rad_Deg +
|
||||
((source._a * source._d - source._b * source._c) * sx * sy > 0 ? offsets[TransformConstraintData::ROTATION]
|
||||
: -offsets[TransformConstraintData::ROTATION]);
|
||||
if (value < 0) value += 360;
|
||||
return value;
|
||||
}
|
||||
|
||||
float ToRotate::mix(TransformConstraintPose &pose) {
|
||||
return pose._mixRotate;
|
||||
}
|
||||
|
||||
void ToRotate::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) {
|
||||
if (local) {
|
||||
bone._rotation += (additive ? value : value - bone._rotation) * pose._mixRotate;
|
||||
} else {
|
||||
float sx = skeleton.getScaleX(), sy = skeleton.getScaleY(), ix = 1 / sx, iy = 1 / sy;
|
||||
float a = bone._a * ix, b = bone._b * ix, c = bone._c * iy, d = bone._d * iy;
|
||||
value *= MathUtil::Deg_Rad;
|
||||
if (!additive) value -= MathUtil::atan2(c, a);
|
||||
if (value > MathUtil::Pi)
|
||||
value -= MathUtil::Pi_2;
|
||||
else if (value < -MathUtil::Pi)//
|
||||
value += MathUtil::Pi_2;
|
||||
value *= pose._mixRotate;
|
||||
float cosVal = MathUtil::cos(value), sinVal = MathUtil::sin(value);
|
||||
bone._a = (cosVal * a - sinVal * c) * sx;
|
||||
bone._b = (cosVal * b - sinVal * d) * sx;
|
||||
bone._c = (sinVal * a + cosVal * c) * sy;
|
||||
bone._d = (sinVal * b + cosVal * d) * sy;
|
||||
}
|
||||
}
|
||||
|
||||
float FromX::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) {
|
||||
return local
|
||||
? source._x + offsets[TransformConstraintData::X]
|
||||
: (offsets[TransformConstraintData::X] * source._a + offsets[TransformConstraintData::Y] * source._b + source._worldX) / skeleton.getScaleX();
|
||||
}
|
||||
|
||||
float ToX::mix(TransformConstraintPose &pose) {
|
||||
return pose._mixX;
|
||||
}
|
||||
|
||||
void ToX::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) {
|
||||
if (local) {
|
||||
bone._x += (additive ? value : value - bone._x) * pose._mixX;
|
||||
} else {
|
||||
if (!additive) value -= bone._worldX / skeleton.getScaleX();
|
||||
bone._worldX += value * pose._mixX * skeleton.getScaleX();
|
||||
}
|
||||
}
|
||||
|
||||
float FromY::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) {
|
||||
return local
|
||||
? source._y + offsets[TransformConstraintData::Y]
|
||||
: (offsets[TransformConstraintData::X] * source._c + offsets[TransformConstraintData::Y] * source._d + source._worldY) / skeleton.getScaleY();
|
||||
}
|
||||
|
||||
float ToY::mix(TransformConstraintPose &pose) {
|
||||
return pose._mixY;
|
||||
}
|
||||
|
||||
void ToY::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) {
|
||||
if (local) {
|
||||
bone._y += (additive ? value : value - bone._y) * pose._mixY;
|
||||
} else {
|
||||
if (!additive) value -= bone._worldY / skeleton.getScaleY();
|
||||
bone._worldY += value * pose._mixY * skeleton.getScaleY();
|
||||
}
|
||||
}
|
||||
|
||||
float FromScaleX::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) {
|
||||
if (local) return source._scaleX + offsets[TransformConstraintData::SCALEX];
|
||||
float a = source._a / skeleton.getScaleX(), c = source._c / skeleton.getScaleY();
|
||||
return MathUtil::sqrt(a * a + c * c) + offsets[TransformConstraintData::SCALEX];
|
||||
}
|
||||
|
||||
float ToScaleX::mix(TransformConstraintPose &pose) {
|
||||
return pose._mixScaleX;
|
||||
}
|
||||
|
||||
void ToScaleX::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) {
|
||||
if (local) {
|
||||
if (additive)
|
||||
bone._scaleX *= 1 + (value - 1) * pose._mixScaleX;
|
||||
else if (bone._scaleX != 0)//
|
||||
bone._scaleX += (value - bone._scaleX) * pose._mixScaleX;
|
||||
} else if (additive) {
|
||||
float s = 1 + (value - 1) * pose._mixScaleX;
|
||||
bone._a *= s;
|
||||
bone._c *= s;
|
||||
} else {
|
||||
float a = bone._a / skeleton.getScaleX(), c = bone._c / skeleton.getScaleY(), s = MathUtil::sqrt(a * a + c * c);
|
||||
if (s != 0) {
|
||||
s = 1 + (value - s) * pose._mixScaleX / s;
|
||||
bone._a *= s;
|
||||
bone._c *= s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float FromScaleY::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) {
|
||||
if (local) return source._scaleY + offsets[TransformConstraintData::SCALEY];
|
||||
float b = source._b / skeleton.getScaleX(), d = source._d / skeleton.getScaleY();
|
||||
return MathUtil::sqrt(b * b + d * d) + offsets[TransformConstraintData::SCALEY];
|
||||
}
|
||||
|
||||
float ToScaleY::mix(TransformConstraintPose &pose) {
|
||||
return pose._mixScaleY;
|
||||
}
|
||||
|
||||
void ToScaleY::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) {
|
||||
if (local) {
|
||||
if (additive)
|
||||
bone._scaleY *= 1 + (value - 1) * pose._mixScaleY;
|
||||
else if (bone._scaleY != 0)//
|
||||
bone._scaleY += (value - bone._scaleY) * pose._mixScaleY;
|
||||
} else if (additive) {
|
||||
float s = 1 + (value - 1) * pose._mixScaleY;
|
||||
bone._b *= s;
|
||||
bone._d *= s;
|
||||
} else {
|
||||
float b = bone._b / skeleton.getScaleX(), d = bone._d / skeleton.getScaleY(), s = MathUtil::sqrt(b * b + d * d);
|
||||
if (s != 0) {
|
||||
s = 1 + (value - s) * pose._mixScaleY / s;
|
||||
bone._b *= s;
|
||||
bone._d *= s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float FromShearY::value(Skeleton &skeleton, BonePose &source, bool local, float *offsets) {
|
||||
if (local) return source._shearY + offsets[TransformConstraintData::SHEARY];
|
||||
float ix = 1 / skeleton.getScaleX(), iy = 1 / skeleton.getScaleY();
|
||||
return (MathUtil::atan2(source._d * iy, source._b * ix) - MathUtil::atan2(source._c * iy, source._a * ix)) * MathUtil::Rad_Deg - 90 +
|
||||
offsets[TransformConstraintData::SHEARY];
|
||||
}
|
||||
|
||||
float ToShearY::mix(TransformConstraintPose &pose) {
|
||||
return pose._mixShearY;
|
||||
}
|
||||
|
||||
void ToShearY::apply(Skeleton &skeleton, TransformConstraintPose &pose, BonePose &bone, float value, bool local, bool additive) {
|
||||
if (local) {
|
||||
if (!additive) value -= bone._shearY;
|
||||
bone._shearY += value * pose._mixShearY;
|
||||
} else {
|
||||
float sx = skeleton.getScaleX(), sy = skeleton.getScaleY(), b = bone._b / sx, d = bone._d / sy, by = MathUtil::atan2(d, b);
|
||||
value = (value + 90) * MathUtil::Deg_Rad;
|
||||
if (additive)
|
||||
value -= MathUtil::Pi / 2;
|
||||
else {
|
||||
value -= by - MathUtil::atan2(bone._c / sy, bone._a / sx);
|
||||
if (value > MathUtil::Pi)
|
||||
value -= MathUtil::Pi_2;
|
||||
else if (value < -MathUtil::Pi)//
|
||||
value += MathUtil::Pi_2;
|
||||
}
|
||||
value = by + value * pose._mixShearY;
|
||||
float s = MathUtil::sqrt(b * b + d * d);
|
||||
bone._b = MathUtil::cos(value) * s * sx;
|
||||
bone._d = MathUtil::sin(value) * s * sy;
|
||||
}
|
||||
}
|
||||
|
||||
TransformConstraintData::~TransformConstraintData() {
|
||||
// Clean up all FromProperty objects, which will in turn clean up their ToProperty objects
|
||||
for (size_t i = 0; i < _properties.size(); i++) {
|
||||
FromProperty *fromProp = _properties[i];
|
||||
if (fromProp) {
|
||||
// Clean up the ToProperty objects in the FromProperty
|
||||
ArrayUtils::deleteElements(fromProp->_to);
|
||||
delete fromProp;
|
||||
}
|
||||
}
|
||||
_properties.clear();
|
||||
}
|
||||
|
||||
Constraint &TransformConstraintData::create(Skeleton &skeleton) {
|
||||
return *(new (__FILE__, __LINE__) TransformConstraint(*this, skeleton));
|
||||
}
|
||||
@ -1,95 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/TransformConstraintPose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
TransformConstraintPose::TransformConstraintPose() : _mixRotate(0), _mixX(0), _mixY(0), _mixScaleX(0), _mixScaleY(0), _mixShearY(0) {
|
||||
}
|
||||
|
||||
TransformConstraintPose::~TransformConstraintPose() {
|
||||
}
|
||||
|
||||
void TransformConstraintPose::set(TransformConstraintPose &pose) {
|
||||
_mixRotate = pose._mixRotate;
|
||||
_mixX = pose._mixX;
|
||||
_mixY = pose._mixY;
|
||||
_mixScaleX = pose._mixScaleX;
|
||||
_mixScaleY = pose._mixScaleY;
|
||||
_mixShearY = pose._mixShearY;
|
||||
}
|
||||
|
||||
float TransformConstraintPose::getMixRotate() {
|
||||
return _mixRotate;
|
||||
}
|
||||
|
||||
void TransformConstraintPose::setMixRotate(float mixRotate) {
|
||||
this->_mixRotate = mixRotate;
|
||||
}
|
||||
|
||||
float TransformConstraintPose::getMixX() {
|
||||
return _mixX;
|
||||
}
|
||||
|
||||
void TransformConstraintPose::setMixX(float mixX) {
|
||||
this->_mixX = mixX;
|
||||
}
|
||||
|
||||
float TransformConstraintPose::getMixY() {
|
||||
return _mixY;
|
||||
}
|
||||
|
||||
void TransformConstraintPose::setMixY(float mixY) {
|
||||
this->_mixY = mixY;
|
||||
}
|
||||
|
||||
float TransformConstraintPose::getMixScaleX() {
|
||||
return _mixScaleX;
|
||||
}
|
||||
|
||||
void TransformConstraintPose::setMixScaleX(float mixScaleX) {
|
||||
this->_mixScaleX = mixScaleX;
|
||||
}
|
||||
|
||||
float TransformConstraintPose::getMixScaleY() {
|
||||
return _mixScaleY;
|
||||
}
|
||||
|
||||
void TransformConstraintPose::setMixScaleY(float mixScaleY) {
|
||||
this->_mixScaleY = mixScaleY;
|
||||
}
|
||||
|
||||
float TransformConstraintPose::getMixShearY() {
|
||||
return _mixShearY;
|
||||
}
|
||||
|
||||
void TransformConstraintPose::setMixShearY(float mixShearY) {
|
||||
this->_mixShearY = mixShearY;
|
||||
}
|
||||
@ -1,148 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/TransformConstraintTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
#include <spine/Animation.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/TransformConstraint.h>
|
||||
#include <spine/TransformConstraintData.h>
|
||||
#include <spine/TransformConstraintPose.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_MULTI(TransformConstraintTimeline, CurveTimeline, ConstraintTimeline)
|
||||
|
||||
TransformConstraintTimeline::TransformConstraintTimeline(size_t frameCount, size_t bezierCount, int transformConstraintIndex)
|
||||
: CurveTimeline(frameCount, TransformConstraintTimeline::ENTRIES, bezierCount), ConstraintTimeline(), _constraintIndex(transformConstraintIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_TransformConstraint << 32) | transformConstraintIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
TransformConstraintTimeline::~TransformConstraintTimeline() {
|
||||
}
|
||||
|
||||
void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(out);
|
||||
|
||||
TransformConstraint *constraint = (TransformConstraint *) skeleton._constraints[_constraintIndex];
|
||||
if (!constraint->isActive()) return;
|
||||
TransformConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) {
|
||||
TransformConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mixRotate = setup._mixRotate;
|
||||
pose._mixX = setup._mixX;
|
||||
pose._mixY = setup._mixY;
|
||||
pose._mixScaleX = setup._mixScaleX;
|
||||
pose._mixScaleY = setup._mixScaleY;
|
||||
pose._mixShearY = setup._mixShearY;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float rotate, x, y, scaleX, scaleY, shearY;
|
||||
int i = Animation::search(_frames, time, ENTRIES);
|
||||
int curveType = (int) _curves[i / ENTRIES];
|
||||
switch (curveType) {
|
||||
case LINEAR: {
|
||||
float before = _frames[i];
|
||||
rotate = _frames[i + ROTATE];
|
||||
x = _frames[i + X];
|
||||
y = _frames[i + Y];
|
||||
scaleX = _frames[i + SCALEX];
|
||||
scaleY = _frames[i + SCALEY];
|
||||
shearY = _frames[i + SHEARY];
|
||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||
rotate += (_frames[i + ENTRIES + ROTATE] - rotate) * t;
|
||||
x += (_frames[i + ENTRIES + X] - x) * t;
|
||||
y += (_frames[i + ENTRIES + Y] - y) * t;
|
||||
scaleX += (_frames[i + ENTRIES + SCALEX] - scaleX) * t;
|
||||
scaleY += (_frames[i + ENTRIES + SCALEY] - scaleY) * t;
|
||||
shearY += (_frames[i + ENTRIES + SHEARY] - shearY) * t;
|
||||
break;
|
||||
}
|
||||
case STEPPED: {
|
||||
rotate = _frames[i + ROTATE];
|
||||
x = _frames[i + X];
|
||||
y = _frames[i + Y];
|
||||
scaleX = _frames[i + SCALEX];
|
||||
scaleY = _frames[i + SCALEY];
|
||||
shearY = _frames[i + SHEARY];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
rotate = getBezierValue(time, i, ROTATE, curveType - BEZIER);
|
||||
x = getBezierValue(time, i, X, curveType + BEZIER_SIZE - BEZIER);
|
||||
y = getBezierValue(time, i, Y, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||
scaleX = getBezierValue(time, i, SCALEX, curveType + BEZIER_SIZE * 3 - BEZIER);
|
||||
scaleY = getBezierValue(time, i, SCALEY, curveType + BEZIER_SIZE * 4 - BEZIER);
|
||||
shearY = getBezierValue(time, i, SHEARY, curveType + BEZIER_SIZE * 5 - BEZIER);
|
||||
}
|
||||
}
|
||||
|
||||
TransformConstraintPose &base = fromSetup ? constraint->_data._setup : pose;
|
||||
if (add) {
|
||||
pose._mixRotate = base._mixRotate + rotate * alpha;
|
||||
pose._mixX = base._mixX + x * alpha;
|
||||
pose._mixY = base._mixY + y * alpha;
|
||||
pose._mixScaleX = base._mixScaleX + scaleX * alpha;
|
||||
pose._mixScaleY = base._mixScaleY + scaleY * alpha;
|
||||
pose._mixShearY = base._mixShearY + shearY * alpha;
|
||||
} else {
|
||||
pose._mixRotate = base._mixRotate + (rotate - base._mixRotate) * alpha;
|
||||
pose._mixX = base._mixX + (x - base._mixX) * alpha;
|
||||
pose._mixY = base._mixY + (y - base._mixY) * alpha;
|
||||
pose._mixScaleX = base._mixScaleX + (scaleX - base._mixScaleX) * alpha;
|
||||
pose._mixScaleY = base._mixScaleY + (scaleY - base._mixScaleY) * alpha;
|
||||
pose._mixShearY = base._mixShearY + (shearY - base._mixShearY) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
void TransformConstraintTimeline::setFrame(int frame, float time, float mixRotate, float mixX, float mixY, float mixScaleX, float mixScaleY,
|
||||
float mixShearY) {
|
||||
frame *= ENTRIES;
|
||||
_frames[frame] = time;
|
||||
_frames[frame + ROTATE] = mixRotate;
|
||||
_frames[frame + X] = mixX;
|
||||
_frames[frame + Y] = mixY;
|
||||
_frames[frame + SCALEX] = mixScaleX;
|
||||
_frames[frame + SCALEY] = mixScaleY;
|
||||
_frames[frame + SHEARY] = mixShearY;
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/TranslateTimeline.h>
|
||||
|
||||
#include <spine/Event.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/Animation.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/Slot.h>
|
||||
#include <spine/SlotData.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(TranslateTimeline, BoneTimeline2)
|
||||
|
||||
TranslateTimeline::TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex)
|
||||
: BoneTimeline2(frameCount, bezierCount, boneIndex, Property_X, Property_Y) {
|
||||
}
|
||||
|
||||
void TranslateTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
SP_UNUSED(out);
|
||||
if (time < _frames[0]) {
|
||||
if (fromSetup) {
|
||||
pose._x = setup._x;
|
||||
pose._y = setup._y;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float x, y;
|
||||
int i = Animation::search(_frames, time, BoneTimeline2::ENTRIES);
|
||||
int curveType = (int) _curves[i / BoneTimeline2::ENTRIES];
|
||||
switch (curveType) {
|
||||
case CurveTimeline::LINEAR: {
|
||||
float before = _frames[i];
|
||||
x = _frames[i + BoneTimeline2::VALUE1];
|
||||
y = _frames[i + BoneTimeline2::VALUE2];
|
||||
float t = (time - before) / (_frames[i + BoneTimeline2::ENTRIES] - before);
|
||||
x += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE1] - x) * t;
|
||||
y += (_frames[i + BoneTimeline2::ENTRIES + BoneTimeline2::VALUE2] - y) * t;
|
||||
break;
|
||||
}
|
||||
case CurveTimeline::STEPPED: {
|
||||
x = _frames[i + BoneTimeline2::VALUE1];
|
||||
y = _frames[i + BoneTimeline2::VALUE2];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
x = getBezierValue(time, i, BoneTimeline2::VALUE1, curveType - BoneTimeline2::BEZIER);
|
||||
y = getBezierValue(time, i, BoneTimeline2::VALUE2, curveType + BoneTimeline2::BEZIER_SIZE - BoneTimeline2::BEZIER);
|
||||
}
|
||||
}
|
||||
|
||||
if (fromSetup) {
|
||||
pose._x = setup._x + x * alpha;
|
||||
pose._y = setup._y + y * alpha;
|
||||
} else if (add) {
|
||||
pose._x += x * alpha;
|
||||
pose._y += y * alpha;
|
||||
} else {
|
||||
pose._x += (setup._x + x - pose._x) * alpha;
|
||||
pose._y += (setup._y + y - pose._y) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
RTTI_IMPL(TranslateXTimeline, BoneTimeline1)
|
||||
|
||||
TranslateXTimeline::TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex)
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_X) {
|
||||
}
|
||||
|
||||
void TranslateXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
SP_UNUSED(out);
|
||||
pose._x = getRelativeValue(time, alpha, fromSetup, add, pose._x, setup._x);
|
||||
}
|
||||
|
||||
RTTI_IMPL(TranslateYTimeline, BoneTimeline1)
|
||||
|
||||
TranslateYTimeline::TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex)
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Y) {
|
||||
}
|
||||
|
||||
void TranslateYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
SP_UNUSED(out);
|
||||
pose._y = getRelativeValue(time, alpha, fromSetup, add, pose._y, setup._y);
|
||||
}
|
||||
@ -1,281 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Triangulator.h>
|
||||
|
||||
#include <spine/MathUtil.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
Triangulator::~Triangulator() {
|
||||
ArrayUtils::deleteElements(_convexPolygons);
|
||||
ArrayUtils::deleteElements(_convexPolygonsIndices);
|
||||
}
|
||||
|
||||
Array<int> &Triangulator::triangulate(Array<float> &vertices) {
|
||||
size_t vertexCount = vertices.size() >> 1;
|
||||
|
||||
Array<int> &indices = _indices;
|
||||
indices.clear();
|
||||
indices.ensureCapacity(vertexCount);
|
||||
indices.setSize(vertexCount, 0);
|
||||
for (int i = 0; i < (int) vertexCount; ++i) {
|
||||
indices[i] = i;
|
||||
}
|
||||
|
||||
Array<bool> &isConcaveArray = _isConcaveArray;
|
||||
isConcaveArray.ensureCapacity(vertexCount);
|
||||
isConcaveArray.setSize(vertexCount, 0);
|
||||
for (int i = 0, n = (int) vertexCount; i < n; ++i) {
|
||||
isConcaveArray[i] = isConcave(i, (int) vertexCount, vertices, indices);
|
||||
}
|
||||
|
||||
Array<int> &triangles = _triangles;
|
||||
triangles.clear();
|
||||
triangles.ensureCapacity(MathUtil::max((int) 0, (int) vertexCount - 2) << 2);
|
||||
|
||||
while (vertexCount > 3) {
|
||||
// Find ear tip.
|
||||
size_t previous = vertexCount - 1, i = 0, next = 1;
|
||||
|
||||
// outer:
|
||||
while (true) {
|
||||
if (!isConcaveArray[i]) {
|
||||
int p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
|
||||
float p1x = vertices[p1], p1y = vertices[p1 + 1];
|
||||
float p2x = vertices[p2], p2y = vertices[p2 + 1];
|
||||
float p3x = vertices[p3], p3y = vertices[p3 + 1];
|
||||
for (size_t ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
|
||||
if (!isConcaveArray[ii]) continue;
|
||||
|
||||
int v = indices[ii] << 1;
|
||||
float &vx = vertices[v], vy = vertices[v + 1];
|
||||
if (positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
|
||||
if (positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
|
||||
if (positiveArea(p2x, p2y, p3x, p3y, vx, vy)) {
|
||||
goto break_outer;// break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break_outer:
|
||||
|
||||
if (next == 0) {
|
||||
do {
|
||||
if (!isConcaveArray[i]) break;
|
||||
i--;
|
||||
} while (i > 0);
|
||||
break;
|
||||
}
|
||||
|
||||
previous = i;
|
||||
i = next;
|
||||
next = (next + 1) % vertexCount;
|
||||
}
|
||||
|
||||
// Cut ear tip.
|
||||
triangles.add(indices[(vertexCount + i - 1) % vertexCount]);
|
||||
triangles.add(indices[i]);
|
||||
triangles.add(indices[(i + 1) % vertexCount]);
|
||||
indices.removeAt(i);
|
||||
isConcaveArray.removeAt(i);
|
||||
vertexCount--;
|
||||
|
||||
int previousIndex = (int) ((vertexCount + i - 1) % vertexCount);
|
||||
int nextIndex = (int) (i == vertexCount ? 0 : i);
|
||||
isConcaveArray[previousIndex] = isConcave(previousIndex, (int) vertexCount, vertices, indices);
|
||||
isConcaveArray[nextIndex] = isConcave(nextIndex, (int) vertexCount, vertices, indices);
|
||||
}
|
||||
|
||||
if (vertexCount == 3) {
|
||||
triangles.add(indices[2]);
|
||||
triangles.add(indices[0]);
|
||||
triangles.add(indices[1]);
|
||||
}
|
||||
|
||||
return triangles;
|
||||
}
|
||||
|
||||
Array<Array<float> *> &Triangulator::decompose(Array<float> &vertices, Array<int> &triangles) {
|
||||
Array<Array<float> *> &convexPolygons = _convexPolygons;
|
||||
for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) _polygonPool.free(convexPolygons[i]);
|
||||
convexPolygons.clear();
|
||||
|
||||
Array<Array<int> *> &convexPolygonsIndices = _convexPolygonsIndices;
|
||||
for (size_t i = 0, n = convexPolygonsIndices.size(); i < n; ++i) _polygonIndicesPool.free(convexPolygonsIndices[i]);
|
||||
convexPolygonsIndices.clear();
|
||||
|
||||
Array<int> *polygonIndices = _polygonIndicesPool.obtain();
|
||||
polygonIndices->clear();
|
||||
|
||||
Array<float> *polygon = _polygonPool.obtain();
|
||||
polygon->clear();
|
||||
|
||||
// Merge subsequent triangles if they form a triangle fan.
|
||||
int fanBaseIndex = -1, lastwinding = 0;
|
||||
for (size_t i = 0, n = triangles.size(); i < n; i += 3) {
|
||||
int t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1;
|
||||
float x1 = vertices[t1], y1 = vertices[t1 + 1];
|
||||
float x2 = vertices[t2], y2 = vertices[t2 + 1];
|
||||
float x3 = vertices[t3], y3 = vertices[t3 + 1];
|
||||
|
||||
// If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan).
|
||||
bool merged = false;
|
||||
if (fanBaseIndex == t1) {
|
||||
size_t o = polygon->size() - 4;
|
||||
Array<float> &p = *polygon;
|
||||
int winding1 = winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3);
|
||||
int winding2 = winding(x3, y3, p[0], p[1], p[2], p[3]);
|
||||
if (winding1 == lastwinding && winding2 == lastwinding) {
|
||||
polygon->add(x3);
|
||||
polygon->add(y3);
|
||||
polygonIndices->add(t3);
|
||||
merged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise make this triangle the new base.
|
||||
if (!merged) {
|
||||
if (polygon->size() > 0) {
|
||||
convexPolygons.add(polygon);
|
||||
convexPolygonsIndices.add(polygonIndices);
|
||||
} else {
|
||||
_polygonPool.free(polygon);
|
||||
_polygonIndicesPool.free(polygonIndices);
|
||||
}
|
||||
|
||||
polygon = _polygonPool.obtain();
|
||||
polygon->clear();
|
||||
polygon->add(x1);
|
||||
polygon->add(y1);
|
||||
polygon->add(x2);
|
||||
polygon->add(y2);
|
||||
polygon->add(x3);
|
||||
polygon->add(y3);
|
||||
polygonIndices = _polygonIndicesPool.obtain();
|
||||
polygonIndices->clear();
|
||||
polygonIndices->add(t1);
|
||||
polygonIndices->add(t2);
|
||||
polygonIndices->add(t3);
|
||||
lastwinding = winding(x1, y1, x2, y2, x3, y3);
|
||||
fanBaseIndex = t1;
|
||||
}
|
||||
}
|
||||
|
||||
if (polygon->size() > 0) {
|
||||
convexPolygons.add(polygon);
|
||||
convexPolygonsIndices.add(polygonIndices);
|
||||
}
|
||||
|
||||
// Go through the list of polygons and try to merge the remaining triangles with the found triangle fans.
|
||||
for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) {
|
||||
polygonIndices = convexPolygonsIndices[i];
|
||||
|
||||
if (polygonIndices->size() == 0) continue;
|
||||
int firstIndex = (*polygonIndices)[0];
|
||||
int lastIndex = (*polygonIndices)[polygonIndices->size() - 1];
|
||||
|
||||
polygon = convexPolygons[i];
|
||||
size_t o = polygon->size() - 4;
|
||||
Array<float> &p = *polygon;
|
||||
float prevPrevX = p[o], prevPrevY = p[o + 1];
|
||||
float prevX = p[o + 2], prevY = p[o + 3];
|
||||
float firstX = p[0], firstY = p[1];
|
||||
float secondX = p[2], secondY = p[3];
|
||||
int winding0 = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
|
||||
|
||||
for (size_t ii = 0; ii < n; ++ii) {
|
||||
if (ii == i) continue;
|
||||
|
||||
Array<int> *otherIndicesP = convexPolygonsIndices[ii];
|
||||
Array<int> &otherIndices = *otherIndicesP;
|
||||
|
||||
if (otherIndices.size() != 3) continue;
|
||||
|
||||
int otherFirstIndex = otherIndices[0];
|
||||
int otherSecondIndex = otherIndices[1];
|
||||
int otherLastIndex = otherIndices[2];
|
||||
|
||||
Array<float> *otherPolyP = convexPolygons[ii];
|
||||
Array<float> &otherPoly = *otherPolyP;
|
||||
|
||||
float x3 = otherPoly[otherPoly.size() - 2], y3 = otherPoly[otherPoly.size() - 1];
|
||||
|
||||
if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue;
|
||||
|
||||
int winding1 = winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
|
||||
int winding2 = winding(x3, y3, firstX, firstY, secondX, secondY);
|
||||
if (winding1 == winding0 && winding2 == winding0) {
|
||||
otherPoly.clear();
|
||||
otherIndices.clear();
|
||||
polygon->add(x3);
|
||||
polygon->add(y3);
|
||||
polygonIndices->add(otherLastIndex);
|
||||
prevPrevX = prevX;
|
||||
prevPrevY = prevY;
|
||||
prevX = x3;
|
||||
prevY = y3;
|
||||
ii = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove empty polygons that resulted from the merge step above.
|
||||
for (int i = (int) convexPolygons.size() - 1; i >= 0; --i) {
|
||||
polygon = convexPolygons[i];
|
||||
if (polygon->size() == 0) {
|
||||
convexPolygons.removeAt(i);
|
||||
_polygonPool.free(polygon);
|
||||
polygonIndices = convexPolygonsIndices[i];
|
||||
convexPolygonsIndices.removeAt(i);
|
||||
_polygonIndicesPool.free(polygonIndices);
|
||||
}
|
||||
}
|
||||
|
||||
return convexPolygons;
|
||||
}
|
||||
|
||||
bool Triangulator::isConcave(int index, int vertexCount, Array<float> &vertices, Array<int> &indices) {
|
||||
int previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
|
||||
int current = indices[index] << 1;
|
||||
int next = indices[(index + 1) % vertexCount] << 1;
|
||||
|
||||
return !positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]);
|
||||
}
|
||||
|
||||
bool Triangulator::positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) {
|
||||
return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
|
||||
}
|
||||
|
||||
int Triangulator::winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) {
|
||||
float px = p2x - p1x, py = p2y - p1y;
|
||||
return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/Update.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL_NOPARENT(Update)
|
||||
|
||||
Update::Update() {
|
||||
}
|
||||
|
||||
Update::~Update() {
|
||||
}
|
||||
@ -1,166 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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/VertexAttachment.h>
|
||||
|
||||
#include <spine/Slot.h>
|
||||
|
||||
#include <spine/Bone.h>
|
||||
#include <spine/Skeleton.h>
|
||||
|
||||
using namespace spine;
|
||||
|
||||
RTTI_IMPL(VertexAttachment, Attachment)
|
||||
|
||||
VertexAttachment::VertexAttachment(const String &name) : Attachment(name), _worldVerticesLength(0), _id(getNextID()) {
|
||||
}
|
||||
|
||||
VertexAttachment::~VertexAttachment() {
|
||||
}
|
||||
|
||||
|
||||
void VertexAttachment::computeWorldVertices(Skeleton &skeleton, Slot &slot, size_t start, size_t count, Array<float> &worldVertices, size_t offset,
|
||||
size_t stride) {
|
||||
computeWorldVertices(skeleton, slot, start, count, worldVertices.buffer(), offset, stride);
|
||||
}
|
||||
|
||||
void VertexAttachment::computeWorldVertices(Skeleton &skeleton, Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset,
|
||||
size_t stride) {
|
||||
count = offset + (count >> 1) * stride;
|
||||
Array<float> *deformArray = &slot.getAppliedPose().getDeform();
|
||||
Array<float> *vertices = &_vertices;
|
||||
Array<int> &bones = _bones;
|
||||
if (bones.size() == 0) {
|
||||
if (deformArray->size() > 0) vertices = deformArray;
|
||||
|
||||
BonePose &bone = slot.getBone().getAppliedPose();
|
||||
float x = bone.getWorldX();
|
||||
float y = bone.getWorldY();
|
||||
float a = bone.getA(), b = bone.getB(), c = bone.getC(), d = bone.getD();
|
||||
for (size_t vv = start, w = offset; w < count; vv += 2, w += stride) {
|
||||
float vx = (*vertices)[vv];
|
||||
float vy = (*vertices)[vv + 1];
|
||||
worldVertices[w] = vx * a + vy * b + x;
|
||||
worldVertices[w + 1] = vx * c + vy * d + y;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int v = 0, skip = 0;
|
||||
for (size_t i = 0; i < start; i += 2) {
|
||||
int n = (int) bones[v];
|
||||
v += n + 1;
|
||||
skip += n;
|
||||
}
|
||||
|
||||
Array<Bone *> &skeletonBones = skeleton.getBones();
|
||||
if (deformArray->size() == 0) {
|
||||
for (size_t w = offset, b = skip * 3; w < count; w += stride) {
|
||||
float wx = 0, wy = 0;
|
||||
int n = (int) bones[v++];
|
||||
n += v;
|
||||
for (; v < n; v++, b += 3) {
|
||||
Bone *boneP = skeletonBones[bones[v]];
|
||||
BonePose &bonePose = boneP->getAppliedPose();
|
||||
float vx = (*vertices)[b];
|
||||
float vy = (*vertices)[b + 1];
|
||||
float weight = (*vertices)[b + 2];
|
||||
wx += (vx * bonePose.getA() + vy * bonePose.getB() + bonePose.getWorldX()) * weight;
|
||||
wy += (vx * bonePose.getC() + vy * bonePose.getD() + bonePose.getWorldY()) * weight;
|
||||
}
|
||||
worldVertices[w] = wx;
|
||||
worldVertices[w + 1] = wy;
|
||||
}
|
||||
} else {
|
||||
for (size_t w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) {
|
||||
float wx = 0, wy = 0;
|
||||
int n = (int) bones[v++];
|
||||
n += v;
|
||||
for (; v < n; v++, b += 3, f += 2) {
|
||||
Bone *boneP = skeletonBones[bones[v]];
|
||||
BonePose &bonePose = boneP->getAppliedPose();
|
||||
float vx = (*vertices)[b] + (*deformArray)[f];
|
||||
float vy = (*vertices)[b + 1] + (*deformArray)[f + 1];
|
||||
float weight = (*vertices)[b + 2];
|
||||
wx += (vx * bonePose.getA() + vy * bonePose.getB() + bonePose.getWorldX()) * weight;
|
||||
wy += (vx * bonePose.getC() + vy * bonePose.getD() + bonePose.getWorldY()) * weight;
|
||||
}
|
||||
worldVertices[w] = wx;
|
||||
worldVertices[w + 1] = wy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int VertexAttachment::getId() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
Array<int> &VertexAttachment::getBones() {
|
||||
return _bones;
|
||||
}
|
||||
|
||||
void VertexAttachment::setBones(Array<int> &bones) {
|
||||
_bones.clearAndAddAll(bones);
|
||||
}
|
||||
|
||||
Array<float> &VertexAttachment::getVertices() {
|
||||
return _vertices;
|
||||
}
|
||||
|
||||
void VertexAttachment::setVertices(Array<float> &vertices) {
|
||||
_vertices.clearAndAddAll(vertices);
|
||||
}
|
||||
|
||||
size_t VertexAttachment::getWorldVerticesLength() {
|
||||
return _worldVerticesLength;
|
||||
}
|
||||
|
||||
void VertexAttachment::setWorldVerticesLength(size_t inValue) {
|
||||
_worldVerticesLength = inValue;
|
||||
}
|
||||
|
||||
Attachment *VertexAttachment::getTimelineAttachment() {
|
||||
return Attachment::getTimelineAttachment();
|
||||
}
|
||||
|
||||
void VertexAttachment::setTimelineAttachment(Attachment *attachment) {
|
||||
Attachment::setTimelineAttachment(attachment);
|
||||
}
|
||||
|
||||
int VertexAttachment::getNextID() {
|
||||
static int nextID = 0;
|
||||
return nextID++;
|
||||
}
|
||||
|
||||
void VertexAttachment::copyTo(VertexAttachment &other) {
|
||||
other._bones.clearAndAddAll(this->_bones);
|
||||
other._vertices.clearAndAddAll(this->_vertices);
|
||||
other._worldVerticesLength = this->_worldVerticesLength;
|
||||
other.setTimelineAttachment(this->getTimelineAttachment());
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user