Initial commit: Client Doc docs Server Tools
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,535 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated September 24, 2021. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2021, 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.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE 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
|
||||
* THE SPINE RUNTIMES, 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
|
||||
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
#define PER_MATERIAL_PROPERTY_BLOCKS
|
||||
#endif
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
#define CONFIGURABLE_ENTER_PLAY_MODE
|
||||
#endif
|
||||
|
||||
#if !SPINE_DISABLE_THREADING
|
||||
#define USE_THREADED_ANIMATION_UPDATE
|
||||
#endif
|
||||
|
||||
#if !SPINE_AUTO_UPGRADE_COMPONENTS_OFF
|
||||
#define AUTO_UPGRADE_TO_43_COMPONENTS
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
[System.Serializable]
|
||||
public abstract class SkeletonAnimationBase : MonoBehaviour,
|
||||
ISkeletonAnimation, ISkeletonComponent, IHasSkeletonRenderer,
|
||||
ISkeletonRendererEvents, IHasModifyableSkeletonDataAsset, IUpgradable {
|
||||
|
||||
[SerializeField] protected UpdateTiming updateTiming = UpdateTiming.InUpdate;
|
||||
protected int frameOfLastUpdate = -1;
|
||||
protected ISkeletonRenderer skeletonRenderer;
|
||||
protected bool skipUpdate = false;
|
||||
|
||||
public UpdateTiming UpdateTiming {
|
||||
get { return updateTiming; }
|
||||
set {
|
||||
if (updateTiming == value) return;
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
if (Application.isPlaying && UsesThreadedAnimation && isUpdatedExternally) {
|
||||
SkeletonUpdateSystem system = SkeletonUpdateSystem.Instance;
|
||||
if (system) {
|
||||
// unregister from old update timing mode, register for new one.
|
||||
system.UnregisterFromUpdate(updateTiming, this);
|
||||
system.RegisterForUpdate(value, this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
updateTiming = value;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected bool requiresEditorUpdate = false;
|
||||
#endif
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
#region Threaded update system
|
||||
protected static int mainThreadID = -1;
|
||||
|
||||
protected static float externalDeltaTime = 0f;
|
||||
protected static float unscaledDeltaTime = 0f;
|
||||
|
||||
[SerializeField] protected SettingsTriState threadedAnimation = SettingsTriState.UseGlobalSetting;
|
||||
protected bool isUpdatedExternally = false;
|
||||
|
||||
public static float ExternalDeltaTime {
|
||||
get { return externalDeltaTime; }
|
||||
set { externalDeltaTime = value; }
|
||||
}
|
||||
public static float ExternalUnscaledDeltaTime {
|
||||
get { return unscaledDeltaTime; }
|
||||
set { unscaledDeltaTime = value; }
|
||||
}
|
||||
public virtual float UsedExternalDeltaTime { get { return ExternalDeltaTime; } }
|
||||
|
||||
public bool IsUpdatedExternally {
|
||||
get { return isUpdatedExternally; }
|
||||
set { isUpdatedExternally = value; }
|
||||
}
|
||||
|
||||
protected bool UsesThreadedAnimation {
|
||||
get { return threadedAnimation == SettingsTriState.Enable || RuntimeSettings.UseThreadedAnimation; }
|
||||
}
|
||||
|
||||
public SettingsTriState ThreadedAnimation {
|
||||
get { return threadedAnimation; }
|
||||
set {
|
||||
if (threadedAnimation == value) return;
|
||||
threadedAnimation = value;
|
||||
|
||||
SkeletonUpdateSystem system = SkeletonUpdateSystem.Instance;
|
||||
if (system) {
|
||||
if (threadedAnimation == SettingsTriState.Enable || RuntimeSettings.UseThreadedAnimation)
|
||||
system.RegisterForUpdate(updateTiming, this);
|
||||
else
|
||||
system.UnregisterFromUpdate(updateTiming, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#if UNITY_EDITOR
|
||||
static bool applicationIsPlaying = false;
|
||||
// ApplicationIsPlaying for threaded access. Unfortunately Application.isPlaying throws
|
||||
// when called from worker thread.
|
||||
public static bool ApplicationIsPlaying {
|
||||
get { return applicationIsPlaying; }
|
||||
set { applicationIsPlaying = value; }
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
protected bool UseThreading {
|
||||
get { return false; }
|
||||
set { }
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
public static bool ApplicationIsPlaying {
|
||||
get { return Application.isPlaying; }
|
||||
set { }
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#region Threading Asserts
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
protected void InitializeMainThreadID () {
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
if (mainThreadID == -1)
|
||||
mainThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
|
||||
#endif
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
private void AssertIsMainThread () {
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
if (System.Threading.Thread.CurrentThread.ManagedThreadId != mainThreadID)
|
||||
Debug.LogError("AssertIsMainThread failed: worker thread calling main thread code. Thread ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
|
||||
#endif
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional("UNITY_EDITOR")]
|
||||
private void AssertIsWorkerThread () {
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
if (System.Threading.Thread.CurrentThread.ManagedThreadId == mainThreadID)
|
||||
Debug.LogError("AssertIsWorkerThread failed: main thread calling worker thread code! Thread ID:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Interface Implementation
|
||||
public UnityEngine.MonoBehaviour Component { get { return this; } }
|
||||
|
||||
public ISkeletonRenderer Renderer {
|
||||
get {
|
||||
if (skeletonRenderer == null) {
|
||||
skeletonRenderer = this.GetComponent<ISkeletonRenderer>();
|
||||
#if UNITY_EDITOR && AUTO_UPGRADE_TO_43_COMPONENTS
|
||||
if (skeletonRenderer == null) {
|
||||
UpgradeTo43();
|
||||
skeletonRenderer = this.GetComponent<ISkeletonRenderer>();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return skeletonRenderer;
|
||||
}
|
||||
}
|
||||
public Skeleton Skeleton {
|
||||
get { return Renderer.Skeleton; }
|
||||
set { Renderer.Skeleton = value; }
|
||||
}
|
||||
public Skeleton skeleton {
|
||||
get { return Renderer.Skeleton; }
|
||||
set { Renderer.Skeleton = value; }
|
||||
}
|
||||
public SkeletonDataAsset SkeletonDataAsset {
|
||||
get { return Renderer.SkeletonDataAsset; }
|
||||
set { Renderer.SkeletonDataAsset = value; }
|
||||
}
|
||||
public SkeletonDataAsset skeletonDataAsset {
|
||||
get { return Renderer.SkeletonDataAsset; }
|
||||
set { Renderer.SkeletonDataAsset = value; }
|
||||
}
|
||||
|
||||
protected event SkeletonAnimationDelegate _BeforeUpdate, _BeforeApply, _OnAnimationRebuild;
|
||||
|
||||
/// <summary>OnAnimationRebuild is raised after the SkeletonAnimation component is successfully initialized.</summary>
|
||||
public event SkeletonAnimationDelegate OnAnimationRebuild { add { _OnAnimationRebuild += value; } remove { _OnAnimationRebuild -= value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before the animation state is updated.
|
||||
/// Use this callback when you want to change the skeleton state before animation state is updated.
|
||||
/// </summary>
|
||||
public event SkeletonAnimationDelegate BeforeUpdate { add { _BeforeUpdate += value; } remove { _BeforeUpdate -= value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before the animations are applied.
|
||||
/// Use this callback when you want to change the skeleton state before animations are applied on top.
|
||||
/// </summary>
|
||||
public event SkeletonAnimationDelegate BeforeApply { add { _BeforeApply += value; } remove { _BeforeApply -= value; } }
|
||||
|
||||
/// <summary>A compatibility wrapper for <see cref="SkeletonRenderer.UpdateLocal"/></summary>
|
||||
public event SkeletonRendererDelegate UpdateLocal { add { Renderer.UpdateLocal += value; } remove { Renderer.UpdateLocal -= value; } }
|
||||
/// <summary>A compatibility wrapper for <see cref="Renderer.UpdateWorld"/></summary>
|
||||
public event SkeletonRendererDelegate UpdateWorld { add { Renderer.UpdateWorld += value; } remove { Renderer.UpdateWorld -= value; } }
|
||||
/// <summary>A compatibility wrapper for <see cref="Renderer.UpdateComplete"/></summary>
|
||||
public event SkeletonRendererDelegate UpdateComplete { add { Renderer.UpdateComplete += value; } remove { Renderer.UpdateComplete -= value; } }
|
||||
/// <summary>A compatibility wrapper for <see cref="Renderer.OnRebuild"/></summary>
|
||||
public event SkeletonRendererDelegate OnRebuild { add { Renderer.OnRebuild += value; } remove { Renderer.OnRebuild -= value; } }
|
||||
/// <summary>A compatibility wrapper for <see cref="Renderer.OnMeshAndMaterialsUpdated"/></summary>
|
||||
public event SkeletonRendererDelegate OnMeshAndMaterialsUpdated { add { Renderer.OnMeshAndMaterialsUpdated += value; } remove { Renderer.OnMeshAndMaterialsUpdated -= value; } }
|
||||
|
||||
/// <summary>Update mode to optionally limit updates to e.g. only apply animations but not update the mesh.</summary>
|
||||
public UpdateMode UpdateMode { get { return Renderer.UpdateMode; } set { Renderer.UpdateMode = value; } }
|
||||
|
||||
public abstract bool IsValid { get; }
|
||||
#endregion
|
||||
|
||||
public virtual void Awake () {
|
||||
#if UNITY_EDITOR && AUTO_UPGRADE_TO_43_COMPONENTS
|
||||
UpgradeTo43();
|
||||
#endif
|
||||
InitializeMainThreadID();
|
||||
#if UNITY_EDITOR
|
||||
SkeletonAnimationBase.ApplicationIsPlaying = Application.isPlaying;
|
||||
#endif
|
||||
EnsureRendererEventsSubscribed();
|
||||
}
|
||||
|
||||
public void EnsureRendererEventsSubscribed () {
|
||||
Renderer.OnRebuild -= OnRendererRebuild;
|
||||
Renderer.OnRebuild += OnRendererRebuild;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR && AUTO_UPGRADE_TO_43_COMPONENTS
|
||||
// compatibility layer between 4.1 and 4.2, automatically transfer serialized attributes.
|
||||
public abstract void UpgradeTo43 ();
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the associated renderer component and subsequently this animation component.
|
||||
/// Creates the internal Spine objects and buffers.</summary>
|
||||
/// <param name="overwrite">If set to <c>true</c>, force overwrite an already initialized object.</param>
|
||||
public virtual void Initialize (bool overwrite, bool quiet = false, bool calledFromRendererCallback = false) {
|
||||
#if UNITY_EDITOR
|
||||
if (BuildUtilities.IsInSkeletonAssetBuildPreProcessing)
|
||||
return;
|
||||
#endif
|
||||
if (!calledFromRendererCallback) {
|
||||
if (skeletonRenderer == null)
|
||||
skeletonRenderer = this.GetComponent<ISkeletonRenderer>();
|
||||
if (!skeletonRenderer.IsValid || !this.IsValid || overwrite)
|
||||
skeletonRenderer.Initialize(overwrite, quiet);
|
||||
}
|
||||
if (this.IsValid && !overwrite)
|
||||
return;
|
||||
InitializeAnimationComponent();
|
||||
|
||||
if (_OnAnimationRebuild != null)
|
||||
_OnAnimationRebuild(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually initializes just this animation component without initializing the associated renderer component.
|
||||
/// The renderer component has to be initialized before calling this method, which happens automatically via
|
||||
/// renderer component Awake, or when needed earlier by calling <see cref="Initialize(bool, bool, bool)"/> on
|
||||
/// this animation component which initializes both components in the correct order.
|
||||
/// </summary>
|
||||
public virtual void InitializeAnimationComponent () {
|
||||
if (skeletonRenderer == null)
|
||||
skeletonRenderer = this.GetComponent<ISkeletonRenderer>();
|
||||
#if UNITY_EDITOR
|
||||
if (requiresEditorUpdate && skeletonRenderer != null && skeletonRenderer.Skeleton != null)
|
||||
skeletonRenderer.Skeleton.SetupPose();
|
||||
requiresEditorUpdate = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the previously generated mesh, resets the skeleton's pose, and clears all previously active animations.</summary>
|
||||
public void ClearState () {
|
||||
skeletonRenderer.ClearSkeletonState();
|
||||
ClearAnimationState();
|
||||
}
|
||||
|
||||
public virtual void ClearAnimationState () { }
|
||||
|
||||
public void OnEnable () {
|
||||
if (skeletonRenderer == null)
|
||||
skeletonRenderer = this.GetComponent<SkeletonRenderer>();
|
||||
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
if (Application.isPlaying && UsesThreadedAnimation && !isUpdatedExternally) {
|
||||
SkeletonUpdateSystem system = SkeletonUpdateSystem.Instance;
|
||||
if (system)
|
||||
system.RegisterForUpdate(updateTiming, this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
public void OnDisable () {
|
||||
if (Application.isPlaying && UsesThreadedAnimation) {
|
||||
SkeletonUpdateSystem system = SkeletonUpdateSystem.Instance;
|
||||
if (system)
|
||||
system.UnregisterFromUpdate(updateTiming, this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
protected void OnRendererRebuild (ISkeletonRenderer skeletonRenderer) {
|
||||
Initialize(overwrite: true, quiet: false, calledFromRendererCallback: true); //InitializeAnimationComponent();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected void OnValidate () {
|
||||
if (!Application.isPlaying) {
|
||||
Renderer.OnRebuild -= OnRendererRebuild;
|
||||
Renderer.OnRebuild += OnRendererRebuild;
|
||||
requiresEditorUpdate = true;
|
||||
} else if (Time.frameCount != 0) {
|
||||
// OnValidate is called once when starting play mode in the Editor, don't trigger re-init then.
|
||||
requiresEditorUpdate = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
protected virtual void Update () {
|
||||
#if UNITY_EDITOR
|
||||
if (requiresEditorUpdate)
|
||||
InitializeAnimationComponent();
|
||||
if (!ApplicationIsPlaying) {
|
||||
if (!IsValid)
|
||||
Initialize(false);
|
||||
Update(0f);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
if (isUpdatedExternally) return;
|
||||
#endif
|
||||
if (updateTiming != UpdateTiming.InUpdate) return;
|
||||
UpdateOncePerFrame(DeltaTime);
|
||||
}
|
||||
|
||||
protected virtual void FixedUpdate () {
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
if (isUpdatedExternally) return;
|
||||
#endif
|
||||
if (updateTiming != UpdateTiming.InFixedUpdate) return;
|
||||
UpdateOncePerFrame(DeltaTime);
|
||||
}
|
||||
|
||||
protected virtual void LateUpdate () {
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
if (isUpdatedExternally) return;
|
||||
#endif
|
||||
if (updateTiming != UpdateTiming.InLateUpdate) return;
|
||||
UpdateOncePerFrame(DeltaTime);
|
||||
}
|
||||
|
||||
/// <summary>Calls <see cref="Update()"/> if it has not yet been called this frame.</summary>
|
||||
public virtual void UpdateOncePerFrame (float deltaTime) {
|
||||
if (frameOfLastUpdate != Time.frameCount) {
|
||||
MainThreadBeforeUpdateInternal();
|
||||
UpdateInternal(deltaTime, Time.frameCount, calledFromOnlyMainThread: true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main thread update part preparing properties only accessible from main thread.
|
||||
/// To be followed by a potentially threaded call to <see cref="UpdateInternal"/>.
|
||||
/// </summary>
|
||||
public virtual void MainThreadBeforeUpdateInternal () {
|
||||
if (skeletonRenderer == null || !skeletonRenderer.IsValid || skeletonRenderer.Freeze || !this.IsValid
|
||||
|| skeletonRenderer.UpdateMode < UpdateMode.OnlyAnimationStatus) {
|
||||
skipUpdate = true;
|
||||
return;
|
||||
}
|
||||
skipUpdate = false;
|
||||
skeletonRenderer.GatherTransformMovementForPhysics();
|
||||
if (_BeforeUpdate != null)
|
||||
_BeforeUpdate(this);
|
||||
}
|
||||
|
||||
public virtual void MainThreadAfterUpdateInternal () { }
|
||||
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
public virtual void UpdateExternal (int currentFrameCount, bool calledFromOnlyMainThread = true) {
|
||||
UpdateInternal(UsedExternalDeltaTime, currentFrameCount, calledFromOnlyMainThread);
|
||||
}
|
||||
#endif
|
||||
public virtual void UpdateInternal (float deltaTime, int currentFrameCount, bool calledFromOnlyMainThread = true) {
|
||||
if (skipUpdate)
|
||||
return;
|
||||
|
||||
frameOfLastUpdate = currentFrameCount;
|
||||
UpdateAnimationStatus(deltaTime);
|
||||
skeletonRenderer.ApplyTransformMovementToPhysics();
|
||||
|
||||
if (skeletonRenderer.UpdateMode == UpdateMode.OnlyAnimationStatus)
|
||||
return;
|
||||
|
||||
ApplyAnimation(calledFromOnlyMainThread);
|
||||
}
|
||||
|
||||
#if USE_THREADED_ANIMATION_UPDATE
|
||||
/// <summary>Progresses the AnimationState according to the given deltaTime, and applies it to the Skeleton.
|
||||
/// Use Time.deltaTime to update manually. Use deltaTime 0 to update without progressing the time.</summary>
|
||||
public virtual CoroutineIterator UpdateInternalSplit (CoroutineIterator coroutineIterator,
|
||||
int currentFrameCount) {
|
||||
|
||||
if (coroutineIterator.IsDone)
|
||||
return CoroutineIterator.Done;
|
||||
|
||||
const int StateBits = 1;
|
||||
const uint StateMask = (1 << StateBits) - 1;
|
||||
switch (coroutineIterator.State(StateMask)) {
|
||||
case 0:
|
||||
if (skipUpdate)
|
||||
return CoroutineIterator.Done;
|
||||
frameOfLastUpdate = currentFrameCount;
|
||||
UpdateAnimationStatus(UsedExternalDeltaTime);
|
||||
skeletonRenderer.ApplyTransformMovementToPhysics();
|
||||
|
||||
if (skeletonRenderer.UpdateMode == UpdateMode.OnlyAnimationStatus)
|
||||
return CoroutineIterator.Done;
|
||||
goto case 1;
|
||||
case 1:
|
||||
return ApplyAnimationSplit(coroutineIterator.ToNestedCall(StateBits))
|
||||
.FromNestedCall(1, StateBits);
|
||||
default:
|
||||
Debug.LogError(string.Format(
|
||||
"Internal coroutine logic error: SkeletonAnimationBase.UpdateInternalSplit state was {0}.",
|
||||
coroutineIterator.State(StateMask)), this);
|
||||
return CoroutineIterator.Done;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>Progresses the AnimationState according to the given deltaTime, and applies it to the Skeleton.
|
||||
/// Use Time.deltaTime to update manually. Use deltaTime 0 to update without progressing the time.</summary>
|
||||
public virtual void Update (float deltaTime) {
|
||||
MainThreadBeforeUpdateInternal();
|
||||
UpdateInternal(deltaTime, Time.frameCount, calledFromOnlyMainThread: true);
|
||||
}
|
||||
|
||||
public virtual void ApplyAnimation (bool calledFromMainThread = true) {
|
||||
if (_BeforeApply != null)
|
||||
_BeforeApply(this);
|
||||
|
||||
ApplyStateToSkeleton(calledFromMainThread);
|
||||
skeletonRenderer.AfterAnimationApplied(calledFromMainThread);
|
||||
}
|
||||
|
||||
public virtual CoroutineIterator ApplyAnimationSplit (CoroutineIterator coroutineIterator) {
|
||||
if (coroutineIterator.IsDone)
|
||||
return CoroutineIterator.Done;
|
||||
|
||||
const int StateBits = 2;
|
||||
const uint StateMask = (1 << StateBits) - 1;
|
||||
switch (coroutineIterator.State(StateMask)) {
|
||||
case 0:
|
||||
if (_BeforeApply != null) {
|
||||
AssertIsWorkerThread();
|
||||
return coroutineIterator.YieldReturnAtState(1, StateMask);
|
||||
} else {
|
||||
goto case 2;
|
||||
}
|
||||
case 1:
|
||||
AssertIsMainThread();
|
||||
_BeforeApply(this);
|
||||
return coroutineIterator.YieldReturnAtState(2, StateMask);
|
||||
case 2:
|
||||
AssertIsWorkerThread();
|
||||
ApplyStateToSkeleton(calledFromMainThread: false);
|
||||
goto case 3;
|
||||
case 3:
|
||||
return skeletonRenderer.AfterAnimationAppliedSplit(coroutineIterator.ToNestedCall(StateBits))
|
||||
.FromNestedCall(3, StateBits);
|
||||
default:
|
||||
Debug.LogError(string.Format(
|
||||
"Internal coroutine logic error: SkeletonAnimationBase.ApplyAnimationSplit state was {0}.",
|
||||
coroutineIterator.State(StateMask)), this);
|
||||
return CoroutineIterator.Done;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnBecameVisibleFromMode (UpdateMode previousUpdateMode) {
|
||||
// OnBecameVisible is called after Update and LateUpdate(),
|
||||
// so update if previousUpdateMode didn't already update this frame.
|
||||
if (previousUpdateMode != UpdateMode.FullUpdate &&
|
||||
previousUpdateMode != UpdateMode.EverythingExceptMesh)
|
||||
Update(0);
|
||||
}
|
||||
|
||||
protected virtual float DeltaTime { get { return Time.deltaTime; } }
|
||||
|
||||
protected abstract void UpdateAnimationStatus (float deltaTime);
|
||||
protected abstract void ApplyStateToSkeleton (bool calledFromMainThread = true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user