mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-23 10:11:23 +08:00
spine-unity, made compatible with Unity 4.3.4.
This commit is contained in:
parent
a64d74b728
commit
e30a267c19
5
spine-unity/Assets/Examples.meta
Normal file
5
spine-unity/Assets/Examples.meta
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e6712a5a0c05f9f4092f9a3197925e99
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
@ -31,7 +31,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
#if !UNITY_4_3
|
||||||
using UnityEditor.AnimatedValues;
|
using UnityEditor.AnimatedValues;
|
||||||
|
#endif
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Spine;
|
using Spine;
|
||||||
|
|
||||||
@ -39,12 +41,17 @@ using Spine;
|
|||||||
public class SkeletonDataAssetInspector : Editor {
|
public class SkeletonDataAssetInspector : Editor {
|
||||||
private SerializedProperty atlasAsset, skeletonJSON, scale, fromAnimation, toAnimation, duration, defaultMix;
|
private SerializedProperty atlasAsset, skeletonJSON, scale, fromAnimation, toAnimation, duration, defaultMix;
|
||||||
private bool showAnimationStateData = true;
|
private bool showAnimationStateData = true;
|
||||||
|
|
||||||
|
#if UNITY_4_3
|
||||||
|
private bool m_showAnimationList = true;
|
||||||
|
#else
|
||||||
private AnimBool m_showAnimationList = new AnimBool(true);
|
private AnimBool m_showAnimationList = new AnimBool(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
private bool m_initialized = false;
|
private bool m_initialized = false;
|
||||||
private SkeletonDataAsset m_skeletonDataAsset;
|
private SkeletonDataAsset m_skeletonDataAsset;
|
||||||
private string m_skeletonDataAssetGUID;
|
private string m_skeletonDataAssetGUID;
|
||||||
|
|
||||||
void OnEnable () {
|
void OnEnable () {
|
||||||
atlasAsset = serializedObject.FindProperty("atlasAsset");
|
atlasAsset = serializedObject.FindProperty("atlasAsset");
|
||||||
skeletonJSON = serializedObject.FindProperty("skeletonJSON");
|
skeletonJSON = serializedObject.FindProperty("skeletonJSON");
|
||||||
@ -53,10 +60,10 @@ public class SkeletonDataAssetInspector : Editor {
|
|||||||
toAnimation = serializedObject.FindProperty("toAnimation");
|
toAnimation = serializedObject.FindProperty("toAnimation");
|
||||||
duration = serializedObject.FindProperty("duration");
|
duration = serializedObject.FindProperty("duration");
|
||||||
defaultMix = serializedObject.FindProperty("defaultMix");
|
defaultMix = serializedObject.FindProperty("defaultMix");
|
||||||
|
|
||||||
m_skeletonDataAsset = (SkeletonDataAsset)target;
|
m_skeletonDataAsset = (SkeletonDataAsset)target;
|
||||||
m_skeletonDataAssetGUID = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath(m_skeletonDataAsset) );
|
m_skeletonDataAssetGUID = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath(m_skeletonDataAsset) );
|
||||||
|
|
||||||
EditorApplication.update += Update;
|
EditorApplication.update += Update;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +81,7 @@ public class SkeletonDataAssetInspector : Editor {
|
|||||||
override public void OnInspectorGUI () {
|
override public void OnInspectorGUI () {
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
SkeletonDataAsset asset = (SkeletonDataAsset)target;
|
SkeletonDataAsset asset = (SkeletonDataAsset)target;
|
||||||
|
|
||||||
EditorGUI.BeginChangeCheck();
|
EditorGUI.BeginChangeCheck();
|
||||||
EditorGUILayout.PropertyField(atlasAsset);
|
EditorGUILayout.PropertyField(atlasAsset);
|
||||||
EditorGUILayout.PropertyField(skeletonJSON);
|
EditorGUILayout.PropertyField(skeletonJSON);
|
||||||
@ -85,18 +92,18 @@ public class SkeletonDataAssetInspector : Editor {
|
|||||||
m_previewUtility = null;
|
m_previewUtility = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SkeletonData skeletonData = asset.GetSkeletonData(asset.atlasAsset == null || asset.skeletonJSON == null);
|
SkeletonData skeletonData = asset.GetSkeletonData(asset.atlasAsset == null || asset.skeletonJSON == null);
|
||||||
if (skeletonData != null) {
|
if (skeletonData != null) {
|
||||||
showAnimationStateData = EditorGUILayout.Foldout(showAnimationStateData, "Animation State Data");
|
showAnimationStateData = EditorGUILayout.Foldout(showAnimationStateData, "Animation State Data");
|
||||||
if (showAnimationStateData) {
|
if (showAnimationStateData) {
|
||||||
EditorGUILayout.PropertyField(defaultMix);
|
EditorGUILayout.PropertyField(defaultMix);
|
||||||
|
|
||||||
// Animation names
|
// Animation names
|
||||||
String[] animations = new String[skeletonData.Animations.Count];
|
String[] animations = new String[skeletonData.Animations.Count];
|
||||||
for (int i = 0; i < animations.Length; i++)
|
for (int i = 0; i < animations.Length; i++)
|
||||||
animations[i] = skeletonData.Animations[i].Name;
|
animations[i] = skeletonData.Animations[i].Name;
|
||||||
|
|
||||||
for (int i = 0; i < fromAnimation.arraySize; i++) {
|
for (int i = 0; i < fromAnimation.arraySize; i++) {
|
||||||
SerializedProperty from = fromAnimation.GetArrayElementAtIndex(i);
|
SerializedProperty from = fromAnimation.GetArrayElementAtIndex(i);
|
||||||
SerializedProperty to = toAnimation.GetArrayElementAtIndex(i);
|
SerializedProperty to = toAnimation.GetArrayElementAtIndex(i);
|
||||||
@ -122,356 +129,367 @@ public class SkeletonDataAssetInspector : Editor {
|
|||||||
EditorGUILayout.Space();
|
EditorGUILayout.Space();
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GUILayout.Button(new GUIContent("Setup Pose", SpineEditorUtilities.Icons.skeleton), GUILayout.Width(105), GUILayout.Height(18))){
|
if(GUILayout.Button(new GUIContent("Setup Pose", SpineEditorUtilities.Icons.skeleton), GUILayout.Width(105), GUILayout.Height(18))){
|
||||||
StopAnimation();
|
StopAnimation();
|
||||||
m_skeletonAnimation.skeleton.SetToSetupPose();
|
m_skeletonAnimation.skeleton.SetToSetupPose();
|
||||||
m_requireRefresh = true;
|
m_requireRefresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_showAnimationList.target = EditorGUILayout.Foldout(m_showAnimationList.target, new GUIContent("Animations", SpineEditorUtilities.Icons.animationRoot));
|
#if UNITY_4_3
|
||||||
|
m_showAnimationList = EditorGUILayout.Foldout(m_showAnimationList, new GUIContent("Animations", SpineEditorUtilities.Icons.animationRoot));
|
||||||
if(EditorGUILayout.BeginFadeGroup(m_showAnimationList.faded)){
|
if(m_showAnimationList){
|
||||||
|
#else
|
||||||
EditorGUILayout.LabelField("Name", "Duration");
|
m_showAnimationList.target = EditorGUILayout.Foldout(m_showAnimationList.target, new GUIContent("Animations", SpineEditorUtilities.Icons.animationRoot));
|
||||||
foreach(Spine.Animation a in skeletonData.Animations){
|
if(EditorGUILayout.BeginFadeGroup(m_showAnimationList.faded)){
|
||||||
GUILayout.BeginHorizontal();
|
#endif
|
||||||
|
|
||||||
if(m_skeletonAnimation != null && m_skeletonAnimation.state != null){
|
|
||||||
if(m_skeletonAnimation.state.GetCurrent(0) != null && m_skeletonAnimation.state.GetCurrent(0).Animation == a){
|
|
||||||
GUI.contentColor = Color.black;
|
|
||||||
if(GUILayout.Button("\u25BA", GUILayout.Width(24))){
|
EditorGUILayout.LabelField("Name", "Duration");
|
||||||
StopAnimation();
|
foreach(Spine.Animation a in skeletonData.Animations){
|
||||||
|
GUILayout.BeginHorizontal();
|
||||||
|
|
||||||
|
if(m_skeletonAnimation != null && m_skeletonAnimation.state != null){
|
||||||
|
if(m_skeletonAnimation.state.GetCurrent(0) != null && m_skeletonAnimation.state.GetCurrent(0).Animation == a){
|
||||||
|
GUI.contentColor = Color.black;
|
||||||
|
if(GUILayout.Button("\u25BA", GUILayout.Width(24))){
|
||||||
|
StopAnimation();
|
||||||
|
}
|
||||||
|
GUI.contentColor = Color.white;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(GUILayout.Button("\u25BA", GUILayout.Width(24))){
|
||||||
|
PlayAnimation(a.Name, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GUI.contentColor = Color.white;
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(GUILayout.Button("\u25BA", GUILayout.Width(24))){
|
GUILayout.Label("?", GUILayout.Width(24));
|
||||||
PlayAnimation(a.Name, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
EditorGUILayout.LabelField(new GUIContent(a.Name, SpineEditorUtilities.Icons.animation), new GUIContent(a.Duration.ToString("f3") + "s" + ("(" + (Mathf.RoundToInt(a.Duration * 30)) + ")").PadLeft(12, ' ')));
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
GUILayout.Label("?", GUILayout.Width(24));
|
|
||||||
}
|
|
||||||
EditorGUILayout.LabelField(new GUIContent(a.Name, SpineEditorUtilities.Icons.animation), new GUIContent(a.Duration.ToString("f3") + "s" + ("(" + (Mathf.RoundToInt(a.Duration * 30)) + ")").PadLeft(12, ' ')));
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
}
|
||||||
}
|
#if !UNITY_4_3
|
||||||
EditorGUILayout.EndFadeGroup();
|
EditorGUILayout.EndFadeGroup();
|
||||||
}
|
#endif
|
||||||
|
|
||||||
if (!Application.isPlaying) {
|
|
||||||
if (serializedObject.ApplyModifiedProperties() ||
|
|
||||||
(UnityEngine.Event.current.type == EventType.ValidateCommand && UnityEngine.Event.current.commandName == "UndoRedoPerformed")
|
|
||||||
) {
|
|
||||||
asset.Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//preview window stuff
|
|
||||||
private PreviewRenderUtility m_previewUtility;
|
|
||||||
private GameObject m_previewInstance;
|
|
||||||
private Vector2 previewDir;
|
|
||||||
private SkeletonAnimation m_skeletonAnimation;
|
|
||||||
private SkeletonData m_skeletonData;
|
|
||||||
|
|
||||||
private static int sliderHash = "Slider".GetHashCode();
|
|
||||||
private float m_lastTime;
|
|
||||||
private bool m_playing;
|
|
||||||
private bool m_requireRefresh;
|
|
||||||
|
|
||||||
private Color m_originColor = new Color(0.3f,0.3f,0.3f, 1);
|
|
||||||
|
|
||||||
private void StopAnimation(){
|
|
||||||
m_skeletonAnimation.state.ClearTrack(0);
|
|
||||||
m_playing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
List<Spine.Event> m_animEvents = new List<Spine.Event>();
|
|
||||||
List<float> m_animEventFrames = new List<float>();
|
|
||||||
private void PlayAnimation(string animName, bool loop){
|
|
||||||
m_animEvents.Clear();
|
|
||||||
m_animEventFrames.Clear();
|
|
||||||
|
|
||||||
m_skeletonAnimation.state.SetAnimation(0, animName, loop);
|
|
||||||
|
|
||||||
Spine.Animation a = m_skeletonAnimation.state.GetCurrent(0).Animation;
|
|
||||||
foreach(Timeline t in a.Timelines){
|
|
||||||
if(t.GetType() == typeof(EventTimeline)){
|
|
||||||
EventTimeline et = (EventTimeline)t;
|
|
||||||
|
|
||||||
for(int i = 0; i < et.Events.Length; i++){
|
|
||||||
m_animEvents.Add(et.Events[i]);
|
|
||||||
m_animEventFrames.Add(et.Frames[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_playing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitPreview()
|
|
||||||
{
|
|
||||||
if (this.m_previewUtility == null)
|
|
||||||
{
|
|
||||||
this.m_lastTime = Time.realtimeSinceStartup;
|
|
||||||
this.m_previewUtility = new PreviewRenderUtility(true);
|
|
||||||
this.m_previewUtility.m_Camera.isOrthoGraphic = true;
|
|
||||||
this.m_previewUtility.m_Camera.orthographicSize = 1;
|
|
||||||
this.m_previewUtility.m_Camera.cullingMask = -2147483648;
|
|
||||||
this.CreatePreviewInstances();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreatePreviewInstances()
|
|
||||||
{
|
|
||||||
this.DestroyPreviewInstances();
|
|
||||||
if (this.m_previewInstance == null)
|
|
||||||
{
|
|
||||||
string skinName = EditorPrefs.GetString(m_skeletonDataAssetGUID + "_lastSkin", "");
|
|
||||||
|
|
||||||
m_previewInstance = SpineEditorUtilities.SpawnAnimatedSkeleton( (SkeletonDataAsset)target, skinName ).gameObject;
|
|
||||||
m_previewInstance.hideFlags = HideFlags.HideAndDontSave;
|
|
||||||
m_previewInstance.layer = 0x1f;
|
|
||||||
|
|
||||||
|
|
||||||
m_skeletonAnimation = m_previewInstance.GetComponent<SkeletonAnimation>();
|
|
||||||
m_skeletonAnimation.initialSkinName = skinName;
|
|
||||||
m_skeletonAnimation.LateUpdate();
|
|
||||||
|
|
||||||
m_skeletonData = m_skeletonAnimation.skeletonDataAsset.GetSkeletonData(true);
|
|
||||||
|
|
||||||
m_previewInstance.renderer.enabled = false;
|
|
||||||
|
|
||||||
m_initialized = true;
|
|
||||||
AdjustCameraGoals(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DestroyPreviewInstances()
|
|
||||||
{
|
|
||||||
if (this.m_previewInstance != null)
|
|
||||||
{
|
|
||||||
DestroyImmediate(this.m_previewInstance);
|
|
||||||
m_previewInstance = null;
|
|
||||||
}
|
|
||||||
m_initialized = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool HasPreviewGUI ()
|
|
||||||
{
|
|
||||||
//TODO: validate json data
|
|
||||||
return skeletonJSON.objectReferenceValue != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Texture m_previewTex = new Texture();
|
|
||||||
public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)
|
|
||||||
{
|
|
||||||
this.InitPreview();
|
|
||||||
|
|
||||||
if (UnityEngine.Event.current.type == EventType.Repaint)
|
|
||||||
{
|
|
||||||
if(m_requireRefresh){
|
|
||||||
this.m_previewUtility.BeginPreview(r, background);
|
|
||||||
this.DoRenderPreview(true);
|
|
||||||
this.m_previewTex = this.m_previewUtility.EndPreview();
|
|
||||||
m_requireRefresh = false;
|
|
||||||
}
|
|
||||||
if(this.m_previewTex != null)
|
|
||||||
GUI.DrawTexture(r, m_previewTex, ScaleMode.StretchToFill, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawSkinToolbar(r);
|
|
||||||
NormalizedTimeBar(r);
|
|
||||||
//TODO: implement panning
|
|
||||||
// this.previewDir = Drag2D(this.previewDir, r);
|
|
||||||
MouseScroll(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
float m_orthoGoal = 1;
|
|
||||||
Vector3 m_posGoal = new Vector3(0,0,-10);
|
|
||||||
double m_adjustFrameEndTime = 0;
|
|
||||||
private void AdjustCameraGoals(bool calculateMixTime){
|
|
||||||
if(calculateMixTime){
|
|
||||||
if(m_skeletonAnimation.state.GetCurrent(0) != null){
|
|
||||||
m_adjustFrameEndTime = EditorApplication.timeSinceStartup + m_skeletonAnimation.state.GetCurrent(0).Mix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GameObject go = this.m_previewInstance;
|
|
||||||
Bounds bounds = go.renderer.bounds;
|
|
||||||
m_orthoGoal = bounds.size.y;
|
|
||||||
|
|
||||||
m_posGoal = bounds.center + new Vector3(0,0,-10);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AdjustCameraGoals(){
|
|
||||||
AdjustCameraGoals(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AdjustCamera(){
|
|
||||||
if(m_previewUtility == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
if(EditorApplication.timeSinceStartup < m_adjustFrameEndTime){
|
|
||||||
AdjustCameraGoals();
|
|
||||||
}
|
|
||||||
|
|
||||||
float orthoSet = Mathf.Lerp(this.m_previewUtility.m_Camera.orthographicSize, m_orthoGoal, 0.1f);
|
|
||||||
|
|
||||||
this.m_previewUtility.m_Camera.orthographicSize = orthoSet;
|
|
||||||
|
|
||||||
float dist = Vector3.Distance(m_previewUtility.m_Camera.transform.position, m_posGoal);
|
|
||||||
if(dist > 60f * ((SkeletonDataAsset)target).scale){
|
|
||||||
Vector3 pos = Vector3.Lerp(this.m_previewUtility.m_Camera.transform.position, m_posGoal, 0.1f);
|
|
||||||
pos.x = 0;
|
|
||||||
this.m_previewUtility.m_Camera.transform.position = pos;
|
|
||||||
this.m_previewUtility.m_Camera.transform.rotation = Quaternion.identity;
|
|
||||||
m_requireRefresh = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DoRenderPreview(bool drawHandles)
|
|
||||||
{
|
|
||||||
GameObject go = this.m_previewInstance;
|
|
||||||
|
|
||||||
if(m_requireRefresh){
|
|
||||||
go.renderer.enabled = true;
|
|
||||||
|
|
||||||
if(EditorApplication.isPlaying){
|
|
||||||
//do nothing
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
m_skeletonAnimation.Update((Time.realtimeSinceStartup - m_lastTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lastTime = Time.realtimeSinceStartup;
|
|
||||||
|
|
||||||
if(!EditorApplication.isPlaying)
|
|
||||||
m_skeletonAnimation.LateUpdate();
|
|
||||||
|
|
||||||
if(drawHandles){
|
|
||||||
Handles.SetCamera(m_previewUtility.m_Camera);
|
|
||||||
Handles.color = m_originColor;
|
|
||||||
|
|
||||||
Handles.DrawLine(new Vector3(-1000 * m_skeletonDataAsset.scale,0,0), new Vector3(1000 * m_skeletonDataAsset.scale,0,0));
|
|
||||||
Handles.DrawLine(new Vector3(0,1000 * m_skeletonDataAsset.scale,0), new Vector3(0,-1000 * m_skeletonDataAsset.scale,0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.m_previewUtility.m_Camera.Render();
|
if (!Application.isPlaying) {
|
||||||
go.renderer.enabled = false;
|
if (serializedObject.ApplyModifiedProperties() ||
|
||||||
}
|
(UnityEngine.Event.current.type == EventType.ValidateCommand && UnityEngine.Event.current.commandName == "UndoRedoPerformed")
|
||||||
|
) {
|
||||||
|
asset.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update(){
|
|
||||||
AdjustCamera();
|
|
||||||
|
|
||||||
if (m_playing) {
|
|
||||||
m_requireRefresh = true;
|
|
||||||
Repaint();
|
|
||||||
}
|
|
||||||
else if (m_requireRefresh) {
|
|
||||||
Repaint ();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if(m_showAnimationList.isAnimating)
|
|
||||||
Repaint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawSkinToolbar(Rect r){
|
|
||||||
if(m_skeletonAnimation == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(m_skeletonAnimation.skeleton != null){
|
|
||||||
string label = (m_skeletonAnimation.skeleton != null && m_skeletonAnimation.skeleton.Skin != null) ? m_skeletonAnimation.skeleton.Skin.Name : "default";
|
|
||||||
|
|
||||||
Rect popRect = new Rect(r);
|
|
||||||
popRect.y += 32;
|
|
||||||
popRect.x += 4;
|
|
||||||
popRect.height = 24;
|
|
||||||
popRect.width = 40;
|
|
||||||
EditorGUI.DropShadowLabel(popRect, new GUIContent("Skin", SpineEditorUtilities.Icons.skinsRoot));
|
|
||||||
|
|
||||||
popRect.y += 11;
|
|
||||||
popRect.width = 150;
|
|
||||||
popRect.x += 44;
|
|
||||||
|
|
||||||
if(GUI.Button( popRect, label, EditorStyles.popup)){
|
|
||||||
SelectSkinContext();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void SelectSkinContext(){
|
|
||||||
GenericMenu menu = new GenericMenu();
|
|
||||||
|
|
||||||
foreach(Skin s in m_skeletonData.Skins){
|
//preview window stuff
|
||||||
menu.AddItem( new GUIContent(s.Name), this.m_skeletonAnimation.skeleton.Skin == s, SetSkin, (object)s);
|
private PreviewRenderUtility m_previewUtility;
|
||||||
|
private GameObject m_previewInstance;
|
||||||
|
private Vector2 previewDir;
|
||||||
|
private SkeletonAnimation m_skeletonAnimation;
|
||||||
|
private SkeletonData m_skeletonData;
|
||||||
|
|
||||||
|
private static int sliderHash = "Slider".GetHashCode();
|
||||||
|
private float m_lastTime;
|
||||||
|
private bool m_playing;
|
||||||
|
private bool m_requireRefresh;
|
||||||
|
|
||||||
|
private Color m_originColor = new Color(0.3f,0.3f,0.3f, 1);
|
||||||
|
|
||||||
|
private void StopAnimation(){
|
||||||
|
m_skeletonAnimation.state.ClearTrack(0);
|
||||||
|
m_playing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.ShowAsContext();
|
|
||||||
}
|
List<Spine.Event> m_animEvents = new List<Spine.Event>();
|
||||||
|
List<float> m_animEventFrames = new List<float>();
|
||||||
void SetSkin(object o){
|
private void PlayAnimation(string animName, bool loop){
|
||||||
Skin skin = (Skin)o;
|
m_animEvents.Clear();
|
||||||
|
m_animEventFrames.Clear();
|
||||||
m_skeletonAnimation.initialSkinName = skin.Name;
|
|
||||||
m_skeletonAnimation.Reset();
|
m_skeletonAnimation.state.SetAnimation(0, animName, loop);
|
||||||
m_requireRefresh = true;
|
|
||||||
|
Spine.Animation a = m_skeletonAnimation.state.GetCurrent(0).Animation;
|
||||||
EditorPrefs.SetString(m_skeletonDataAssetGUID + "_lastSkin", skin.Name);
|
foreach(Timeline t in a.Timelines){
|
||||||
}
|
if(t.GetType() == typeof(EventTimeline)){
|
||||||
|
EventTimeline et = (EventTimeline)t;
|
||||||
void NormalizedTimeBar(Rect r){
|
|
||||||
Rect barRect = new Rect(r);
|
for(int i = 0; i < et.Events.Length; i++){
|
||||||
barRect.height = 32;
|
m_animEvents.Add(et.Events[i]);
|
||||||
barRect.x += 4;
|
m_animEventFrames.Add(et.Frames[i]);
|
||||||
barRect.width -=4;
|
}
|
||||||
|
|
||||||
GUI.Box(barRect, "");
|
}
|
||||||
|
}
|
||||||
Rect lineRect = new Rect(barRect);
|
|
||||||
float width = lineRect.width;
|
m_playing = true;
|
||||||
TrackEntry t = m_skeletonAnimation.state.GetCurrent(0);
|
}
|
||||||
|
|
||||||
if(t != null){
|
private void InitPreview()
|
||||||
int loopCount = (int)(t.Time / t.EndTime);
|
{
|
||||||
float currentTime = t.Time - (t.EndTime * loopCount);
|
if (this.m_previewUtility == null)
|
||||||
|
{
|
||||||
float normalizedTime = currentTime / t.Animation.Duration;
|
this.m_lastTime = Time.realtimeSinceStartup;
|
||||||
|
this.m_previewUtility = new PreviewRenderUtility(true);
|
||||||
lineRect.x = barRect.x + (width * normalizedTime) - 0.5f;
|
this.m_previewUtility.m_Camera.isOrthoGraphic = true;
|
||||||
lineRect.width = 2;
|
this.m_previewUtility.m_Camera.orthographicSize = 1;
|
||||||
|
this.m_previewUtility.m_Camera.cullingMask = -2147483648;
|
||||||
GUI.color = Color.red;
|
this.CreatePreviewInstances();
|
||||||
GUI.DrawTexture(lineRect, EditorGUIUtility.whiteTexture);
|
}
|
||||||
GUI.color = Color.white;
|
}
|
||||||
|
|
||||||
for(int i = 0; i < m_animEvents.Count; i++){
|
private void CreatePreviewInstances()
|
||||||
//TODO: Tooltip
|
{
|
||||||
//Spine.Event spev = animEvents[i];
|
this.DestroyPreviewInstances();
|
||||||
|
if (this.m_previewInstance == null)
|
||||||
float fr = m_animEventFrames[i];
|
{
|
||||||
|
string skinName = EditorPrefs.GetString(m_skeletonDataAssetGUID + "_lastSkin", "");
|
||||||
Rect evRect = new Rect(barRect);
|
|
||||||
evRect.x = Mathf.Clamp(((fr / t.Animation.Duration) * width) - (SpineEditorUtilities.Icons._event.width/2), barRect.x, float.MaxValue);
|
m_previewInstance = SpineEditorUtilities.SpawnAnimatedSkeleton( (SkeletonDataAsset)target, skinName ).gameObject;
|
||||||
evRect.width = SpineEditorUtilities.Icons._event.width;
|
m_previewInstance.hideFlags = HideFlags.HideAndDontSave;
|
||||||
evRect.height = SpineEditorUtilities.Icons._event.height;
|
m_previewInstance.layer = 0x1f;
|
||||||
evRect.y += SpineEditorUtilities.Icons._event.height;
|
|
||||||
GUI.DrawTexture(evRect, SpineEditorUtilities.Icons._event);
|
|
||||||
|
m_skeletonAnimation = m_previewInstance.GetComponent<SkeletonAnimation>();
|
||||||
|
m_skeletonAnimation.initialSkinName = skinName;
|
||||||
//TODO: Tooltip
|
m_skeletonAnimation.LateUpdate();
|
||||||
/*
|
|
||||||
|
m_skeletonData = m_skeletonAnimation.skeletonDataAsset.GetSkeletonData(true);
|
||||||
|
|
||||||
|
m_previewInstance.renderer.enabled = false;
|
||||||
|
|
||||||
|
m_initialized = true;
|
||||||
|
AdjustCameraGoals(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DestroyPreviewInstances()
|
||||||
|
{
|
||||||
|
if (this.m_previewInstance != null)
|
||||||
|
{
|
||||||
|
DestroyImmediate(this.m_previewInstance);
|
||||||
|
m_previewInstance = null;
|
||||||
|
}
|
||||||
|
m_initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HasPreviewGUI ()
|
||||||
|
{
|
||||||
|
//TODO: validate json data
|
||||||
|
return skeletonJSON.objectReferenceValue != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture m_previewTex = new Texture();
|
||||||
|
public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)
|
||||||
|
{
|
||||||
|
this.InitPreview();
|
||||||
|
|
||||||
|
if (UnityEngine.Event.current.type == EventType.Repaint)
|
||||||
|
{
|
||||||
|
if(m_requireRefresh){
|
||||||
|
this.m_previewUtility.BeginPreview(r, background);
|
||||||
|
this.DoRenderPreview(true);
|
||||||
|
this.m_previewTex = this.m_previewUtility.EndPreview();
|
||||||
|
m_requireRefresh = false;
|
||||||
|
}
|
||||||
|
if(this.m_previewTex != null)
|
||||||
|
GUI.DrawTexture(r, m_previewTex, ScaleMode.StretchToFill, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawSkinToolbar(r);
|
||||||
|
NormalizedTimeBar(r);
|
||||||
|
//TODO: implement panning
|
||||||
|
// this.previewDir = Drag2D(this.previewDir, r);
|
||||||
|
MouseScroll(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
float m_orthoGoal = 1;
|
||||||
|
Vector3 m_posGoal = new Vector3(0,0,-10);
|
||||||
|
double m_adjustFrameEndTime = 0;
|
||||||
|
private void AdjustCameraGoals(bool calculateMixTime){
|
||||||
|
if(calculateMixTime){
|
||||||
|
if(m_skeletonAnimation.state.GetCurrent(0) != null){
|
||||||
|
m_adjustFrameEndTime = EditorApplication.timeSinceStartup + m_skeletonAnimation.state.GetCurrent(0).Mix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GameObject go = this.m_previewInstance;
|
||||||
|
Bounds bounds = go.renderer.bounds;
|
||||||
|
m_orthoGoal = bounds.size.y;
|
||||||
|
|
||||||
|
m_posGoal = bounds.center + new Vector3(0,0,-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AdjustCameraGoals(){
|
||||||
|
AdjustCameraGoals(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AdjustCamera(){
|
||||||
|
if(m_previewUtility == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
if(EditorApplication.timeSinceStartup < m_adjustFrameEndTime){
|
||||||
|
AdjustCameraGoals();
|
||||||
|
}
|
||||||
|
|
||||||
|
float orthoSet = Mathf.Lerp(this.m_previewUtility.m_Camera.orthographicSize, m_orthoGoal, 0.1f);
|
||||||
|
|
||||||
|
this.m_previewUtility.m_Camera.orthographicSize = orthoSet;
|
||||||
|
|
||||||
|
float dist = Vector3.Distance(m_previewUtility.m_Camera.transform.position, m_posGoal);
|
||||||
|
if(dist > 60f * ((SkeletonDataAsset)target).scale){
|
||||||
|
Vector3 pos = Vector3.Lerp(this.m_previewUtility.m_Camera.transform.position, m_posGoal, 0.1f);
|
||||||
|
pos.x = 0;
|
||||||
|
this.m_previewUtility.m_Camera.transform.position = pos;
|
||||||
|
this.m_previewUtility.m_Camera.transform.rotation = Quaternion.identity;
|
||||||
|
m_requireRefresh = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DoRenderPreview(bool drawHandles)
|
||||||
|
{
|
||||||
|
GameObject go = this.m_previewInstance;
|
||||||
|
|
||||||
|
if(m_requireRefresh){
|
||||||
|
go.renderer.enabled = true;
|
||||||
|
|
||||||
|
if(EditorApplication.isPlaying){
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
m_skeletonAnimation.Update((Time.realtimeSinceStartup - m_lastTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lastTime = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
|
if(!EditorApplication.isPlaying)
|
||||||
|
m_skeletonAnimation.LateUpdate();
|
||||||
|
|
||||||
|
if(drawHandles){
|
||||||
|
Handles.SetCamera(m_previewUtility.m_Camera);
|
||||||
|
Handles.color = m_originColor;
|
||||||
|
|
||||||
|
Handles.DrawLine(new Vector3(-1000 * m_skeletonDataAsset.scale,0,0), new Vector3(1000 * m_skeletonDataAsset.scale,0,0));
|
||||||
|
Handles.DrawLine(new Vector3(0,1000 * m_skeletonDataAsset.scale,0), new Vector3(0,-1000 * m_skeletonDataAsset.scale,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.m_previewUtility.m_Camera.Render();
|
||||||
|
go.renderer.enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(){
|
||||||
|
AdjustCamera();
|
||||||
|
|
||||||
|
if (m_playing) {
|
||||||
|
m_requireRefresh = true;
|
||||||
|
Repaint();
|
||||||
|
}
|
||||||
|
else if (m_requireRefresh) {
|
||||||
|
Repaint ();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
#if !UNITY_4_3
|
||||||
|
if(m_showAnimationList.isAnimating)
|
||||||
|
Repaint();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawSkinToolbar(Rect r){
|
||||||
|
if(m_skeletonAnimation == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_skeletonAnimation.skeleton != null){
|
||||||
|
string label = (m_skeletonAnimation.skeleton != null && m_skeletonAnimation.skeleton.Skin != null) ? m_skeletonAnimation.skeleton.Skin.Name : "default";
|
||||||
|
|
||||||
|
Rect popRect = new Rect(r);
|
||||||
|
popRect.y += 32;
|
||||||
|
popRect.x += 4;
|
||||||
|
popRect.height = 24;
|
||||||
|
popRect.width = 40;
|
||||||
|
EditorGUI.DropShadowLabel(popRect, new GUIContent("Skin", SpineEditorUtilities.Icons.skinsRoot));
|
||||||
|
|
||||||
|
popRect.y += 11;
|
||||||
|
popRect.width = 150;
|
||||||
|
popRect.x += 44;
|
||||||
|
|
||||||
|
if(GUI.Button( popRect, label, EditorStyles.popup)){
|
||||||
|
SelectSkinContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectSkinContext(){
|
||||||
|
GenericMenu menu = new GenericMenu();
|
||||||
|
|
||||||
|
foreach(Skin s in m_skeletonData.Skins){
|
||||||
|
menu.AddItem( new GUIContent(s.Name), this.m_skeletonAnimation.skeleton.Skin == s, SetSkin, (object)s);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.ShowAsContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSkin(object o){
|
||||||
|
Skin skin = (Skin)o;
|
||||||
|
|
||||||
|
m_skeletonAnimation.initialSkinName = skin.Name;
|
||||||
|
m_skeletonAnimation.Reset();
|
||||||
|
m_requireRefresh = true;
|
||||||
|
|
||||||
|
EditorPrefs.SetString(m_skeletonDataAssetGUID + "_lastSkin", skin.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NormalizedTimeBar(Rect r){
|
||||||
|
Rect barRect = new Rect(r);
|
||||||
|
barRect.height = 32;
|
||||||
|
barRect.x += 4;
|
||||||
|
barRect.width -=4;
|
||||||
|
|
||||||
|
GUI.Box(barRect, "");
|
||||||
|
|
||||||
|
Rect lineRect = new Rect(barRect);
|
||||||
|
float width = lineRect.width;
|
||||||
|
TrackEntry t = m_skeletonAnimation.state.GetCurrent(0);
|
||||||
|
|
||||||
|
if(t != null){
|
||||||
|
int loopCount = (int)(t.Time / t.EndTime);
|
||||||
|
float currentTime = t.Time - (t.EndTime * loopCount);
|
||||||
|
|
||||||
|
float normalizedTime = currentTime / t.Animation.Duration;
|
||||||
|
|
||||||
|
lineRect.x = barRect.x + (width * normalizedTime) - 0.5f;
|
||||||
|
lineRect.width = 2;
|
||||||
|
|
||||||
|
GUI.color = Color.red;
|
||||||
|
GUI.DrawTexture(lineRect, EditorGUIUtility.whiteTexture);
|
||||||
|
GUI.color = Color.white;
|
||||||
|
|
||||||
|
for(int i = 0; i < m_animEvents.Count; i++){
|
||||||
|
//TODO: Tooltip
|
||||||
|
//Spine.Event spev = animEvents[i];
|
||||||
|
|
||||||
|
float fr = m_animEventFrames[i];
|
||||||
|
|
||||||
|
Rect evRect = new Rect(barRect);
|
||||||
|
evRect.x = Mathf.Clamp(((fr / t.Animation.Duration) * width) - (SpineEditorUtilities.Icons._event.width/2), barRect.x, float.MaxValue);
|
||||||
|
evRect.width = SpineEditorUtilities.Icons._event.width;
|
||||||
|
evRect.height = SpineEditorUtilities.Icons._event.height;
|
||||||
|
evRect.y += SpineEditorUtilities.Icons._event.height;
|
||||||
|
GUI.DrawTexture(evRect, SpineEditorUtilities.Icons._event);
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: Tooltip
|
||||||
|
/*
|
||||||
UnityEngine.Event ev = UnityEngine.Event.current;
|
UnityEngine.Event ev = UnityEngine.Event.current;
|
||||||
if(ev.isMouse){
|
if(ev.isMouse){
|
||||||
if(evRect.Contains(ev.mousePosition)){
|
if(evRect.Contains(ev.mousePosition)){
|
||||||
@ -483,29 +501,29 @@ public class SkeletonDataAssetInspector : Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
void MouseScroll(Rect position){
|
||||||
void MouseScroll(Rect position){
|
UnityEngine.Event current = UnityEngine.Event.current;
|
||||||
UnityEngine.Event current = UnityEngine.Event.current;
|
int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
|
||||||
int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
|
|
||||||
|
switch(current.GetTypeForControl(controlID)){
|
||||||
switch(current.GetTypeForControl(controlID)){
|
case EventType.ScrollWheel:
|
||||||
case EventType.ScrollWheel:
|
if(position.Contains(current.mousePosition)){
|
||||||
if(position.Contains(current.mousePosition)){
|
|
||||||
|
m_orthoGoal += current.delta.y * ((SkeletonDataAsset)target).scale * 10;
|
||||||
m_orthoGoal += current.delta.y * ((SkeletonDataAsset)target).scale * 10;
|
GUIUtility.hotControl = controlID;
|
||||||
GUIUtility.hotControl = controlID;
|
current.Use();
|
||||||
current.Use();
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
//TODO: Implement preview panning
|
||||||
|
/*
|
||||||
//TODO: Implement preview panning
|
|
||||||
/*
|
|
||||||
static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
|
static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
|
||||||
{
|
{
|
||||||
int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
|
int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
|
||||||
@ -545,57 +563,57 @@ public class SkeletonDataAssetInspector : Editor {
|
|||||||
return scrollPosition;
|
return scrollPosition;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public override GUIContent GetPreviewTitle ()
|
public override GUIContent GetPreviewTitle ()
|
||||||
{
|
{
|
||||||
return new GUIContent ("Preview");
|
return new GUIContent ("Preview");
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnPreviewSettings ()
|
|
||||||
{
|
|
||||||
if(!m_initialized){
|
|
||||||
GUILayout.HorizontalSlider(0,0,2, GUILayout.MaxWidth(64));
|
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
float speed = GUILayout.HorizontalSlider( m_skeletonAnimation.timeScale, 0, 2, GUILayout.MaxWidth(64));
|
public override void OnPreviewSettings ()
|
||||||
|
{
|
||||||
//snap to nearest 0.25
|
if(!m_initialized){
|
||||||
float y = speed / 0.25f;
|
GUILayout.HorizontalSlider(0,0,2, GUILayout.MaxWidth(64));
|
||||||
int q = Mathf.RoundToInt(y);
|
}
|
||||||
speed = q * 0.25f;
|
else{
|
||||||
|
float speed = GUILayout.HorizontalSlider( m_skeletonAnimation.timeScale, 0, 2, GUILayout.MaxWidth(64));
|
||||||
m_skeletonAnimation.timeScale = speed;
|
|
||||||
|
//snap to nearest 0.25
|
||||||
|
float y = speed / 0.25f;
|
||||||
|
int q = Mathf.RoundToInt(y);
|
||||||
|
speed = q * 0.25f;
|
||||||
|
|
||||||
|
m_skeletonAnimation.timeScale = speed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
//TODO: Fix first-import error
|
||||||
//TODO: Fix first-import error
|
//TODO: Update preview without thumbnail
|
||||||
//TODO: Update preview without thumbnail
|
public override Texture2D RenderStaticPreview (string assetPath, UnityEngine.Object[] subAssets, int width, int height)
|
||||||
public override Texture2D RenderStaticPreview (string assetPath, UnityEngine.Object[] subAssets, int width, int height)
|
{
|
||||||
{
|
Texture2D tex = new Texture2D(width, height, TextureFormat.ARGB32, false);
|
||||||
Texture2D tex = new Texture2D(width, height, TextureFormat.ARGB32, false);
|
|
||||||
|
this.InitPreview();
|
||||||
this.InitPreview();
|
|
||||||
|
if(this.m_previewUtility.m_Camera == null)
|
||||||
if(this.m_previewUtility.m_Camera == null)
|
return null;
|
||||||
return null;
|
|
||||||
|
|
||||||
m_requireRefresh = true;
|
m_requireRefresh = true;
|
||||||
this.DoRenderPreview(false);
|
this.DoRenderPreview(false);
|
||||||
AdjustCameraGoals(false);
|
AdjustCameraGoals(false);
|
||||||
|
|
||||||
this.m_previewUtility.m_Camera.orthographicSize = m_orthoGoal/2;
|
this.m_previewUtility.m_Camera.orthographicSize = m_orthoGoal/2;
|
||||||
this.m_previewUtility.m_Camera.transform.position = m_posGoal;
|
this.m_previewUtility.m_Camera.transform.position = m_posGoal;
|
||||||
this.m_previewUtility.BeginStaticPreview(new Rect(0,0,width,height));
|
this.m_previewUtility.BeginStaticPreview(new Rect(0,0,width,height));
|
||||||
this.DoRenderPreview(false);
|
this.DoRenderPreview(false);
|
||||||
|
|
||||||
//TODO: Figure out why this is throwing errors on first attempt
|
//TODO: Figure out why this is throwing errors on first attempt
|
||||||
// if(m_previewUtility != null){
|
// if(m_previewUtility != null){
|
||||||
// Handles.SetCamera(this.m_previewUtility.m_Camera);
|
// Handles.SetCamera(this.m_previewUtility.m_Camera);
|
||||||
// Handles.BeginGUI();
|
// Handles.BeginGUI();
|
||||||
// GUI.DrawTexture(new Rect(40,60,width,height), SpineEditorUtilities.Icons.spine, ScaleMode.StretchToFill);
|
// GUI.DrawTexture(new Rect(40,60,width,height), SpineEditorUtilities.Icons.spine, ScaleMode.StretchToFill);
|
||||||
// Handles.EndGUI();
|
// Handles.EndGUI();
|
||||||
// }
|
// }
|
||||||
tex = this.m_previewUtility.EndStaticPreview();
|
tex = this.m_previewUtility.EndStaticPreview();
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 46fcc9a83c504b54ea65c12fc11d52ab
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
Loading…
x
Reference in New Issue
Block a user