Merge branch '3.6' into 3.7-beta

This commit is contained in:
badlogic 2018-05-15 11:26:43 +02:00
commit 74d71691fb
52 changed files with 1718 additions and 266 deletions

View File

@ -34,13 +34,15 @@ using UnityEngine;
namespace Spine.Unity {
[CreateAssetMenu(menuName = "Spine/Animation Reference Asset")]
public class AnimationReferenceAsset : ScriptableObject {
public class AnimationReferenceAsset : ScriptableObject, IHasSkeletonDataAsset {
const bool QuietSkeletonData = true;
[SerializeField] protected SkeletonDataAsset skeletonDataAsset;
[SerializeField, SpineAnimation(dataField: "skeletonDataAsset")] protected string animationName;
[SerializeField, SpineAnimation] protected string animationName;
private Animation animation;
public SkeletonDataAsset SkeletonDataAsset { get { return skeletonDataAsset; } }
public Animation Animation {
get {
#if AUTOINIT_SPINEREFERENCE
@ -51,7 +53,7 @@ namespace Spine.Unity {
return animation;
}
}
public void Initialize () {
if (skeletonDataAsset == null) return;
this.animation = skeletonDataAsset.GetSkeletonData(AnimationReferenceAsset.QuietSkeletonData).FindAnimation(animationName);

View File

@ -98,7 +98,7 @@ namespace Spine.Unity {
}
if (_UpdateComplete != null)
_UpdateComplete(this);
_UpdateComplete(this);
}
}
@ -163,14 +163,14 @@ namespace Spine.Unity {
for (int c = 0; c < clipInfoCount; c++) {
var info = clipInfo[c];
float weight = info.weight * layerWeight; if (weight == 0) continue;
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
previousAnimations.Add(GetAnimation(info.clip));
}
if (hasNext) {
for (int c = 0; c < nextClipInfoCount; c++) {
var info = nextClipInfo[c];
float weight = info.weight * layerWeight; if (weight == 0) continue;
previousAnimations.Add(animationTable[NameHashCode(info.clip)]);
previousAnimations.Add(GetAnimation(info.clip));
}
}
}
@ -193,12 +193,12 @@ namespace Spine.Unity {
// Always use Mix instead of Applying the first non-zero weighted clip.
for (int c = 0; c < clipInfoCount; c++) {
var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, weight, MixBlend.Replace, MixDirection.In);
GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
}
if (hasNext) {
for (int c = 0; c < nextClipInfoCount; c++) {
var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, MixBlend.Replace, MixDirection.In);
GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length, nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
}
}
} else { // case MixNext || SpineStyle
@ -206,13 +206,13 @@ namespace Spine.Unity {
int c = 0;
for (; c < clipInfoCount; c++) {
var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, 1f, MixBlend.Replace, MixDirection.In);
GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, 1f, MixPose.Current, MixDirection.In);
break;
}
// Mix the rest
for (; c < clipInfoCount; c++) {
var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, weight, MixBlend.Replace, MixDirection.In);
GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
}
c = 0;
@ -221,14 +221,14 @@ namespace Spine.Unity {
if (mode == MixMode.SpineStyle) {
for (; c < nextClipInfoCount; c++) {
var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, 1f, MixBlend.Replace, MixDirection.In);
GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length, nextStateInfo.speed < 0), nextStateInfo.loop, null, 1f, MixPose.Current, MixDirection.In);
break;
}
}
// Mix the rest
for (; c < nextClipInfoCount; c++) {
var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0) continue;
animationTable[NameHashCode(info.clip)].Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length,nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, MixBlend.Replace, MixDirection.In);
GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime , info.clip.length, nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, MixPose.Current, MixDirection.In);
}
}
}
@ -268,25 +268,21 @@ namespace Spine.Unity {
nextClipInfo = nextClipInfoCache;
}
int NameHashCode (AnimationClip clip) {
Spine.Animation GetAnimation (AnimationClip clip) {
int clipNameHashCode;
if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) {
clipNameHashCode = clip.name.GetHashCode();
clipNameHashCodeTable.Add(clip, clipNameHashCode);
}
return clipNameHashCode;
Spine.Animation animation;
animationTable.TryGetValue(clipNameHashCode, out animation);
return animation;
}
class AnimationClipEqualityComparer : IEqualityComparer<AnimationClip> {
internal static readonly IEqualityComparer<AnimationClip> Instance = new AnimationClipEqualityComparer();
public bool Equals (AnimationClip x, AnimationClip y) {
return x.GetInstanceID() == y.GetInstanceID();
}
public int GetHashCode (AnimationClip o) {
return o.GetInstanceID();
}
public bool Equals (AnimationClip x, AnimationClip y) { return x.GetInstanceID() == y.GetInstanceID(); }
public int GetHashCode (AnimationClip o) { return o.GetInstanceID(); }
}
class IntEqualityComparer : IEqualityComparer<int> {

View File

@ -63,8 +63,15 @@ namespace Spine.Unity.Editor {
public override void OnInspectorGUI () {
animationNameProperty = animationNameProperty ?? serializedObject.FindProperty("animationName");
string animationName = animationNameProperty.stringValue;
Animation animation = ThisSkeletonDataAsset.GetSkeletonData(true).FindAnimation(animationName);
bool animationNotFound = animation == null;
Animation animation = null;
if (ThisSkeletonDataAsset != null) {
var skeletonData = ThisSkeletonDataAsset.GetSkeletonData(true);
if (skeletonData != null) {
animation = skeletonData.FindAnimation(animationName);
}
}
bool animationNotFound = (animation == null);
if (changeNextFrame) {
changeNextFrame = false;

View File

@ -73,15 +73,14 @@ namespace Spine.Unity.Editor {
#region SkeletonAnimator's Mecanim Clips
#if SPINE_SKELETON_ANIMATOR
public static void GenerateMecanimAnimationClips (SkeletonDataAsset skeletonDataAsset) {
//skeletonDataAsset.Clear();
var data = skeletonDataAsset.GetSkeletonData(true);
if (data == null) {
Debug.LogError("SkeletonData failed!", skeletonDataAsset);
Debug.LogError("SkeletonData loading failed!", skeletonDataAsset);
return;
}
string dataPath = AssetDatabase.GetAssetPath(skeletonDataAsset);
string controllerPath = dataPath.Replace("_SkeletonData", "_Controller").Replace(".asset", ".controller");
string controllerPath = dataPath.Replace(SpineEditorUtilities.SkeletonDataSuffix, "_Controller").Replace(".asset", ".controller");
UnityEditor.Animations.AnimatorController controller;
if (skeletonDataAsset.controller != null) {
controller = (UnityEditor.Animations.AnimatorController)skeletonDataAsset.controller;
@ -123,40 +122,35 @@ namespace Spine.Unity.Editor {
}
}
foreach (var anim in data.Animations) {
string name = anim.Name;
spineAnimationTable.Add(name, anim);
foreach (var animations in data.Animations) {
string animationName = animations.Name; // Review for unsafe names. Requires runtime implementation too.
spineAnimationTable.Add(animationName, animations);
if (unityAnimationClipTable.ContainsKey(name) == false) {
//generate new dummy clip
AnimationClip newClip = new AnimationClip();
newClip.name = name;
if (unityAnimationClipTable.ContainsKey(animationName) == false) {
AnimationClip newClip = new AnimationClip {
name = animationName
};
//AssetDatabase.CreateAsset(newClip, Path.GetDirectoryName(dataPath) + "/" + animationName + ".asset");
AssetDatabase.AddObjectToAsset(newClip, controller);
unityAnimationClipTable.Add(name, newClip);
unityAnimationClipTable.Add(animationName, newClip);
}
AnimationClip clip = unityAnimationClipTable[name];
clip.SetCurve("", typeof(GameObject), "dummy", AnimationCurve.Linear(0, 0, anim.Duration, 0));
AnimationClip clip = unityAnimationClipTable[animationName];
clip.SetCurve("", typeof(GameObject), "dummy", AnimationCurve.Linear(0, 0, animations.Duration, 0));
var settings = AnimationUtility.GetAnimationClipSettings(clip);
settings.stopTime = anim.Duration;
settings.stopTime = animations.Duration;
SetAnimationSettings(clip, settings);
AnimationUtility.SetAnimationEvents(clip, new AnimationEvent[0]);
foreach (Timeline t in anim.Timelines) {
if (t is EventTimeline) {
foreach (Timeline t in animations.Timelines) {
if (t is EventTimeline)
ParseEventTimeline((EventTimeline)t, clip, SendMessageOptions.DontRequireReceiver);
}
}
EditorUtility.SetDirty(clip);
unityAnimationClipTable.Remove(name);
unityAnimationClipTable.Remove(animationName);
}
//clear no longer used animations
foreach (var clip in unityAnimationClipTable.Values) {
AnimationClip.DestroyImmediate(clip, true);
}

View File

@ -36,7 +36,6 @@ using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Spine;
namespace Spine.Unity.Editor {
@ -80,6 +79,12 @@ namespace Spine.Unity.Editor {
void OnDestroy () {
HandleOnDestroyPreview();
AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
EditorApplication.update -= preview.HandleEditorUpdate;
}
private void OnDomainUnload (object sender, EventArgs e) {
OnDestroy();
}
void InitializeEditor () {
@ -105,7 +110,11 @@ namespace Spine.Unity.Editor {
#else
// Analysis disable once ConvertIfToOrExpression
if (newAtlasAssets) atlasAssets.isExpanded = true;
#endif
#endif
// This handles the case where the managed editor assembly is unloaded before recompilation when code changes.
AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
AppDomain.CurrentDomain.DomainUnload += OnDomainUnload;
EditorApplication.update -= preview.HandleEditorUpdate;
EditorApplication.update += preview.HandleEditorUpdate;
@ -678,23 +687,43 @@ namespace Spine.Unity.Editor {
set { if (IsValid) skeletonAnimation.timeScale = value; }
}
public bool IsPlayingAnimation {
get {
public bool IsPlayingAnimation { get {
if (!IsValid) return false;
var currentTrack = skeletonAnimation.AnimationState.GetCurrent(0);
return currentTrack != null && currentTrack.TimeScale > 0;
}
}
public TrackEntry ActiveTrack {
get { return IsValid ? skeletonAnimation.AnimationState.GetCurrent(0) : null; }
}
public TrackEntry ActiveTrack { get { return IsValid ? skeletonAnimation.AnimationState.GetCurrent(0) : null; } }
public Vector3 PreviewCameraPosition {
get { return PreviewUtilityCamera.transform.position; }
set { PreviewUtilityCamera.transform.position = value; }
}
public void HandleDrawSettings () {
const float SliderWidth = 150;
const float SliderSnap = 0.25f;
const float SliderMin = 0f;
const float SliderMax = 2f;
if (IsValid) {
float timeScale = GUILayout.HorizontalSlider(TimeScale, SliderMin, SliderMax, GUILayout.MaxWidth(SliderWidth));
timeScale = Mathf.RoundToInt(timeScale / SliderSnap) * SliderSnap;
TimeScale = timeScale;
}
}
public void HandleEditorUpdate () {
AdjustCamera();
if (IsPlayingAnimation) {
RefreshOnNextUpdate();
Repaint();
} else if (requiresRefresh) {
Repaint();
}
}
public void Initialize (Action repaintCallback, SkeletonDataAsset skeletonDataAsset, string skinName = "") {
if (skeletonDataAsset == null) return;
if (skeletonDataAsset.GetSkeletonData(false) == null) {
@ -715,7 +744,7 @@ namespace Spine.Unity.Editor {
previewRenderUtility = new PreviewRenderUtility(true);
animationLastTime = Time.realtimeSinceStartup;
const int PreviewLayer = 31;
const int PreviewLayer = 30;
const int PreviewCameraCullingMask = 1 << PreviewLayer;
{
@ -743,49 +772,136 @@ namespace Spine.Unity.Editor {
previewGameObject.GetComponent<Renderer>().enabled = false;
}
AdjustCameraGoals(true);
if (this.ActiveTrack != null) cameraAdjustEndFrame = EditorApplication.timeSinceStartup + skeletonAnimation.AnimationState.GetCurrent(0).Alpha;
AdjustCameraGoals();
} catch {
DestroyPreviewGameObject();
}
RefreshOnNextUpdate();
}
}
}
public void HandleDrawSettings () {
const float SliderWidth = 150;
const float SliderSnap = 0.25f;
const float SliderMin = 0f;
const float SliderMax = 2f;
public void HandleInteractivePreviewGUI (Rect r, GUIStyle background) {
if (Event.current.type == EventType.Repaint) {
if (requiresRefresh) {
previewRenderUtility.BeginPreview(r, background);
DoRenderPreview(true);
previewTexture = previewRenderUtility.EndPreview();
requiresRefresh = false;
}
if (previewTexture != null)
GUI.DrawTexture(r, previewTexture, ScaleMode.StretchToFill, false);
}
if (IsValid) {
float timeScale = GUILayout.HorizontalSlider(TimeScale, SliderMin, SliderMax, GUILayout.MaxWidth(SliderWidth));
timeScale = Mathf.RoundToInt(timeScale / SliderSnap) * SliderSnap;
TimeScale = timeScale;
DrawSkinToolbar(r);
//DrawSetupPoseButton(r);
DrawTimeBar(r);
HandleMouseScroll(r);
}
public Texture2D GetStaticPreview (int width, int height) {
var c = this.PreviewUtilityCamera;
if (c == null)
return null;
RefreshOnNextUpdate();
AdjustCameraGoals();
c.orthographicSize = cameraOrthoGoal / 2;
c.transform.position = cameraPositionGoal;
previewRenderUtility.BeginStaticPreview(new Rect(0, 0, width, height));
DoRenderPreview(false);
var tex = previewRenderUtility.EndStaticPreview();
return tex;
}
public void DoRenderPreview (bool drawHandles) {
if (this.PreviewUtilityCamera.activeTexture == null || this.PreviewUtilityCamera.targetTexture == null)
return;
GameObject go = previewGameObject;
if (requiresRefresh && go != null) {
var renderer = go.GetComponent<Renderer>();
renderer.enabled = true;
if (!EditorApplication.isPlaying) {
skeletonAnimation.Update((Time.realtimeSinceStartup - animationLastTime));
skeletonAnimation.LateUpdate();
animationLastTime = Time.realtimeSinceStartup;
}
var thisPreviewUtilityCamera = this.PreviewUtilityCamera;
if (drawHandles) {
Handles.SetCamera(thisPreviewUtilityCamera);
Handles.color = OriginColor;
// Draw Cross
float scale = skeletonDataAsset.scale;
float cl = 1000 * scale;
Handles.DrawLine(new Vector3(-cl, 0), new Vector3(cl, 0));
Handles.DrawLine(new Vector3(0, cl), new Vector3(0, -cl));
}
thisPreviewUtilityCamera.Render();
if (drawHandles) {
Handles.SetCamera(thisPreviewUtilityCamera);
SpineHandles.DrawBoundingBoxes(skeletonAnimation.transform, skeletonAnimation.skeleton);
if (SkeletonDataAssetInspector.showAttachments)
SpineHandles.DrawPaths(skeletonAnimation.transform, skeletonAnimation.skeleton);
}
renderer.enabled = false;
}
}
public void OnDestroy () {
DisposePreviewRenderUtility();
DestroyPreviewGameObject();
}
public void AdjustCamera () {
if (previewRenderUtility == null)
return;
public void Clear () {
DisposePreviewRenderUtility();
DestroyPreviewGameObject();
}
if (EditorApplication.timeSinceStartup < cameraAdjustEndFrame)
AdjustCameraGoals();
void DisposePreviewRenderUtility () {
if (previewRenderUtility != null) {
previewRenderUtility.Cleanup();
previewRenderUtility = null;
lastCameraPositionGoal = cameraPositionGoal;
lastCameraOrthoGoal = cameraOrthoGoal;
var c = this.PreviewUtilityCamera;
float orthoSet = Mathf.Lerp(c.orthographicSize, cameraOrthoGoal, 0.1f);
c.orthographicSize = orthoSet;
float dist = Vector3.Distance(c.transform.position, cameraPositionGoal);
if (dist > 0f) {
Vector3 pos = Vector3.Lerp(c.transform.position, cameraPositionGoal, 0.1f);
pos.x = 0;
c.transform.position = pos;
c.transform.rotation = Quaternion.identity;
RefreshOnNextUpdate();
}
}
void DestroyPreviewGameObject () {
if (previewGameObject != null) {
GameObject.DestroyImmediate(previewGameObject);
previewGameObject = null;
void AdjustCameraGoals () {
if (previewGameObject == null) return;
Bounds bounds = previewGameObject.GetComponent<Renderer>().bounds;
cameraOrthoGoal = bounds.size.y;
cameraPositionGoal = bounds.center + new Vector3(0, 0, -10f);
}
void HandleMouseScroll (Rect position) {
Event current = Event.current;
int controlID = GUIUtility.GetControlID(SliderHash, FocusType.Passive);
switch (current.GetTypeForControl(controlID)) {
case EventType.ScrollWheel:
if (position.Contains(current.mousePosition)) {
cameraOrthoGoal += current.delta.y * 0.06f;
cameraOrthoGoal = Mathf.Max(0.01f, cameraOrthoGoal);
GUIUtility.hotControl = controlID;
current.Use();
}
break;
}
}
@ -820,7 +936,7 @@ namespace Spine.Unity.Editor {
var targetAnimation = skeletonData.FindAnimation(animationName);
if (targetAnimation != null) {
var currentTrack = skeletonAnimation.AnimationState.GetCurrent(0);
var currentTrack = this.ActiveTrack;
bool isEmpty = (currentTrack == null);
bool isNewAnimation = isEmpty || currentTrack.Animation != targetAnimation;
@ -859,128 +975,6 @@ namespace Spine.Unity.Editor {
}
public void HandleInteractivePreviewGUI (Rect r, GUIStyle background) {
if (Event.current.type == EventType.Repaint) {
if (requiresRefresh) {
previewRenderUtility.BeginPreview(r, background);
DoRenderPreview(true);
previewTexture = previewRenderUtility.EndPreview();
requiresRefresh = false;
}
if (previewTexture != null)
GUI.DrawTexture(r, previewTexture, ScaleMode.StretchToFill, false);
}
DrawSkinToolbar(r);
//DrawSetupPoseButton(r);
DrawTimeBar(r);
MouseScroll(r);
}
void AdjustCameraGoals (bool calculateMixTime = false) {
if (previewGameObject == null)
return;
if (calculateMixTime) {
if (skeletonAnimation.AnimationState.GetCurrent(0) != null)
cameraAdjustEndFrame = EditorApplication.timeSinceStartup + skeletonAnimation.AnimationState.GetCurrent(0).Alpha;
}
Bounds bounds = previewGameObject.GetComponent<Renderer>().bounds;
cameraOrthoGoal = bounds.size.y;
cameraPositionGoal = bounds.center + new Vector3(0, 0, -10f);
}
public void AdjustCamera () {
if (previewRenderUtility == null)
return;
if (EditorApplication.timeSinceStartup < cameraAdjustEndFrame)
AdjustCameraGoals();
lastCameraPositionGoal = cameraPositionGoal;
lastCameraOrthoGoal = cameraOrthoGoal;
var c = this.PreviewUtilityCamera;
float orthoSet = Mathf.Lerp(c.orthographicSize, cameraOrthoGoal, 0.1f);
c.orthographicSize = orthoSet;
float dist = Vector3.Distance(c.transform.position, cameraPositionGoal);
if (dist > 0f) {
Vector3 pos = Vector3.Lerp(c.transform.position, cameraPositionGoal, 0.1f);
pos.x = 0;
c.transform.position = pos;
c.transform.rotation = Quaternion.identity;
RefreshOnNextUpdate();
}
}
public Texture2D GetStaticPreview (int width, int height) {
var c = this.PreviewUtilityCamera;
if (c == null) return null;
RefreshOnNextUpdate();
AdjustCameraGoals();
c.orthographicSize = cameraOrthoGoal / 2;
c.transform.position = cameraPositionGoal;
previewRenderUtility.BeginStaticPreview(new Rect(0, 0, width, height));
DoRenderPreview(false);
var tex = previewRenderUtility.EndStaticPreview();
return tex;
}
public void HandleEditorUpdate () {
AdjustCamera();
if (IsPlayingAnimation) {
RefreshOnNextUpdate();
Repaint();
} else if (requiresRefresh) {
Repaint();
}
}
public void DoRenderPreview (bool drawHandles) {
if (this.PreviewUtilityCamera.activeTexture == null || this.PreviewUtilityCamera.targetTexture == null )
return;
GameObject go = previewGameObject;
if (requiresRefresh && go != null) {
go.GetComponent<Renderer>().enabled = true;
if (!EditorApplication.isPlaying)
skeletonAnimation.Update((Time.realtimeSinceStartup - animationLastTime));
animationLastTime = Time.realtimeSinceStartup;
if (!EditorApplication.isPlaying)
skeletonAnimation.LateUpdate();
var thisPreviewUtilityCamera = this.PreviewUtilityCamera;
if (drawHandles) {
Handles.SetCamera(thisPreviewUtilityCamera);
Handles.color = OriginColor;
float scale = skeletonDataAsset.scale;
Handles.DrawLine(new Vector3(-1000 * scale, 0, 0), new Vector3(1000 * scale, 0, 0));
Handles.DrawLine(new Vector3(0, 1000 * scale, 0), new Vector3(0, -1000 * scale, 0));
}
thisPreviewUtilityCamera.Render();
if (drawHandles) {
Handles.SetCamera(thisPreviewUtilityCamera);
SpineHandles.DrawBoundingBoxes(skeletonAnimation.transform, skeletonAnimation.skeleton);
if (SkeletonDataAssetInspector.showAttachments) SpineHandles.DrawPaths(skeletonAnimation.transform, skeletonAnimation.skeleton);
}
go.GetComponent<Renderer>().enabled = false;
}
}
void DrawSkinToolbar (Rect r) {
if (!this.IsValid) return;
@ -1053,7 +1047,7 @@ namespace Spine.Unity.Editor {
GUI.Box(barRect, "");
Rect lineRect = new Rect(barRect);
float width = lineRect.width;
float lineRectWidth = lineRect.width;
TrackEntry t = skeletonAnimation.AnimationState.GetCurrent(0);
if (t != null) {
@ -1062,7 +1056,7 @@ namespace Spine.Unity.Editor {
float normalizedTime = currentTime / t.Animation.Duration;
float wrappedTime = normalizedTime % 1;
lineRect.x = barRect.x + (width * wrappedTime) - 0.5f;
lineRect.x = barRect.x + (lineRectWidth * wrappedTime) - 0.5f;
lineRect.width = 2;
GUI.color = Color.red;
@ -1071,13 +1065,14 @@ namespace Spine.Unity.Editor {
for (int i = 0; i < currentAnimationEvents.Count; i++) {
float fr = currentAnimationEventTimes[i];
var userEventIcon = Icons.userEvent;
var evRect = new Rect(barRect) {
x = Mathf.Clamp(((fr / t.Animation.Duration) * width) - (Icons.userEvent.width / 2), barRect.x, float.MaxValue),
y = barRect.y + Icons.userEvent.height,
width = Icons.userEvent.width,
height = Icons.userEvent.height
x = Mathf.Clamp(((fr / t.Animation.Duration) * lineRectWidth) - (userEventIcon.width / 2), barRect.x, float.MaxValue),
y = barRect.y + userEventIcon.height,
width = userEventIcon.width,
height = userEventIcon.height
};
GUI.DrawTexture(evRect, Icons.userEvent);
GUI.DrawTexture(evRect, userEventIcon);
Event ev = Event.current;
if (ev.type == EventType.Repaint) {
@ -1095,18 +1090,27 @@ namespace Spine.Unity.Editor {
}
}
void MouseScroll (Rect position) {
Event current = Event.current;
int controlID = GUIUtility.GetControlID(SliderHash, FocusType.Passive);
switch (current.GetTypeForControl(controlID)) {
case EventType.ScrollWheel:
if (position.Contains(current.mousePosition)) {
cameraOrthoGoal += current.delta.y * 0.06f;
cameraOrthoGoal = Mathf.Max(0.01f, cameraOrthoGoal);
GUIUtility.hotControl = controlID;
current.Use();
}
break;
public void OnDestroy () {
DisposePreviewRenderUtility();
DestroyPreviewGameObject();
}
public void Clear () {
DisposePreviewRenderUtility();
DestroyPreviewGameObject();
}
void DisposePreviewRenderUtility () {
if (previewRenderUtility != null) {
previewRenderUtility.Cleanup();
previewRenderUtility = null;
}
}
void DestroyPreviewGameObject () {
if (previewGameObject != null) {
GameObject.DestroyImmediate(previewGameObject);
previewGameObject = null;
}
}
}

View File

@ -89,9 +89,16 @@ namespace Spine.Unity.Editor {
return;
}
} else if (property.serializedObject.targetObject is Component) {
var component = (Component)property.serializedObject.targetObject;
var hasSkeletonDataAsset = component.GetComponentInChildren(typeof(IHasSkeletonDataAsset)) as IHasSkeletonDataAsset;
} else {
var targetObject = property.serializedObject.targetObject;
IHasSkeletonDataAsset hasSkeletonDataAsset = targetObject as IHasSkeletonDataAsset;
if (hasSkeletonDataAsset == null) {
var component = targetObject as Component;
if (component != null)
hasSkeletonDataAsset = component.GetComponentInChildren(typeof(IHasSkeletonDataAsset)) as IHasSkeletonDataAsset;
}
if (hasSkeletonDataAsset != null)
skeletonDataAsset = hasSkeletonDataAsset.SkeletonDataAsset;
}

View File

@ -487,11 +487,19 @@ namespace Spine.Unity.Editor {
skeletonUtilityBoneTable.Clear();
boundingBoxFollowerTable.Clear();
#if UNITY_2018
EditorApplication.hierarchyChanged -= HierarchyIconsOnChanged;
#else
EditorApplication.hierarchyWindowChanged -= HierarchyIconsOnChanged;
#endif
EditorApplication.hierarchyWindowItemOnGUI -= HierarchyIconsOnGUI;
if (!Application.isPlaying && showHierarchyIcons) {
#if UNITY_2018
EditorApplication.hierarchyChanged += HierarchyIconsOnChanged;
#else
EditorApplication.hierarchyWindowChanged += HierarchyIconsOnChanged;
#endif
EditorApplication.hierarchyWindowItemOnGUI += HierarchyIconsOnGUI;
HierarchyIconsOnChanged();
}
@ -1189,10 +1197,11 @@ namespace Spine.Unity.Editor {
#endregion
#region Import SkeletonData (json or binary)
public const string SkeletonDataSuffix = "_SkeletonData";
static SkeletonDataAsset IngestSpineProject (TextAsset spineJson, params AtlasAsset[] atlasAssets) {
string primaryName = Path.GetFileNameWithoutExtension(spineJson.name);
string assetPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(spineJson));
string filePath = assetPath + "/" + primaryName + "_SkeletonData.asset";
string filePath = assetPath + "/" + primaryName + SkeletonDataSuffix + ".asset";
#if SPINE_TK2D
if (spineJson != null) {
@ -1554,12 +1563,11 @@ namespace Spine.Unity.Editor {
}
#endregion
//public static string GetPathSafeRegionName (AtlasRegion region) {
// return region.name.Replace("/", "_");
//}
public static string GetPathSafeName (string name) {
return name.Replace("/", "_");
foreach (char c in System.IO.Path.GetInvalidFileNameChars()) { // Doesn't handle more obscure file name limitations.
name = name.Replace(c, '_');
}
return name;
}
}

View File

@ -1395,7 +1395,7 @@ namespace Spine.Unity {
var instruction = instructionsItems[startSubmesh + i];
submeshesItems[i] = instruction;
#if SPINE_TRIANGLECHECK
this.hasActiveClipping = instruction.hasClipping;
this.hasActiveClipping |= instruction.hasClipping;
submeshesItems[i].rawFirstVertexIndex = runningVertexCount; // Ensure current instructions have correct cached values.
runningVertexCount += instruction.rawVertexCount; // vertexCount will also be used for the rest of this method.
#endif

View File

@ -680,7 +680,12 @@ public class SpineSpriteShaderGUI : ShaderGUI {
if (emission && !mixedValue) {
EditorGUI.BeginChangeCheck();
#if UNITY_2018
_materialEditor.TexturePropertyWithHDRColor(_emissionText, _emissionMap, _emissionColor, true);
#else
_materialEditor.TexturePropertyWithHDRColor(_emissionText, _emissionMap, _emissionColor, new ColorPickerHDRConfig(0, 1, 0.01010101f, 3), true);
#endif
_materialEditor.FloatProperty(_emissionPower, _emissionPowerText.text);
dataChanged |= EditorGUI.EndChangeCheck();
}

View File

@ -66,8 +66,9 @@ namespace Spine.Unity {
bone = skeletonGraphic.Skeleton.FindBone(boneName);
#if UNITY_EDITOR
if (Application.isEditor)
if (Application.isEditor) {
LateUpdate();
}
#endif
}
@ -91,7 +92,9 @@ namespace Spine.Unity {
var thisTransform = this.transform as RectTransform;
if (thisTransform == null) return;
float scale = skeletonGraphic.canvas.referencePixelsPerUnit;
var canvas = skeletonGraphic.canvas;
if (canvas == null) canvas = skeletonGraphic.GetComponentInParent<Canvas>();
float scale = canvas.referencePixelsPerUnit;
if (skeletonTransformIsParent) {
// Recommended setup: Use local transform properties if Spine GameObject is the immediate parent
@ -113,12 +116,7 @@ namespace Spine.Unity {
if (followBoneRotation) {
Vector3 worldRotation = skeletonTransform.rotation.eulerAngles;
#if UNITY_5_6_OR_NEWER
thisTransform.SetPositionAndRotation(targetWorldPosition, Quaternion.Euler(worldRotation.x, worldRotation.y, skeletonTransform.rotation.eulerAngles.z + boneWorldRotation));
#else
thisTransform.position = targetWorldPosition;
thisTransform.rotation = Quaternion.Euler(worldRotation.x, worldRotation.y, skeletonTransform.rotation.eulerAngles.z + bone.WorldRotationX);
#endif
} else {
thisTransform.position = targetWorldPosition;
}

View File

@ -115,7 +115,7 @@ namespace Spine.Unity {
public static SkeletonGraphic AddSkeletonGraphicComponent (GameObject gameObject, SkeletonDataAsset skeletonDataAsset) {
var c = gameObject.AddComponent<SkeletonGraphic>();
if (skeletonDataAsset != null) {
c.skeletonDataAsset = skeletonDataAsset;
c.skeletonDataAsset = skeletonDataAsset;
c.Initialize(false);
}
return c;

View File

@ -138,18 +138,13 @@ namespace Spine.Unity.Modules {
skeletonRenderer.GenerateMeshOverride += HandleRender;
#endif
#if UNITY_5_4_OR_NEWER
if (copyMeshRendererFlags) {
var lightProbeUsage = mainMeshRenderer.lightProbeUsage;
bool receiveShadows = mainMeshRenderer.receiveShadows;
#if UNITY_5_5_OR_NEWER
var reflectionProbeUsage = mainMeshRenderer.reflectionProbeUsage;
var shadowCastingMode = mainMeshRenderer.shadowCastingMode;
var motionVectorGenerationMode = mainMeshRenderer.motionVectorGenerationMode;
var probeAnchor = mainMeshRenderer.probeAnchor;
#endif
for (int i = 0; i < partsRenderers.Count; i++) {
var currentRenderer = partsRenderers[i];
@ -158,31 +153,12 @@ namespace Spine.Unity.Modules {
var mr = currentRenderer.MeshRenderer;
mr.lightProbeUsage = lightProbeUsage;
mr.receiveShadows = receiveShadows;
#if UNITY_5_5_OR_NEWER
mr.reflectionProbeUsage = reflectionProbeUsage;
mr.shadowCastingMode = shadowCastingMode;
mr.motionVectorGenerationMode = motionVectorGenerationMode;
mr.probeAnchor = probeAnchor;
#endif
}
}
#else
if (copyMeshRendererFlags) {
var useLightProbes = mainMeshRenderer.useLightProbes;
bool receiveShadows = mainMeshRenderer.receiveShadows;
for (int i = 0; i < partsRenderers.Count; i++) {
var currentRenderer = partsRenderers[i];
if (currentRenderer == null) continue; // skip null items.
var mr = currentRenderer.MeshRenderer;
mr.useLightProbes = useLightProbes;
mr.receiveShadows = receiveShadows;
}
}
#endif
}
void OnDisable () {

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 9192f99585e00e2468a2e2592cfce807
folderAsset: yes
timeCreated: 1505434717
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: a363511f60be37a4199a1a4ad0188b40
folderAsset: yes
timeCreated: 1511505394
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,80 @@
This Documentation is for the Spine Timeline features.
If this documentation contains mistakes or doesn't cover some questions, please feel to comment below, open an issue or post in the official [Spine-Unity forums](http://esotericsoftware.com/forum/viewforum.php?f=3).
# Spine-Unity Timeline Playables
![](add-menu.png)
## Spine Animation Track
Controls the skeleton pose a given Spine component with animations.
**Status:**
- Currently only SkeletonAnimation (via SkeletonAnimationPlayableHandle)
- Mixing has some significant bugs. It should work fine if you don't include mixing, or if all your animations have perfectly matching dopesheet properties.
**To use:**
1. Add `SkeletonAnimationPlayableHandle` component to your SkeletonAnimation GameObject.
2. With an existing Unity Playable Direction, and in the Unity Timeline window, right-click on an empty space on the left and choose **Spine.Unity.Playables** > **Spine Animation Track**.
3. Drag the SkeletonAnimation GameObject onto the empty reference property of the new Spine Skeleton Flip Track.
4. Right-click on the row in an empty space in the Timeline dopesheet and choose **Add Spine Animation Clip Clip**.
5. Adjust the start and end times of the new clip, name it appropriately at the top of the Inspector.
6. Click on the clip inspector's SkeletonDataAsset field and choose your target skeleton's SkeletonDataAsset. This will enable the animation name dropdown to appear.
7. Choose the appropriate animation name, loop, and mix settings.
8. For easier readability, rename your clip to the animation name or something descriptive.
**Track Behavior**
- Currently buggy
-
## Spine Skeleton Flip Track
![](skeleton-flip-clip-inspector.png)
Controls skeleton flip a given Spine component.
**Status:**
- Currently only SkeletonAnimation (via SkeletonAnimationPlayableHandle)
**To use:**
1. Add `SkeletonAnimationPlayableHandle` component to your SkeletonAnimation GameObject.
2. With an existing Unity Playable Director, and in the Unity Timeline window, right-click on an empty space on the left and choose **Spine.Unity.Playables** > **Spine Skeleton Flip Track**.
3. Drag the SkeletonAnimation GameObject onto the empty reference property of the new Spine Skeleton Flip Track.
4. Right-click on the row in an empty space in the Timeline dopesheet and choose **Add Spine Skeleton Flip Clip Clip**.
5. Adjust the start and end times of the new clip, name it appropriately at the top of the Inspector, and choose the desired FlipX and FlipY values.
**Track Behavior**
- The specified skeleton flip values will be applied for every frame within the duration of each track.
- At the end of the timeline, the track will revert the skeleton flip to the flip values it captures when it starts playing that timeline.
## Spine AnimationState Track
![](animationstate-clip-inspector.png)
Sets Animations on the target SkeletonAnimation's AnimationState (via SetAnimation).
**Status:**
- Currently only SkeletonAnimation (directly)
**To use:**
1. With an existing Unity Playable Director, and in the Unity Timeline window, right-click on an empty space on the left and choose **Spine.Unity.Playables** > **Spine Animation State Track**.
2. Drag the SkeletonAnimation GameObject onto the empty reference property of the new Spine AnimationState Track.
3. Right-click on the row in an empty space in the Timeline dopesheet and choose **Add Spine Animation State Clip Clip**.
4. Adjust the start and end times of the new clip, name it appropriately at the top of the Inspector.
5. Click on the clip inspector's SkeletonDataAsset field and choose your target skeleton's SkeletonDataAsset. This will enable the animation name dropdown to appear.
6. Choose the appropriate animation name, loop, and mix settings.
- For easier readability, rename your clip to the animation name or something descriptive.
- To avoid having to do steps 4-6 repeatedly, use the Duplicate function (`CTRL`/`CMD` + `D`)
**Track Behavior**
- `AnimationState.SetAnimation` will be called at the beginning of every clip based on the animationName.
- Clip durations don't matter. Animations won't be cleared where there is no active clip at certain slices of time.
- **EMPTY ANIMATION**: If a clip has no name specified, it will call SetEmptyAnimation instead.
- **ERROR HANDLING**: If the animation with the provided animationName is not found, it will do nothing (the previous animation will continue playing normally).
- Animations playing before the timeline starts playing will not be interrupted until the first clip starts playing.
- At the end of the last clip and at the end of the timeline, nothing happens. This means the effect of the last clip's SetAnimation call will persist until you give other commands to that AnimationState.
- If "custom duration" is unchecked, it will do a normal lookup of the AnimationState data's specified transition-pair mix setting, or the default mix.
- Edit mode preview mixing may look different from Play Mode mixing. Please check in actual Play Mode to see the real results.
## Known Issues
Spine Timeline support is currently experimental and has some known issues and inconveniences.
- The Console logs an incorrect/harmless error `DrivenPropertyManager has failed to register property "m_Script" of object "Spine GameObject (spineboy-pro)" with driver "" because the property doesn't exist.`. This is a known issue on Unity's end. See more here: https://forum.unity.com/threads/default-playables-text-switcher-track-error.502903/
- These Spine Tracks (like other custom Unity Timeline Playable types) do not have labels on them. Unity currently doesn't have API to specify their labels yet.
- Each track clip currently requires you to specify a reference to SkeletonData so its inspector can show you a convenient list of animation names. This is because track clips are agnostic of its track and target component/track binding, and provides no way of automatically finding it while in the editor. The clips will still function correctly without the SkeletonDataAsset references; you just won't get the dropdown of animation names in the editor.
- Each track clip cannot be automatically named based on the chosen animationName. The Timeline object editors currently doesn't provide access to the clip names to do this automatically.

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 970f0962a0a79bf42bdedfc9ed439f56
timeCreated: 1511505255
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,112 @@
fileFormatVersion: 2
guid: ab296920a52d8204ea35ed4385481be3
timeCreated: 1511505440
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Windows Store Apps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,112 @@
fileFormatVersion: 2
guid: ca162358b7b05034cae4e25bfb8b98f8
timeCreated: 1511508127
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Windows Store Apps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,112 @@
fileFormatVersion: 2
guid: 80e301d4353d83640bb50224021a8379
timeCreated: 1511506555
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Windows Store Apps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ff79ab0c89530f24d8f60162bd4c1009
folderAsset: yes
timeCreated: 1507311562
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,114 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//using UnityEngine.Playables;
using Spine;
using Spine.Unity;
using Spine.Unity.Playables;
namespace Spine.Unity.Playables {
[AddComponentMenu("Spine/Playables/SkeletonAnimation Playable Handle (Playables)")]
public class SkeletonAnimationPlayableHandle : SpinePlayableHandleBase {
#region Inspector
public SkeletonAnimation skeletonAnimation;
//public float fadeOutDuration = 0.5f;
#if UNITY_EDITOR
void OnValidate () {
if (this.skeletonAnimation == null)
skeletonAnimation = GetComponent<SkeletonAnimation>();
}
#endif
#endregion
//readonly HashSet<int> frameAppliedProperties = new HashSet<int>();
public override Skeleton Skeleton { get { return skeletonAnimation.Skeleton; } }
public override SkeletonData SkeletonData { get { return skeletonAnimation.Skeleton.data; } }
#if UNITY_2017 || UNITY_2018
void Awake () {
if (skeletonAnimation == null)
skeletonAnimation = GetComponent<SkeletonAnimation>();
//frameAppliedProperties.Clear();
}
//Skeleton skeleton;
//int frameTrackCount = 0;
//int frameCurrentInputs = 0;
//bool firstCleared = false;
//int lastApplyFrame = 0;
//public override void ProcessFrame (Playable playable, FrameData info, SpineAnimationMixerBehaviour mixer) {
// if (skeletonAnimation == null) return;
// if (skeleton == null) skeleton = skeletonAnimation.Skeleton;
// // New frame.
// if (lastApplyFrame != Time.frameCount) {
// if (frameTrackCount > 0)
// frameAppliedProperties.Clear();
// frameCurrentInputs = 0;
// frameTrackCount = 0;
// }
// lastApplyFrame = Time.frameCount;
// int currentInputs = mixer.ApplyPlayableFrame(playable, skeleton, frameAppliedProperties, frameTrackCount);
// frameCurrentInputs += currentInputs;
// // EXPERIMENTAL: Handle overriding SkeletonAnimation.AnimationState.
// if (frameCurrentInputs > 0) {
// var state = skeletonAnimation.AnimationState;
// if (!firstCleared) {
// firstCleared = true;
// for (int i = 0; i < 4; i++) {
// if (state.GetCurrent(i) != null) state.SetEmptyAnimation(i, fadeOutDuration);
// }
// }
// // Update again whenever an animation is playing in the AnimationState. Quite wasteful.
// //if (state.GetCurrent(0) != null) {
// skeleton.UpdateWorldTransform();
// //}
// }
// frameTrackCount++;
//}
#endif
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: bd5f4cbc0a51cc24b86e5f70151bc0c3
timeCreated: 1507311603
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,64 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//using UnityEngine.Playables;
namespace Spine.Unity.Playables {
public delegate void SpineEventDelegate (Spine.Event e);
/// <summary>Base class for Spine Playable Handle components, commonly for integrating with UnityEngine Timeline.</summary>
public abstract class SpinePlayableHandleBase : MonoBehaviour {
/// <summary>Gets the SkeletonData of the targeted Spine component.</summary>
public abstract SkeletonData SkeletonData { get; }
public abstract Skeleton Skeleton { get; }
/// <summary>MixerBehaviour ProcessFrame method handler.</summary>
/// <returns>Returns true if a playable was applied previously</returns>
//public abstract void ProcessFrame (Playable playable, FrameData info, SpineAnimationMixerBehaviour mixer);
/// <summary>Subscribe to this to handle user events played by the Unity playable</summary>
public event SpineEventDelegate AnimationEvents;
public virtual void HandleEvents (ExposedList<Event> eventBuffer) {
if (eventBuffer == null || AnimationEvents == null) return;
for (int i = 0, n = eventBuffer.Count; i < n; i++)
AnimationEvents.Invoke(eventBuffer.Items[i]);
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2dfbb56974b17984ca2534bc8185f665
timeCreated: 1507311422
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 47adfa0aa094be548be25e178c1435d2
folderAsset: yes
timeCreated: 1510816616
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 54bc1978049774f4aa13bfd014a5773a
folderAsset: yes
timeCreated: 1510816616
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,49 @@
using UnityEditor;
using UnityEngine;
using Spine;
using Spine.Unity;
using Spine.Unity.Playables;
//[CustomPropertyDrawer(typeof(SpineAnimationStateBehaviour))]
public class SpineAnimationStateDrawer : PropertyDrawer {
/*
public override float GetPropertyHeight (SerializedProperty property, GUIContent label) {
const int fieldCount = 8;
return fieldCount * EditorGUIUtility.singleLineHeight;
}
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
SerializedProperty skeletonDataAssetProp = property.FindPropertyRelative("skeletonDataAsset");
SerializedProperty animationNameProp = property.FindPropertyRelative("animationName");
SerializedProperty loopProp = property.FindPropertyRelative("loop");
SerializedProperty eventProp = property.FindPropertyRelative("eventThreshold");
SerializedProperty attachmentProp = property.FindPropertyRelative("attachmentThreshold");
SerializedProperty drawOrderProp = property.FindPropertyRelative("drawOrderThreshold");
Rect singleFieldRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
EditorGUI.PropertyField(singleFieldRect, skeletonDataAssetProp);
float lineHeightWithSpacing = EditorGUIUtility.singleLineHeight + 2f;
singleFieldRect.y += lineHeightWithSpacing;
EditorGUI.PropertyField(singleFieldRect, animationNameProp);
singleFieldRect.y += lineHeightWithSpacing;
EditorGUI.PropertyField(singleFieldRect, loopProp);
singleFieldRect.y += lineHeightWithSpacing * 0.5f;
singleFieldRect.y += lineHeightWithSpacing;
EditorGUI.LabelField(singleFieldRect, "Mixing Settings", EditorStyles.boldLabel);
singleFieldRect.y += lineHeightWithSpacing;
EditorGUI.PropertyField(singleFieldRect, eventProp);
singleFieldRect.y += lineHeightWithSpacing;
EditorGUI.PropertyField(singleFieldRect, attachmentProp);
singleFieldRect.y += lineHeightWithSpacing;
EditorGUI.PropertyField(singleFieldRect, drawOrderProp);
}
*/
}

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: cba97e3d11d6d4d428fcfe1a7be16db0
timeCreated: 1510816616
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,64 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2017 || UNITY_2018
using System;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using Spine;
using Spine.Unity;
using System.Collections.Generic;
namespace Spine.Unity.Playables {
using Animation = Spine.Animation;
[Serializable]
public class SpineAnimationStateBehaviour : PlayableBehaviour {
public AnimationReferenceAsset animationReference;
public bool loop;
[Header("Mix Properties")]
public bool customDuration = false;
public float mixDuration = 0.1f;
[Range(0, 1f)]
public float attachmentThreshold = 0.5f;
[Range(0, 1f)]
public float eventThreshold = 0.5f;
[Range(0, 1f)]
public float drawOrderThreshold = 0.5f;
}
}
#endif

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 82bd6e7ec1121b5428c447b7bd16b042
timeCreated: 1510816616
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,52 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2017 || UNITY_2018
using System;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
namespace Spine.Unity.Playables {
[Serializable]
public class SpineAnimationStateClip : PlayableAsset, ITimelineClipAsset {
public SpineAnimationStateBehaviour template = new SpineAnimationStateBehaviour();
public ClipCaps clipCaps { get { return ClipCaps.None; } }
public override Playable CreatePlayable (PlayableGraph graph, GameObject owner) {
var playable = ScriptPlayable<SpineAnimationStateBehaviour>.Create(graph, template);
playable.GetBehaviour(); //SpineAnimationStateBehaviour clone = playable.GetBehaviour();
return playable;
}
}
}
#endif

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 585e20c924ba86a44926c850aa8e1d84
timeCreated: 1510816616
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,168 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#define SPINE_EDITMODEPOSE
#if UNITY_2017 || UNITY_2018
using System;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
namespace Spine.Unity.Playables {
public class SpineAnimationStateMixerBehaviour : PlayableBehaviour {
float[] lastInputWeights;
// NOTE: This function is called at runtime and edit time. Keep that in mind when setting the values of properties.
public override void ProcessFrame (Playable playable, FrameData info, object playerData) {
var spineComponent = playerData as SkeletonAnimation;
if (spineComponent == null) return;
var skeleton = spineComponent.Skeleton;
var state = spineComponent.AnimationState;
if (!Application.isPlaying) {
#if SPINE_EDITMODEPOSE
PreviewEditModePose(playable, spineComponent);
#endif
return;
}
int inputCount = playable.GetInputCount();
// Ensure correct buffer size.
if (this.lastInputWeights == null || this.lastInputWeights.Length < inputCount) {
this.lastInputWeights = new float[inputCount];
for (int i = 0; i < inputCount; i++)
this.lastInputWeights[i] = default(float);
}
var lastInputWeights = this.lastInputWeights;
// Check all clips. If a clip that was weight 0 turned into weight 1, call SetAnimation.
for (int i = 0; i < inputCount; i++) {
float lastInputWeight = lastInputWeights[i];
float inputWeight = playable.GetInputWeight(i);
bool trackStarted = inputWeight > lastInputWeight;
lastInputWeights[i] = inputWeight;
if (trackStarted) {
ScriptPlayable<SpineAnimationStateBehaviour> inputPlayable = (ScriptPlayable<SpineAnimationStateBehaviour>)playable.GetInput(i);
SpineAnimationStateBehaviour clipData = inputPlayable.GetBehaviour();
if (clipData.animationReference == null) {
float mixDuration = clipData.customDuration ? clipData.mixDuration : state.Data.DefaultMix;
state.SetEmptyAnimation(0, mixDuration);
continue;
} else {
if (clipData.animationReference.Animation != null) {
Spine.TrackEntry trackEntry = state.SetAnimation(0, clipData.animationReference.Animation, clipData.loop);
//trackEntry.TrackTime = (float)inputPlayable.GetTime(); // More accurate time-start?
trackEntry.EventThreshold = clipData.eventThreshold;
trackEntry.DrawOrderThreshold = clipData.drawOrderThreshold;
trackEntry.AttachmentThreshold = clipData.attachmentThreshold;
if (clipData.customDuration)
trackEntry.MixDuration = clipData.mixDuration;
}
//else Debug.LogWarningFormat("Animation named '{0}' not found", clipData.animationName);
}
}
}
}
#if SPINE_EDITMODEPOSE
public void PreviewEditModePose (Playable playable, SkeletonAnimation spineComponent) {
if (Application.isPlaying) return;
if (spineComponent == null) return;
int inputCount = playable.GetInputCount();
int lastOneWeight = -1;
for (int i = 0; i < inputCount; i++) {
float inputWeight = playable.GetInputWeight(i);
if (inputWeight >= 1) lastOneWeight = i;
}
if (lastOneWeight != -1) {
ScriptPlayable<SpineAnimationStateBehaviour> inputPlayableClip = (ScriptPlayable<SpineAnimationStateBehaviour>)playable.GetInput(lastOneWeight);
SpineAnimationStateBehaviour clipData = inputPlayableClip.GetBehaviour();
var skeleton = spineComponent.Skeleton;
bool skeletonDataMismatch = clipData.animationReference != null && spineComponent.SkeletonDataAsset.GetSkeletonData(true) != clipData.animationReference.SkeletonDataAsset.GetSkeletonData(true);
if (skeletonDataMismatch) {
Debug.LogWarningFormat("SpineAnimationStateMixerBehaviour tried to apply an animation for the wrong skeleton. Expected {0}. Was {1}", spineComponent.SkeletonDataAsset, clipData.animationReference.SkeletonDataAsset);
}
// Getting the from-animation here because it's required to get the mix information from AnimationStateData.
Animation fromAnimation = null;
float fromClipTime = 0;
bool fromClipLoop = false;
if (lastOneWeight != 0 && inputCount > 1) {
var fromClip = (ScriptPlayable<SpineAnimationStateBehaviour>)playable.GetInput(lastOneWeight - 1);
var fromClipData = fromClip.GetBehaviour();
fromAnimation = fromClipData.animationReference.Animation;
fromClipTime = (float)fromClip.GetTime();
fromClipLoop = fromClipData.loop;
}
Animation toAnimation = clipData.animationReference.Animation;
float toClipTime = (float)inputPlayableClip.GetTime();
float mixDuration = clipData.mixDuration;
if (!clipData.customDuration && fromAnimation != null) {
mixDuration = spineComponent.AnimationState.Data.GetMix(fromAnimation, toAnimation);
}
// Approximate what AnimationState might do at runtime.
if (fromAnimation != null && mixDuration > 0 && toClipTime < mixDuration) {
skeleton.SetToSetupPose();
float fauxFromAlpha = (1f - toClipTime/mixDuration);
fauxFromAlpha = fauxFromAlpha > 0.5f ? 1f : fauxFromAlpha * 2f; // fake value, but reduce dip.
fromAnimation.Apply(skeleton, 0, fromClipTime, fromClipLoop, null, fauxFromAlpha, MixPose.Setup, MixDirection.Out); //fromAnimation.PoseSkeleton(skeleton, fromClipTime, fromClipLoop);
toAnimation.Apply(skeleton, 0, toClipTime, clipData.loop, null, toClipTime/mixDuration, MixPose.Current, MixDirection.In);
} else {
skeleton.SetToSetupPose();
toAnimation.PoseSkeleton(skeleton, toClipTime, clipData.loop);
}
}
// Do nothing outside of the first clip and the last clip.
}
#endif
}
}
#endif

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: f61d2f4ac1c4ad044bf4ae6e63b0eca8
timeCreated: 1510816616
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,46 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2017 || UNITY_2018
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
namespace Spine.Unity.Playables {
[TrackColor(0.9960785f, 0.2509804f, 0.003921569f)]
[TrackClipType(typeof(SpineAnimationStateClip))]
[TrackBindingType(typeof(SkeletonAnimation))]
public class SpineAnimationStateTrack : TrackAsset {
public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount) {
return ScriptPlayable<SpineAnimationStateMixerBehaviour>.Create (graph, inputCount);
}
}
}
#endif

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: dfabb056a779ae34b9ebd7de425c868b
timeCreated: 1510816616
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 3099d730dd2a9e349b3d918960cb42fa
folderAsset: yes
timeCreated: 1500876410
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: fc5fac7eface2ba4fbb6146017e41192
folderAsset: yes
timeCreated: 1500876410
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,27 @@
#if UNITY_2017 || UNITY_2018
using UnityEditor;
using UnityEngine;
using UnityEngine.Playables;
[CustomPropertyDrawer(typeof(SpineSkeletonFlipBehaviour))]
public class SpineSkeletonFlipDrawer : PropertyDrawer
{
public override float GetPropertyHeight (SerializedProperty property, GUIContent label)
{
int fieldCount = 1;
return fieldCount * EditorGUIUtility.singleLineHeight;
}
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty flipXProp = property.FindPropertyRelative("flipX");
SerializedProperty flipYProp = property.FindPropertyRelative("flipY");
Rect singleFieldRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
EditorGUI.PropertyField(singleFieldRect, flipXProp);
singleFieldRect.y += EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(singleFieldRect, flipYProp);
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b8a0a5d3de45a5e48ae96aa414860d3c
timeCreated: 1500876411
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,11 @@
#if UNITY_2017 || UNITY_2018
using System;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
[Serializable]
public class SpineSkeletonFlipBehaviour : PlayableBehaviour {
public bool flipX, flipY;
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3740378c8a8da8042991fbbe4b4a2094
timeCreated: 1500876411
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,50 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2017 || UNITY_2018
using System;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
[Serializable]
public class SpineSkeletonFlipClip : PlayableAsset, ITimelineClipAsset {
public SpineSkeletonFlipBehaviour template = new SpineSkeletonFlipBehaviour();
public ClipCaps clipCaps {
get { return ClipCaps.None; }
}
public override Playable CreatePlayable (PlayableGraph graph, GameObject owner) {
var playable = ScriptPlayable<SpineSkeletonFlipBehaviour>.Create(graph, template);
return playable;
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0a29ac408b701f84c93882fb506759d1
timeCreated: 1500876411
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,102 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2017 || UNITY_2018
using System;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using Spine.Unity;
namespace Spine.Unity.Playables {
public class SpineSkeletonFlipMixerBehaviour : PlayableBehaviour {
bool defaultFlipX, defaultFlipY;
SpinePlayableHandleBase playableHandle;
bool m_FirstFrameHappened;
public override void ProcessFrame (Playable playable, FrameData info, object playerData) {
playableHandle = playerData as SpinePlayableHandleBase;
if (playableHandle == null)
return;
var skeleton = playableHandle.Skeleton;
if (!m_FirstFrameHappened) {
defaultFlipX = skeleton.flipX;
defaultFlipY = skeleton.flipY;
m_FirstFrameHappened = true;
}
int inputCount = playable.GetInputCount();
float totalWeight = 0f;
float greatestWeight = 0f;
int currentInputs = 0;
for (int i = 0; i < inputCount; i++) {
float inputWeight = playable.GetInputWeight(i);
ScriptPlayable<SpineSkeletonFlipBehaviour> inputPlayable = (ScriptPlayable<SpineSkeletonFlipBehaviour>)playable.GetInput(i);
SpineSkeletonFlipBehaviour input = inputPlayable.GetBehaviour();
totalWeight += inputWeight;
if (inputWeight > greatestWeight) {
skeleton.flipX = input.flipX;
skeleton.flipY = input.flipY;
greatestWeight = inputWeight;
}
if (!Mathf.Approximately(inputWeight, 0f))
currentInputs++;
}
if (currentInputs != 1 && 1f - totalWeight > greatestWeight) {
skeleton.flipX = defaultFlipX;
skeleton.flipY = defaultFlipY;
}
}
public override void OnGraphStop (Playable playable) {
m_FirstFrameHappened = false;
if (playableHandle == null)
return;
var skeleton = playableHandle.Skeleton;
skeleton.flipX = defaultFlipX;
skeleton.flipY = defaultFlipY;
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f25dcf1fb34ab8643ac8734e57a9540f
timeCreated: 1500876411
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,68 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes or (b) remove,
* delete, alter, or obscure any trademarks or any copyright, trademark, patent,
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if UNITY_2017 || UNITY_2018
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using System.Collections.Generic;
using Spine.Unity;
namespace Spine.Unity.Playables {
[TrackColor(0.855f, 0.8623f, 0.87f)]
[TrackClipType(typeof(SpineSkeletonFlipClip))]
[TrackBindingType(typeof(SpinePlayableHandleBase))]
public class SpineSkeletonFlipTrack : TrackAsset {
public override Playable CreateTrackMixer (PlayableGraph graph, GameObject go, int inputCount) {
return ScriptPlayable<SpineSkeletonFlipMixerBehaviour>.Create(graph, inputCount);
}
public override void GatherProperties (PlayableDirector director, IPropertyCollector driver) {
#if UNITY_EDITOR
SpinePlayableHandleBase trackBinding = director.GetGenericBinding(this) as SpinePlayableHandleBase;
if (trackBinding == null)
return;
var serializedObject = new UnityEditor.SerializedObject(trackBinding);
var iterator = serializedObject.GetIterator();
while (iterator.NextVisible(true)) {
if (iterator.hasVisibleChildren)
continue;
driver.AddFromName<SpinePlayableHandleBase>(trackBinding.gameObject, iterator.propertyPath);
}
#endif
base.GatherProperties(director, driver);
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 82ac803eb1878814bba380a18b6b5d9d
timeCreated: 1500876411
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: