mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 07:14:55 +08:00
Merge branch '3.8' of https://github.com/EsotericSoftware/spine-runtimes into 3.8
This commit is contained in:
commit
f619a972cb
@ -37,11 +37,15 @@ namespace Spine {
|
||||
public class Animation {
|
||||
internal String name;
|
||||
internal ExposedList<Timeline> timelines;
|
||||
internal HashSet<int> timelineIds;
|
||||
internal float duration;
|
||||
|
||||
public Animation (string name, ExposedList<Timeline> timelines, float duration) {
|
||||
if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
|
||||
if (timelines == null) throw new ArgumentNullException("timelines", "timelines cannot be null.");
|
||||
this.timelineIds = new HashSet<int>();
|
||||
foreach (Timeline timeline in timelines)
|
||||
timelineIds.Add(timeline.PropertyId);
|
||||
this.name = name;
|
||||
this.timelines = timelines;
|
||||
this.duration = duration;
|
||||
@ -55,6 +59,11 @@ namespace Spine {
|
||||
/// <summary>The animation's name, which is unique across all animations in the skeleton.</summary>
|
||||
public string Name { get { return name; } }
|
||||
|
||||
/// <summary>Whether the timeline with the property id is contained in this animation.</summary>
|
||||
public bool HasTimeline (int id) {
|
||||
return timelineIds.Contains(id);
|
||||
}
|
||||
|
||||
/// <summary>Applies all the animation's timelines to the specified skeleton.</summary>
|
||||
/// <seealso cref="Timeline.Apply(Skeleton, float, float, ExposedList, float, MixBlend, MixDirection)"/>
|
||||
public void Apply (Skeleton skeleton, float lastTime, float time, bool loop, ExposedList<Event> events, float alpha, MixBlend blend,
|
||||
|
||||
@ -777,11 +777,11 @@ namespace Spine {
|
||||
if (!propertyIDs.Add(id))
|
||||
timelineMode[i] = AnimationState.Subsequent;
|
||||
else if (to == null || timeline is AttachmentTimeline || timeline is DrawOrderTimeline
|
||||
|| timeline is EventTimeline || !HasTimeline(to, id)) {
|
||||
|| timeline is EventTimeline || !to.animation.HasTimeline(id)) {
|
||||
timelineMode[i] = AnimationState.First;
|
||||
} else {
|
||||
for (TrackEntry next = to.mixingTo; next != null; next = next.mixingTo) {
|
||||
if (HasTimeline(next, id)) continue;
|
||||
if (next.animation.HasTimeline(id)) continue;
|
||||
if (next.mixDuration > 0) {
|
||||
timelineMode[i] = AnimationState.HoldMix;
|
||||
timelineHoldMix[i] = next;
|
||||
@ -809,13 +809,6 @@ namespace Spine {
|
||||
}
|
||||
}
|
||||
|
||||
static bool HasTimeline (TrackEntry entry, int id) {
|
||||
var timelines = entry.animation.timelines.Items;
|
||||
for (int i = 0, n = entry.animation.timelines.Count; i < n; i++)
|
||||
if (timelines[i].PropertyId == id) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <returns>The track entry for the animation currently playing on the track, or null if no animation is currently playing.</returns>
|
||||
public TrackEntry GetCurrent (int trackIndex) {
|
||||
if (trackIndex >= tracks.Count) return null;
|
||||
|
||||
@ -138,6 +138,9 @@ namespace Spine.Unity.Editor {
|
||||
const string MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY = "SPINE_MECANIM_EVENT_INCLUDE_FOLDERNAME";
|
||||
public static bool mecanimEventIncludeFolderName = SpinePreferences.DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME;
|
||||
|
||||
const string TIMELINE_USE_BLEND_DURATION_KEY = "SPINE_TIMELINE_USE_BLEND_DURATION_KEY";
|
||||
public static bool timelineUseBlendDuration = SpinePreferences.DEFAULT_TIMELINE_USE_BLEND_DURATION;
|
||||
|
||||
static bool preferencesLoaded = false;
|
||||
|
||||
public static void Load () {
|
||||
@ -154,6 +157,7 @@ namespace Spine.Unity.Editor {
|
||||
mecanimEventIncludeFolderName = EditorPrefs.GetBool(MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, SpinePreferences.DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME);
|
||||
atlasTxtImportWarning = EditorPrefs.GetBool(ATLASTXT_WARNING_KEY, SpinePreferences.DEFAULT_ATLASTXT_WARNING);
|
||||
textureImporterWarning = EditorPrefs.GetBool(TEXTUREIMPORTER_WARNING_KEY, SpinePreferences.DEFAULT_TEXTUREIMPORTER_WARNING);
|
||||
timelineUseBlendDuration = EditorPrefs.GetBool(TIMELINE_USE_BLEND_DURATION_KEY, SpinePreferences.DEFAULT_TIMELINE_USE_BLEND_DURATION);
|
||||
|
||||
SpineHandles.handleScale = EditorPrefs.GetFloat(SCENE_ICONS_SCALE_KEY, DEFAULT_SCENE_ICONS_SCALE);
|
||||
preferencesLoaded = true;
|
||||
@ -171,6 +175,7 @@ namespace Spine.Unity.Editor {
|
||||
newPreferences.mecanimEventIncludeFolderName = EditorPrefs.GetBool(MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, SpinePreferences.DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME);
|
||||
newPreferences.atlasTxtImportWarning = EditorPrefs.GetBool(ATLASTXT_WARNING_KEY, SpinePreferences.DEFAULT_ATLASTXT_WARNING);
|
||||
newPreferences.textureImporterWarning = EditorPrefs.GetBool(TEXTUREIMPORTER_WARNING_KEY, SpinePreferences.DEFAULT_TEXTUREIMPORTER_WARNING);
|
||||
newPreferences.timelineUseBlendDuration = EditorPrefs.GetBool(TIMELINE_USE_BLEND_DURATION_KEY, SpinePreferences.DEFAULT_TIMELINE_USE_BLEND_DURATION);
|
||||
}
|
||||
|
||||
public static void SaveToEditorPrefs(SpinePreferences preferences) {
|
||||
@ -184,6 +189,7 @@ namespace Spine.Unity.Editor {
|
||||
EditorPrefs.SetBool(MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, preferences.mecanimEventIncludeFolderName);
|
||||
EditorPrefs.SetBool(ATLASTXT_WARNING_KEY, preferences.atlasTxtImportWarning);
|
||||
EditorPrefs.SetBool(TEXTUREIMPORTER_WARNING_KEY, preferences.textureImporterWarning);
|
||||
EditorPrefs.SetBool(TIMELINE_USE_BLEND_DURATION_KEY, preferences.timelineUseBlendDuration);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -265,6 +271,12 @@ namespace Spine.Unity.Editor {
|
||||
if (GUILayout.Button("Disable", GUILayout.Width(64)))
|
||||
SpineTK2DEditorUtility.DisableTK2D();
|
||||
}
|
||||
|
||||
GUILayout.Space(20);
|
||||
EditorGUILayout.LabelField("Timeline Extension", EditorStyles.boldLabel);
|
||||
{
|
||||
SpineEditorUtilities.BoolPrefsField(ref timelineUseBlendDuration, TIMELINE_USE_BLEND_DURATION_KEY, new GUIContent("Use Blend Duration", "When enabled, MixDuration will be synced with timeline clip transition duration 'Ease In Duration'."));
|
||||
}
|
||||
}
|
||||
#endif // !NEW_PREFERENCES_SETTINGS_PROVIDER
|
||||
}
|
||||
|
||||
@ -184,9 +184,7 @@ namespace Spine.Unity.Editor {
|
||||
Debug.LogError("Could not export Spine Skeleton because SkeletonDataAsset is null or invalid!");
|
||||
return;
|
||||
}
|
||||
|
||||
#if !NEW_PREFAB_SYSTEM
|
||||
|
||||
|
||||
if (outputPath == "") {
|
||||
outputPath = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(skeletonDataAsset)) + "/Baked";
|
||||
System.IO.Directory.CreateDirectory(outputPath);
|
||||
@ -281,7 +279,13 @@ namespace Spine.Unity.Editor {
|
||||
Object prefab = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject));
|
||||
|
||||
if (prefab == null) {
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
GameObject emptyGameObject = new GameObject();
|
||||
prefab = PrefabUtility.SaveAsPrefabAssetAndConnect(emptyGameObject, prefabPath, InteractionMode.AutomatedAction);
|
||||
GameObject.DestroyImmediate(emptyGameObject);
|
||||
#else
|
||||
prefab = PrefabUtility.CreateEmptyPrefab(prefabPath);
|
||||
#endif
|
||||
newPrefab = true;
|
||||
}
|
||||
|
||||
@ -428,14 +432,22 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
|
||||
if (newPrefab) {
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
PrefabUtility.SaveAsPrefabAssetAndConnect(prefabRoot, prefabPath, InteractionMode.AutomatedAction);
|
||||
#else
|
||||
PrefabUtility.ReplacePrefab(prefabRoot, prefab, ReplacePrefabOptions.ConnectToPrefab);
|
||||
#endif
|
||||
} else {
|
||||
|
||||
foreach (string str in unusedMeshNames) {
|
||||
Mesh.DestroyImmediate(meshTable[str], true);
|
||||
}
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
PrefabUtility.SaveAsPrefabAssetAndConnect(prefabRoot, prefabPath, InteractionMode.AutomatedAction);
|
||||
#else
|
||||
PrefabUtility.ReplacePrefab(prefabRoot, prefab, ReplacePrefabOptions.ReplaceNameBased);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -447,8 +459,6 @@ namespace Spine.Unity.Editor {
|
||||
GameObject.DestroyImmediate(prefabRoot);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#region Attachment Baking
|
||||
|
||||
@ -27,10 +27,6 @@
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
@ -44,7 +40,6 @@ namespace Spine.Unity.Editor {
|
||||
public class SkeletonBakingWindow : EditorWindow {
|
||||
const bool IsUtilityWindow = true;
|
||||
|
||||
#if !NEW_PREFAB_SYSTEM
|
||||
[MenuItem("CONTEXT/SkeletonDataAsset/Skeleton Baking", false, 5000)]
|
||||
public static void Init (MenuCommand command) {
|
||||
var window = EditorWindow.GetWindow<SkeletonBakingWindow>(IsUtilityWindow);
|
||||
@ -54,7 +49,6 @@ namespace Spine.Unity.Editor {
|
||||
window.skeletonDataAsset = command.context as SkeletonDataAsset;
|
||||
window.Show();
|
||||
}
|
||||
#endif
|
||||
|
||||
public SkeletonDataAsset skeletonDataAsset;
|
||||
[SpineSkin(dataField:"skeletonDataAsset")]
|
||||
|
||||
@ -92,6 +92,10 @@ namespace Spine.Unity.Editor {
|
||||
public const bool DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME = true;
|
||||
public bool mecanimEventIncludeFolderName = DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME;
|
||||
|
||||
// Timeline extension module
|
||||
public const bool DEFAULT_TIMELINE_USE_BLEND_DURATION = true;
|
||||
public bool timelineUseBlendDuration = DEFAULT_TIMELINE_USE_BLEND_DURATION;
|
||||
|
||||
#if NEW_PREFERENCES_SETTINGS_PROVIDER
|
||||
public static void Load () {
|
||||
SpineHandles.handleScale = EditorPrefs.GetFloat(SCENE_ICONS_SCALE_KEY, DEFAULT_SCENE_ICONS_SCALE);
|
||||
@ -185,6 +189,12 @@ namespace Spine.Unity.Editor {
|
||||
if (GUILayout.Button("Disable", GUILayout.Width(64)))
|
||||
SpineEditorUtilities.SpineTK2DEditorUtility.DisableTK2D();
|
||||
}
|
||||
|
||||
GUILayout.Space(20);
|
||||
EditorGUILayout.LabelField("Timeline Extension", EditorStyles.boldLabel);
|
||||
{
|
||||
EditorGUILayout.PropertyField(settings.FindProperty("timelineUseBlendDuration"), new GUIContent("Use Blend Duration", "When enabled, MixDuration will be synced with timeline clip transition duration 'Ease In Duration'."));
|
||||
}
|
||||
}
|
||||
EditorGUIUtility.labelWidth = prevLabelWidth;
|
||||
}
|
||||
|
||||
@ -96,8 +96,11 @@ namespace Spine.Unity {
|
||||
}
|
||||
}
|
||||
set {
|
||||
if (_animationName == value)
|
||||
return;
|
||||
if (_animationName == value) {
|
||||
TrackEntry entry = state.GetCurrent(0);
|
||||
if (entry != null && entry.loop == loop)
|
||||
return;
|
||||
}
|
||||
_animationName = value;
|
||||
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
|
||||
@ -288,6 +288,8 @@ namespace Spine.Unity {
|
||||
if (!Application.isPlaying)
|
||||
Update(0f);
|
||||
#endif
|
||||
if (freeze)
|
||||
Update(0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -580,7 +580,9 @@ namespace Spine.Unity.AttachmentTools {
|
||||
static void CopyTextureAttributesFrom(this Texture2D destination, Texture2D source) {
|
||||
destination.filterMode = source.filterMode;
|
||||
destination.anisoLevel = source.anisoLevel;
|
||||
#if UNITY_EDITOR
|
||||
destination.alphaIsTransparency = source.alphaIsTransparency;
|
||||
#endif
|
||||
destination.wrapModeU = source.wrapModeU;
|
||||
destination.wrapModeV = source.wrapModeV;
|
||||
destination.wrapModeW = source.wrapModeW;
|
||||
|
||||
@ -0,0 +1,116 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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 Spine.Unity.Playables;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
[CustomEditor(typeof(SpineAnimationStateClip))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SpineAnimationStateClipInspector : UnityEditor.Editor {
|
||||
|
||||
protected SerializedProperty templateProp = null;
|
||||
|
||||
protected class ClipInfo {
|
||||
public TimelineClip timelineClip;
|
||||
public float previousBlendInDuration = -1.0f;
|
||||
public float unblendedMixDuration = 0.2f;
|
||||
}
|
||||
|
||||
protected ClipInfo[] clipInfo = null;
|
||||
|
||||
public void OnEnable () {
|
||||
templateProp = serializedObject.FindProperty("template");
|
||||
System.Array.Resize(ref clipInfo, targets.Length);
|
||||
for (int i = 0; i < targets.Length; ++i) {
|
||||
var clip = (SpineAnimationStateClip)targets[i];
|
||||
clipInfo[i] = new ClipInfo();
|
||||
clipInfo[i].timelineClip = FindTimelineClip(clip);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
serializedObject.Update();
|
||||
EditorGUILayout.PropertyField(templateProp);
|
||||
|
||||
for (int i = 0; i < targets.Length; ++i) {
|
||||
var targetClip = (SpineAnimationStateClip)targets[i];
|
||||
if (targetClip.template.useBlendDuration)
|
||||
AdjustMixDuration(targetClip, clipInfo[i]);
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
protected void AdjustMixDuration(SpineAnimationStateClip targetClip, ClipInfo timelineClipInfo) {
|
||||
|
||||
if (timelineClipInfo == null)
|
||||
return;
|
||||
|
||||
var timelineClip = timelineClipInfo.timelineClip;
|
||||
if (timelineClip == null)
|
||||
return;
|
||||
|
||||
float blendInDur = (float)timelineClip.blendInDuration;
|
||||
bool isBlendingNow = blendInDur > 0;
|
||||
bool wasBlendingBefore = timelineClipInfo.previousBlendInDuration > 0;
|
||||
|
||||
if (isBlendingNow) {
|
||||
if (!wasBlendingBefore) {
|
||||
timelineClipInfo.unblendedMixDuration = targetClip.template.mixDuration;
|
||||
}
|
||||
targetClip.template.mixDuration = blendInDur;
|
||||
EditorUtility.SetDirty(targetClip);
|
||||
}
|
||||
else if (wasBlendingBefore) {
|
||||
targetClip.template.mixDuration = timelineClipInfo.unblendedMixDuration;
|
||||
EditorUtility.SetDirty(targetClip);
|
||||
}
|
||||
timelineClipInfo.previousBlendInDuration = blendInDur;
|
||||
}
|
||||
|
||||
protected TimelineClip FindTimelineClip(SpineAnimationStateClip targetClip) {
|
||||
string[] guids = AssetDatabase.FindAssets("t:TimelineAsset");
|
||||
foreach (string guid in guids) {
|
||||
TimelineAsset timeline = (TimelineAsset)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid), typeof(TimelineAsset));
|
||||
foreach (var track in timeline.GetOutputTracks()) {
|
||||
foreach (var clip in track.GetClips()) {
|
||||
if (clip.asset.GetType() == typeof(SpineAnimationStateClip) && object.ReferenceEquals(clip.asset, targetClip)) {
|
||||
return clip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95642d062fbcfda4e8d9262fa715b098
|
||||
timeCreated: 1570044805
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -32,30 +32,39 @@ using UnityEngine;
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
using Spine.Unity.Playables;
|
||||
using Spine.Unity.Editor;
|
||||
|
||||
//[CustomPropertyDrawer(typeof(SpineAnimationStateBehaviour))]
|
||||
[CustomPropertyDrawer(typeof(SpineAnimationStateBehaviour))]
|
||||
public class SpineAnimationStateDrawer : PropertyDrawer {
|
||||
/*
|
||||
|
||||
public override float GetPropertyHeight (SerializedProperty property, GUIContent label) {
|
||||
const int fieldCount = 8;
|
||||
return fieldCount * EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
|
||||
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
|
||||
SerializedProperty skeletonDataAssetProp = property.FindPropertyRelative("skeletonDataAsset");
|
||||
SerializedProperty animationNameProp = property.FindPropertyRelative("animationName");
|
||||
SerializedProperty animationReferenceProp = property.FindPropertyRelative("animationReference");
|
||||
SerializedProperty loopProp = property.FindPropertyRelative("loop");
|
||||
|
||||
SerializedProperty customDurationProp = property.FindPropertyRelative("customDuration");
|
||||
SerializedProperty useBlendDurationProp = property.FindPropertyRelative("useBlendDuration");
|
||||
SerializedProperty mixDurationProp = property.FindPropertyRelative("mixDuration");
|
||||
SerializedProperty eventProp = property.FindPropertyRelative("eventThreshold");
|
||||
SerializedProperty attachmentProp = property.FindPropertyRelative("attachmentThreshold");
|
||||
SerializedProperty drawOrderProp = property.FindPropertyRelative("drawOrderThreshold");
|
||||
|
||||
// initialize useBlendDuration parameter according to preferences
|
||||
SerializedProperty isInitializedProp = property.FindPropertyRelative("isInitialized");
|
||||
if (!isInitializedProp.hasMultipleDifferentValues && isInitializedProp.boolValue == false) {
|
||||
useBlendDurationProp.boolValue = SpineEditorUtilities.Preferences.timelineUseBlendDuration;
|
||||
isInitializedProp.boolValue = true;
|
||||
}
|
||||
|
||||
Rect singleFieldRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
|
||||
EditorGUI.PropertyField(singleFieldRect, skeletonDataAssetProp);
|
||||
|
||||
float lineHeightWithSpacing = EditorGUIUtility.singleLineHeight + 2f;
|
||||
|
||||
singleFieldRect.y += lineHeightWithSpacing;
|
||||
EditorGUI.PropertyField(singleFieldRect, animationNameProp);
|
||||
EditorGUI.PropertyField(singleFieldRect, animationReferenceProp);
|
||||
|
||||
singleFieldRect.y += lineHeightWithSpacing;
|
||||
EditorGUI.PropertyField(singleFieldRect, loopProp);
|
||||
@ -65,6 +74,19 @@ public class SpineAnimationStateDrawer : PropertyDrawer {
|
||||
singleFieldRect.y += lineHeightWithSpacing;
|
||||
EditorGUI.LabelField(singleFieldRect, "Mixing Settings", EditorStyles.boldLabel);
|
||||
|
||||
singleFieldRect.y += lineHeightWithSpacing;
|
||||
EditorGUI.PropertyField(singleFieldRect, customDurationProp);
|
||||
|
||||
bool greyOutCustomDurations = (!customDurationProp.hasMultipleDifferentValues &&
|
||||
customDurationProp.boolValue == false);
|
||||
using (new EditorGUI.DisabledGroupScope(greyOutCustomDurations)) {
|
||||
singleFieldRect.y += lineHeightWithSpacing;
|
||||
EditorGUI.PropertyField(singleFieldRect, useBlendDurationProp);
|
||||
|
||||
singleFieldRect.y += lineHeightWithSpacing;
|
||||
EditorGUI.PropertyField(singleFieldRect, mixDurationProp);
|
||||
}
|
||||
|
||||
singleFieldRect.y += lineHeightWithSpacing;
|
||||
EditorGUI.PropertyField(singleFieldRect, eventProp);
|
||||
|
||||
@ -74,5 +96,4 @@ public class SpineAnimationStateDrawer : PropertyDrawer {
|
||||
singleFieldRect.y += lineHeightWithSpacing;
|
||||
EditorGUI.PropertyField(singleFieldRect, drawOrderProp);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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 Spine.Unity.Playables;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
[CustomEditor(typeof(SpineSkeletonFlipClip))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SpineSkeletonFlipClipInspector : UnityEditor.Editor {
|
||||
|
||||
protected SerializedProperty templateProp = null;
|
||||
|
||||
public void OnEnable () {
|
||||
templateProp = serializedObject.FindProperty("template");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
serializedObject.Update();
|
||||
EditorGUILayout.PropertyField(templateProp);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6d7cdfbf1ccc0042b92586542f085a4
|
||||
timeCreated: 1570045635
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -44,8 +44,11 @@ namespace Spine.Unity.Playables {
|
||||
public AnimationReferenceAsset animationReference;
|
||||
public bool loop;
|
||||
|
||||
[Header("Mix Properties")]
|
||||
// Mix Properties
|
||||
public bool customDuration = false;
|
||||
public bool useBlendDuration = true;
|
||||
[SerializeField]
|
||||
private bool isInitialized = false; // required to read preferences values from editor side.
|
||||
public float mixDuration = 0.1f;
|
||||
|
||||
[Range(0, 1f)]
|
||||
|
||||
@ -37,13 +37,21 @@ namespace Spine.Unity.Playables {
|
||||
public class SpineAnimationStateClip : PlayableAsset, ITimelineClipAsset {
|
||||
public SpineAnimationStateBehaviour template = new SpineAnimationStateBehaviour();
|
||||
|
||||
public ClipCaps clipCaps { get { return ClipCaps.None; } }
|
||||
public ClipCaps clipCaps { get { return ClipCaps.Blending | ClipCaps.ClipIn | ClipCaps.SpeedMultiplier | (template.loop ? ClipCaps.Looping : 0); } }
|
||||
|
||||
public override Playable CreatePlayable (PlayableGraph graph, GameObject owner) {
|
||||
var playable = ScriptPlayable<SpineAnimationStateBehaviour>.Create(graph, template);
|
||||
playable.GetBehaviour();
|
||||
return playable;
|
||||
}
|
||||
|
||||
public override double duration {
|
||||
get {
|
||||
if (template.animationReference == null)
|
||||
return 0;
|
||||
return template.animationReference.Animation.Duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ namespace Spine.Unity.Playables {
|
||||
for (int i = 0; i < inputCount; i++) {
|
||||
float lastInputWeight = lastInputWeights[i];
|
||||
float inputWeight = playable.GetInputWeight(i);
|
||||
bool trackStarted = inputWeight > lastInputWeight;
|
||||
bool trackStarted = lastInputWeight == 0 && inputWeight > 0;
|
||||
lastInputWeights[i] = inputWeight;
|
||||
|
||||
if (trackStarted) {
|
||||
@ -84,9 +84,10 @@ namespace Spine.Unity.Playables {
|
||||
if (clipData.animationReference.Animation != null) {
|
||||
Spine.TrackEntry trackEntry = state.SetAnimation(trackIndex, clipData.animationReference.Animation, clipData.loop);
|
||||
|
||||
//trackEntry.TrackTime = (float)inputPlayable.GetTime(); // More accurate time-start?
|
||||
trackEntry.EventThreshold = clipData.eventThreshold;
|
||||
trackEntry.DrawOrderThreshold = clipData.drawOrderThreshold;
|
||||
trackEntry.TrackTime = (float)inputPlayable.GetTime() * (float)inputPlayable.GetSpeed();
|
||||
trackEntry.TimeScale = (float)inputPlayable.GetSpeed();
|
||||
trackEntry.AttachmentThreshold = clipData.attachmentThreshold;
|
||||
|
||||
if (clipData.customDuration)
|
||||
@ -111,15 +112,15 @@ namespace Spine.Unity.Playables {
|
||||
if (spineComponent == null) return;
|
||||
|
||||
int inputCount = playable.GetInputCount();
|
||||
int lastOneWeight = -1;
|
||||
int lastNonZeroWeightTrack = -1;
|
||||
|
||||
for (int i = 0; i < inputCount; i++) {
|
||||
float inputWeight = playable.GetInputWeight(i);
|
||||
if (inputWeight >= 1) lastOneWeight = i;
|
||||
if (inputWeight > 0) lastNonZeroWeightTrack = i;
|
||||
}
|
||||
|
||||
if (lastOneWeight != -1) {
|
||||
ScriptPlayable<SpineAnimationStateBehaviour> inputPlayableClip = (ScriptPlayable<SpineAnimationStateBehaviour>)playable.GetInput(lastOneWeight);
|
||||
if (lastNonZeroWeightTrack != -1) {
|
||||
ScriptPlayable<SpineAnimationStateBehaviour> inputPlayableClip = (ScriptPlayable<SpineAnimationStateBehaviour>)playable.GetInput(lastNonZeroWeightTrack);
|
||||
SpineAnimationStateBehaviour clipData = inputPlayableClip.GetBehaviour();
|
||||
|
||||
var skeleton = spineComponent.Skeleton;
|
||||
@ -133,16 +134,16 @@ namespace Spine.Unity.Playables {
|
||||
Animation fromAnimation = null;
|
||||
float fromClipTime = 0;
|
||||
bool fromClipLoop = false;
|
||||
if (lastOneWeight != 0 && inputCount > 1) {
|
||||
var fromClip = (ScriptPlayable<SpineAnimationStateBehaviour>)playable.GetInput(lastOneWeight - 1);
|
||||
if (lastNonZeroWeightTrack != 0 && inputCount > 1) {
|
||||
var fromClip = (ScriptPlayable<SpineAnimationStateBehaviour>)playable.GetInput(lastNonZeroWeightTrack - 1);
|
||||
var fromClipData = fromClip.GetBehaviour();
|
||||
fromAnimation = fromClipData.animationReference != null ? fromClipData.animationReference.Animation : null;
|
||||
fromClipTime = (float)fromClip.GetTime();
|
||||
fromClipTime = (float)fromClip.GetTime() * (float)fromClip.GetSpeed();
|
||||
fromClipLoop = fromClipData.loop;
|
||||
}
|
||||
|
||||
Animation toAnimation = clipData.animationReference != null ? clipData.animationReference.Animation : null;
|
||||
float toClipTime = (float)inputPlayableClip.GetTime();
|
||||
float toClipTime = (float)inputPlayableClip.GetTime() * (float)inputPlayableClip.GetSpeed();
|
||||
float mixDuration = clipData.mixDuration;
|
||||
|
||||
if (!clipData.customDuration && fromAnimation != null && toAnimation != null) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user