Merge branch 'master' into spine-ue4

This commit is contained in:
badlogic 2017-01-06 15:08:50 +01:00
commit e9bbe8b417
68 changed files with 651 additions and 307 deletions

19
.npmignore Normal file
View File

@ -0,0 +1,19 @@
CMakeLists.txt
examples
spine-as3
spine-c
spine-cocos2d-objc
spine-cocos2dx
spine-corona
spine-csharp
spine-js
spine-libgdx
spine-love
spine-lua
spine-monogame
spine-sfml
spine-starling
spine-threejs
spine-tk2d
spine-unity
spine-xna

29
package.json Normal file
View File

@ -0,0 +1,29 @@
{
"name": "spine-runtimes",
"version": "3.5.35",
"description": "2D skeletal animation runtimes for Spine.",
"main": "spine-ts/build/spine-all.js",
"directories": {
"example": "examples"
},
"files": [
"spine-ts"
],
"repository": {
"type": "git",
"url": "git@github.com:EsotericSoftware/spine-runtimes.git"
},
"keywords": [
"spine",
"runtimes",
"2d",
"skeletal",
"animation"
],
"author": "Esoteric Software",
"license": "SEE LICENSE IN LICENSE",
"bugs": {
"url": "https://github.com/EsotericSoftware/spine-runtimes/issues"
},
"homepage": "https://github.com/EsotericSoftware/spine-runtimes#readme"
}

View File

@ -96,6 +96,7 @@ public class Skeleton {
public function updateCache () : void {
var updateCache:Vector.<Updatable> = this._updateCache;
updateCache.length = 0;
this._updateCacheReset.length = 0;
var bones:Vector.<Bone> = this.bones;
var i:Number = 0;

View File

@ -323,11 +323,12 @@ public class AnimationState {
}
public function clearTracks ():void {
var oldTrainDisabled:Boolean = queue.drainDisabled;
queue.drainDisabled = true;
for (var i:int = 0, n:int = tracks.length; i < n; i++)
clearTrack(i);
tracks.length = 0;
queue.drainDisabled = false;
queue.drainDisabled = oldTrainDisabled;
queue.drain();
}
@ -452,12 +453,13 @@ public class AnimationState {
}
public function setEmptyAnimations (mixDuration:Number):void {
var oldDrainDisabled:Boolean = queue.drainDisabled;
queue.drainDisabled = true;
for (var i:int = 0, n:int = tracks.length; i < n; i++) {
var current:TrackEntry = tracks[i];
if (current != null) setEmptyAnimation(current.trackIndex, mixDuration);
}
queue.drainDisabled = false;
queue.drainDisabled = oldDrainDisabled;
queue.drain();
}

View File

@ -3,7 +3,7 @@ project(spine_unit_test)
set(CMAKE_INSTALL_PREFIX "./")
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -DKANJI_MEMTRACE -DUSE_CPP11_MUTEX")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -DKANJI_MEMTRACE -DUSE_CPP11_MUTEX -std=c++11")
#########################################################
# set includes
@ -55,4 +55,4 @@ add_custom_command(TARGET spine_unit_test PRE_BUILD
add_custom_command(TARGET spine_unit_test PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_LIST_DIR}/../../examples/goblins/export $<TARGET_FILE_DIR:spine_unit_test>/testdata/goblins)
${CMAKE_CURRENT_LIST_DIR}/../../examples/goblins/export $<TARGET_FILE_DIR:spine_unit_test>/testdata/goblins)

View File

@ -11,6 +11,7 @@
#include <ctime>
#include "KString.h"
#include <stdio.h>
#include "spine/extension.h"
#include "spine/spine.h"
@ -63,7 +64,7 @@ int main(int argc, char* argv[])
extern "C" { // probably unnecessary
void _spAtlasPage_createTexture(spAtlasPage* self, const char* path) {
self->rendererObject = nullptr;
self->rendererObject = 0;
self->width = 2048;
self->height = 2048;
}
@ -74,4 +75,4 @@ extern "C" { // probably unnecessary
char* _spUtil_readFile(const char* path, int* length) {
return _readFile(path, length);
}
}
}

View File

@ -27,10 +27,10 @@ void C_InterfaceTestFixture::tearDown()
static spSkeletonData* readSkeletonJsonData(const char* filename, spAtlas* atlas) {
spSkeletonJson* json = spSkeletonJson_create(atlas);
ASSERT(json != nullptr);
ASSERT(json != 0);
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, filename);
ASSERT(skeletonData != nullptr);
ASSERT(skeletonData != 0);
spSkeletonJson_dispose(json);
return skeletonData;
@ -54,22 +54,22 @@ static void testRunner(const char* jsonName, const char* atlasName)
///////////////////////////////////////////////////////////////////////////
// Global Animation Information
spAtlas* atlas = spAtlas_createFromFile(atlasName, 0);
ASSERT(atlas != nullptr);
ASSERT(atlas != 0);
spSkeletonData* skeletonData = readSkeletonJsonData(jsonName, atlas);
ASSERT(skeletonData != nullptr);
ASSERT(skeletonData != 0);
spAnimationStateData* stateData = spAnimationStateData_create(skeletonData);
ASSERT(stateData != nullptr);
ASSERT(stateData != 0);
stateData->defaultMix = 0.2f; // force mixing
///////////////////////////////////////////////////////////////////////////
// Animation Instance
spSkeleton* skeleton = spSkeleton_create(skeletonData);
ASSERT(skeleton != nullptr);
ASSERT(skeleton != 0);
spAnimationState* state = spAnimationState_create(stateData);
ASSERT(state != nullptr);
ASSERT(state != 0);
///////////////////////////////////////////////////////////////////////////

View File

