mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
Merge branch 'master' into spine-ue4
This commit is contained in:
commit
e9bbe8b417
19
.npmignore
Normal file
19
.npmignore
Normal 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
29
package.json
Normal 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"
|
||||
}
|
||||
Binary file not shown.
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -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 ();
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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++)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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++)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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")
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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++)
|
||||
|
||||
@ -164,6 +164,7 @@ module spine {
|
||||
this.regionUVs = parentMesh.regionUVs;
|
||||
this.triangles = parentMesh.triangles;
|
||||
this.hullLength = parentMesh.hullLength;
|
||||
this.worldVerticesLength = parentMesh.worldVerticesLength
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) { }
|
||||
}
|
||||
}
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
BIN
spine-unity/Assets/spine-unity/Editor/GUI/icon-path.png
Normal file
BIN
spine-unity/Assets/spine-unity/Editor/GUI/icon-path.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 519 B |
59
spine-unity/Assets/spine-unity/Editor/GUI/icon-path.png.meta
Normal file
59
spine-unity/Assets/spine-unity/Editor/GUI/icon-path.png.meta
Normal 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:
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -194,7 +194,6 @@ namespace Spine.Unity {
|
||||
}
|
||||
|
||||
public void RegisterConstraint (SkeletonUtilityConstraint constraint) {
|
||||
|
||||
if (utilityConstraints.Contains(constraint))
|
||||
return;
|
||||
else {
|
||||
|
||||
@ -30,9 +30,6 @@
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Spine;
|
||||
|
||||
|
||||
@ -28,8 +28,9 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Spine.Unity {
|
||||
[RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
|
||||
|
||||
@ -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:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user