mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
Yay, now the C++ Runtime passes all the same tests as the C Runtime!
This commit is contained in:
parent
c1995586aa
commit
e24b061c61
@ -281,6 +281,7 @@
|
|||||||
BB6017F01FD92A5B009BD546 /* SimpleTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SimpleTest.h; sourceTree = "<group>"; };
|
BB6017F01FD92A5B009BD546 /* SimpleTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SimpleTest.h; sourceTree = "<group>"; };
|
||||||
BB6017FC1FD92AF3009BD546 /* SpineEventMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpineEventMonitor.h; sourceTree = "<group>"; };
|
BB6017FC1FD92AF3009BD546 /* SpineEventMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpineEventMonitor.h; sourceTree = "<group>"; };
|
||||||
BB6017FD1FD92AF3009BD546 /* SpineEventMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpineEventMonitor.cpp; sourceTree = "<group>"; };
|
BB6017FD1FD92AF3009BD546 /* SpineEventMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpineEventMonitor.cpp; sourceTree = "<group>"; };
|
||||||
|
BBFB507F1FDAF6CD005B22B6 /* MemoryTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MemoryTest.h; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -326,6 +327,7 @@
|
|||||||
children = (
|
children = (
|
||||||
BB6017121FD9289A009BD546 /* main.cpp */,
|
BB6017121FD9289A009BD546 /* main.cpp */,
|
||||||
BB6017F01FD92A5B009BD546 /* SimpleTest.h */,
|
BB6017F01FD92A5B009BD546 /* SimpleTest.h */,
|
||||||
|
BBFB507F1FDAF6CD005B22B6 /* MemoryTest.h */,
|
||||||
);
|
);
|
||||||
path = spine_unit_test;
|
path = spine_unit_test;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|||||||
@ -0,0 +1,444 @@
|
|||||||
|
//
|
||||||
|
// MemoryTest.h
|
||||||
|
// spine_unit_test
|
||||||
|
//
|
||||||
|
// Created by Stephen Gowen on 12/8/17.
|
||||||
|
// Copyright © 2017 Noctis Games. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MemoryTest_h
|
||||||
|
#define MemoryTest_h
|
||||||
|
|
||||||
|
#include "SpineEventMonitor.h"
|
||||||
|
|
||||||
|
#include <spine/SkeletonJson.h>
|
||||||
|
#include <spine/SkeletonData.h>
|
||||||
|
#include <spine/Atlas.h>
|
||||||
|
#include <spine/AnimationStateData.h>
|
||||||
|
#include <spine/Skeleton.h>
|
||||||
|
#include <spine/AnimationState.h>
|
||||||
|
#include <spine/Animation.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <spine/Extension.h>
|
||||||
|
#include <spine/TextureLoader.h>
|
||||||
|
#include <spine/Vector.h>
|
||||||
|
|
||||||
|
#include <spine/CurveTimeline.h>
|
||||||
|
#include <spine/VertexAttachment.h>
|
||||||
|
#include <spine/Json.h>
|
||||||
|
|
||||||
|
#include <spine/AttachmentLoader.h>
|
||||||
|
#include <spine/AtlasAttachmentLoader.h>
|
||||||
|
#include <spine/LinkedMesh.h>
|
||||||
|
#include <spine/Triangulator.h>
|
||||||
|
#include <spine/SkeletonClipping.h>
|
||||||
|
#include <spine/BoneData.h>
|
||||||
|
#include <spine/Bone.h>
|
||||||
|
#include <spine/SlotData.h>
|
||||||
|
#include <spine/Slot.h>
|
||||||
|
#include <spine/ClippingAttachment.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "KMemory.h" // last include
|
||||||
|
|
||||||
|
#define SPINEBOY_JSON "testdata/spineboy/spineboy-ess.json"
|
||||||
|
#define SPINEBOY_ATLAS "testdata/spineboy/spineboy.atlas"
|
||||||
|
|
||||||
|
#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution
|
||||||
|
|
||||||
|
namespace Spine
|
||||||
|
{
|
||||||
|
class MemoryTest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class MyTextureLoader : public TextureLoader
|
||||||
|
{
|
||||||
|
virtual void load(AtlasPage& page, std::string path)
|
||||||
|
{
|
||||||
|
page.rendererObject = NULL;
|
||||||
|
page.width = 2048;
|
||||||
|
page.height = 2048;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void unload(void* texture)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Helper methods
|
||||||
|
static SkeletonData* readSkeletonJsonData(const char* filename, Atlas* atlas)
|
||||||
|
{
|
||||||
|
Vector<Atlas*> atlasArray;
|
||||||
|
atlasArray.push_back(atlas);
|
||||||
|
|
||||||
|
SkeletonJson* skeletonJson = NEW(SkeletonJson);
|
||||||
|
new (skeletonJson) SkeletonJson(atlasArray);
|
||||||
|
assert(skeletonJson != 0);
|
||||||
|
|
||||||
|
SkeletonData* skeletonData = skeletonJson->readSkeletonDataFile(filename);
|
||||||
|
assert(skeletonData != 0);
|
||||||
|
|
||||||
|
DESTROY(SkeletonJson, skeletonJson);
|
||||||
|
|
||||||
|
return skeletonData;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loadSpineboyExample(Atlas* &atlas, SkeletonData* &skeletonData, AnimationStateData* &stateData, Skeleton* &skeleton, AnimationState* &state)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Global Animation Information
|
||||||
|
static MyTextureLoader myTextureLoader;
|
||||||
|
atlas = NEW(Atlas);
|
||||||
|
new (atlas) Atlas(SPINEBOY_ATLAS, myTextureLoader);
|
||||||
|
assert(atlas != 0);
|
||||||
|
|
||||||
|
skeletonData = readSkeletonJsonData(SPINEBOY_JSON, atlas);
|
||||||
|
assert(skeletonData != 0);
|
||||||
|
|
||||||
|
stateData = NEW(AnimationStateData);
|
||||||
|
new (stateData) AnimationStateData(*skeletonData);
|
||||||
|
assert(stateData != 0);
|
||||||
|
stateData->setDefaultMix(0.2f); // force mixing
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Animation Instance
|
||||||
|
skeleton = NEW(Skeleton);
|
||||||
|
new (skeleton) Skeleton(*skeletonData);
|
||||||
|
assert(skeleton != 0);
|
||||||
|
|
||||||
|
state = NEW(AnimationState);
|
||||||
|
new (state) AnimationState(*stateData);
|
||||||
|
assert(state != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disposeAll(Skeleton* skeleton, AnimationState* state, AnimationStateData* stateData, SkeletonData* skeletonData, Atlas* atlas)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Dispose Instance
|
||||||
|
DESTROY(Skeleton, skeleton);
|
||||||
|
DESTROY(AnimationState, state);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Dispose Global
|
||||||
|
DESTROY(AnimationStateData, stateData);
|
||||||
|
DESTROY(SkeletonData, skeletonData);
|
||||||
|
DESTROY(Atlas, atlas);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Reproduce Memory leak as described in Issue #776
|
||||||
|
// https://github.com/EsotericSoftware/spine-runtimes/issues/776
|
||||||
|
static void reproduceIssue_776()
|
||||||
|
{
|
||||||
|
Atlas* atlas = NULL;
|
||||||
|
SkeletonData* skeletonData = NULL;
|
||||||
|
AnimationStateData* stateData = NULL;
|
||||||
|
Skeleton* skeleton = NULL;
|
||||||
|
AnimationState* state = NULL;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Initialize Animations
|
||||||
|
loadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Run animation
|
||||||
|
skeleton->setToSetupPose();
|
||||||
|
InterruptMonitor eventMonitor(state);
|
||||||
|
|
||||||
|
// Interrupt the animation on this specific sequence of spEventType(s)
|
||||||
|
eventMonitor
|
||||||
|
.AddInterruptEvent(EventType_Interrupt, "jump")
|
||||||
|
.AddInterruptEvent(EventType_Start);
|
||||||
|
|
||||||
|
state->setAnimation(0, "walk", true);
|
||||||
|
state->addAnimation(0, "jump", false, 0.0f);
|
||||||
|
state->addAnimation(0, "run", true, 0.0f);
|
||||||
|
state->addAnimation(0, "jump", false, 3.0f);
|
||||||
|
state->addAnimation(0, "walk", true, 0.0f);
|
||||||
|
state->addAnimation(0, "idle", false, 1.0f);
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_RUN_TIME && eventMonitor.isAnimationPlaying(); ++i)
|
||||||
|
{
|
||||||
|
const float timeSlice = 1.0f / 60.0f;
|
||||||
|
skeleton->update(timeSlice);
|
||||||
|
state->update(timeSlice);
|
||||||
|
state->apply(*skeleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Cleanup Animations
|
||||||
|
disposeAll(skeleton, state, stateData, skeletonData, atlas);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reproduceIssue_777()
|
||||||
|
{
|
||||||
|
Atlas* atlas = NULL;
|
||||||
|
SkeletonData* skeletonData = NULL;
|
||||||
|
AnimationStateData* stateData = NULL;
|
||||||
|
Skeleton* skeleton = NULL;
|
||||||
|
AnimationState* state = NULL;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Initialize Animations
|
||||||
|
loadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Run animation
|
||||||
|
skeleton->setToSetupPose();
|
||||||
|
SpineEventMonitor eventMonitor(state);
|
||||||
|
|
||||||
|
// Set Animation and Play for 5 frames
|
||||||
|
state->setAnimation(0, "walk", true);
|
||||||
|
for (int i = 0; i < 5; ++i)
|
||||||
|
{
|
||||||
|
const float timeSlice = 1.0f / 60.0f;
|
||||||
|
skeleton->update(timeSlice);
|
||||||
|
state->update(timeSlice);
|
||||||
|
state->apply(*skeleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change animation twice in a row
|
||||||
|
state->setAnimation(0, "walk", false);
|
||||||
|
state->setAnimation(0, "run", false);
|
||||||
|
|
||||||
|
// run normal update
|
||||||
|
for (int i = 0; i < 5; ++i)
|
||||||
|
{
|
||||||
|
const float timeSlice = 1.0f / 60.0f;
|
||||||
|
skeleton->update(timeSlice);
|
||||||
|
state->update(timeSlice);
|
||||||
|
state->apply(*skeleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we'd lose mixingFrom (the first "walk" entry we set above) and should leak
|
||||||
|
state->setAnimation(0, "run", false);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Cleanup Animations
|
||||||
|
disposeAll(skeleton, state, stateData, skeletonData, atlas);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spineAnimStateHandler(AnimationState* state, EventType type, TrackEntry* entry, Event* event)
|
||||||
|
{
|
||||||
|
if (type == EventType_Complete)
|
||||||
|
{
|
||||||
|
state->setAnimation(0, "walk", false);
|
||||||
|
state->update(0);
|
||||||
|
state->apply(*skeleton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reproduceIssue_Loop()
|
||||||
|
{
|
||||||
|
Atlas* atlas = NULL;
|
||||||
|
SkeletonData* skeletonData = NULL;
|
||||||
|
AnimationStateData* stateData = NULL;
|
||||||
|
AnimationState* state = NULL;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Initialize Animations
|
||||||
|
loadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
if (state)
|
||||||
|
{
|
||||||
|
state->setOnAnimationEventFunc(spineAnimStateHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
state->setAnimation(0, "walk", false);
|
||||||
|
|
||||||
|
// run normal update
|
||||||
|
for (int i = 0; i < 50; ++i)
|
||||||
|
{
|
||||||
|
const float timeSlice = 1.0f / 60.0f;
|
||||||
|
skeleton->update(timeSlice);
|
||||||
|
state->update(timeSlice);
|
||||||
|
state->apply(*skeleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
disposeAll(skeleton, state, stateData, skeletonData, atlas);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void triangulator()
|
||||||
|
{
|
||||||
|
Triangulator* triangulator = NEW(Triangulator);
|
||||||
|
new (triangulator) Triangulator();
|
||||||
|
|
||||||
|
Vector<float> polygon;
|
||||||
|
polygon.reserve(16);
|
||||||
|
polygon.push_back(0);
|
||||||
|
polygon.push_back(0);
|
||||||
|
polygon.push_back(100);
|
||||||
|
polygon.push_back(0);
|
||||||
|
polygon.push_back(100);
|
||||||
|
polygon.push_back(100);
|
||||||
|
polygon.push_back(0);
|
||||||
|
polygon.push_back(100);
|
||||||
|
|
||||||
|
Vector<int> triangles = triangulator->triangulate(polygon);
|
||||||
|
assert(triangles.size() == 6);
|
||||||
|
assert(triangles[0] == 3);
|
||||||
|
assert(triangles[1] == 0);
|
||||||
|
assert(triangles[2] == 1);
|
||||||
|
assert(triangles[3] == 3);
|
||||||
|
assert(triangles[4] == 1);
|
||||||
|
assert(triangles[5] == 2);
|
||||||
|
|
||||||
|
Vector< Vector<float> *> polys = triangulator->decompose(polygon, triangles);
|
||||||
|
assert(polys.size() == 1);
|
||||||
|
assert(polys[0]->size() == 8);
|
||||||
|
|
||||||
|
assert(polys[0]->operator[](0) == 0);
|
||||||
|
assert(polys[0]->operator[](1) == 100);
|
||||||
|
assert(polys[0]->operator[](2) == 0);
|
||||||
|
assert(polys[0]->operator[](3) == 0);
|
||||||
|
assert(polys[0]->operator[](4) == 100);
|
||||||
|
assert(polys[0]->operator[](5) == 0);
|
||||||
|
assert(polys[0]->operator[](6) == 100);
|
||||||
|
assert(polys[0]->operator[](7) == 100);
|
||||||
|
|
||||||
|
DESTROY(Triangulator, triangulator);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void skeletonClipper()
|
||||||
|
{
|
||||||
|
Atlas* atlas = NULL;
|
||||||
|
SkeletonData* skeletonData = NULL;
|
||||||
|
AnimationStateData* stateData = NULL;
|
||||||
|
Skeleton* skeleton = NULL;
|
||||||
|
AnimationState* state = NULL;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Initialize Animations
|
||||||
|
loadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);
|
||||||
|
|
||||||
|
SkeletonClipping* clipping = NEW(SkeletonClipping);
|
||||||
|
new (clipping) SkeletonClipping();
|
||||||
|
|
||||||
|
BoneData* boneData = NEW(BoneData);
|
||||||
|
new (boneData) BoneData(0, "bone", 0);
|
||||||
|
|
||||||
|
Bone* bone = NEW(Bone);
|
||||||
|
new(bone) Bone(*boneData, *skeleton, NULL);
|
||||||
|
|
||||||
|
bone->setA(1);
|
||||||
|
bone->setB(0);
|
||||||
|
bone->setC(0);
|
||||||
|
bone->setD(1);
|
||||||
|
bone->setWorldX(0);
|
||||||
|
bone->setWorldY(0);
|
||||||
|
|
||||||
|
SlotData* slotData = NEW(SlotData);
|
||||||
|
new (slotData) SlotData(0, "slot", *boneData);
|
||||||
|
|
||||||
|
Slot* slot = NEW(Slot);
|
||||||
|
new(slot) Slot(*slotData, *bone);
|
||||||
|
|
||||||
|
ClippingAttachment* clip = NEW(ClippingAttachment);
|
||||||
|
new(clip) ClippingAttachment("clipping");
|
||||||
|
|
||||||
|
clip->setEndSlot(slotData);
|
||||||
|
clip->setWorldVerticesLength(4 * 2);
|
||||||
|
|
||||||
|
Vector<float> clipVertices;
|
||||||
|
clipVertices.reserve(8);
|
||||||
|
clipVertices.setSize(8);
|
||||||
|
|
||||||
|
clip->setVertices(clipVertices);
|
||||||
|
clip->getVertices()[0] = 0;
|
||||||
|
clip->getVertices()[1] = 50;
|
||||||
|
clip->getVertices()[2] = 100;
|
||||||
|
clip->getVertices()[3] = 50;
|
||||||
|
clip->getVertices()[4] = 100;
|
||||||
|
clip->getVertices()[5] = 70;
|
||||||
|
clip->getVertices()[6] = 0;
|
||||||
|
clip->getVertices()[7] = 70;
|
||||||
|
|
||||||
|
clipping->clipStart(*slot, clip);
|
||||||
|
|
||||||
|
Vector<float> vertices;
|
||||||
|
vertices.reserve(16);
|
||||||
|
vertices.push_back(0);
|
||||||
|
vertices.push_back(0);
|
||||||
|
vertices.push_back(100);
|
||||||
|
vertices.push_back(0);
|
||||||
|
vertices.push_back(50);
|
||||||
|
vertices.push_back(150);
|
||||||
|
|
||||||
|
Vector<float> uvs;
|
||||||
|
uvs.reserve(16);
|
||||||
|
uvs.push_back(0);
|
||||||
|
uvs.push_back(0);
|
||||||
|
uvs.push_back(1);
|
||||||
|
uvs.push_back(0);
|
||||||
|
uvs.push_back(0.5f);
|
||||||
|
uvs.push_back(1);
|
||||||
|
|
||||||
|
Vector<int> indices;
|
||||||
|
indices.reserve(16);
|
||||||
|
indices.push_back(0);
|
||||||
|
indices.push_back(1);
|
||||||
|
indices.push_back(2);
|
||||||
|
|
||||||
|
clipping->clipTriangles(vertices, static_cast<int>(vertices.size()), indices, static_cast<int>(indices.size()), uvs);
|
||||||
|
|
||||||
|
float expectedVertices[8] = { 83.333328, 50.000000, 76.666664, 70.000000, 23.333334, 70.000000, 16.666672, 50.000000 };
|
||||||
|
assert(clipping->getClippedVertices().size() == 8);
|
||||||
|
for (int i = 0; i < clipping->getClippedVertices().size(); i++)
|
||||||
|
{
|
||||||
|
assert(abs(clipping->getClippedVertices()[i] - expectedVertices[i]) < 0.001);
|
||||||
|
}
|
||||||
|
|
||||||
|
float expectedUVs[8] = { 0.833333f, 0.333333, 0.766667, 0.466667, 0.233333, 0.466667, 0.166667, 0.333333 };
|
||||||
|
assert(clipping->getClippedUVs().size() == 8);
|
||||||
|
for (int i = 0; i < clipping->getClippedUVs().size(); i++)
|
||||||
|
{
|
||||||
|
assert(abs(clipping->getClippedUVs()[i] - expectedUVs[i]) < 0.001);
|
||||||
|
}
|
||||||
|
|
||||||
|
short expectedIndices[6] = { 0, 1, 2, 0, 2, 3 };
|
||||||
|
assert(clipping->getClippedTriangles().size() == 6);
|
||||||
|
for (int i = 0; i < clipping->getClippedTriangles().size(); i++)
|
||||||
|
{
|
||||||
|
assert(clipping->getClippedTriangles()[i] == expectedIndices[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DESTROY(SlotData, slotData);
|
||||||
|
DESTROY(Slot, slot);
|
||||||
|
DESTROY(BoneData, boneData);
|
||||||
|
DESTROY(Bone, bone);
|
||||||
|
DESTROY(ClippingAttachment, clip);
|
||||||
|
DESTROY(SkeletonClipping, clipping);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Cleanup Animations
|
||||||
|
disposeAll(skeleton, state, stateData, skeletonData, atlas);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test()
|
||||||
|
{
|
||||||
|
reproduceIssue_776();
|
||||||
|
reproduceIssue_777();
|
||||||
|
reproduceIssue_Loop();
|
||||||
|
triangulator();
|
||||||
|
skeletonClipper();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Skeleton* skeleton;
|
||||||
|
|
||||||
|
// ctor, copy ctor, and assignment should be private in a Singleton
|
||||||
|
MemoryTest();
|
||||||
|
MemoryTest(const MemoryTest&);
|
||||||
|
MemoryTest& operator=(const MemoryTest&);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Skeleton* MemoryTest::skeleton = NULL;
|
||||||
|
|
||||||
|
#endif /* MemoryTest_h */
|
||||||
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// SimpleTest.h
|
// SimpleTest.h
|
||||||
// TestHarness
|
// spine_unit_test
|
||||||
//
|
//
|
||||||
// Created by Stephen Gowen on 11/9/17.
|
// Created by Stephen Gowen on 11/9/17.
|
||||||
// Copyright © 2017 Noctis Games. All rights reserved.
|
// Copyright © 2017 Noctis Games. All rights reserved.
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include "spine/Extension.h"
|
#include "spine/Extension.h"
|
||||||
|
|
||||||
#include "SimpleTest.h"
|
#include "SimpleTest.h"
|
||||||
|
#include "MemoryTest.h"
|
||||||
|
|
||||||
#include "KMemory.h" // last include
|
#include "KMemory.h" // last include
|
||||||
|
|
||||||
@ -101,6 +102,7 @@ int main(int argc, char* argv[])
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
SimpleTest::test();
|
SimpleTest::test();
|
||||||
|
MemoryTest::test();
|
||||||
|
|
||||||
// End Timing
|
// End Timing
|
||||||
time(&end_time);
|
time(&end_time);
|
||||||
|
|||||||
@ -1,338 +1,339 @@
|
|||||||
//#include <spine/Extension.h>
|
#include <spine/Extension.h>
|
||||||
//#include "MemoryTestFixture.h"
|
#include "MemoryTestFixture.h"
|
||||||
//#include "SpineEventMonitor.h"
|
#include "SpineEventMonitor.h"
|
||||||
//
|
|
||||||
//#include "KMemory.h" // last include
|
#include "KMemory.h" // last include
|
||||||
//
|
|
||||||
//#define SPINEBOY_JSON "testdata/spineboy/spineboy-ess.json"
|
#define SPINEBOY_JSON "testdata/spineboy/spineboy-ess.json"
|
||||||
//#define SPINEBOY_ATLAS "testdata/spineboy/spineboy.atlas"
|
#define SPINEBOY_ATLAS "testdata/spineboy/spineboy.atlas"
|
||||||
//
|
|
||||||
//#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution
|
#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution
|
||||||
//
|
|
||||||
//MemoryTestFixture::~MemoryTestFixture()
|
MemoryTestFixture::~MemoryTestFixture()
|
||||||
//{
|
{
|
||||||
// finalize();
|
finalize();
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//void MemoryTestFixture::initialize()
|
void MemoryTestFixture::initialize()
|
||||||
//{
|
{
|
||||||
// // on a Per- Fixture Basis, before Test execution
|
// on a Per- Fixture Basis, before Test execution
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//void MemoryTestFixture::finalize()
|
void MemoryTestFixture::finalize()
|
||||||
//{
|
{
|
||||||
// // on a Per- Fixture Basis, after all tests pass/fail
|
// on a Per- Fixture Basis, after all tests pass/fail
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//void MemoryTestFixture::setUp()
|
void MemoryTestFixture::setUp()
|
||||||
//{
|
{
|
||||||
// // Setup on Per-Test Basis
|
// Setup on Per-Test Basis
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//void MemoryTestFixture::tearDown()
|
void MemoryTestFixture::tearDown()
|
||||||
//{
|
{
|
||||||
// // Tear Down on Per-Test Basis
|
// Tear Down on Per-Test Basis
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
//// Helper methods
|
// Helper methods
|
||||||
//static spSkeletonData* readSkeletonJsonData(const char* filename, spAtlas* atlas) {
|
static spSkeletonData* readSkeletonJsonData(const char* filename, spAtlas* atlas) {
|
||||||
// spSkeletonJson* json = spSkeletonJson_create(atlas);
|
spSkeletonJson* json = spSkeletonJson_create(atlas);
|
||||||
// ASSERT(json != 0);
|
ASSERT(json != 0);
|
||||||
//
|
|
||||||
// spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, filename);
|
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, filename);
|
||||||
// ASSERT(skeletonData != 0);
|
ASSERT(skeletonData != 0);
|
||||||
//
|
|
||||||
// spSkeletonJson_dispose(json);
|
spSkeletonJson_dispose(json);
|
||||||
// return skeletonData;
|
return skeletonData;
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//static void LoadSpineboyExample(spAtlas* &atlas, spSkeletonData* &skeletonData, spAnimationStateData* &stateData, spSkeleton* &skeleton, spAnimationState* &state)
|
static void LoadSpineboyExample(spAtlas* &atlas, spSkeletonData* &skeletonData, spAnimationStateData* &stateData, spSkeleton* &skeleton, spAnimationState* &state)
|
||||||
//{
|
{
|
||||||
// ///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// // Global Animation Information
|
// Global Animation Information
|
||||||
// atlas = spAtlas_createFromFile(SPINEBOY_ATLAS, 0);
|
atlas = spAtlas_createFromFile(SPINEBOY_ATLAS, 0);
|
||||||
// ASSERT(atlas != 0);
|
ASSERT(atlas != 0);
|
||||||
//
|
|
||||||
// skeletonData = readSkeletonJsonData(SPINEBOY_JSON, atlas);
|
skeletonData = readSkeletonJsonData(SPINEBOY_JSON, atlas);
|
||||||
// ASSERT(skeletonData != 0);
|
ASSERT(skeletonData != 0);
|
||||||
//
|
|
||||||
// stateData = spAnimationStateData_create(skeletonData);
|
stateData = spAnimationStateData_create(skeletonData);
|
||||||
// ASSERT(stateData != 0);
|
ASSERT(stateData != 0);
|
||||||
// stateData->defaultMix = 0.4f; // force mixing
|
stateData->defaultMix = 0.4f; // force mixing
|
||||||
//
|
|
||||||
// ///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// // Animation Instance
|
// Animation Instance
|
||||||
// skeleton = spSkeleton_create(skeletonData);
|
skeleton = spSkeleton_create(skeletonData);
|
||||||
// ASSERT(skeleton != 0);
|
ASSERT(skeleton != 0);
|
||||||
//
|
|
||||||
// state = spAnimationState_create(stateData);
|
state = spAnimationState_create(stateData);
|
||||||
// ASSERT(state != 0);
|
ASSERT(state != 0);
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//static void DisposeAll(spSkeleton* skeleton, spAnimationState* state, spAnimationStateData* stateData, spSkeletonData* skeletonData, spAtlas* atlas)
|
static void DisposeAll(spSkeleton* skeleton, spAnimationState* state, spAnimationStateData* stateData, spSkeletonData* skeletonData, spAtlas* atlas)
|
||||||
//{
|
{
|
||||||
// ///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// // Dispose Instance
|
// Dispose Instance
|
||||||
// spSkeleton_dispose(skeleton);
|
spSkeleton_dispose(skeleton);
|
||||||
// spAnimationState_dispose(state);
|
spAnimationState_dispose(state);
|
||||||
//
|
|
||||||
// ///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// // Dispose Global
|
// Dispose Global
|
||||||
// spAnimationStateData_dispose(stateData);
|
spAnimationStateData_dispose(stateData);
|
||||||
// spSkeletonData_dispose(skeletonData);
|
spSkeletonData_dispose(skeletonData);
|
||||||
// spAtlas_dispose(atlas);
|
spAtlas_dispose(atlas);
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
//// Reproduce Memory leak as described in Issue #776
|
// Reproduce Memory leak as described in Issue #776
|
||||||
//// https://github.com/EsotericSoftware/spine-runtimes/issues/776
|
// https://github.com/EsotericSoftware/spine-runtimes/issues/776
|
||||||
//void MemoryTestFixture::reproduceIssue_776()
|
void MemoryTestFixture::reproduceIssue_776()
|
||||||
//{
|
{
|
||||||
// spAtlas* atlas = 0;
|
spAtlas* atlas = 0;
|
||||||
// spSkeletonData* skeletonData = 0;
|
spSkeletonData* skeletonData = 0;
|
||||||
// spAnimationStateData* stateData = 0;
|
spAnimationStateData* stateData = 0;
|
||||||
// spSkeleton* skeleton = 0;
|
spSkeleton* skeleton = 0;
|
||||||
// spAnimationState* state = 0;
|
spAnimationState* state = 0;
|
||||||
//
|
|
||||||
// //////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// // Initialize Animations
|
// Initialize Animations
|
||||||
// LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);
|
LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);
|
||||||
//
|
|
||||||
// ///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// // Run animation
|
// Run animation
|
||||||
// spSkeleton_setToSetupPose(skeleton);
|
spSkeleton_setToSetupPose(skeleton);
|
||||||
// InterruptMonitor eventMonitor(state);
|
InterruptMonitor eventMonitor(state);
|
||||||
// //eventMonitor.SetDebugLogging(true);
|
//eventMonitor.SetDebugLogging(true);
|
||||||
//
|
|
||||||
// // Interrupt the animation on this specific sequence of spEventType(s)
|
// Interrupt the animation on this specific sequence of spEventType(s)
|
||||||
// eventMonitor
|
eventMonitor
|
||||||
// .AddInterruptEvent(SP_ANIMATION_INTERRUPT, "jump")
|
.AddInterruptEvent(SP_ANIMATION_INTERRUPT, "jump")
|
||||||
// .AddInterruptEvent(SP_ANIMATION_START);
|
.AddInterruptEvent(SP_ANIMATION_START);
|
||||||
//
|
|
||||||
// spAnimationState_setAnimationByName(state, 0, "walk", true);
|
spAnimationState_setAnimationByName(state, 0, "walk", true);
|
||||||
// spAnimationState_addAnimationByName(state, 0, "jump", false, 0.0f);
|
spAnimationState_addAnimationByName(state, 0, "jump", false, 0.0f);
|
||||||
// spAnimationState_addAnimationByName(state, 0, "run", true, 0.0f);
|
spAnimationState_addAnimationByName(state, 0, "run", true, 0.0f);
|
||||||
// spAnimationState_addAnimationByName(state, 0, "jump", false, 3.0f);
|
spAnimationState_addAnimationByName(state, 0, "jump", false, 3.0f);
|
||||||
// spAnimationState_addAnimationByName(state, 0, "walk", true, 0.0f);
|
spAnimationState_addAnimationByName(state, 0, "walk", true, 0.0f);
|
||||||
// spAnimationState_addAnimationByName(state, 0, "idle", false, 1.0f);
|
spAnimationState_addAnimationByName(state, 0, "idle", false, 1.0f);
|
||||||
//
|
|
||||||
// for (int i = 0; i < MAX_RUN_TIME && eventMonitor.isAnimationPlaying(); ++i) {
|
for (int i = 0; i < MAX_RUN_TIME && eventMonitor.isAnimationPlaying(); ++i) {
|
||||||
// const float timeSlice = 1.0f / 60.0f;
|
const float timeSlice = 1.0f / 60.0f;
|
||||||
// spSkeleton_update(skeleton, timeSlice);
|
spSkeleton_update(skeleton, timeSlice);
|
||||||
// spAnimationState_update(state, timeSlice);
|
spAnimationState_update(state, timeSlice);
|
||||||
// spAnimationState_apply(state, skeleton);
|
spAnimationState_apply(state, skeleton);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// //////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// // Cleanup Animations
|
// Cleanup Animations
|
||||||
// DisposeAll(skeleton, state, stateData, skeletonData, atlas);
|
DisposeAll(skeleton, state, stateData, skeletonData, atlas);
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//void MemoryTestFixture::reproduceIssue_777()
|
void MemoryTestFixture::reproduceIssue_777()
|
||||||
//{
|
{
|
||||||
// spAtlas* atlas = 0;
|
spAtlas* atlas = 0;
|
||||||
// spSkeletonData* skeletonData = 0;
|
spSkeletonData* skeletonData = 0;
|
||||||
// spAnimationStateData* stateData = 0;
|
spAnimationStateData* stateData = 0;
|
||||||
// spSkeleton* skeleton = 0;
|
spSkeleton* skeleton = 0;
|
||||||
// spAnimationState* state = 0;
|
spAnimationState* state = 0;
|
||||||
//
|
|
||||||
// //////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// // Initialize Animations
|
// Initialize Animations
|
||||||
// LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);
|
LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);
|
||||||
//
|
|
||||||
// ///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// // Run animation
|
// Run animation
|
||||||
// spSkeleton_setToSetupPose(skeleton);
|
spSkeleton_setToSetupPose(skeleton);
|
||||||
// SpineEventMonitor eventMonitor(state);
|
SpineEventMonitor eventMonitor(state);
|
||||||
// //eventMonitor.SetDebugLogging(true);
|
//eventMonitor.SetDebugLogging(true);
|
||||||
//
|
|
||||||
// // Set Animation and Play for 5 frames
|
// Set Animation and Play for 5 frames
|
||||||
// spAnimationState_setAnimationByName(state, 0, "walk", true);
|
spAnimationState_setAnimationByName(state, 0, "walk", true);
|
||||||
// for (int i = 0; i < 5; ++i) {
|
for (int i = 0; i < 5; ++i) {
|
||||||
// const float timeSlice = 1.0f / 60.0f;
|
const float timeSlice = 1.0f / 60.0f;
|
||||||
// spSkeleton_update(skeleton, timeSlice);
|
spSkeleton_update(skeleton, timeSlice);
|
||||||
// spAnimationState_update(state, timeSlice);
|
spAnimationState_update(state, timeSlice);
|
||||||
// spAnimationState_apply(state, skeleton);
|
spAnimationState_apply(state, skeleton);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// // Change animation twice in a row
|
// Change animation twice in a row
|
||||||
// spAnimationState_setAnimationByName(state, 0, "walk", false);
|
spAnimationState_setAnimationByName(state, 0, "walk", false);
|
||||||
// spAnimationState_setAnimationByName(state, 0, "run", false);
|
spAnimationState_setAnimationByName(state, 0, "run", false);
|
||||||
//
|
|
||||||
// // run normal update
|
// run normal update
|
||||||
// for (int i = 0; i < 5; ++i) {
|
for (int i = 0; i < 5; ++i) {
|
||||||
// const float timeSlice = 1.0f / 60.0f;
|
const float timeSlice = 1.0f / 60.0f;
|
||||||
// spSkeleton_update(skeleton, timeSlice);
|
spSkeleton_update(skeleton, timeSlice);
|
||||||
// spAnimationState_update(state, timeSlice);
|
spAnimationState_update(state, timeSlice);
|
||||||
// spAnimationState_apply(state, skeleton);
|
spAnimationState_apply(state, skeleton);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// // Now we'd lose mixingFrom (the first "walk" entry we set above) and should leak
|
// Now we'd lose mixingFrom (the first "walk" entry we set above) and should leak
|
||||||
// spAnimationState_setAnimationByName(state, 0, "run", false);
|
spAnimationState_setAnimationByName(state, 0, "run", false);
|
||||||
//
|
|
||||||
// //////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// // Cleanup Animations
|
// Cleanup Animations
|
||||||
// DisposeAll(skeleton, state, stateData, skeletonData, atlas);
|
DisposeAll(skeleton, state, stateData, skeletonData, atlas);
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//spSkeleton* skeleton = 0;
|
spSkeleton* skeleton = 0;
|
||||||
//static void spineAnimStateHandler(spAnimationState* state, int type, spTrackEntry* entry, spEvent* event)
|
static void spineAnimStateHandler(spAnimationState* state, int type, spTrackEntry* entry, spEvent* event)
|
||||||
//{
|
{
|
||||||
// if (type == SP_ANIMATION_COMPLETE)
|
if (type == SP_ANIMATION_COMPLETE)
|
||||||
// {
|
{
|
||||||
// spAnimationState_setAnimationByName(state, 0, "walk", false);
|
spAnimationState_setAnimationByName(state, 0, "walk", false);
|
||||||
// spAnimationState_update(state, 0);
|
spAnimationState_update(state, 0);
|
||||||
// spAnimationState_apply(state, skeleton);
|
spAnimationState_apply(state, skeleton);
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//void MemoryTestFixture::reproduceIssue_Loop()
|
void MemoryTestFixture::reproduceIssue_Loop()
|
||||||
//{
|
{
|
||||||
// spAtlas* atlas = 0;
|
spAtlas* atlas = 0;
|
||||||
// spSkeletonData* skeletonData = 0;
|
spSkeletonData* skeletonData = 0;
|
||||||
// spAnimationStateData* stateData = 0;
|
spAnimationStateData* stateData = 0;
|
||||||
// spAnimationState* state = 0;
|
spAnimationState* state = 0;
|
||||||
//
|
|
||||||
// //////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// // Initialize Animations
|
// Initialize Animations
|
||||||
// LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);
|
LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state);
|
||||||
//
|
|
||||||
// ///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
//
|
|
||||||
// if (state)
|
if (state)
|
||||||
// state->listener = (spAnimationStateListener)&spineAnimStateHandler;
|
state->listener = (spAnimationStateListener)&spineAnimStateHandler;
|
||||||
//
|
|
||||||
// spAnimationState_setAnimationByName(state, 0, "walk", false);
|
spAnimationState_setAnimationByName(state, 0, "walk", false);
|
||||||
//
|
|
||||||
// // run normal update
|
// run normal update
|
||||||
// for (int i = 0; i < 50; ++i) {
|
for (int i = 0; i < 50; ++i) {
|
||||||
// const float timeSlice = 1.0f / 60.0f;
|
const float timeSlice = 1.0f / 60.0f;
|
||||||
// spSkeleton_update(skeleton, timeSlice);
|
spSkeleton_update(skeleton, timeSlice);
|
||||||
// spAnimationState_update(state, timeSlice);
|
spAnimationState_update(state, timeSlice);
|
||||||
// spAnimationState_apply(state, skeleton);
|
spAnimationState_apply(state, skeleton);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// DisposeAll(skeleton, state, stateData, skeletonData, atlas);
|
DisposeAll(skeleton, state, stateData, skeletonData, atlas);
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//void MemoryTestFixture::triangulator() {
|
void MemoryTestFixture::triangulator() {
|
||||||
// spTriangulator* triangulator = spTriangulator_create();
|
spTriangulator* triangulator = spTriangulator_create();
|
||||||
// spFloatArray* polygon = spFloatArray_create(16);
|
spFloatArray* polygon = spFloatArray_create(16);
|
||||||
// spFloatArray_add(polygon, 0);
|
spFloatArray_add(polygon, 0);
|
||||||
// spFloatArray_add(polygon, 0);
|
spFloatArray_add(polygon, 0);
|
||||||
// spFloatArray_add(polygon, 100);
|
spFloatArray_add(polygon, 100);
|
||||||
// spFloatArray_add(polygon, 0);
|
spFloatArray_add(polygon, 0);
|
||||||
// spFloatArray_add(polygon, 100);
|
spFloatArray_add(polygon, 100);
|
||||||
// spFloatArray_add(polygon, 100);
|
spFloatArray_add(polygon, 100);
|
||||||
// spFloatArray_add(polygon, 0);
|
spFloatArray_add(polygon, 0);
|
||||||
// spFloatArray_add(polygon, 100);
|
spFloatArray_add(polygon, 100);
|
||||||
//
|
|
||||||
// spShortArray* triangles = spTriangulator_triangulate(triangulator, polygon);
|
spShortArray* triangles = spTriangulator_triangulate(triangulator, polygon);
|
||||||
// ASSERT(triangles->size == 6);
|
ASSERT(triangles->size == 6);
|
||||||
// ASSERT(triangles->items[0] == 3);
|
ASSERT(triangles->items[0] == 3);
|
||||||
// ASSERT(triangles->items[1] == 0);
|
ASSERT(triangles->items[1] == 0);
|
||||||
// ASSERT(triangles->items[2] == 1);
|
ASSERT(triangles->items[2] == 1);
|
||||||
// ASSERT(triangles->items[3] == 3);
|
ASSERT(triangles->items[3] == 3);
|
||||||
// ASSERT(triangles->items[4] == 1);
|
ASSERT(triangles->items[4] == 1);
|
||||||
// ASSERT(triangles->items[5] == 2);
|
ASSERT(triangles->items[5] == 2);
|
||||||
//
|
|
||||||
// spArrayFloatArray* polys = spTriangulator_decompose(triangulator, polygon, triangles);
|
spArrayFloatArray* polys = spTriangulator_decompose(triangulator, polygon, triangles);
|
||||||
// ASSERT(polys->size == 1);
|
ASSERT(polys->size == 1);
|
||||||
// ASSERT(polys->items[0]->size == 8);
|
ASSERT(polys->items[0]->size == 8);
|
||||||
// ASSERT(polys->items[0]->items[0] == 0);
|
ASSERT(polys->items[0]->items[0] == 0);
|
||||||
// ASSERT(polys->items[0]->items[1] == 100);
|
ASSERT(polys->items[0]->items[1] == 100);
|
||||||
// ASSERT(polys->items[0]->items[2] == 0);
|
ASSERT(polys->items[0]->items[2] == 0);
|
||||||
// ASSERT(polys->items[0]->items[3] == 0);
|
ASSERT(polys->items[0]->items[3] == 0);
|
||||||
// ASSERT(polys->items[0]->items[4] == 100);
|
ASSERT(polys->items[0]->items[4] == 100);
|
||||||
// ASSERT(polys->items[0]->items[5] == 0);
|
ASSERT(polys->items[0]->items[5] == 0);
|
||||||
// ASSERT(polys->items[0]->items[6] == 100);
|
ASSERT(polys->items[0]->items[6] == 100);
|
||||||
// ASSERT(polys->items[0]->items[7] == 100);
|
ASSERT(polys->items[0]->items[7] == 100);
|
||||||
//
|
|
||||||
// spFloatArray_dispose(polygon);
|
spFloatArray_dispose(polygon);
|
||||||
// spTriangulator_dispose(triangulator);
|
spTriangulator_dispose(triangulator);
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//void MemoryTestFixture::skeletonClipper() {
|
void MemoryTestFixture::skeletonClipper() {
|
||||||
// spSkeletonClipping* clipping = spSkeletonClipping_create();
|
spSkeletonClipping* clipping = spSkeletonClipping_create();
|
||||||
//
|
|
||||||
// spBoneData* boneData = spBoneData_create(0, "bone", 0);
|
spBoneData* boneData = spBoneData_create(0, "bone", 0);
|
||||||
// spBone* bone = spBone_create(boneData, 0, 0);
|
spBone* bone = spBone_create(boneData, 0, 0);
|
||||||
// CONST_CAST(float, bone->a) = 1;
|
CONST_CAST(float, bone->a) = 1;
|
||||||
// CONST_CAST(float, bone->b) = 0;
|
CONST_CAST(float, bone->b) = 0;
|
||||||
// CONST_CAST(float, bone->c) = 0;
|
CONST_CAST(float, bone->c) = 0;
|
||||||
// CONST_CAST(float, bone->d) = 1;
|
CONST_CAST(float, bone->d) = 1;
|
||||||
// CONST_CAST(float, bone->worldX) = 0;
|
CONST_CAST(float, bone->worldX) = 0;
|
||||||
// CONST_CAST(float, bone->worldY) = 0;
|
CONST_CAST(float, bone->worldY) = 0;
|
||||||
// spSlotData* slotData = spSlotData_create(0, "slot", 0);
|
spSlotData* slotData = spSlotData_create(0, "slot", 0);
|
||||||
// spSlot* slot = spSlot_create(slotData, bone);
|
spSlot* slot = spSlot_create(slotData, bone);
|
||||||
// spClippingAttachment* clip = spClippingAttachment_create("clipping");
|
spClippingAttachment* clip = spClippingAttachment_create("clipping");
|
||||||
// clip->endSlot = slotData;
|
clip->endSlot = slotData;
|
||||||
// clip->super.worldVerticesLength = 4 * 2;
|
clip->super.worldVerticesLength = 4 * 2;
|
||||||
// clip->super.verticesCount = 4;
|
clip->super.verticesCount = 4;
|
||||||
// clip->super.vertices = MALLOC(float, 4 * 8);
|
clip->super.vertices = MALLOC(float, 4 * 8);
|
||||||
// clip->super.vertices[0] = 0;
|
clip->super.vertices[0] = 0;
|
||||||
// clip->super.vertices[1] = 50;
|
clip->super.vertices[1] = 50;
|
||||||
// clip->super.vertices[2] = 100;
|
clip->super.vertices[2] = 100;
|
||||||
// clip->super.vertices[3] = 50;
|
clip->super.vertices[3] = 50;
|
||||||
// clip->super.vertices[4] = 100;
|
clip->super.vertices[4] = 100;
|
||||||
// clip->super.vertices[5] = 70;
|
clip->super.vertices[5] = 70;
|
||||||
// clip->super.vertices[6] = 0;
|
clip->super.vertices[6] = 0;
|
||||||
// clip->super.vertices[7] = 70;
|
clip->super.vertices[7] = 70;
|
||||||
//
|
|
||||||
// spSkeletonClipping_clipStart(clipping, slot, clip);
|
spSkeletonClipping_clipStart(clipping, slot, clip);
|
||||||
//
|
|
||||||
// spFloatArray* vertices = spFloatArray_create(16);
|
spFloatArray* vertices = spFloatArray_create(16);
|
||||||
// spFloatArray_add(vertices, 0);
|
spFloatArray_add(vertices, 0);
|
||||||
// spFloatArray_add(vertices, 0);
|
spFloatArray_add(vertices, 0);
|
||||||
// spFloatArray_add(vertices, 100);
|
spFloatArray_add(vertices, 100);
|
||||||
// spFloatArray_add(vertices, 0);
|
spFloatArray_add(vertices, 0);
|
||||||
// spFloatArray_add(vertices, 50);
|
spFloatArray_add(vertices, 50);
|
||||||
// spFloatArray_add(vertices, 150);
|
spFloatArray_add(vertices, 150);
|
||||||
// spFloatArray* uvs = spFloatArray_create(16);
|
spFloatArray* uvs = spFloatArray_create(16);
|
||||||
// spFloatArray_add(uvs, 0);
|
spFloatArray_add(uvs, 0);
|
||||||
// spFloatArray_add(uvs, 0);
|
spFloatArray_add(uvs, 0);
|
||||||
// spFloatArray_add(uvs, 1);
|
spFloatArray_add(uvs, 1);
|
||||||
// spFloatArray_add(uvs, 0);
|
spFloatArray_add(uvs, 0);
|
||||||
// spFloatArray_add(uvs, 0.5f);
|
spFloatArray_add(uvs, 0.5f);
|
||||||
// spFloatArray_add(uvs, 1);
|
spFloatArray_add(uvs, 1);
|
||||||
// spUnsignedShortArray* indices = spUnsignedShortArray_create(16);
|
spUnsignedShortArray* indices = spUnsignedShortArray_create(16);
|
||||||
// spUnsignedShortArray_add(indices, 0);
|
spUnsignedShortArray_add(indices, 0);
|
||||||
// spUnsignedShortArray_add(indices, 1);
|
spUnsignedShortArray_add(indices, 1);
|
||||||
// spUnsignedShortArray_add(indices, 2);
|
spUnsignedShortArray_add(indices, 2);
|
||||||
//
|
|
||||||
// spSkeletonClipping_clipTriangles(clipping, vertices->items, vertices->size, indices->items, indices->size, uvs->items, 2);
|
spSkeletonClipping_clipTriangles(clipping, vertices->items, vertices->size, indices->items, indices->size, uvs->items, 2);
|
||||||
//
|
|
||||||
// float expectedVertices[8] = { 83.333328, 50.000000, 76.666664, 70.000000, 23.333334, 70.000000, 16.666672, 50.000000 };
|
float expectedVertices[8] = { 83.333328, 50.000000, 76.666664, 70.000000, 23.333334, 70.000000, 16.666672, 50.000000 };
|
||||||
// ASSERT(clipping->clippedVertices->size == 8);
|
ASSERT(clipping->clippedVertices->size == 8);
|
||||||
// for (int i = 0; i < clipping->clippedVertices->size; i++) {
|
for (int i = 0; i < clipping->clippedVertices->size; i++) {
|
||||||
// ASSERT(ABS(clipping->clippedVertices->items[i] - expectedVertices[i]) < 0.001);
|
ASSERT(ABS(clipping->clippedVertices->items[i] - expectedVertices[i]) < 0.001);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// float expectedUVs[8] = { 0.833333f, 0.333333, 0.766667, 0.466667, 0.233333, 0.466667, 0.166667, 0.333333 };
|
float expectedUVs[8] = { 0.833333f, 0.333333, 0.766667, 0.466667, 0.233333, 0.466667, 0.166667, 0.333333 };
|
||||||
// ASSERT(clipping->clippedUVs->size == 8);
|
ASSERT(clipping->clippedUVs->size == 8);
|
||||||
// for (int i = 0; i < clipping->clippedUVs->size; i++) {
|
for (int i = 0; i < clipping->clippedUVs->size; i++) {
|
||||||
// ASSERT(ABS(clipping->clippedUVs->items[i] - expectedUVs[i]) < 0.001);
|
ASSERT(ABS(clipping->clippedUVs->items[i] - expectedUVs[i]) < 0.001);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// short expectedIndices[6] = { 0, 1, 2, 0, 2, 3 };
|
short expectedIndices[6] = { 0, 1, 2, 0, 2, 3 };
|
||||||
// ASSERT(clipping->clippedTriangles->size == 6);
|
ASSERT(clipping->clippedTriangles->size == 6);
|
||||||
// for (int i = 0; i < clipping->clippedTriangles->size; i++) {
|
for (int i = 0; i < clipping->clippedTriangles->size; i++) {
|
||||||
// ASSERT(clipping->clippedTriangles->items[i] == expectedIndices[i]);
|
ASSERT(clipping->clippedTriangles->items[i] == expectedIndices[i]);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// spFloatArray_dispose(vertices);
|
spFloatArray_dispose(vertices);
|
||||||
// spFloatArray_dispose(uvs);
|
spFloatArray_dispose(uvs);
|
||||||
// spUnsignedShortArray_dispose(indices);
|
spUnsignedShortArray_dispose(indices);
|
||||||
//
|
|
||||||
// spSlotData_dispose(slotData);
|
spSlotData_dispose(slotData);
|
||||||
// spSlot_dispose(slot);
|
spSlot_dispose(slot);
|
||||||
// spBoneData_dispose(boneData);
|
spBoneData_dispose(boneData);
|
||||||
// spBone_dispose(bone);
|
spBone_dispose(bone);
|
||||||
// _spClippingAttachment_dispose(SUPER(SUPER(clip)));
|
_spClippingAttachment_dispose(SUPER(SUPER(clip)));
|
||||||
// spSkeletonClipping_dispose(clipping);
|
spSkeletonClipping_dispose(clipping);
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|||||||
@ -116,7 +116,7 @@ InterruptMonitor& InterruptMonitor::AddInterruptEvent(int theEventType, TrackEnt
|
|||||||
InterruptMonitor& InterruptMonitor::AddInterruptEventTrigger(const std::string & theEventTriggerName)
|
InterruptMonitor& InterruptMonitor::AddInterruptEventTrigger(const std::string & theEventTriggerName)
|
||||||
{
|
{
|
||||||
InterruptEvent ev;
|
InterruptEvent ev;
|
||||||
// ev.mEventType = SP_ANIMATION_EVENT;
|
ev.mEventType = EventType_Event;
|
||||||
ev.mEventName = theEventTriggerName;
|
ev.mEventName = theEventTriggerName;
|
||||||
mEventStack.push_back(ev);
|
mEventStack.push_back(ev);
|
||||||
return *this;
|
return *this;
|
||||||
@ -143,7 +143,7 @@ void InterruptMonitor::OnSpineAnimationStateEvent(AnimationState * state, EventT
|
|||||||
|
|
||||||
inline bool InterruptMonitor::InterruptEvent::matches(AnimationState * state, EventType type, TrackEntry * trackEntry, Event * event)
|
inline bool InterruptMonitor::InterruptEvent::matches(AnimationState * state, EventType type, TrackEntry * trackEntry, Event * event)
|
||||||
{
|
{
|
||||||
// Must match spEventType {SP_ANIMATION_START, SP_ANIMATION_INTERRUPT, SP_ANIMATION_END, SP_ANIMATION_COMPLETE, SP_ANIMATION_DISPOSE, SP_ANIMATION_EVENT }
|
// Must match EventType {EventType_Start, EventType_Interrupt, EventType_End, EventType_Complete, EventType_Dispose, EventType_Event }
|
||||||
if (mEventType == type)
|
if (mEventType == type)
|
||||||
{
|
{
|
||||||
// Looking for specific TrackEntry by pointer
|
// Looking for specific TrackEntry by pointer
|
||||||
|
|||||||
@ -162,12 +162,18 @@ namespace Spine
|
|||||||
void setAShearY(float inValue);
|
void setAShearY(float inValue);
|
||||||
|
|
||||||
float getA();
|
float getA();
|
||||||
|
void setA(float inValue);
|
||||||
float getB();
|
float getB();
|
||||||
|
void setB(float inValue);
|
||||||
float getC();
|
float getC();
|
||||||
|
void setC(float inValue);
|
||||||
float getD();
|
float getD();
|
||||||
|
void setD(float inValue);
|
||||||
|
|
||||||
float getWorldX();
|
float getWorldX();
|
||||||
|
void setWorldX(float inValue);
|
||||||
float getWorldY();
|
float getWorldY();
|
||||||
|
void setWorldY(float inValue);
|
||||||
float getWorldRotationX();
|
float getWorldRotationX();
|
||||||
float getWorldRotationY();
|
float getWorldRotationY();
|
||||||
|
|
||||||
|
|||||||
@ -54,6 +54,10 @@ namespace Spine
|
|||||||
|
|
||||||
bool isClipping();
|
bool isClipping();
|
||||||
|
|
||||||
|
Vector<float>& getClippedVertices();
|
||||||
|
Vector<int>& getClippedTriangles();
|
||||||
|
Vector<float>& getClippedUVs();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Triangulator _triangulator;
|
Triangulator _triangulator;
|
||||||
Vector<float> _clippingPolygon;
|
Vector<float> _clippingPolygon;
|
||||||
|
|||||||
@ -66,6 +66,7 @@ namespace Spine
|
|||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
deallocate(_buffer);
|
deallocate(_buffer);
|
||||||
|
_buffer = NULL;
|
||||||
|
|
||||||
_size = inVector._size;
|
_size = inVector._size;
|
||||||
_capacity = inVector._capacity;
|
_capacity = inVector._capacity;
|
||||||
@ -194,6 +195,8 @@ namespace Spine
|
|||||||
|
|
||||||
void setSize(size_t inValue)
|
void setSize(size_t inValue)
|
||||||
{
|
{
|
||||||
|
assert(inValue <= _capacity);
|
||||||
|
|
||||||
_size = inValue;
|
_size = inValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -230,7 +230,7 @@ namespace Spine
|
|||||||
_timelineDipMix.clear();
|
_timelineDipMix.clear();
|
||||||
_timelinesRotation.clear();
|
_timelinesRotation.clear();
|
||||||
|
|
||||||
_onAnimationEventFunc = NULL;
|
_onAnimationEventFunc = dummyOnAnimationEventFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event) :
|
EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event) :
|
||||||
|
|||||||
@ -521,31 +521,61 @@ namespace Spine
|
|||||||
return _a;
|
return _a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bone::setA(float inValue)
|
||||||
|
{
|
||||||
|
_a = inValue;
|
||||||
|
}
|
||||||
|
|
||||||
float Bone::getB()
|
float Bone::getB()
|
||||||
{
|
{
|
||||||
return _b;
|
return _b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bone::setB(float inValue)
|
||||||
|
{
|
||||||
|
_b = inValue;
|
||||||
|
}
|
||||||
|
|
||||||
float Bone::getC()
|
float Bone::getC()
|
||||||
{
|
{
|
||||||
return _c;
|
return _c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bone::setC(float inValue)
|
||||||
|
{
|
||||||
|
_c = inValue;
|
||||||
|
}
|
||||||
|
|
||||||
float Bone::getD()
|
float Bone::getD()
|
||||||
{
|
{
|
||||||
return _d;
|
return _d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bone::setD(float inValue)
|
||||||
|
{
|
||||||
|
_d = inValue;
|
||||||
|
}
|
||||||
|
|
||||||
float Bone::getWorldX()
|
float Bone::getWorldX()
|
||||||
{
|
{
|
||||||
return _worldX;
|
return _worldX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bone::setWorldX(float inValue)
|
||||||
|
{
|
||||||
|
_worldX = inValue;
|
||||||
|
}
|
||||||
|
|
||||||
float Bone::getWorldY()
|
float Bone::getWorldY()
|
||||||
{
|
{
|
||||||
return _worldY;
|
return _worldY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bone::setWorldY(float inValue)
|
||||||
|
{
|
||||||
|
_worldY = inValue;
|
||||||
|
}
|
||||||
|
|
||||||
float Bone::getWorldRotationX()
|
float Bone::getWorldRotationX()
|
||||||
{
|
{
|
||||||
return MathUtil::atan2(_c, _a) * RadDeg;
|
return MathUtil::atan2(_c, _a) * RadDeg;
|
||||||
|
|||||||
@ -54,6 +54,7 @@ namespace Spine
|
|||||||
|
|
||||||
int n = clip->getWorldVerticesLength();
|
int n = clip->getWorldVerticesLength();
|
||||||
_clippingPolygon.reserve(n);
|
_clippingPolygon.reserve(n);
|
||||||
|
_clippingPolygon.setSize(n);
|
||||||
clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2);
|
clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2);
|
||||||
makeClockwise(_clippingPolygon);
|
makeClockwise(_clippingPolygon);
|
||||||
Vector< Vector<float>* > clippingPolygons = _triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon));
|
Vector< Vector<float>* > clippingPolygons = _triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon));
|
||||||
@ -96,7 +97,8 @@ namespace Spine
|
|||||||
|
|
||||||
void SkeletonClipping::clipTriangles(Vector<float>& vertices, int verticesLength, Vector<int>& triangles, int trianglesLength, Vector<float>& uvs)
|
void SkeletonClipping::clipTriangles(Vector<float>& vertices, int verticesLength, Vector<int>& triangles, int trianglesLength, Vector<float>& uvs)
|
||||||
{
|
{
|
||||||
Vector<float>& clipOutput = _clipOutput, clippedVertices = _clippedVertices;
|
Vector<float>& clipOutput = _clipOutput;
|
||||||
|
Vector<float>& clippedVertices = _clippedVertices;
|
||||||
Vector<int>& clippedTriangles = _clippedTriangles;
|
Vector<int>& clippedTriangles = _clippedTriangles;
|
||||||
Vector< Vector<float>* >& polygons = _clippingPolygons;
|
Vector< Vector<float>* >& polygons = _clippingPolygons;
|
||||||
int polygonsCount = static_cast<int>(_clippingPolygons.size());
|
int polygonsCount = static_cast<int>(_clippingPolygons.size());
|
||||||
@ -135,7 +137,9 @@ namespace Spine
|
|||||||
|
|
||||||
int clipOutputCount = clipOutputLength >> 1;
|
int clipOutputCount = clipOutputLength >> 1;
|
||||||
clippedVertices.reserve(s + clipOutputCount * 2);
|
clippedVertices.reserve(s + clipOutputCount * 2);
|
||||||
|
clippedVertices.setSize(s + clipOutputCount * 2);
|
||||||
_clippedUVs.reserve(s + clipOutputCount * 2);
|
_clippedUVs.reserve(s + clipOutputCount * 2);
|
||||||
|
_clippedUVs.setSize(s + clipOutputCount * 2);
|
||||||
for (int ii = 0; ii < clipOutputLength; ii += 2)
|
for (int ii = 0; ii < clipOutputLength; ii += 2)
|
||||||
{
|
{
|
||||||
float x = clipOutput[ii], y = clipOutput[ii + 1];
|
float x = clipOutput[ii], y = clipOutput[ii + 1];
|
||||||
@ -152,6 +156,7 @@ namespace Spine
|
|||||||
|
|
||||||
s = static_cast<int>(clippedTriangles.size());
|
s = static_cast<int>(clippedTriangles.size());
|
||||||
clippedTriangles.reserve(s + 3 * (clipOutputCount - 2));
|
clippedTriangles.reserve(s + 3 * (clipOutputCount - 2));
|
||||||
|
clippedTriangles.setSize(s + 3 * (clipOutputCount - 2));
|
||||||
clipOutputCount--;
|
clipOutputCount--;
|
||||||
for (int ii = 1; ii < clipOutputCount; ii++)
|
for (int ii = 1; ii < clipOutputCount; ii++)
|
||||||
{
|
{
|
||||||
@ -165,7 +170,9 @@ namespace Spine
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
clippedVertices.reserve(s + 3 * 2);
|
clippedVertices.reserve(s + 3 * 2);
|
||||||
|
clippedVertices.setSize(s + 3 * 2);
|
||||||
_clippedUVs.reserve(s + 3 * 2);
|
_clippedUVs.reserve(s + 3 * 2);
|
||||||
|
_clippedUVs.setSize(s + 3 * 2);
|
||||||
clippedVertices[s] = x1;
|
clippedVertices[s] = x1;
|
||||||
clippedVertices[s + 1] = y1;
|
clippedVertices[s + 1] = y1;
|
||||||
clippedVertices[s + 2] = x2;
|
clippedVertices[s + 2] = x2;
|
||||||
@ -182,6 +189,7 @@ namespace Spine
|
|||||||
|
|
||||||
s = static_cast<int>(clippedTriangles.size());
|
s = static_cast<int>(clippedTriangles.size());
|
||||||
clippedTriangles.reserve(s + 3);
|
clippedTriangles.reserve(s + 3);
|
||||||
|
clippedTriangles.setSize(s + 3);
|
||||||
clippedTriangles[s] = index;
|
clippedTriangles[s] = index;
|
||||||
clippedTriangles[s + 1] = index + 1;
|
clippedTriangles[s + 1] = index + 1;
|
||||||
clippedTriangles[s + 2] = index + 2;
|
clippedTriangles[s + 2] = index + 2;
|
||||||
@ -197,9 +205,24 @@ namespace Spine
|
|||||||
return _clipAttachment != NULL;
|
return _clipAttachment != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<float>& SkeletonClipping::getClippedVertices()
|
||||||
|
{
|
||||||
|
return _clippedVertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<int>& SkeletonClipping::getClippedTriangles()
|
||||||
|
{
|
||||||
|
return _clippedTriangles;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<float>& SkeletonClipping::getClippedUVs()
|
||||||
|
{
|
||||||
|
return _clippedUVs;
|
||||||
|
}
|
||||||
|
|
||||||
bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector<float>& clippingArea, Vector<float>& output)
|
bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector<float>& clippingArea, Vector<float>& output)
|
||||||
{
|
{
|
||||||
Vector<float> originalOutput = output;
|
Vector<float>& originalOutput = output;
|
||||||
bool clipped = false;
|
bool clipped = false;
|
||||||
|
|
||||||
// Avoid copy at the end.
|
// Avoid copy at the end.
|
||||||
@ -225,7 +248,7 @@ namespace Spine
|
|||||||
input.push_back(y1);
|
input.push_back(y1);
|
||||||
output.clear();
|
output.clear();
|
||||||
|
|
||||||
Vector<float> clippingVertices = clippingArea;
|
Vector<float>& clippingVertices = clippingArea;
|
||||||
int clippingVerticesLast = static_cast<int>(clippingArea.size()) - 4;
|
int clippingVerticesLast = static_cast<int>(clippingArea.size()) - 4;
|
||||||
for (int i = 0; ; i += 2)
|
for (int i = 0; ; i += 2)
|
||||||
{
|
{
|
||||||
@ -233,7 +256,7 @@ namespace Spine
|
|||||||
float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
|
float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
|
||||||
float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
|
float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
|
||||||
|
|
||||||
Vector<float> inputVertices = input;
|
Vector<float>& inputVertices = input;
|
||||||
int inputVerticesLength = static_cast<int>(input.size()) - 2, outputStart = static_cast<int>(output.size());
|
int inputVerticesLength = static_cast<int>(input.size()) - 2, outputStart = static_cast<int>(output.size());
|
||||||
for (int ii = 0; ii < inputVerticesLength; ii += 2)
|
for (int ii = 0; ii < inputVerticesLength; ii += 2)
|
||||||
{
|
{
|
||||||
@ -299,6 +322,7 @@ namespace Spine
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
originalOutput.reserve(originalOutput.size() - 2);
|
originalOutput.reserve(originalOutput.size() - 2);
|
||||||
|
originalOutput.setSize(originalOutput.size() - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return clipped;
|
return clipped;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user