Merge branch '3.7-beta' into 3.7-beta-ue4-cpp
@ -138,6 +138,9 @@ namespace Spine {
|
||||
|
||||
bool finished = UpdateMixingFrom(from, delta);
|
||||
|
||||
from.animationLast = from.nextAnimationLast;
|
||||
from.trackLast = from.nextTrackLast;
|
||||
|
||||
// Require mixTime > 0 to ensure the mixing from entry was applied at least once.
|
||||
if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) {
|
||||
// Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame).
|
||||
@ -149,8 +152,6 @@ namespace Spine {
|
||||
return finished;
|
||||
}
|
||||
|
||||
from.animationLast = from.nextAnimationLast;
|
||||
from.trackLast = from.nextTrackLast;
|
||||
from.trackTime += delta * from.timeScale;
|
||||
to.mixTime += delta * to.timeScale;
|
||||
return false;
|
||||
|
||||
@ -166,6 +166,9 @@ public class AnimationState {
|
||||
|
||||
boolean finished = updateMixingFrom(from, delta);
|
||||
|
||||
from.animationLast = from.nextAnimationLast;
|
||||
from.trackLast = from.nextTrackLast;
|
||||
|
||||
// Require mixTime > 0 to ensure the mixing from entry was applied at least once.
|
||||
if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) {
|
||||
// Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame).
|
||||
@ -177,8 +180,6 @@ public class AnimationState {
|
||||
return finished;
|
||||
}
|
||||
|
||||
from.animationLast = from.nextAnimationLast;
|
||||
from.trackLast = from.nextTrackLast;
|
||||
from.trackTime += delta * from.timeScale;
|
||||
to.mixTime += delta * to.timeScale;
|
||||
return false;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cb4e560224445d44affd8e57c1ae8b1
|
||||
guid: 30918bcaadaaecc42bc215ff52f75b21
|
||||
folderAsset: yes
|
||||
timeCreated: 1495071888
|
||||
timeCreated: 1488288531
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@ -1,7 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc5fac7eface2ba4fbb6146017e41192
|
||||
guid: ad14d5a4cd7a0444286d315541ee0495
|
||||
folderAsset: yes
|
||||
timeCreated: 1500876410
|
||||
timeCreated: 1527569319
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
12
spine-unity/Assets/Spine/Editor/spine-unity-editor.asmdef
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "spine-unity-editor",
|
||||
"references": [
|
||||
"spine-unity"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 173464ddf4cdb6640a4dfa8a9281ad69
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
spine-unity/Assets/Spine/Editor/spine-unity.meta
Normal file
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83fbec88df35fe34bab43a5dde6788af
|
||||
folderAsset: yes
|
||||
timeCreated: 1527569675
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,51 +1,51 @@
|
||||
/******************************************************************************
|
||||
* 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 UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
public static class AssetDatabaseAvailabilityDetector {
|
||||
const string MARKER_RESOURCE_NAME = "SpineAssetDatabaseMarker";
|
||||
private static bool _isMarkerLoaded;
|
||||
|
||||
public static bool IsAssetDatabaseAvailable (bool forceCheck = false) {
|
||||
if (!forceCheck && _isMarkerLoaded)
|
||||
return true;
|
||||
|
||||
TextAsset markerTextAsset = Resources.Load<TextAsset>(MARKER_RESOURCE_NAME);
|
||||
_isMarkerLoaded = markerTextAsset != null;
|
||||
if (markerTextAsset != null) {
|
||||
Resources.UnloadAsset(markerTextAsset);
|
||||
}
|
||||
|
||||
return _isMarkerLoaded;
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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 UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
public static class AssetDatabaseAvailabilityDetector {
|
||||
const string MARKER_RESOURCE_NAME = "SpineAssetDatabaseMarker";
|
||||
private static bool _isMarkerLoaded;
|
||||
|
||||
public static bool IsAssetDatabaseAvailable (bool forceCheck = false) {
|
||||
if (!forceCheck && _isMarkerLoaded)
|
||||
return true;
|
||||
|
||||
TextAsset markerTextAsset = Resources.Load<TextAsset>(MARKER_RESOURCE_NAME);
|
||||
_isMarkerLoaded = markerTextAsset != null;
|
||||
if (markerTextAsset != null) {
|
||||
Resources.UnloadAsset(markerTextAsset);
|
||||
}
|
||||
|
||||
return _isMarkerLoaded;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,208 +1,208 @@
|
||||
/******************************************************************************
|
||||
* 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 UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
using Editor = UnityEditor.Editor;
|
||||
using Event = UnityEngine.Event;
|
||||
|
||||
[CustomEditor(typeof(BoneFollower)), CanEditMultipleObjects]
|
||||
public class BoneFollowerInspector : Editor {
|
||||
SerializedProperty boneName, skeletonRenderer, followZPosition, followBoneRotation, followLocalScale, followSkeletonFlip;
|
||||
BoneFollower targetBoneFollower;
|
||||
bool needsReset;
|
||||
|
||||
#region Context Menu Item
|
||||
[MenuItem ("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject")]
|
||||
static void AddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
var skeletonRenderer = cmd.context as SkeletonRenderer;
|
||||
var go = new GameObject("BoneFollower");
|
||||
var t = go.transform;
|
||||
t.SetParent(skeletonRenderer.transform);
|
||||
t.localPosition = Vector3.zero;
|
||||
|
||||
var f = go.AddComponent<BoneFollower>();
|
||||
f.skeletonRenderer = skeletonRenderer;
|
||||
|
||||
EditorGUIUtility.PingObject(t);
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(go, "Add BoneFollower");
|
||||
}
|
||||
|
||||
// Validate
|
||||
[MenuItem ("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject", true)]
|
||||
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
var skeletonRenderer = cmd.context as SkeletonRenderer;
|
||||
return skeletonRenderer.valid;
|
||||
}
|
||||
#endregion
|
||||
|
||||
void OnEnable () {
|
||||
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
|
||||
boneName = serializedObject.FindProperty("boneName");
|
||||
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
|
||||
followZPosition = serializedObject.FindProperty("followZPosition");
|
||||
followLocalScale = serializedObject.FindProperty("followLocalScale");
|
||||
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
|
||||
|
||||
targetBoneFollower = (BoneFollower)target;
|
||||
if (targetBoneFollower.SkeletonRenderer != null)
|
||||
targetBoneFollower.SkeletonRenderer.Initialize(false);
|
||||
|
||||
if (!targetBoneFollower.valid || needsReset) {
|
||||
targetBoneFollower.Initialize();
|
||||
targetBoneFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSceneGUI () {
|
||||
var tbf = target as BoneFollower;
|
||||
var skeletonRendererComponent = tbf.skeletonRenderer;
|
||||
if (skeletonRendererComponent == null) return;
|
||||
|
||||
var transform = skeletonRendererComponent.transform;
|
||||
var skeleton = skeletonRendererComponent.skeleton;
|
||||
|
||||
if (string.IsNullOrEmpty(boneName.stringValue)) {
|
||||
SpineHandles.DrawBones(transform, skeleton);
|
||||
SpineHandles.DrawBoneNames(transform, skeleton);
|
||||
Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox);
|
||||
} else {
|
||||
var targetBone = tbf.bone;
|
||||
if (targetBone == null) return;
|
||||
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor);
|
||||
Handles.Label(targetBone.GetWorldPosition(transform), targetBone.Data.Name, SpineHandles.BoneNameStyle);
|
||||
}
|
||||
}
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
if (serializedObject.isEditingMultipleObjects) {
|
||||
if (needsReset) {
|
||||
needsReset = false;
|
||||
foreach (var o in targets) {
|
||||
var bf = (BoneFollower)o;
|
||||
bf.Initialize();
|
||||
bf.LateUpdate();
|
||||
}
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
DrawDefaultInspector();
|
||||
needsReset |= EditorGUI.EndChangeCheck();
|
||||
return;
|
||||
}
|
||||
|
||||
if (needsReset && Event.current.type == EventType.Layout) {
|
||||
targetBoneFollower.Initialize();
|
||||
targetBoneFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
serializedObject.Update();
|
||||
|
||||
// Find Renderer
|
||||
if (skeletonRenderer.objectReferenceValue == null) {
|
||||
SkeletonRenderer parentRenderer = targetBoneFollower.GetComponentInParent<SkeletonRenderer>();
|
||||
if (parentRenderer != null && parentRenderer.gameObject != targetBoneFollower.gameObject) {
|
||||
skeletonRenderer.objectReferenceValue = parentRenderer;
|
||||
Debug.Log("Inspector automatically assigned BoneFollower.SkeletonRenderer");
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(skeletonRenderer);
|
||||
var skeletonRendererReference = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
|
||||
if (skeletonRendererReference != null) {
|
||||
if (skeletonRendererReference.gameObject == targetBoneFollower.gameObject) {
|
||||
skeletonRenderer.objectReferenceValue = null;
|
||||
EditorUtility.DisplayDialog("Invalid assignment.", "BoneFollower can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your BoneFollower, or choose a SkeletonRenderer from a different GameObject.", "Ok");
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetBoneFollower.valid) {
|
||||
needsReset = true;
|
||||
}
|
||||
|
||||
if (targetBoneFollower.valid) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(boneName);
|
||||
needsReset |= EditorGUI.EndChangeCheck();
|
||||
|
||||
EditorGUILayout.PropertyField(followBoneRotation);
|
||||
EditorGUILayout.PropertyField(followZPosition);
|
||||
EditorGUILayout.PropertyField(followLocalScale);
|
||||
EditorGUILayout.PropertyField(followSkeletonFlip);
|
||||
|
||||
BoneFollowerInspector.RecommendRigidbodyButton(targetBoneFollower);
|
||||
} else {
|
||||
var boneFollowerSkeletonRenderer = targetBoneFollower.skeletonRenderer;
|
||||
if (boneFollowerSkeletonRenderer == null) {
|
||||
EditorGUILayout.HelpBox("SkeletonRenderer is unassigned. Please assign a SkeletonRenderer (SkeletonAnimation or SkeletonAnimator).", MessageType.Warning);
|
||||
} else {
|
||||
boneFollowerSkeletonRenderer.Initialize(false);
|
||||
|
||||
if (boneFollowerSkeletonRenderer.skeletonDataAsset == null)
|
||||
EditorGUILayout.HelpBox("Assigned SkeletonRenderer does not have SkeletonData assigned to it.", MessageType.Warning);
|
||||
|
||||
if (!boneFollowerSkeletonRenderer.valid)
|
||||
EditorGUILayout.HelpBox("Assigned SkeletonRenderer is invalid. Check target SkeletonRenderer, its SkeletonDataAsset or the console for other errors.", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
var current = Event.current;
|
||||
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
|
||||
if (wasUndo)
|
||||
targetBoneFollower.Initialize();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
internal static void RecommendRigidbodyButton (Component component) {
|
||||
bool hasCollider2D = component.GetComponent<Collider2D>() != null || component.GetComponent<BoundingBoxFollower>() != null;
|
||||
bool hasCollider3D = !hasCollider2D && component.GetComponent<Collider>();
|
||||
bool missingRigidBody = (hasCollider2D && component.GetComponent<Rigidbody2D>() == null) || (hasCollider3D && component.GetComponent<Rigidbody>() == null);
|
||||
if (missingRigidBody) {
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
EditorGUILayout.HelpBox("Collider detected. Unity recommends adding a Rigidbody to the parent Transforms of any colliders that are intended to be dynamically repositioned and rotated.", MessageType.Warning);
|
||||
var rbType = hasCollider2D ? typeof(Rigidbody2D) : typeof(Rigidbody);
|
||||
string rbLabel = string.Format("Add {0}", rbType.Name);
|
||||
var rbContent = SpineInspectorUtility.TempContent(rbLabel, SpineInspectorUtility.UnityIcon(rbType), "Add a rigidbody to this GameObject to be the Physics body parent of the attached collider.");
|
||||
if (SpineInspectorUtility.CenteredButton(rbContent)) component.gameObject.AddComponent(rbType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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 UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
using Editor = UnityEditor.Editor;
|
||||
using Event = UnityEngine.Event;
|
||||
|
||||
[CustomEditor(typeof(BoneFollower)), CanEditMultipleObjects]
|
||||
public class BoneFollowerInspector : Editor {
|
||||
SerializedProperty boneName, skeletonRenderer, followZPosition, followBoneRotation, followLocalScale, followSkeletonFlip;
|
||||
BoneFollower targetBoneFollower;
|
||||
bool needsReset;
|
||||
|
||||
#region Context Menu Item
|
||||
[MenuItem ("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject")]
|
||||
static void AddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
var skeletonRenderer = cmd.context as SkeletonRenderer;
|
||||
var go = new GameObject("BoneFollower");
|
||||
var t = go.transform;
|
||||
t.SetParent(skeletonRenderer.transform);
|
||||
t.localPosition = Vector3.zero;
|
||||
|
||||
var f = go.AddComponent<BoneFollower>();
|
||||
f.skeletonRenderer = skeletonRenderer;
|
||||
|
||||
EditorGUIUtility.PingObject(t);
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(go, "Add BoneFollower");
|
||||
}
|
||||
|
||||
// Validate
|
||||
[MenuItem ("CONTEXT/SkeletonRenderer/Add BoneFollower GameObject", true)]
|
||||
static bool ValidateAddBoneFollowerGameObject (MenuCommand cmd) {
|
||||
var skeletonRenderer = cmd.context as SkeletonRenderer;
|
||||
return skeletonRenderer.valid;
|
||||
}
|
||||
#endregion
|
||||
|
||||
void OnEnable () {
|
||||
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
|
||||
boneName = serializedObject.FindProperty("boneName");
|
||||
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
|
||||
followZPosition = serializedObject.FindProperty("followZPosition");
|
||||
followLocalScale = serializedObject.FindProperty("followLocalScale");
|
||||
followSkeletonFlip = serializedObject.FindProperty("followSkeletonFlip");
|
||||
|
||||
targetBoneFollower = (BoneFollower)target;
|
||||
if (targetBoneFollower.SkeletonRenderer != null)
|
||||
targetBoneFollower.SkeletonRenderer.Initialize(false);
|
||||
|
||||
if (!targetBoneFollower.valid || needsReset) {
|
||||
targetBoneFollower.Initialize();
|
||||
targetBoneFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSceneGUI () {
|
||||
var tbf = target as BoneFollower;
|
||||
var skeletonRendererComponent = tbf.skeletonRenderer;
|
||||
if (skeletonRendererComponent == null) return;
|
||||
|
||||
var transform = skeletonRendererComponent.transform;
|
||||
var skeleton = skeletonRendererComponent.skeleton;
|
||||
|
||||
if (string.IsNullOrEmpty(boneName.stringValue)) {
|
||||
SpineHandles.DrawBones(transform, skeleton);
|
||||
SpineHandles.DrawBoneNames(transform, skeleton);
|
||||
Handles.Label(tbf.transform.position, "No bone selected", EditorStyles.helpBox);
|
||||
} else {
|
||||
var targetBone = tbf.bone;
|
||||
if (targetBone == null) return;
|
||||
SpineHandles.DrawBoneWireframe(transform, targetBone, SpineHandles.TransformContraintColor);
|
||||
Handles.Label(targetBone.GetWorldPosition(transform), targetBone.Data.Name, SpineHandles.BoneNameStyle);
|
||||
}
|
||||
}
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
if (serializedObject.isEditingMultipleObjects) {
|
||||
if (needsReset) {
|
||||
needsReset = false;
|
||||
foreach (var o in targets) {
|
||||
var bf = (BoneFollower)o;
|
||||
bf.Initialize();
|
||||
bf.LateUpdate();
|
||||
}
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
DrawDefaultInspector();
|
||||
needsReset |= EditorGUI.EndChangeCheck();
|
||||
return;
|
||||
}
|
||||
|
||||
if (needsReset && Event.current.type == EventType.Layout) {
|
||||
targetBoneFollower.Initialize();
|
||||
targetBoneFollower.LateUpdate();
|
||||
needsReset = false;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
serializedObject.Update();
|
||||
|
||||
// Find Renderer
|
||||
if (skeletonRenderer.objectReferenceValue == null) {
|
||||
SkeletonRenderer parentRenderer = targetBoneFollower.GetComponentInParent<SkeletonRenderer>();
|
||||
if (parentRenderer != null && parentRenderer.gameObject != targetBoneFollower.gameObject) {
|
||||
skeletonRenderer.objectReferenceValue = parentRenderer;
|
||||
Debug.Log("Inspector automatically assigned BoneFollower.SkeletonRenderer");
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(skeletonRenderer);
|
||||
var skeletonRendererReference = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
|
||||
if (skeletonRendererReference != null) {
|
||||
if (skeletonRendererReference.gameObject == targetBoneFollower.gameObject) {
|
||||
skeletonRenderer.objectReferenceValue = null;
|
||||
EditorUtility.DisplayDialog("Invalid assignment.", "BoneFollower can only follow a skeleton on a separate GameObject.\n\nCreate a new GameObject for your BoneFollower, or choose a SkeletonRenderer from a different GameObject.", "Ok");
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetBoneFollower.valid) {
|
||||
needsReset = true;
|
||||
}
|
||||
|
||||
if (targetBoneFollower.valid) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(boneName);
|
||||
needsReset |= EditorGUI.EndChangeCheck();
|
||||
|
||||
EditorGUILayout.PropertyField(followBoneRotation);
|
||||
EditorGUILayout.PropertyField(followZPosition);
|
||||
EditorGUILayout.PropertyField(followLocalScale);
|
||||
EditorGUILayout.PropertyField(followSkeletonFlip);
|
||||
|
||||
BoneFollowerInspector.RecommendRigidbodyButton(targetBoneFollower);
|
||||
} else {
|
||||
var boneFollowerSkeletonRenderer = targetBoneFollower.skeletonRenderer;
|
||||
if (boneFollowerSkeletonRenderer == null) {
|
||||
EditorGUILayout.HelpBox("SkeletonRenderer is unassigned. Please assign a SkeletonRenderer (SkeletonAnimation or SkeletonAnimator).", MessageType.Warning);
|
||||
} else {
|
||||
boneFollowerSkeletonRenderer.Initialize(false);
|
||||
|
||||
if (boneFollowerSkeletonRenderer.skeletonDataAsset == null)
|
||||
EditorGUILayout.HelpBox("Assigned SkeletonRenderer does not have SkeletonData assigned to it.", MessageType.Warning);
|
||||
|
||||
if (!boneFollowerSkeletonRenderer.valid)
|
||||
EditorGUILayout.HelpBox("Assigned SkeletonRenderer is invalid. Check target SkeletonRenderer, its SkeletonDataAsset or the console for other errors.", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
var current = Event.current;
|
||||
bool wasUndo = (current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed");
|
||||
if (wasUndo)
|
||||
targetBoneFollower.Initialize();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
internal static void RecommendRigidbodyButton (Component component) {
|
||||
bool hasCollider2D = component.GetComponent<Collider2D>() != null || component.GetComponent<BoundingBoxFollower>() != null;
|
||||
bool hasCollider3D = !hasCollider2D && component.GetComponent<Collider>();
|
||||
bool missingRigidBody = (hasCollider2D && component.GetComponent<Rigidbody2D>() == null) || (hasCollider3D && component.GetComponent<Rigidbody>() == null);
|
||||
if (missingRigidBody) {
|
||||
using (new SpineInspectorUtility.BoxScope()) {
|
||||
EditorGUILayout.HelpBox("Collider detected. Unity recommends adding a Rigidbody to the parent Transforms of any colliders that are intended to be dynamically repositioned and rotated.", MessageType.Warning);
|
||||
var rbType = hasCollider2D ? typeof(Rigidbody2D) : typeof(Rigidbody);
|
||||
string rbLabel = string.Format("Add {0}", rbType.Name);
|
||||
var rbContent = SpineInspectorUtility.TempContent(rbLabel, SpineInspectorUtility.UnityIcon(rbType), "Add a rigidbody to this GameObject to be the Physics body parent of the attached collider.");
|
||||
if (SpineInspectorUtility.CenteredButton(rbContent)) component.gameObject.AddComponent(rbType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Before Width: | Height: | Size: 591 B After Width: | Height: | Size: 591 B |
|
Before Width: | Height: | Size: 563 B After Width: | Height: | Size: 563 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 461 B After Width: | Height: | Size: 461 B |
|
Before Width: | Height: | Size: 515 B After Width: | Height: | Size: 515 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 587 B After Width: | Height: | Size: 587 B |
|
Before Width: | Height: | Size: 698 B After Width: | Height: | Size: 698 B |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 639 B After Width: | Height: | Size: 639 B |
|
Before Width: | Height: | Size: 613 B After Width: | Height: | Size: 613 B |
|
Before Width: | Height: | Size: 741 B After Width: | Height: | Size: 741 B |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 757 B After Width: | Height: | Size: 757 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 603 B After Width: | Height: | Size: 603 B |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 519 B After Width: | Height: | Size: 519 B |
|
Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 687 B |
|
Before Width: | Height: | Size: 555 B After Width: | Height: | Size: 555 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 634 B After Width: | Height: | Size: 634 B |
|
Before Width: | Height: | Size: 643 B After Width: | Height: | Size: 643 B |
|
Before Width: | Height: | Size: 672 B After Width: | Height: | Size: 672 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 649 B After Width: | Height: | Size: 649 B |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 698 B After Width: | Height: | Size: 698 B |
@ -1,84 +1,59 @@
|
||||
/******************************************************************************
|
||||
* 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;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
public static class Menus {
|
||||
[MenuItem("Assets/Create/Spine/Atlas Asset")]
|
||||
static public void CreateAtlas () {
|
||||
CreateAsset<AtlasAsset>("New Atlas");
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Create/Spine/SkeletonData Asset")]
|
||||
static public void CreateSkeletonData () {
|
||||
CreateAsset<SkeletonDataAsset>("New SkeletonData");
|
||||
}
|
||||
|
||||
static void CreateAsset<T> (String name) where T : ScriptableObject {
|
||||
var dir = "Assets/";
|
||||
var selected = Selection.activeObject;
|
||||
if (selected != null) {
|
||||
var assetDir = AssetDatabase.GetAssetPath(selected.GetInstanceID());
|
||||
if (assetDir.Length > 0 && Directory.Exists(assetDir))
|
||||
dir = assetDir + "/";
|
||||
}
|
||||
ScriptableObject asset = ScriptableObject.CreateInstance<T>();
|
||||
AssetDatabase.CreateAsset(asset, dir + name + ".asset");
|
||||
AssetDatabase.SaveAssets();
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = asset;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
|
||||
static public void CreateSkeletonRendererGameObject () {
|
||||
CreateSpineGameObject<SkeletonRenderer>("New SkeletonRenderer");
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
|
||||
static public void CreateSkeletonAnimationGameObject () {
|
||||
CreateSpineGameObject<SkeletonAnimation>("New SkeletonAnimation");
|
||||
}
|
||||
|
||||
static void CreateSpineGameObject<T> (string name) where T : MonoBehaviour {
|
||||
var parentGameObject = Selection.activeObject as GameObject;
|
||||
var parentTransform = parentGameObject == null ? null : parentGameObject.transform;
|
||||
|
||||
var gameObject = new GameObject(name, typeof(T));
|
||||
gameObject.transform.SetParent(parentTransform, false);
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = gameObject;
|
||||
EditorGUIUtility.PingObject(Selection.activeObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
public static class Menus {
|
||||
[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
|
||||
static public void CreateSkeletonRendererGameObject () {
|
||||
CreateSpineGameObject<SkeletonRenderer>("New SkeletonRenderer");
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
|
||||
static public void CreateSkeletonAnimationGameObject () {
|
||||
CreateSpineGameObject<SkeletonAnimation>("New SkeletonAnimation");
|
||||
}
|
||||
|
||||
static void CreateSpineGameObject<T> (string name) where T : MonoBehaviour {
|
||||
var parentGameObject = Selection.activeObject as GameObject;
|
||||
var parentTransform = parentGameObject == null ? null : parentGameObject.transform;
|
||||
|
||||
var gameObject = new GameObject(name, typeof(T));
|
||||
gameObject.transform.SetParent(parentTransform, false);
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = gameObject;
|
||||
EditorGUIUtility.PingObject(Selection.activeObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,143 +1,143 @@
|
||||
/******************************************************************************
|
||||
* 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 UnityEditor;
|
||||
using UnityEngine;
|
||||
using Spine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
[CustomEditor(typeof(SkeletonAnimation))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SkeletonAnimationInspector : SkeletonRendererInspector {
|
||||
protected SerializedProperty animationName, loop, timeScale, autoReset;
|
||||
protected bool wasAnimationNameChanged;
|
||||
protected bool requireRepaint;
|
||||
readonly GUIContent LoopLabel = new GUIContent("Loop", "Whether or not .AnimationName should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.");
|
||||
readonly GUIContent TimeScaleLabel = new GUIContent("Time Scale", "The rate at which animations progress over time. 1 means normal speed. 0.5 means 50% speed.");
|
||||
|
||||
protected override void OnEnable () {
|
||||
base.OnEnable();
|
||||
animationName = serializedObject.FindProperty("_animationName");
|
||||
loop = serializedObject.FindProperty("loop");
|
||||
timeScale = serializedObject.FindProperty("timeScale");
|
||||
}
|
||||
|
||||
protected override void DrawInspectorGUI (bool multi) {
|
||||
base.DrawInspectorGUI(multi);
|
||||
if (!TargetIsValid) return;
|
||||
bool sameData = SpineInspectorUtility.TargetsUseSameData(serializedObject);
|
||||
|
||||
if (multi) {
|
||||
foreach (var o in targets)
|
||||
TrySetAnimation(o, multi);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
if (!sameData) {
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
EditorGUILayout.DelayedTextField(animationName);
|
||||
#else
|
||||
animationName.stringValue = EditorGUILayout.TextField(animationName.displayName, animationName.stringValue);
|
||||
#endif
|
||||
} else {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(animationName);
|
||||
wasAnimationNameChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
|
||||
}
|
||||
EditorGUILayout.PropertyField(loop);
|
||||
EditorGUILayout.PropertyField(timeScale);
|
||||
foreach (var o in targets) {
|
||||
var component = o as SkeletonAnimation;
|
||||
component.timeScale = Mathf.Max(component.timeScale, 0);
|
||||
}
|
||||
} else {
|
||||
TrySetAnimation(target, multi);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(animationName);
|
||||
wasAnimationNameChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
|
||||
EditorGUILayout.PropertyField(loop, LoopLabel);
|
||||
EditorGUILayout.PropertyField(timeScale, TimeScaleLabel);
|
||||
var component = (SkeletonAnimation)target;
|
||||
component.timeScale = Mathf.Max(component.timeScale, 0);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
if (!isInspectingPrefab) {
|
||||
if (requireRepaint) {
|
||||
SceneView.RepaintAll();
|
||||
requireRepaint = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void TrySetAnimation (Object o, bool multi) {
|
||||
var skeletonAnimation = o as SkeletonAnimation;
|
||||
if (skeletonAnimation == null) return;
|
||||
if (!skeletonAnimation.valid)
|
||||
return;
|
||||
|
||||
if (!isInspectingPrefab) {
|
||||
if (wasAnimationNameChanged) {
|
||||
if (!Application.isPlaying) {
|
||||
if (skeletonAnimation.state != null) skeletonAnimation.state.ClearTrack(0);
|
||||
skeletonAnimation.skeleton.SetToSetupPose();
|
||||
}
|
||||
|
||||
Spine.Animation animationToUse = skeletonAnimation.skeleton.Data.FindAnimation(animationName.stringValue);
|
||||
|
||||
if (!Application.isPlaying) {
|
||||
if (animationToUse != null) animationToUse.PoseSkeleton(skeletonAnimation.Skeleton, 0f);
|
||||
skeletonAnimation.Update(0);
|
||||
skeletonAnimation.LateUpdate();
|
||||
requireRepaint = true;
|
||||
} else {
|
||||
if (animationToUse != null)
|
||||
skeletonAnimation.state.SetAnimation(0, animationToUse, loop.boolValue);
|
||||
else
|
||||
skeletonAnimation.state.ClearTrack(0);
|
||||
}
|
||||
|
||||
wasAnimationNameChanged = false;
|
||||
}
|
||||
|
||||
// Reflect animationName serialized property in the inspector even if SetAnimation API was used.
|
||||
if (!multi && Application.isPlaying) {
|
||||
TrackEntry current = skeletonAnimation.state.GetCurrent(0);
|
||||
if (current != null) {
|
||||
if (skeletonAnimation.AnimationName != animationName.stringValue)
|
||||
animationName.stringValue = current.Animation.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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 UnityEditor;
|
||||
using UnityEngine;
|
||||
using Spine;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
[CustomEditor(typeof(SkeletonAnimation))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SkeletonAnimationInspector : SkeletonRendererInspector {
|
||||
protected SerializedProperty animationName, loop, timeScale, autoReset;
|
||||
protected bool wasAnimationNameChanged;
|
||||
protected bool requireRepaint;
|
||||
readonly GUIContent LoopLabel = new GUIContent("Loop", "Whether or not .AnimationName should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.");
|
||||
readonly GUIContent TimeScaleLabel = new GUIContent("Time Scale", "The rate at which animations progress over time. 1 means normal speed. 0.5 means 50% speed.");
|
||||
|
||||
protected override void OnEnable () {
|
||||
base.OnEnable();
|
||||
animationName = serializedObject.FindProperty("_animationName");
|
||||
loop = serializedObject.FindProperty("loop");
|
||||
timeScale = serializedObject.FindProperty("timeScale");
|
||||
}
|
||||
|
||||
protected override void DrawInspectorGUI (bool multi) {
|
||||
base.DrawInspectorGUI(multi);
|
||||
if (!TargetIsValid) return;
|
||||
bool sameData = SpineInspectorUtility.TargetsUseSameData(serializedObject);
|
||||
|
||||
if (multi) {
|
||||
foreach (var o in targets)
|
||||
TrySetAnimation(o, multi);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
if (!sameData) {
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
EditorGUILayout.DelayedTextField(animationName);
|
||||
#else
|
||||
animationName.stringValue = EditorGUILayout.TextField(animationName.displayName, animationName.stringValue);
|
||||
#endif
|
||||
} else {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(animationName);
|
||||
wasAnimationNameChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
|
||||
}
|
||||
EditorGUILayout.PropertyField(loop);
|
||||
EditorGUILayout.PropertyField(timeScale);
|
||||
foreach (var o in targets) {
|
||||
var component = o as SkeletonAnimation;
|
||||
component.timeScale = Mathf.Max(component.timeScale, 0);
|
||||
}
|
||||
} else {
|
||||
TrySetAnimation(target, multi);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(animationName);
|
||||
wasAnimationNameChanged |= EditorGUI.EndChangeCheck(); // Value used in the next update.
|
||||
EditorGUILayout.PropertyField(loop, LoopLabel);
|
||||
EditorGUILayout.PropertyField(timeScale, TimeScaleLabel);
|
||||
var component = (SkeletonAnimation)target;
|
||||
component.timeScale = Mathf.Max(component.timeScale, 0);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
if (!isInspectingPrefab) {
|
||||
if (requireRepaint) {
|
||||
SceneView.RepaintAll();
|
||||
requireRepaint = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void TrySetAnimation (Object o, bool multi) {
|
||||
var skeletonAnimation = o as SkeletonAnimation;
|
||||
if (skeletonAnimation == null) return;
|
||||
if (!skeletonAnimation.valid)
|
||||
return;
|
||||
|
||||
if (!isInspectingPrefab) {
|
||||
if (wasAnimationNameChanged) {
|
||||
if (!Application.isPlaying) {
|
||||
if (skeletonAnimation.state != null) skeletonAnimation.state.ClearTrack(0);
|
||||
skeletonAnimation.skeleton.SetToSetupPose();
|
||||
}
|
||||
|
||||
Spine.Animation animationToUse = skeletonAnimation.skeleton.Data.FindAnimation(animationName.stringValue);
|
||||
|
||||
if (!Application.isPlaying) {
|
||||
if (animationToUse != null) animationToUse.PoseSkeleton(skeletonAnimation.Skeleton, 0f);
|
||||
skeletonAnimation.Update(0);
|
||||
skeletonAnimation.LateUpdate();
|
||||
requireRepaint = true;
|
||||
} else {
|
||||
if (animationToUse != null)
|
||||
skeletonAnimation.state.SetAnimation(0, animationToUse, loop.boolValue);
|
||||
else
|
||||
skeletonAnimation.state.ClearTrack(0);
|
||||
}
|
||||
|
||||
wasAnimationNameChanged = false;
|
||||
}
|
||||
|
||||
// Reflect animationName serialized property in the inspector even if SetAnimation API was used.
|
||||
if (!multi && Application.isPlaying) {
|
||||
TrackEntry current = skeletonAnimation.state.GetCurrent(0);
|
||||
if (current != null) {
|
||||
if (skeletonAnimation.AnimationName != animationName.stringValue)
|
||||
animationName.stringValue = current.Animation.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -332,7 +332,7 @@ namespace Spine.Unity.Editor {
|
||||
else {
|
||||
EditorGUILayout.HelpBox("Atlas array should not have null entries!", MessageType.Error);
|
||||
if (SpineInspectorUtility.CenteredButton(SpineInspectorUtility.TempContent("Remove null entries"))) {
|
||||
var trimmedAtlasAssets = new List<AtlasAsset>();
|
||||
var trimmedAtlasAssets = new List<AtlasAssetBase>();
|
||||
foreach (var a in targetSkeletonDataAsset.atlasAssets) {
|
||||
if (a != null)
|
||||
trimmedAtlasAssets.Add(a);
|
||||
@ -651,7 +651,12 @@ namespace Spine.Unity.Editor {
|
||||
SkeletonAnimation skeletonAnimation;
|
||||
GameObject previewGameObject;
|
||||
internal bool requiresRefresh;
|
||||
|
||||
#if !(UNITY_2017_4 || UNITY_2018)
|
||||
float animationLastTime;
|
||||
#endif
|
||||
|
||||
static float CurrentTime { get { return (float)EditorApplication.timeSinceStartup; } }
|
||||
|
||||
Action Repaint;
|
||||
public event Action<string> OnSkinChanged;
|
||||
@ -742,7 +747,9 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
if (previewRenderUtility == null) {
|
||||
previewRenderUtility = new PreviewRenderUtility(true);
|
||||
animationLastTime = Time.realtimeSinceStartup;
|
||||
#if !(UNITY_2017_4 || UNITY_2018)
|
||||
animationLastTime = CurrentTime;
|
||||
#endif
|
||||
|
||||
const int PreviewLayer = 30;
|
||||
const int PreviewCameraCullingMask = 1 << PreviewLayer;
|
||||
@ -770,6 +777,10 @@ namespace Spine.Unity.Editor {
|
||||
skeletonAnimation.initialSkinName = skinName;
|
||||
skeletonAnimation.LateUpdate();
|
||||
previewGameObject.GetComponent<Renderer>().enabled = false;
|
||||
|
||||
#if UNITY_2017_4 || UNITY_2018
|
||||
previewRenderUtility.AddSingleGO(previewGameObject);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (this.ActiveTrack != null) cameraAdjustEndFrame = EditorApplication.timeSinceStartup + skeletonAnimation.AnimationState.GetCurrent(0).Alpha;
|
||||
@ -813,6 +824,7 @@ namespace Spine.Unity.Editor {
|
||||
previewRenderUtility.BeginStaticPreview(new Rect(0, 0, width, height));
|
||||
DoRenderPreview(false);
|
||||
var tex = previewRenderUtility.EndStaticPreview();
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
@ -825,12 +837,17 @@ namespace Spine.Unity.Editor {
|
||||
var renderer = go.GetComponent<Renderer>();
|
||||
renderer.enabled = true;
|
||||
|
||||
if (!EditorApplication.isPlaying) {
|
||||
skeletonAnimation.Update((Time.realtimeSinceStartup - animationLastTime));
|
||||
skeletonAnimation.LateUpdate();
|
||||
animationLastTime = Time.realtimeSinceStartup;
|
||||
}
|
||||
|
||||
if (!EditorApplication.isPlaying) {
|
||||
#if !(UNITY_2017_4 || UNITY_2018)
|
||||
float current = CurrentTime;
|
||||
float deltaTime = (current - animationLastTime);
|
||||
skeletonAnimation.Update(deltaTime);
|
||||
animationLastTime = current;
|
||||
#endif
|
||||
skeletonAnimation.LateUpdate();
|
||||
}
|
||||
|
||||
var thisPreviewUtilityCamera = this.PreviewUtilityCamera;
|
||||
|
||||
if (drawHandles) {
|
||||
@ -861,7 +878,7 @@ namespace Spine.Unity.Editor {
|
||||
if (previewRenderUtility == null)
|
||||
return;
|
||||
|
||||
if (EditorApplication.timeSinceStartup < cameraAdjustEndFrame)
|
||||
if (CurrentTime < cameraAdjustEndFrame)
|
||||
AdjustCameraGoals();
|
||||
|
||||
lastCameraPositionGoal = cameraPositionGoal;
|
||||
@ -33,9 +33,9 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
[CustomEditor(typeof(SkeletonAnimator))]
|
||||
[CustomEditor(typeof(SkeletonMecanim))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SkeletonAnimatorInspector : SkeletonRendererInspector {
|
||||
public class SkeletonMecanimInspector : SkeletonRendererInspector {
|
||||
protected SerializedProperty mecanimTranslator;
|
||||
|
||||
protected override void OnEnable () {
|
||||