@ -40,10 +40,10 @@ void MemoryTestFixture::tearDown()
// Helper methods
static spSkeletonData* readSkeletonJsonData(const char* filename, spAtlas* atlas) {
spSkeletonJson* json = spSkeletonJson_create(atlas);
ASSERT(json != nullptr);
ASSERT(json != 0);
spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, filename);
ASSERT(skeletonData != nullptr);
ASSERT(skeletonData != 0);
spSkeletonJson_dispose(json);
return skeletonData;
@ -54,22 +54,22 @@ static void LoadSpineboyExample(spAtlas* &atlas, spSkeletonData* &skeletonData,
///////////////////////////////////////////////////////////////////////////
// Global Animation Information
atlas = spAtlas_createFromFile(SPINEBOY_ATLAS, 0);
ASSERT(atlas != nullptr);
ASSERT(atlas != 0);
skeletonData = readSkeletonJsonData(SPINEBOY_JSON, atlas);
ASSERT(skeletonData != nullptr);
ASSERT(skeletonData != 0);
stateData = spAnimationStateData_create(skeletonData);
ASSERT(stateData != nullptr);
ASSERT(stateData != 0);
stateData->defaultMix = 0.4f; // force mixing
///////////////////////////////////////////////////////////////////////////
// Animation Instance
skeleton = spSkeleton_create(skeletonData);
ASSERT(skeleton != nullptr);
ASSERT(skeleton != 0);
state = spAnimationState_create(stateData);
ASSERT(state != nullptr);
ASSERT(state != 0);
}
static void DisposeAll(spSkeleton* skeleton, spAnimationState* state, spAnimationStateData* stateData, spSkeletonData* skeletonData, spAtlas* atlas)
@ -92,11 +92,11 @@ static void DisposeAll(spSkeleton* skeleton, spAnimationState* state, spAnimatio
// https://github.com/EsotericSoftware/spine-runtimes/issues/776
void MemoryTestFixture::reproduceIssue_776()
{
spAtlas* atlas = nullptr;
spSkeletonData* skeletonData = nullptr;
spAnimationStateData* stateData = nullptr;
spSkeleton* skeleton = nullptr;
spAnimationState* state = nullptr;
spAtlas* atlas = 0;
spSkeletonData* skeletonData = 0;
spAnimationStateData* stateData = 0;
spSkeleton* skeleton = 0;
spAnimationState* state = 0;
//////////////////////////////////////////////////////////////////////////
// Initialize Animations
@ -134,11 +134,11 @@ void MemoryTestFixture::reproduceIssue_776()
void MemoryTestFixture::reproduceIssue_777()
{
spAtlas* atlas = nullptr;
spSkeletonData* skeletonData = nullptr;
spAnimationStateData* stateData = nullptr;
spSkeleton* skeleton = nullptr;
spAnimationState* state = nullptr;
spAtlas* atlas = 0;
spSkeletonData* skeletonData = 0;
spAnimationStateData* stateData = 0;
spSkeleton* skeleton = 0;
spAnimationState* state = 0;
//////////////////////////////////////////////////////////////////////////
// Initialize Animations
@ -179,7 +179,7 @@ void MemoryTestFixture::reproduceIssue_777()
DisposeAll(skeleton, state, stateData, skeletonData, atlas);
}
spSkeleton* skeleton = nullptr;
spSkeleton* skeleton = 0;
static void spineAnimStateHandler(spAnimationState* state, int type, spTrackEntry* entry, spEvent* event)
{
if (type == SP_ANIMATION_COMPLETE)
@ -192,10 +192,10 @@ static void spineAnimStateHandler(spAnimationState* state, int type, spTrackEnt
void MemoryTestFixture::reproduceIssue_Loop()
{
spAtlas* atlas = nullptr;
spSkeletonData* skeletonData = nullptr;
spAnimationStateData* stateData = nullptr;
spAnimationState* state = nullptr;
spAtlas* atlas = 0;
spSkeletonData* skeletonData = 0;
spAnimationStateData* stateData = 0;
spAnimationState* state = 0;
//////////////////////////////////////////////////////////////////////////
// Initialize Animations

View File

@ -13,7 +13,7 @@ SpineEventMonitor::SpineEventMonitor(spAnimationState* _pAnimationState /*= null
SpineEventMonitor::~SpineEventMonitor()
{
pAnimState = nullptr;
pAnimState = 0;
}
void SpineEventMonitor::RegisterListener(spAnimationState * _pAnimationState)
@ -28,7 +28,7 @@ void SpineEventMonitor::RegisterListener(spAnimationState * _pAnimationState)
bool SpineEventMonitor::isAnimationPlaying()
{
if (pAnimState)
return spAnimationState_getCurrent(pAnimState, 0) != nullptr;
return spAnimationState_getCurrent(pAnimState, 0) != 0;
return false;
}
@ -42,7 +42,7 @@ void SpineEventMonitor::spineAnimStateHandler(spAnimationState * state, int type
void SpineEventMonitor::OnSpineAnimationStateEvent(spAnimationState * state, int type, spTrackEntry * trackEntry, spEvent * event)
{
const char* eventName = nullptr;
const char* eventName = 0;
if (state == pAnimState) { // only monitor ours
switch(type)
{
@ -135,7 +135,7 @@ inline bool InterruptMonitor::InterruptEvent::matches(spAnimationState * state,
if (mEventType == type) {
// Looking for specific TrackEntry by pointer
if (mTrackEntry != nullptr) {
if (mTrackEntry != 0) {
return mTrackEntry == trackEntry;
}

View File

@ -25,7 +25,7 @@ typedef struct spEvent spEvent;
class SpineEventMonitor
{
public:
SpineEventMonitor(spAnimationState* _pAnimationState = nullptr);
SpineEventMonitor(spAnimationState* _pAnimationState = 0);
virtual ~SpineEventMonitor();
void RegisterListener(spAnimationState* _pAnimationState);
@ -58,7 +58,7 @@ private:
{
InterruptEvent() {
mEventType = -1; // invalid
mTrackEntry = nullptr;
mTrackEntry = 0;
}
bool matches(spAnimationState* state, int type, spTrackEntry* trackEntry, spEvent* event);
@ -72,7 +72,7 @@ private:
public:
InterruptMonitor(spAnimationState* _pAnimationState = nullptr);
InterruptMonitor(spAnimationState* _pAnimationState = 0);
~InterruptMonitor() {}
virtual bool isAnimationPlaying() override;
@ -119,4 +119,4 @@ eventMonitor
.AddInterruptEvent(SP_ANIMATION_START); // Then, stop on any following START signal
*/
*/

View File

@ -534,12 +534,13 @@ void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry,
void spAnimationState_clearTracks (spAnimationState* self) {
_spAnimationState* internal = SUB_CAST(_spAnimationState, self);
int i, n;
int i, n, oldDrainDisabled;
oldDrainDisabled = internal->queue->drainDisabled;
internal->queue->drainDisabled = 1;
for (i = 0, n = self->tracksCount; i < n; i++)
spAnimationState_clearTrack(self, i);
self->tracksCount = 0;
internal->queue->drainDisabled = 0;
internal->queue->drainDisabled = oldDrainDisabled;
_spEventQueue_drain(internal->queue);
}
@ -674,15 +675,16 @@ spTrackEntry* spAnimationState_addEmptyAnimation(spAnimationState* self, int tra
}
void spAnimationState_setEmptyAnimations(spAnimationState* self, float mixDuration) {
int i, n;
int i, n, oldDrainDisabled;
spTrackEntry* current;
_spAnimationState* internal = SUB_CAST(_spAnimationState, self);
oldDrainDisabled = internal->queue->drainDisabled;
internal->queue->drainDisabled = 1;
for (i = 0, n = self->tracksCount; i < n; i++) {
current = self->tracks[i];
if (current) spAnimationState_setEmptyAnimation(self, current->trackIndex, mixDuration);
}
internal->queue->drainDisabled = 0;
internal->queue->drainDisabled = oldDrainDisabled;
_spEventQueue_drain(internal->queue);
}

View File

@ -81,7 +81,6 @@ void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, spSlot* slot
void spMeshAttachment_setParentMesh (spMeshAttachment* self, spMeshAttachment* parentMesh) {
CONST_CAST(spMeshAttachment*, self->parentMesh) = parentMesh;
if (parentMesh) {
self->super.worldVerticesLength = parentMesh->super.worldVerticesLength;
self->super.bones = parentMesh->super.bones;
self->super.bonesCount = parentMesh->super.bonesCount;
@ -95,6 +94,8 @@ void spMeshAttachment_setParentMesh (spMeshAttachment* self, spMeshAttachment* p
self->trianglesCount = parentMesh->trianglesCount;
self->hullLength = parentMesh->hullLength;
self->super.worldVerticesLength = parentMesh->super.worldVerticesLength;
self->edges = parentMesh->edges;
self->edgesCount = parentMesh->edgesCount;

View File

@ -14,8 +14,6 @@ spine-cocos2dx works with data exported from Spine 3.5.xx.
spine-cocos2dx supports all Spine features.
spine-cocos2dx does not yet support loading the binary format.
## Setup
The setup for cocos2d-x differs from most other Spine Runtimes because the cocos2d-x distribution includes a copy of the Spine Runtime files. This is not ideal because these files may be old and fail to work with the latest Spine editor. Also it means if cocos2d-x is updated, you may get newer Spine Runtime files which can break your application if you are not using the latest Spine editor. For these reasons, we have requested cocos2d-x to cease distributing the Spine Runtime files, but they continue to do so. The following instructions allow you to use the official Spine cocos2d-x runtime with your cocos2d-x project.

View File

@ -170,6 +170,18 @@ spTrackEntry* SkeletonAnimation::addAnimation (int trackIndex, const std::string
return spAnimationState_addAnimation(_state, trackIndex, animation, loop, delay);
}
spTrackEntry* SkeletonAnimation::setEmptyAnimation (int trackIndex, float mixDuration) {
return spAnimationState_setEmptyAnimation(_state, trackIndex, mixDuration);
}
void SkeletonAnimation::setEmptyAnimations (float mixDuration) {
spAnimationState_setEmptyAnimations(_state, mixDuration);
}
spTrackEntry* SkeletonAnimation::addEmptyAnimation (int trackIndex, float mixDuration, float delay) {
return spAnimationState_addEmptyAnimation(_state, trackIndex, mixDuration, delay);
}
spAnimation* SkeletonAnimation::findAnimation(const std::string& name) const {
return spSkeletonData_findAnimation(_skeleton->data, name.c_str());
}

View File

@ -73,6 +73,9 @@ public:
spTrackEntry* setAnimation (int trackIndex, const std::string& name, bool loop);
spTrackEntry* addAnimation (int trackIndex, const std::string& name, bool loop, float delay = 0);
spTrackEntry* setEmptyAnimation (int trackIndex, float mixDuration);
void setEmptyAnimations (float mixDuration);
spTrackEntry* addEmptyAnimation (int trackIndex, float mixDuration, float delay = 0);
spAnimation* findAnimation(const std::string& name) const;
spTrackEntry* getCurrent (int trackIndex = 0);
void clearTracks ();

View File

@ -343,12 +343,13 @@ namespace Spine {
/// It may be desired to use <see cref="AnimationState.SetEmptyAnimations(float)"/> to mix the skeletons back to the setup pose,
/// rather than leaving them in their previous pose.</summary>
public void ClearTracks () {
bool oldDrainDisabled = queue.drainDisabled;
queue.drainDisabled = true;
for (int i = 0, n = tracks.Count; i < n; i++) {
ClearTrack(i);
}
tracks.Clear();
queue.drainDisabled = false;
queue.drainDisabled = oldDrainDisabled;
queue.Drain();
}
@ -510,12 +511,13 @@ namespace Spine {
/// <summary>
/// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration.</summary>
public void SetEmptyAnimations (float mixDuration) {
bool oldDrainDisabled = queue.drainDisabled;
queue.drainDisabled = true;
for (int i = 0, n = tracks.Count; i < n; i++) {
TrackEntry current = tracks.Items[i];
if (current != null) SetEmptyAnimation(i, mixDuration);
}
queue.drainDisabled = false;
queue.drainDisabled = oldDrainDisabled;
queue.Drain();
}

View File

@ -118,6 +118,7 @@ namespace Spine {
public void UpdateCache () {
ExposedList<IUpdatable> updateCache = this.updateCache;
updateCache.Clear();
this.updateCacheReset.Clear();
ExposedList<Bone> bones = this.bones;
for (int i = 0, n = bones.Count; i < n; i++)

View File

@ -110,6 +110,30 @@ namespace Spine {
TransformMode.NoScaleOrReflection
};
/// <summary>Returns the version string of binary skeleton data.</summary>
public static string GetVersionString (Stream input) {
if (input == null) throw new ArgumentNullException("input");
try {
// Hash.
int byteCount = ReadVarint(input, true);
if (byteCount > 1) input.Position += byteCount - 1;
// Version.
byteCount = ReadVarint(input, true);
if (byteCount > 1) {
byteCount--;
var buffer = new byte[byteCount];
ReadFully(input, buffer, 0, byteCount);
return System.Text.Encoding.UTF8.GetString(buffer, 0, byteCount);
}
throw new ArgumentException("Stream does not contain a valid binary Skeleton Data.", "input");
} catch (Exception e) {
throw new ArgumentException("Stream does not contain a valid binary Skeleton Data.\n" + e, "input");
}
}
public SkeletonData ReadSkeletonData (Stream input) {
if (input == null) throw new ArgumentNullException("input");
float scale = Scale;

View File

@ -339,11 +339,12 @@ public class AnimationState {
* It may be desired to use {@link AnimationState#setEmptyAnimations(float)} to mix the skeletons back to the setup pose,
* rather than leaving them in their previous pose. */
public void clearTracks () {
boolean oldDrainDisabled = queue.drainDisabled;
queue.drainDisabled = true;
for (int i = 0, n = tracks.size; i < n; i++)
clearTrack(i);
tracks.clear();
queue.drainDisabled = false;
queue.drainDisabled = oldDrainDisabled;
queue.drain();
}
@ -504,12 +505,13 @@ public class AnimationState {
/** Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix
* duration. */
public void setEmptyAnimations (float mixDuration) {
boolean oldDrainDisabled = queue.drainDisabled;
queue.drainDisabled = true;
for (int i = 0, n = tracks.size; i < n; i++) {
TrackEntry current = tracks.get(i);
if (current != null) setEmptyAnimation(current.trackIndex, mixDuration);
}
queue.drainDisabled = false;
queue.drainDisabled = oldDrainDisabled;
queue.drain();
}

View File

@ -157,6 +157,7 @@ public class Skeleton {
public void updateCache () {
Array<Updatable> updateCache = this.updateCache;
updateCache.clear();
updateCacheReset.clear();
Array<Bone> bones = this.bones;
for (int i = 0, n = bones.size; i < n; i++)

View File

@ -261,6 +261,7 @@ public class MeshAttachment extends VertexAttachment {
regionUVs = parentMesh.regionUVs;
triangles = parentMesh.triangles;
hullLength = parentMesh.hullLength;
worldVerticesLength = parentMesh.worldVerticesLength;
edges = parentMesh.edges;
width = parentMesh.width;
height = parentMesh.height;

View File

@ -496,12 +496,13 @@ end
function AnimationState:clearTracks ()
local queue = self.queue
local tracks = self.tracks
local oldDrainDisabled = queue.drainDisabled
queue.drainDisabled = true;
for i,track in pairs(tracks) do
self:clearTrack(i)
end
tracks = {}
queue.drainDisabled = false;
queue.drainDisabled = oldDrainDisabled
queue:drain();
end
@ -635,11 +636,12 @@ end
function AnimationState:setEmptyAnimations (mixDuration)
local queue = self.queue
local oldDrainDisabled = queue.drainDisabled
queue.drainDisabled = true
for i,current in pairs(self.tracks) do
if current then self:setEmptyAnimation(current.trackIndex, mixDuration) end
end
queue.drainDisabled = false
queue.drainDisabled = oldDrainDisabled
queue:drain()
end

View File

@ -110,6 +110,7 @@ end
function Skeleton:updateCache ()
local updateCache = {}
self._updateCache = updateCache
self.updateCacheReset = {}
local bones = self.bones
for i, bone in ipairs(bones) do
@ -511,10 +512,10 @@ function Skeleton:update (delta)
end
function Skeleton:setColor (r, g, b, a)
self.r = r
self.g = g
self.b = b
self.a = a
self.color.r = r
self.color.g = g
self.color.b = b
self.color.a = a
end
return Skeleton

View File

@ -224,6 +224,7 @@ function MeshAttachment:setParentMesh (parentMesh)
self.regionUVs = parentMesh.regionUVs
self.triangles = parentMesh.triangles
self.hullLength = parentMesh.hullLength
self.worldVerticesLength = parentMesh.worldVerticesLength
end
end

View File

@ -3,8 +3,8 @@
#
set(DEPS_DIR "${CMAKE_CURRENT_LIST_DIR}/dependencies/")
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(SFML_URL "http://www.sfml-dev.org/files/SFML-2.3.2-osx-clang-universal.tar.gz")
set(SFML_DIR ${DEPS_DIR}/SFML-2.3.2-osx-clang-universal)
set(SFML_URL "http://www.sfml-dev.org/files/SFML-2.4.1-osx-clang.tar.gz")
set(SFML_DIR ${DEPS_DIR}/SFML-2.4.1-osx-clang)
if (NOT EXISTS "${SFML_DIR}")
message("Downloading SFML for Mac OS X")
file(DOWNLOAD "${SFML_URL}" "${DEPS_DIR}/sfml.tar.gz")
@ -19,8 +19,8 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
)
endif()
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(SFML_URL "http://www.sfml-dev.org/files/SFML-2.3.2-linux-gcc-64-bit.tar.gz")
set(SFML_DIR ${DEPS_DIR}/SFML-2.3.2)
set(SFML_URL "http://www.sfml-dev.org/files/SFML-2.4.1-linux-gcc-64-bit.tar.gz")
set(SFML_DIR ${DEPS_DIR}/SFML-2.4.1)
if (NOT EXISTS ${SFML_DIR})
message("Downloading SFML for Linux 64-bit")
file(DOWNLOAD "${SFML_URL}" "${DEPS_DIR}/sfml.tar.gz")
@ -30,8 +30,8 @@ elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
)
endif()
else()
set(SFML_URL "http://www.sfml-dev.org/files/SFML-2.3.2-windows-vc14-32-bit.zip")
set(SFML_DIR ${DEPS_DIR}/SFML-2.3.2)
set(SFML_URL "http://www.sfml-dev.org/files/SFML-2.4.1-windows-vc14-32-bit.zip")
set(SFML_DIR ${DEPS_DIR}/SFML-2.4.1)
if (NOT EXISTS ${SFML_DIR})
message("Downloading SFML for Windows 32-bit")
file(DOWNLOAD "${SFML_URL}" "${DEPS_DIR}/sfml.zip")

View File

@ -1534,11 +1534,12 @@ var spine;
}
};
AnimationState.prototype.clearTracks = function () {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++)
this.clearTrack(i);
this.tracks.length = 0;
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.clearTrack = function (trackIndex) {
@ -1650,13 +1651,14 @@ var spine;
return entry;
};
AnimationState.prototype.setEmptyAnimations = function (mixDuration) {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++) {
var current = this.tracks[i];
if (current != null)
this.setEmptyAnimation(current.trackIndex, mixDuration);
}
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.expandToIndex = function (index) {
@ -2232,6 +2234,7 @@ var spine;
this.regionUVs = parentMesh.regionUVs;
this.triangles = parentMesh.triangles;
this.hullLength = parentMesh.hullLength;
this.worldVerticesLength = parentMesh.worldVerticesLength;
}
};
return MeshAttachment;
@ -3554,6 +3557,7 @@ var spine;
Skeleton.prototype.updateCache = function () {
var updateCache = this._updateCache;
updateCache.length = 0;
this.updateCacheReset.length = 0;
var bones = this.bones;
for (var i = 0, n = bones.length; i < n; i++)
bones[i].sorted = false;

File diff suppressed because one or more lines are too long

View File

@ -1534,11 +1534,12 @@ var spine;
}
};
AnimationState.prototype.clearTracks = function () {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++)
this.clearTrack(i);
this.tracks.length = 0;
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.clearTrack = function (trackIndex) {
@ -1650,13 +1651,14 @@ var spine;
return entry;
};
AnimationState.prototype.setEmptyAnimations = function (mixDuration) {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++) {
var current = this.tracks[i];
if (current != null)
this.setEmptyAnimation(current.trackIndex, mixDuration);
}
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.expandToIndex = function (index) {
@ -2232,6 +2234,7 @@ var spine;
this.regionUVs = parentMesh.regionUVs;
this.triangles = parentMesh.triangles;
this.hullLength = parentMesh.hullLength;
this.worldVerticesLength = parentMesh.worldVerticesLength;
}
};
return MeshAttachment;
@ -3554,6 +3557,7 @@ var spine;
Skeleton.prototype.updateCache = function () {
var updateCache = this._updateCache;
updateCache.length = 0;
this.updateCacheReset.length = 0;
var bones = this.bones;
for (var i = 0, n = bones.length; i < n; i++)
bones[i].sorted = false;

File diff suppressed because one or more lines are too long

View File

@ -1187,11 +1187,12 @@ var spine;
}
};
AnimationState.prototype.clearTracks = function () {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++)
this.clearTrack(i);
this.tracks.length = 0;
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.clearTrack = function (trackIndex) {
@ -1303,13 +1304,14 @@ var spine;
return entry;
};
AnimationState.prototype.setEmptyAnimations = function (mixDuration) {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++) {
var current = this.tracks[i];
if (current != null)
this.setEmptyAnimation(current.trackIndex, mixDuration);
}
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.expandToIndex = function (index) {
@ -1989,6 +1991,7 @@ var spine;
this.regionUVs = parentMesh.regionUVs;
this.triangles = parentMesh.triangles;
this.hullLength = parentMesh.hullLength;
this.worldVerticesLength = parentMesh.worldVerticesLength;
}
};
return MeshAttachment;
@ -3311,6 +3314,7 @@ var spine;
Skeleton.prototype.updateCache = function () {
var updateCache = this._updateCache;
updateCache.length = 0;
this.updateCacheReset.length = 0;
var bones = this.bones;
for (var i = 0, n = bones.length; i < n; i++)
bones[i].sorted = false;

File diff suppressed because one or more lines are too long

View File

@ -1187,11 +1187,12 @@ var spine;
}
};
AnimationState.prototype.clearTracks = function () {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++)
this.clearTrack(i);
this.tracks.length = 0;
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.clearTrack = function (trackIndex) {
@ -1303,13 +1304,14 @@ var spine;
return entry;
};
AnimationState.prototype.setEmptyAnimations = function (mixDuration) {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++) {
var current = this.tracks[i];
if (current != null)
this.setEmptyAnimation(current.trackIndex, mixDuration);
}
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.expandToIndex = function (index) {
@ -1989,6 +1991,7 @@ var spine;
this.regionUVs = parentMesh.regionUVs;
this.triangles = parentMesh.triangles;
this.hullLength = parentMesh.hullLength;
this.worldVerticesLength = parentMesh.worldVerticesLength;
}
};
return MeshAttachment;
@ -3311,6 +3314,7 @@ var spine;
Skeleton.prototype.updateCache = function () {
var updateCache = this._updateCache;
updateCache.length = 0;
this.updateCacheReset.length = 0;
var bones = this.bones;
for (var i = 0, n = bones.length; i < n; i++)
bones[i].sorted = false;

File diff suppressed because one or more lines are too long

View File

@ -1187,11 +1187,12 @@ var spine;
}
};
AnimationState.prototype.clearTracks = function () {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++)
this.clearTrack(i);
this.tracks.length = 0;
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.clearTrack = function (trackIndex) {
@ -1303,13 +1304,14 @@ var spine;
return entry;
};
AnimationState.prototype.setEmptyAnimations = function (mixDuration) {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++) {
var current = this.tracks[i];
if (current != null)
this.setEmptyAnimation(current.trackIndex, mixDuration);
}
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.expandToIndex = function (index) {
@ -1989,6 +1991,7 @@ var spine;
this.regionUVs = parentMesh.regionUVs;
this.triangles = parentMesh.triangles;
this.hullLength = parentMesh.hullLength;
this.worldVerticesLength = parentMesh.worldVerticesLength;
}
};
return MeshAttachment;
@ -3311,6 +3314,7 @@ var spine;
Skeleton.prototype.updateCache = function () {
var updateCache = this._updateCache;
updateCache.length = 0;
this.updateCacheReset.length = 0;
var bones = this.bones;
for (var i = 0, n = bones.length; i < n; i++)
bones[i].sorted = false;

File diff suppressed because one or more lines are too long

View File

@ -1187,11 +1187,12 @@ var spine;
}
};
AnimationState.prototype.clearTracks = function () {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++)
this.clearTrack(i);
this.tracks.length = 0;
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.clearTrack = function (trackIndex) {
@ -1303,13 +1304,14 @@ var spine;
return entry;
};
AnimationState.prototype.setEmptyAnimations = function (mixDuration) {
var oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (var i = 0, n = this.tracks.length; i < n; i++) {
var current = this.tracks[i];
if (current != null)
this.setEmptyAnimation(current.trackIndex, mixDuration);
}
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
};
AnimationState.prototype.expandToIndex = function (index) {
@ -1989,6 +1991,7 @@ var spine;
this.regionUVs = parentMesh.regionUVs;
this.triangles = parentMesh.triangles;
this.hullLength = parentMesh.hullLength;
this.worldVerticesLength = parentMesh.worldVerticesLength;
}
};
return MeshAttachment;
@ -3311,6 +3314,7 @@ var spine;
Skeleton.prototype.updateCache = function () {
var updateCache = this._updateCache;
updateCache.length = 0;
this.updateCacheReset.length = 0;
var bones = this.bones;
for (var i = 0, n = bones.length; i < n; i++)
bones[i].sorted = false;

File diff suppressed because one or more lines are too long

View File

@ -307,11 +307,12 @@ module spine {
}
clearTracks () {
let oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (let i = 0, n = this.tracks.length; i < n; i++)
this.clearTrack(i);
this.tracks.length = 0;
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
}
@ -435,12 +436,13 @@ module spine {
}
setEmptyAnimations (mixDuration: number) {
let oldDrainDisabled = this.queue.drainDisabled;
this.queue.drainDisabled = true;
for (let i = 0, n = this.tracks.length; i < n; i++) {
let current = this.tracks[i];
if (current != null) this.setEmptyAnimation(current.trackIndex, mixDuration);
}
this.queue.drainDisabled = false;
this.queue.drainDisabled = oldDrainDisabled;
this.queue.drain();
}

View File

@ -98,6 +98,7 @@ module spine {
updateCache () {
let updateCache = this._updateCache;
updateCache.length = 0;
this.updateCacheReset.length = 0;
let bones = this.bones;
for (let i = 0, n = bones.length; i < n; i++)

View File

@ -164,6 +164,7 @@ module spine {
this.regionUVs = parentMesh.regionUVs;
this.triangles = parentMesh.triangles;
this.hullLength = parentMesh.hullLength;
this.worldVerticesLength = parentMesh.worldVerticesLength
}
}
}

View File

@ -41,6 +41,8 @@ namespace Spine.Unity {
public Material[] materials;
protected Atlas atlas;
public bool IsLoaded { get { return this.atlas != null; } }
#region Runtime Instantiation
/// <summary>
/// Creates a runtime AtlasAsset</summary>
@ -122,8 +124,7 @@ namespace Spine.Unity {
return null;
}
if (atlas != null)
return atlas;
if (atlas != null) return atlas;
try {
atlas = new Atlas(new StringReader(atlasFile.text), "", new MaterialsTextureLoader(this));
@ -201,7 +202,7 @@ namespace Spine.Unity {
this.atlasAsset = atlasAsset;
}
public void Load (AtlasPage page, String path) {
public void Load (AtlasPage page, string path) {
String name = Path.GetFileNameWithoutExtension(path);
Material material = null;
foreach (Material other in atlasAsset.materials) {
@ -227,7 +228,6 @@ namespace Spine.Unity {
}
}
public void Unload (object texture) {
}
public void Unload (object texture) { }
}
}

View File

@ -41,7 +41,7 @@ using Spine;
namespace Spine.Unity.Editor {
using Event = UnityEngine.Event;
[CustomEditor(typeof(AtlasAsset))]
[CustomEditor(typeof(AtlasAsset)), CanEditMultipleObjects]
public class AtlasAssetInspector : UnityEditor.Editor {
SerializedProperty atlasFile, materials;
AtlasAsset atlasAsset;
@ -103,6 +103,11 @@ namespace Spine.Unity.Editor {
#endif
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
DrawDefaultInspector();
return;
}
serializedObject.Update();
atlasAsset = atlasAsset ?? (AtlasAsset)target;
EditorGUI.BeginChangeCheck();
@ -113,7 +118,6 @@ namespace Spine.Unity.Editor {
atlasAsset.Clear();
atlasAsset.GetAtlas();
}
if (materials.arraySize == 0) {
EditorGUILayout.LabelField(new GUIContent("Error: Missing materials", SpineEditorUtilities.Icons.warning));

View File

@ -43,7 +43,7 @@ namespace Spine.Unity.Editor {
using Event = UnityEngine.Event;
using Icons = SpineEditorUtilities.Icons;
[CustomEditor(typeof(SkeletonDataAsset))]
[CustomEditor(typeof(SkeletonDataAsset)), CanEditMultipleObjects]
public class SkeletonDataAssetInspector : UnityEditor.Editor {
static bool showAnimationStateData = true;
static bool showAnimationList = true;
@ -79,9 +79,27 @@ namespace Spine.Unity.Editor {
GUIStyle activePlayButtonStyle, idlePlayButtonStyle;
readonly GUIContent DefaultMixLabel = new GUIContent("Default Mix Duration", "Sets 'SkeletonDataAsset.defaultMix' in the asset and 'AnimationState.data.defaultMix' at runtime load time.");
void OnEnable () {
SpineEditorUtilities.ConfirmInitialization();
m_skeletonDataAsset = (SkeletonDataAsset)target;
// Clear empty atlas array items.
{
bool hasNulls = false;
foreach (var a in m_skeletonDataAsset.atlasAssets) {
if (a == null) {
hasNulls = true;
break;
}
}
if (hasNulls) {
var trimmedAtlasAssets = new List<AtlasAsset>();
foreach (var a in m_skeletonDataAsset.atlasAssets) {
if (a != null) trimmedAtlasAssets.Add(a);
}
m_skeletonDataAsset.atlasAssets = trimmedAtlasAssets.ToArray();
}
}
atlasAssets = serializedObject.FindProperty("atlasAssets");
skeletonJSON = serializedObject.FindProperty("skeletonJSON");
@ -106,7 +124,6 @@ namespace Spine.Unity.Editor {
isBakingExpanded = EditorPrefs.GetBool(ShowBakingPrefsKey, false);
#endif
m_skeletonDataAsset = (SkeletonDataAsset)target;
m_skeletonDataAssetGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(m_skeletonDataAsset));
EditorApplication.update += EditorUpdate;
m_skeletonData = m_skeletonDataAsset.GetSkeletonData(false);
@ -124,8 +141,35 @@ namespace Spine.Unity.Editor {
}
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
using (new SpineInspectorUtility.BoxScope()) {
EditorGUILayout.LabelField("SkeletonData", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(skeletonJSON, new GUIContent(skeletonJSON.displayName, Icons.spine));
EditorGUILayout.PropertyField(scale);
}
using (new SpineInspectorUtility.BoxScope()) {
EditorGUILayout.LabelField("Atlas", EditorStyles.boldLabel);
#if !SPINE_TK2D
EditorGUILayout.PropertyField(atlasAssets, true);
#else
using (new EditorGUI.DisabledGroupScope(spriteCollection.objectReferenceValue != null)) {
EditorGUILayout.PropertyField(atlasAssets, true);
}
EditorGUILayout.LabelField("spine-tk2d", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(spriteCollection, true);
#endif
}
using (new SpineInspectorUtility.BoxScope()) {
EditorGUILayout.LabelField("Mix Settings", EditorStyles.boldLabel);
SpineInspectorUtility.PropertyFieldWideLabel(defaultMix, DefaultMixLabel, 160);
EditorGUILayout.Space();
}
return;
}
{
// Lazy initialization because accessing EditorStyles values in OnEnable during a recompile causes UnityEditor to throw null exceptions. (Unity 5.3.5)
idlePlayButtonStyle = idlePlayButtonStyle ?? new GUIStyle(EditorStyles.miniButton);
if (activePlayButtonStyle == null) {
@ -207,7 +251,6 @@ namespace Spine.Unity.Editor {
EditorGUILayout.Space();
DrawSlotList();
EditorGUILayout.Space();
DrawUnityTools();
} else {
#if !SPINE_TK2D
@ -467,28 +510,8 @@ namespace Spine.Unity.Editor {
for (int a = 0; a < slotAttachments.Count; a++) {
Attachment attachment = slotAttachments[a];
string attachmentName = slotAttachmentNames[a];
Texture2D icon = null;
var type = attachment.GetType();
if (type == typeof(RegionAttachment))
icon = Icons.image;
else if (type == typeof(MeshAttachment))
icon = Icons.mesh;
else if (type == typeof(BoundingBoxAttachment))
icon = Icons.boundingBox;
else if (type == typeof(PathAttachment))
icon = Icons.boundingBox;
else
icon = Icons.warning;
//JOHN: left todo: Icon for paths. Generic icon for unidentified attachments.
// MITCH: left todo: Waterboard Nate
//if (name != attachment.Name)
//icon = SpineEditorUtilities.Icons.skinPlaceholder;
Texture2D icon = Icons.GetAttachmentIcon(attachment);
bool initialState = slot.Attachment == attachment;
bool toggled = EditorGUILayout.ToggleLeft(new GUIContent(attachmentName, icon), slot.Attachment == attachment);
if (!defaultSkinAttachmentNames.Contains(attachmentName)) {
@ -515,7 +538,7 @@ namespace Spine.Unity.Editor {
if (skeletonJSON.objectReferenceValue == null) {
warnings.Add("Missing Skeleton JSON");
} else {
if (SpineEditorUtilities.IsValidSpineData((TextAsset)skeletonJSON.objectReferenceValue) == false) {
if (SpineEditorUtilities.IsSpineData((TextAsset)skeletonJSON.objectReferenceValue) == false) {
warnings.Add("Skeleton data file is not a valid JSON or binary file.");
} else {
#if !SPINE_TK2D
@ -606,11 +629,12 @@ namespace Spine.Unity.Editor {
if (this.m_previewUtility == null) {
this.m_lastTime = Time.realtimeSinceStartup;
this.m_previewUtility = new PreviewRenderUtility(true);
this.m_previewUtility.m_Camera.orthographic = true;
this.m_previewUtility.m_Camera.orthographicSize = 1;
this.m_previewUtility.m_Camera.cullingMask = -2147483648;
this.m_previewUtility.m_Camera.nearClipPlane = 0.01f;
this.m_previewUtility.m_Camera.farClipPlane = 1000f;
var c = this.m_previewUtility.m_Camera;
c.orthographic = true;
c.orthographicSize = 1;
c.cullingMask = -2147483648;
c.nearClipPlane = 0.01f;
c.farClipPlane = 1000f;
this.CreatePreviewInstances();
}
}
@ -649,8 +673,11 @@ namespace Spine.Unity.Editor {
m_initialized = false;
}
public override bool HasPreviewGUI () {
// MITCH: left todo: validate json data
public override bool HasPreviewGUI () {
if (serializedObject.isEditingMultipleObjects) {
// JOHN: Implement multi-preview.
return false;
}
for (int i = 0; i < atlasAssets.arraySize; i++) {
var prop = atlasAssets.GetArrayElementAtIndex(i);

View File

@ -50,6 +50,8 @@ namespace Spine.Unity {
public float defaultMix;
public RuntimeAnimatorController controller;
public bool IsLoaded { get { return this.skeletonData != null; } }
void Reset () {
Clear();
}
@ -109,77 +111,90 @@ namespace Spine.Unity {
}
#else
if (atlasAssets.Length == 0 && spriteCollection == null) {
Reset();
Clear();
return null;
}
#endif
Atlas[] atlasArr = new Atlas[atlasAssets.Length];
for (int i = 0; i < atlasAssets.Length; i++) {
if (atlasAssets[i] == null) {
Clear();
return null;
}
atlasArr[i] = atlasAssets[i].GetAtlas();
if (atlasArr[i] == null) {
Clear();
return null;
}
}
if (skeletonData != null)
return skeletonData;
AttachmentLoader attachmentLoader;
float skeletonDataScale;
Atlas[] atlasArray = this.GetAtlasArray();
#if !SPINE_TK2D
attachmentLoader = new AtlasAttachmentLoader(atlasArr);
attachmentLoader = new AtlasAttachmentLoader(atlasArray);
skeletonDataScale = scale;
#else
if (spriteCollection != null) {
attachmentLoader = new Spine.Unity.TK2D.SpriteCollectionAttachmentLoader(spriteCollection);
skeletonDataScale = (1.0f / (spriteCollection.invOrthoSize * spriteCollection.halfTargetHeight) * scale);
} else {
if (atlasArr.Length == 0) {
if (atlasArray.Length == 0) {
Reset();
if (!quiet) Debug.LogError("Atlas not set for SkeletonData asset: " + name, this);
return null;
}
attachmentLoader = new AtlasAttachmentLoader(atlasArr);
attachmentLoader = new AtlasAttachmentLoader(atlasArray);
skeletonDataScale = scale;
}
#endif
bool isBinary = skeletonJSON.name.ToLower().Contains(".skel");
SkeletonData loadedSkeletonData;
try {
//var stopwatch = new System.Diagnostics.Stopwatch();
if (skeletonJSON.name.ToLower().Contains(".skel")) {
var input = new MemoryStream(skeletonJSON.bytes);
var binary = new SkeletonBinary(attachmentLoader);
binary.Scale = skeletonDataScale;
//stopwatch.Start();
skeletonData = binary.ReadSkeletonData(input);
} else {
var input = new StringReader(skeletonJSON.text);
var json = new SkeletonJson(attachmentLoader);
json.Scale = skeletonDataScale;
//stopwatch.Start();
skeletonData = json.ReadSkeletonData(input);
}
//stopwatch.Stop();
//Debug.Log(stopwatch.Elapsed);
if (isBinary)
loadedSkeletonData = SkeletonDataAsset.ReadSkeletonData(skeletonJSON.bytes, attachmentLoader, skeletonDataScale);
else
loadedSkeletonData = SkeletonDataAsset.ReadSkeletonData(skeletonJSON.text, attachmentLoader, skeletonDataScale);
} catch (Exception ex) {
if (!quiet)
Debug.LogError("Error reading skeleton JSON file for SkeletonData asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
return null;
}
stateData = new AnimationStateData(skeletonData);
FillStateData();
this.InitializeWithData(loadedSkeletonData);
return skeletonData;
}
internal void InitializeWithData (SkeletonData sd) {
this.skeletonData = sd;
this.stateData = new AnimationStateData(skeletonData);
FillStateData();
}
internal Atlas[] GetAtlasArray () {
var returnList = new System.Collections.Generic.List<Atlas>(atlasAssets.Length);
for (int i = 0; i < atlasAssets.Length; i++) {
var aa = atlasAssets[i];
if (aa == null) continue;
var a = aa.GetAtlas();
if (a == null) continue;
returnList.Add(a);
}
return returnList.ToArray();
}
internal static SkeletonData ReadSkeletonData (byte[] bytes, AttachmentLoader attachmentLoader, float scale) {
var input = new MemoryStream(bytes);
var binary = new SkeletonBinary(attachmentLoader) {
Scale = scale
};
return binary.ReadSkeletonData(input);
}
internal static SkeletonData ReadSkeletonData (string text, AttachmentLoader attachmentLoader, float scale) {
var input = new StringReader(text);
var json = new SkeletonJson(attachmentLoader) {
Scale = scale
};
return json.ReadSkeletonData(input);
}
public void FillStateData () {
if (stateData != null) {
stateData.defaultMix = defaultMix;

View File

@ -85,6 +85,9 @@ namespace Spine.Unity {
skeletonRenderer.OnRebuild -= HandleRebuildRenderer;
skeletonRenderer.OnRebuild += HandleRebuildRenderer;
if (!string.IsNullOrEmpty(boneName))
bone = skeletonRenderer.skeleton.FindBone(boneName);
#if UNITY_EDITOR
if (Application.isEditor)
LateUpdate();

View File

@ -32,45 +32,12 @@ using UnityEditor;
using UnityEngine;
namespace Spine.Unity.Editor {
[CustomEditor(typeof(BoneFollower))]
[CustomEditor(typeof(BoneFollower)), CanEditMultipleObjects]
public class BoneFollowerInspector : UnityEditor.Editor {
SerializedProperty boneName, skeletonRenderer, followZPosition, followBoneRotation, followLocalScale, followSkeletonFlip;
BoneFollower targetBoneFollower;
bool needsReset;
void OnEnable () {
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
boneName = serializedObject.FindProperty("boneName");
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
followZPosition = serializedObject.FindProperty("followZPosition");
followLocalScale = serializedObject.FindProperty("followLocalScale");
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
targetBoneFollower = (BoneFollower)target;
if (targetBoneFollower.SkeletonRenderer != null)
targetBoneFollower.SkeletonRenderer.Initialize(false);
}
public void OnSceneGUI () {
if (targetBoneFollower == null) return;
var skeletonRendererComponent = targetBoneFollower.skeletonRenderer;
if (skeletonRendererComponent == null) return;
var transform = skeletonRendererComponent.transform;
var skeleton = skeletonRendererComponent.skeleton;
if (string.IsNullOrEmpty(targetBoneFollower.boneName)) {
SpineHandles.DrawBones(transform, skeleton);
SpineHandles.DrawBoneNames(transform, skeleton);
Handles.Label(targetBoneFollower.transform.position, "No bone selected", EditorStyles.helpBox);
} else {
var targetBone = targetBoneFollower.bone;
if (targetBone == null) return;
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor);
Handles.Label(targetBone.GetWorldPosition(transform), targetBone.Data.Name, SpineHandles.BoneNameStyle);
}
}
#region Context Menu Item
[MenuItem ("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject")]
static void AddBoneFollowerGameObject (MenuCommand cmd) {
@ -96,7 +63,57 @@ namespace Spine.Unity.Editor {
}
#endregion
void OnEnable () {
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
boneName = serializedObject.FindProperty("boneName");
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
followZPosition = serializedObject.FindProperty("followZPosition");
followLocalScale = serializedObject.FindProperty("followLocalScale");
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
targetBoneFollower = (BoneFollower)target;
if (targetBoneFollower.SkeletonRenderer != null)
targetBoneFollower.SkeletonRenderer.Initialize(false);
}
public void OnSceneGUI () {
var tbf = target as BoneFollower;
var skeletonRendererComponent = tbf.skeletonRenderer;
if (skeletonRendererComponent == null) return;
var transform = skeletonRendererComponent.transform;
var skeleton = skeletonRendererComponent.skeleton;
if (string.IsNullOrEmpty(tbf.boneName)) {
SpineHandles.DrawBones(transform, skeleton);
SpineHandles.DrawBoneNames(transform, skeleton);
Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox);
} else {
var targetBone = tbf.bone;
if (targetBone == null) return;
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor);
Handles.Label(targetBone.GetWorldPosition(transform), targetBone.Data.Name, SpineHandles.BoneNameStyle);
}
}
override public void OnInspectorGUI () {
if (serializedObject.isEditingMultipleObjects) {
if (needsReset) {
needsReset = false;
foreach (var o in targets) {
var bf = (BoneFollower)o;
bf.Initialize();
bf.LateUpdate();
}
SceneView.RepaintAll();
}
EditorGUI.BeginChangeCheck();
DrawDefaultInspector();
needsReset |= EditorGUI.EndChangeCheck();
return;
}
if (needsReset) {
targetBoneFollower.Initialize();
targetBoneFollower.LateUpdate();
@ -144,7 +161,7 @@ namespace Spine.Unity.Editor {
if (boneFollowerSkeletonRenderer.skeletonDataAsset == null)
EditorGUILayout.HelpBox("Assigned SkeletonRenderer does not have SkeletonData assigned to it.", MessageType.Warning);
if (!boneFollowerSkeletonRenderer.valid)
EditorGUILayout.HelpBox("Assigned SkeletonRenderer is invalid. Check target SkeletonRenderer, its SkeletonDataAsset or the console for other errors.", MessageType.Warning);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 B

View File

@ -0,0 +1,59 @@
fileFormatVersion: 2
guid: dbc817a6c9e9c5747b7f6261bf5d1d09
timeCreated: 1482240904
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 7
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
rGBM: 0
compressionQuality: 50
allowsAlphaSplitting: 0
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
buildTargetSettings: []
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -37,17 +37,19 @@ namespace Spine.Unity.Editor {
[CanEditMultipleObjects]
public class SkeletonAnimatorInspector : SkeletonRendererInspector {
protected SerializedProperty layerMixModes;
protected SerializedProperty autoReset;
protected override void OnEnable () {
base.OnEnable();
autoReset = serializedObject.FindProperty("autoReset");
layerMixModes = serializedObject.FindProperty("layerMixModes");
}
protected override void DrawInspectorGUI (bool multi) {
base.DrawInspectorGUI(multi);
EditorGUILayout.PropertyField(autoReset);
EditorGUILayout.PropertyField(layerMixModes, true);
if (!TargetIsValid) return;
if (!isInspectingPrefab)
DrawSkeletonUtilityButton(multi);
}

View File

@ -62,6 +62,7 @@ namespace Spine.Unity.Editor {
public static Texture2D boundingBox;
public static Texture2D mesh;
public static Texture2D weights;
public static Texture2D path;
public static Texture2D skin;
public static Texture2D skinsRoot;
public static Texture2D animation;
@ -100,10 +101,25 @@ namespace Spine.Unity.Editor {
skeletonUtility = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skeletonUtility.png");
hingeChain = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-hingeChain.png");
subMeshRenderer = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-subMeshRenderer.png");
path = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-path.png");
unityIcon = EditorGUIUtility.FindTexture("SceneAsset Icon");
controllerIcon = EditorGUIUtility.FindTexture("AnimatorController Icon");
}
public static Texture2D GetAttachmentIcon (Attachment attachment) {
if (attachment is RegionAttachment)
return Icons.image;
// Analysis disable once CanBeReplacedWithTryCastAndCheckForNull
else if (attachment is MeshAttachment)
return ((MeshAttachment)attachment).IsWeighted() ? Icons.weights : Icons.mesh;
else if (attachment is BoundingBoxAttachment)
return Icons.boundingBox;
else if (attachment is PathAttachment)
return Icons.path;
else
return Icons.warning;
}
}
public static string editorPath = "";
@ -159,9 +175,6 @@ namespace Spine.Unity.Editor {
preferencesLoaded = true;
}
SceneView.onSceneGUIDelegate -= OnSceneGUI;
SceneView.onSceneGUIDelegate += OnSceneGUI;
DirectoryInfo rootDir = new DirectoryInfo(Application.dataPath);
FileInfo[] files = rootDir.GetFiles("SpineEditorUtilities.cs", SearchOption.AllDirectories);
editorPath = Path.GetDirectoryName(files[0].FullName.Replace("\\", "/").Replace(Application.dataPath, "Assets"));
@ -174,12 +187,19 @@ namespace Spine.Unity.Editor {
skeletonUtilityBoneTable = new Dictionary<int, SkeletonUtilityBone>();
boundingBoxFollowerTable = new Dictionary<int, BoundingBoxFollower>();
EditorApplication.hierarchyWindowChanged -= HierarchyWindowChanged;
EditorApplication.hierarchyWindowChanged += HierarchyWindowChanged;
EditorApplication.hierarchyWindowItemOnGUI -= HierarchyWindowItemOnGUI;
EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
// Drag and Drop
SceneView.onSceneGUIDelegate -= SceneViewDragAndDrop;
SceneView.onSceneGUIDelegate += SceneViewDragAndDrop;
EditorApplication.hierarchyWindowItemOnGUI -= HierarchyDragAndDrop;
EditorApplication.hierarchyWindowItemOnGUI += HierarchyDragAndDrop;
HierarchyWindowChanged();
// Hierarchy Icons
EditorApplication.hierarchyWindowChanged -= HierarchyIconsOnChanged;
EditorApplication.hierarchyWindowChanged += HierarchyIconsOnChanged;
EditorApplication.hierarchyWindowItemOnGUI -= HierarchyIconsOnGUI;
EditorApplication.hierarchyWindowItemOnGUI += HierarchyIconsOnGUI;
HierarchyIconsOnChanged();
initialized = true;
}
@ -207,7 +227,7 @@ namespace Spine.Unity.Editor {
showHierarchyIcons = EditorGUILayout.Toggle(new GUIContent("Show Hierarchy Icons", "Show relevant icons on GameObjects with Spine Components on them. Disable this if you have large, complex scenes."), showHierarchyIcons);
if (EditorGUI.EndChangeCheck()) {
EditorPrefs.SetBool(SHOW_HIERARCHY_ICONS_KEY, showHierarchyIcons);
HierarchyWindowChanged();
HierarchyIconsOnChanged();
}
EditorGUILayout.Separator();
@ -276,9 +296,10 @@ namespace Spine.Unity.Editor {
public static readonly List<SkeletonComponentSpawnType> additionalSpawnTypes = new List<SkeletonComponentSpawnType>();
static void OnSceneGUI (SceneView sceneview) {
static void SceneViewDragAndDrop (SceneView sceneview) {
var current = UnityEngine.Event.current;
var references = DragAndDrop.objectReferences;
if (current.type == EventType.Repaint || current.type == EventType.Layout) return;
// Allow drag and drop of one SkeletonDataAsset.
if (references.Length == 1) {
@ -303,8 +324,47 @@ namespace Spine.Unity.Editor {
RectTransform rectTransform = (Selection.activeGameObject == null) ? null : Selection.activeGameObject.GetComponent<RectTransform>();
Plane plane = (rectTransform == null) ? new Plane(Vector3.back, Vector3.zero) : new Plane(-rectTransform.forward, rectTransform.position);
Vector3 spawnPoint = MousePointToWorldPoint2D(mousePos, sceneview.camera, plane);
ShowInstantiateContextMenu(skeletonDataAsset, spawnPoint);
DragAndDrop.AcceptDrag();
current.Use();
}
}
}
}
}
static void HierarchyDragAndDrop (int instanceId, Rect selectionRect) {
// HACK: Uses EditorApplication.hierarchyWindowItemOnGUI.
// Only works when there is at least one item in the scene.
var current = UnityEngine.Event.current;
var eventType = current.type;
bool isDraggingEvent = eventType == EventType.DragUpdated;
bool isDropEvent = eventType == EventType.DragPerform;
if (isDraggingEvent || isDropEvent) {
var mouseOverWindow = EditorWindow.mouseOverWindow;
if (mouseOverWindow != null) {
// One, existing, valid SkeletonDataAsset
var references = DragAndDrop.objectReferences;
if (references.Length == 1) {
var skeletonDataAsset = references[0] as SkeletonDataAsset;
if (skeletonDataAsset != null && skeletonDataAsset.GetSkeletonData(true) != null) {
// Allow drag-and-dropping anywhere in the Hierarchy Window.
// HACK: string-compare because we can't get its type via reflection.
const string HierarchyWindow = "UnityEditor.SceneHierarchyWindow";
if (HierarchyWindow.Equals(mouseOverWindow.GetType().ToString(), System.StringComparison.Ordinal)) {
if (isDraggingEvent) {
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
current.Use();
} else if (isDropEvent) {
ShowInstantiateContextMenu(skeletonDataAsset, Vector3.zero);
DragAndDrop.AcceptDrag();
current.Use();
return;
}
}
}
}
}
@ -377,6 +437,7 @@ namespace Spine.Unity.Editor {
Debug.Log("New Spine GameObject was parented to a scaled Transform. It may not be the intended size.");
Selection.activeGameObject = newGameObject;
//EditorGUIUtility.PingObject(newGameObject); // Doesn't work when setting activeGameObject.
Undo.RegisterCreatedObjectUndo(newGameObject, "Create Spine GameObject");
}
@ -402,8 +463,8 @@ namespace Spine.Unity.Editor {
}
#endregion
#region Hierarchy Icons
static void HierarchyWindowChanged () {
#region Hierarchy
static void HierarchyIconsOnChanged () {
if (showHierarchyIcons) {
skeletonRendererTable.Clear();
skeletonUtilityBoneTable.Clear();
@ -423,9 +484,8 @@ namespace Spine.Unity.Editor {
}
}
static void HierarchyWindowItemOnGUI (int instanceId, Rect selectionRect) {
static void HierarchyIconsOnGUI (int instanceId, Rect selectionRect) {
if (showHierarchyIcons) {
Rect r = new Rect(selectionRect);
if (skeletonRendererTable.ContainsKey(instanceId)) {
r.x = r.width - 15;
@ -507,12 +567,12 @@ namespace Spine.Unity.Editor {
imagePaths.Add(str);
break;
case ".json":
if (IsValidSpineData((TextAsset)AssetDatabase.LoadAssetAtPath(str, typeof(TextAsset))))
if (IsSpineData((TextAsset)AssetDatabase.LoadAssetAtPath(str, typeof(TextAsset))))
skeletonPaths.Add(str);
break;
case ".bytes":
if (str.ToLower().EndsWith(".skel.bytes", System.StringComparison.Ordinal)) {
if (IsValidSpineData((TextAsset)AssetDatabase.LoadAssetAtPath(str, typeof(TextAsset))))
if (IsSpineData((TextAsset)AssetDatabase.LoadAssetAtPath(str, typeof(TextAsset))))
skeletonPaths.Add(str);
}
break;
@ -558,7 +618,7 @@ namespace Spine.Unity.Editor {
switch (result) {
case -1:
Debug.Log("Select Atlas");
//Debug.Log("Select Atlas");
AtlasAsset selectedAtlas = GetAtlasDialog(Path.GetDirectoryName(sp));
if (selectedAtlas != null) {
localAtlases.Clear();
@ -1123,37 +1183,53 @@ namespace Spine.Unity.Editor {
return false;
}
public static bool IsValidSpineData (TextAsset asset) {
if (asset.name.Contains(".skel")) return true;
public static bool IsSpineData (TextAsset asset) {
bool isSpineData = false;
string rawVersion = null;
object obj = null;
obj = Json.Deserialize(new StringReader(asset.text));
if (asset.name.Contains(".skel")) {
try {
rawVersion = SkeletonBinary.GetVersionString(new MemoryStream(asset.bytes));
//Debug.Log(rawVersion);
isSpineData = !(string.IsNullOrEmpty(rawVersion));
} catch (System.Exception e) {
Debug.LogErrorFormat("Failed to read '{0}'. It is likely not a binary Spine SkeletonData file.\n{1}", asset.name, e);
return false;
}
} else {
var obj = Json.Deserialize(new StringReader(asset.text));
if (obj == null) {
Debug.LogErrorFormat("'{0}' is not valid JSON.", asset.name);
return false;
}
if (obj == null) {
Debug.LogError("Is not valid JSON.");
return false;
var root = obj as Dictionary<string, object>;
if (root == null) {
Debug.LogError("Parser returned an incorrect type.");
return false;
}
isSpineData = root.ContainsKey("skeleton");
if (isSpineData) {
var skeletonInfo = (Dictionary<string, object>)root["skeleton"];
object jv;
skeletonInfo.TryGetValue("spine", out jv);
rawVersion = jv as string;
}
}
var root = obj as Dictionary<string, object>;
if (root == null) {
Debug.LogError("Parser returned an incorrect type.");
return false;
}
bool isSpineJson = root.ContainsKey("skeleton");
// Version warning
if (isSpineJson) {
var skeletonInfo = (Dictionary<string, object>)root["skeleton"];
object jv;
skeletonInfo.TryGetValue("spine", out jv);
string jsonVersion = jv as string;
if (!string.IsNullOrEmpty(jsonVersion)) {
string[] jsonVersionSplit = jsonVersion.Split('.');
{
string runtimeVersion = compatibleVersions[0][0] + "." + compatibleVersions[0][1];
if (string.IsNullOrEmpty(rawVersion)) {
Debug.LogWarningFormat("Skeleton '{0}' has no version information. It may be incompatible with your runtime version: spine-unity v{1}", asset.name, runtimeVersion);
} else {
string[] versionSplit = rawVersion.Split('.');
bool match = false;
foreach (var version in compatibleVersions) {
bool primaryMatch = version[0] == int.Parse(jsonVersionSplit[0]);
bool secondaryMatch = version[1] == int.Parse(jsonVersionSplit[1]);
bool primaryMatch = version[0] == int.Parse(versionSplit[0]);
bool secondaryMatch = version[1] == int.Parse(versionSplit[1]);
// if (isFixVersionRequired) secondaryMatch &= version[2] <= int.Parse(jsonVersionSplit[2]);
@ -1163,16 +1239,12 @@ namespace Spine.Unity.Editor {
}
}
if (!match) {
string runtimeVersion = compatibleVersions[0][0] + "." + compatibleVersions[0][1];
Debug.LogWarning(string.Format("Skeleton '{0}' (exported with Spine {1}) may be incompatible with your runtime version: spine-unity v{2}", asset.name, jsonVersion, runtimeVersion));
}
} else {
isSpineJson = false;
if (!match)
Debug.LogWarningFormat("Skeleton '{0}' (exported with Spine {1}) may be incompatible with your runtime version: spine-unity v{2}", asset.name, rawVersion, runtimeVersion);
}
}
return isSpineJson;
return isSpineData;
}
#endregion

View File

@ -29,7 +29,7 @@
*****************************************************************************/
namespace Spine.Unity {
public delegate void UpdateBonesDelegate (ISkeletonAnimation animatedSkeletonComponent);
public delegate void UpdateBonesDelegate (ISkeletonAnimation animated);
/// <summary>A Spine-Unity Component that animates a Skeleton but not necessarily with a Spine.AnimationState.</summary>
public interface ISkeletonAnimation {

View File

@ -37,6 +37,10 @@ namespace Spine.Unity.Modules {
[RequireComponent(typeof(SkeletonRenderer))]
public class SkeletonGhost : MonoBehaviour {
// Internal Settings
const HideFlags GhostHideFlags = HideFlags.HideInHierarchy;
const string GhostingShaderName = "Spine/Special/SkeletonGhost";
public bool ghostingEnabled = true;
public float spawnRate = 0.05f;
public Color32 color = new Color32(0xFF, 0xFF, 0xFF, 0x00); // default for additive.
@ -60,12 +64,11 @@ namespace Spine.Unity.Modules {
MeshRenderer meshRenderer;
MeshFilter meshFilter;
Dictionary<Material, Material> materialTable = new Dictionary<Material, Material>();
readonly Dictionary<Material, Material> materialTable = new Dictionary<Material, Material>();
void Start () {
if (ghostShader == null)
ghostShader = Shader.Find("Spine/Special/SkeletonGhost");
ghostShader = Shader.Find(GhostingShaderName);
skeletonRenderer = GetComponent<SkeletonRenderer>();
meshFilter = GetComponent<MeshFilter>();
@ -76,12 +79,11 @@ namespace Spine.Unity.Modules {
GameObject go = new GameObject(gameObject.name + " Ghost", typeof(SkeletonGhostRenderer));
pool[i] = go.GetComponent<SkeletonGhostRenderer>();
go.SetActive(false);
go.hideFlags = HideFlags.HideInHierarchy;
go.hideFlags = GhostHideFlags;
}
if (skeletonRenderer is SkeletonAnimation)
((SkeletonAnimation)skeletonRenderer).state.Event += OnEvent;
var skeletonAnimation = skeletonRenderer as Spine.Unity.IAnimationStateComponent;
if (skeletonAnimation != null) skeletonAnimation.AnimationState.Event += OnEvent;
}
//SkeletonAnimation
@ -91,13 +93,13 @@ namespace Spine.Unity.Modules {
* String Value: Pass RGBA hex color values in to set the color property. IE: "A0FF8BFF"
*/
void OnEvent (Spine.TrackEntry trackEntry, Spine.Event e) {
if (e.Data.Name == "Ghosting") {
if (e.Data.Name.Equals("Ghosting", System.StringComparison.Ordinal)) {
ghostingEnabled = e.Int > 0;
if (e.Float > 0)
spawnRate = e.Float;
if (e.String != null) {
if (!string.IsNullOrEmpty(e.stringValue))
this.color = HexToColor(e.String);
}
}
}
@ -153,16 +155,13 @@ namespace Spine.Unity.Modules {
}
void OnDestroy () {
for (int i = 0; i < maximumGhosts; i++) {
if (pool[i] != null)
pool[i].Cleanup();
}
for (int i = 0; i < maximumGhosts; i++)
if (pool[i] != null) pool[i].Cleanup();
foreach (var mat in materialTable.Values)
Destroy(mat);
}
//based on UnifyWiki http://wiki.unity3d.com/index.php?title=HexConverter
static Color32 HexToColor (string hex) {
if (hex.Length < 6)

View File

@ -8,7 +8,7 @@ Shader "Spine/Skeleton Tint" {
Properties {
_Color ("Tint Color", Color) = (1,1,1,1)
_Black ("Black Point", Color) = (0,0,0,0)
_MainTex ("MainTex", 2D) = "black" {}
[NoScaleOffset] _MainTex ("MainTex", 2D) = "black" {}
_Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
}

View File

@ -1,7 +1,7 @@
Shader "Spine/Skeleton" {
Properties {
_Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
_MainTex ("Texture to blend", 2D) = "black" {}
[NoScaleOffset] _MainTex ("Texture to blend", 2D) = "black" {}
}
// 2 texture stage GPUs
SubShader {

View File

@ -1,7 +1,7 @@
Shader "Spine/Skeleton Lit" {
Properties {
_Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
_MainTex ("Texture to blend", 2D) = "black" {}
[NoScaleOffset] _MainTex ("Texture to blend", 2D) = "black" {}
}
// 2 texture stage GPUs
SubShader {

View File

@ -129,7 +129,7 @@ namespace Spine.Unity {
protected override void ClearState () {
base.ClearState();
state.ClearTracks();
if (state != null) state.ClearTracks();
}
public override void Initialize (bool overwrite) {

View File

@ -39,7 +39,9 @@ namespace Spine.Unity {
public enum MixMode { AlwaysMix, MixNext, SpineStyle }
public MixMode[] layerMixModes = new MixMode[0];
public bool autoReset = false;
List<Animation> previousAnimations = new List<Animation>();
#region Bone Callbacks (ISkeletonAnimation)
protected event UpdateBonesDelegate _UpdateLocal;
@ -90,53 +92,50 @@ namespace Spine.Unity {
//skeleton.Update(Time.deltaTime); // Doesn't actually do anything, currently. (Spine 3.5).
// Clear Previous
if (autoReset)
{
if (autoReset) {
var previousAnimations = this.previousAnimations;
for (int i = 0, n = previousAnimations.Count; i < n; i++)
previousAnimations[i].SetKeyedItemsToSetupPose(skeleton);
previousAnimations.Clear();
for (int layer = 0, n = animator.layerCount; layer < n; layer++) {
float layerWeight = animator.GetLayerWeight(layer);
float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer); // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.
if (layerWeight <= 0) continue;
AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
#if UNITY_5
bool hasNext = nextStateInfo.fullPathHash != 0;
AnimatorClipInfo[] clipInfo = animator.GetCurrentAnimatorClipInfo(layer);
AnimatorClipInfo[] nextClipInfo = animator.GetNextAnimatorClipInfo(layer);
#else
bool hasNext = nextStateInfo.nameHash != 0;
var clipInfo = animator.GetCurrentAnimationClipState(i);
var nextClipInfo = animator.GetNextAnimationClipState(i);
#endif
for (int c = 0; c < clipInfo.Length; c++) {
var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
animationTable[NameHashCode(info.clip)].SetKeyedItemsToSetupPose(skeleton);
var info = clipInfo[c];
float weight = info.weight * layerWeight; if (weight == 0) continue;
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
}
if (hasNext) {
for (int c = 0; c < nextClipInfo.Length; c++) {
var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
animationTable[NameHashCode(info.clip)].SetKeyedItemsToSetupPose(skeleton);
var info = nextClipInfo[c];
float weight = info.weight * layerWeight; if (weight == 0) continue;
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
}
}
}
}
// Apply
for (int layer = 0, n = animator.layerCount; layer < n; layer++) {
float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer);
float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer); // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(layer);
AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);
#if UNITY_5
bool hasNext = nextStateInfo.fullPathHash != 0;
AnimatorClipInfo[] clipInfo = animator.GetCurrentAnimatorClipInfo(layer);
AnimatorClipInfo[] nextClipInfo = animator.GetNextAnimatorClipInfo(layer);
#else
bool hasNext = nextStateInfo.nameHash != 0;
var clipInfo = animator.GetCurrentAnimationClipState(i);
var nextClipInfo = animator.GetNextAnimationClipState(i);
#endif
// UNITY 4
// bool hasNext = nextStateInfo.nameHash != 0;
// var clipInfo = animator.GetCurrentAnimationClipState(i);
// var nextClipInfo = animator.GetNextAnimationClipState(i);
MixMode mode = layerMixModes[layer];
if (mode == MixMode.AlwaysMix) {

View File

@ -114,10 +114,12 @@ namespace Spine.Unity {
return new Vector2(bone.x, bone.y);
}
/// <summary>Gets the position of the bone in Skeleton-space.</summary>
public static Vector2 GetSkeletonSpacePosition (this Bone bone) {
return new Vector2(bone.worldX, bone.worldY);
}
/// <summary>Gets a local offset from the bone and converts it into Skeleton-space.</summary>
public static Vector2 GetSkeletonSpacePosition (this Bone bone, Vector2 boneLocal) {
Vector2 o;
bone.LocalToWorld(boneLocal.x, boneLocal.y, out o.x, out o.y);
@ -136,6 +138,7 @@ namespace Spine.Unity {
};
}
/// <summary>Outputs a 2x2 Transformation Matrix that can convert a skeleton-space position to a bone-local position.</summary>
public static void GetWorldToLocalMatrix (this Bone bone, out float ia, out float ib, out float ic, out float id) {
float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
float invDet = 1 / (a * d - b * c);
@ -144,6 +147,13 @@ namespace Spine.Unity {
ic = invDet * -c;
id = invDet * a;
}
/// <summary>UnityEngine.Vector2 override of Bone.WorldToLocal. This converts a skeleton-space position into a bone local position.</summary>
public static Vector2 WorldToLocal (this Bone bone, Vector2 worldPosition) {
Vector2 o;
bone.WorldToLocal(worldPosition.x, worldPosition.y, out o.x, out o.y);
return o;
}
#endregion
#region Attachments

View File

@ -161,14 +161,14 @@ namespace Spine.Unity {
}
void OnDisable () {
if (clearStateOnDisable)
if (clearStateOnDisable && valid)
ClearState();
}
protected virtual void ClearState () {
meshFilter.sharedMesh = null;
currentInstructions.Clear();
skeleton.SetToSetupPose();
if (skeleton != null) skeleton.SetToSetupPose();
}
public virtual void Initialize (bool overwrite) {
@ -534,11 +534,20 @@ namespace Spine.Unity {
bool mustUpdateRendererMaterials = mustUpdateMeshStructure ||
(lastPushedMaterials.Length != submeshCount);
// Assumption at this point: (lastPushedMaterials.Count == workingSubmeshInstructions.Count == thisSubmeshMaterials.Count == submeshCount)
// Case: mesh structure or submesh count did not change but materials changed.
if (!mustUpdateRendererMaterials) {
var workingSubmeshInstructionsItems = workingSubmeshInstructions.Items;
for (int i = 0, n = lastPushedMaterials.Length; i < n; i++) {
if (lastPushedMaterials[i].GetInstanceID() != workingSubmeshInstructionsItems[i].material.GetInstanceID()) { // Bounds check is implied above.
for (int i = 0; i < submeshCount; i++) {
if (lastPushedMaterials[i].GetInstanceID() != workingSubmeshInstructionsItems[i].material.GetInstanceID()) { // Bounds check is implied by submeshCount above.
mustUpdateRendererMaterials = true;
{
var thisSubmeshMaterials = this.submeshMaterials.Items;
if (mustUpdateRendererMaterials)
for (int j = 0; j < submeshCount; j++)
thisSubmeshMaterials[j] = workingSubmeshInstructionsItems[j].material;
}
break;
}
}

View File

@ -36,6 +36,8 @@ using System.Collections.Generic;
using Spine;
namespace Spine.Unity.Editor {
using Icons = SpineEditorUtilities.Icons;
[CustomEditor(typeof(SkeletonUtilityBone)), CanEditMultipleObjects]
public class SkeletonUtilityBoneInspector : UnityEditor.Editor {
SerializedProperty mode, boneName, zPosition, position, rotation, scale, overrideAlpha, parentReference;
@ -162,11 +164,11 @@ namespace Spine.Unity.Editor {
using (new GUILayout.HorizontalScope()) {
EditorGUILayout.Space();
using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || utilityBone.bone == null || utilityBone.bone.Children.Count == 0)) {
if (GUILayout.Button(new GUIContent("Add Child", SpineEditorUtilities.Icons.bone), GUILayout.MinWidth(120), GUILayout.Height(24)))
if (GUILayout.Button(new GUIContent("Add Child", Icons.bone), GUILayout.MinWidth(120), GUILayout.Height(24)))
BoneSelectorContextMenu("", utilityBone.bone.Children, "<Recursively>", SpawnChildBoneSelected);
}
using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || utilityBone.bone == null || containsOverrides)) {
if (GUILayout.Button(new GUIContent("Add Override", SpineEditorUtilities.Icons.poseBones), GUILayout.MinWidth(120), GUILayout.Height(24)))
if (GUILayout.Button(new GUIContent("Add Override", Icons.poseBones), GUILayout.MinWidth(120), GUILayout.Height(24)))
SpawnOverride();
}
EditorGUILayout.Space();
@ -175,14 +177,14 @@ namespace Spine.Unity.Editor {
using (new GUILayout.HorizontalScope()) {
EditorGUILayout.Space();
using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || !canCreateHingeChain)) {
if (GUILayout.Button(new GUIContent("Create Hinge Chain", SpineEditorUtilities.Icons.hingeChain), GUILayout.Width(150), GUILayout.Height(24)))
if (GUILayout.Button(new GUIContent("Create Hinge Chain", Icons.hingeChain), GUILayout.Width(150), GUILayout.Height(24)))
CreateHingeChain();
}
EditorGUILayout.Space();
}
using (new EditorGUI.DisabledGroupScope(multiObject || boundingBoxTable.Count == 0)) {
EditorGUILayout.LabelField(new GUIContent("Bounding Boxes", SpineEditorUtilities.Icons.boundingBox), EditorStyles.boldLabel);
EditorGUILayout.LabelField(new GUIContent("Bounding Boxes", Icons.boundingBox), EditorStyles.boldLabel);
foreach (var entry in boundingBoxTable){
Slot slot = entry.Key;

View File

@ -130,7 +130,7 @@ namespace Spine.Unity.Editor {
foreach (var attachment in pair.Value) {
GUI.contentColor = slot.Attachment == attachment ? Color.white : Color.grey;
EditorGUI.indentLevel = baseIndent + 2;
var icon = (attachment is MeshAttachment) ? Icons.mesh : Icons.image;
var icon = Icons.GetAttachmentIcon(attachment);
bool isAttached = (attachment == slot.Attachment);
bool swap = EditorGUILayout.ToggleLeft(new GUIContent(attachment.Name, icon), attachment == slot.Attachment);
if (isAttached != swap) {

View File

@ -194,7 +194,6 @@ namespace Spine.Unity {
}
public void RegisterConstraint (SkeletonUtilityConstraint constraint) {
if (utilityConstraints.Contains(constraint))
return;
else {

View File

@ -30,9 +30,6 @@
// Contributed by: Mitch Thompson
using System;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using Spine;

View File

@ -28,8 +28,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
// Contributed by: Mitch Thompson
using UnityEngine;
using System.Collections;
namespace Spine.Unity {
[RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]

View File

@ -38,8 +38,6 @@ Download the latest Spine-Unity unitypackage from the download page: http://esot
In the `Assets/Examples/Scenes` folder you will find many example scenes that demonstrate various spine-unity features.
> Note: If you are still using Spine 2.1.xx, you'll need to use the older 2.1.xx compatible runtime. You can find it here: [spine-unity-v2.unitypackage](http://esotericsoftware.com/files/runtimes/unity/spine-unity-v2.unitypackage)
## Manual installation
You can also choose to setup and run from the Git files: