mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 09:16:01 +08:00
[unity] SkeletonRenderer components now provide an additional update mode Only Event Timelines at the Update When Invisible property. Added methods to AnimationState for proper behaviour during transitions. Closes #1815.
This commit is contained in:
parent
af9d807460
commit
3151c18b6c
@ -247,6 +247,7 @@
|
||||
* Added `BoundingBoxFollowerGraphic` component. This class is a counterpart of `BoundingBoxFollower` that can be used with `SkeletonGraphic`.
|
||||
* Added Inspector context menu functions `SkeletonRenderer - Add all BoundingBoxFollower GameObjects` and `SkeletonGraphic - Add all BoundingBoxFollowerGraphic GameObjects` that automatically generate bounding box follower GameObjects for every `BoundingBoxAttachment` for all skins of a skeleton.
|
||||
* `GetRemappedClone()` now provides an additional parameter `pivotShiftsMeshUVCoords` for `MeshAttachment` to prevent uv shifts at a non-central Sprite pivot. This parameter defaults to `true` to maintain previous behaviour.
|
||||
* `SkeletonRenderer` components now provide an additional update mode `Only Event Timelines` at the `Update When Invisible` property. This mode saves additional timeline updates compared to update mode `Everything Except Mesh`.
|
||||
|
||||
* **Changes of default values**
|
||||
* `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.MixNext` instead of `MixMode.MixAlways`.
|
||||
|
||||
@ -300,6 +300,43 @@ namespace Spine {
|
||||
return applied;
|
||||
}
|
||||
|
||||
/// <summary>Version of <see cref="Apply"/> only applying EventTimelines for lightweight off-screen updates.</summary>
|
||||
// Note: This method is not part of the libgdx reference implementation.
|
||||
public bool ApplyEventTimelinesOnly (Skeleton skeleton) {
|
||||
if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
|
||||
|
||||
var events = this.events;
|
||||
bool applied = false;
|
||||
var tracksItems = tracks.Items;
|
||||
for (int i = 0, n = tracks.Count; i < n; i++) {
|
||||
TrackEntry current = tracksItems[i];
|
||||
if (current == null || current.delay > 0) continue;
|
||||
applied = true;
|
||||
|
||||
// Apply mixing from entries first.
|
||||
if (current.mixingFrom != null)
|
||||
ApplyMixingFromEventTimelinesOnly(current, skeleton);
|
||||
|
||||
// Apply current entry.
|
||||
float animationLast = current.animationLast, animationTime = current.AnimationTime;
|
||||
int timelineCount = current.animation.timelines.Count;
|
||||
var timelines = current.animation.timelines;
|
||||
var timelinesItems = timelines.Items;
|
||||
for (int ii = 0; ii < timelineCount; ii++) {
|
||||
Timeline timeline = timelinesItems[ii];
|
||||
if (timeline is EventTimeline)
|
||||
timeline.Apply(skeleton, animationLast, animationTime, events, 1.0f, MixBlend.Setup, MixDirection.In);
|
||||
}
|
||||
QueueEvents(current, animationTime);
|
||||
events.Clear(false);
|
||||
current.nextAnimationLast = animationTime;
|
||||
current.nextTrackLast = current.trackTime;
|
||||
}
|
||||
|
||||
queue.Drain();
|
||||
return applied;
|
||||
}
|
||||
|
||||
private float ApplyMixingFrom (TrackEntry to, Skeleton skeleton, MixBlend blend) {
|
||||
TrackEntry from = to.mixingFrom;
|
||||
if (from.mixingFrom != null) ApplyMixingFrom(from, skeleton, blend);
|
||||
@ -386,6 +423,43 @@ namespace Spine {
|
||||
return mix;
|
||||
}
|
||||
|
||||
/// <summary>Version of <see cref="ApplyMixingFrom"/> only applying EventTimelines for lightweight off-screen updates.</summary>
|
||||
// Note: This method is not part of the libgdx reference implementation.
|
||||
private float ApplyMixingFromEventTimelinesOnly (TrackEntry to, Skeleton skeleton) {
|
||||
TrackEntry from = to.mixingFrom;
|
||||
if (from.mixingFrom != null) ApplyMixingFromEventTimelinesOnly(from, skeleton);
|
||||
|
||||
float mix;
|
||||
if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes.
|
||||
mix = 1;
|
||||
}
|
||||
else {
|
||||
mix = to.mixTime / to.mixDuration;
|
||||
if (mix > 1) mix = 1;
|
||||
}
|
||||
|
||||
var eventBuffer = mix < from.eventThreshold ? this.events : null;
|
||||
if (eventBuffer == null)
|
||||
return mix;
|
||||
|
||||
float animationLast = from.animationLast, animationTime = from.AnimationTime;
|
||||
var timelines = from.animation.timelines;
|
||||
int timelineCount = timelines.Count;
|
||||
var timelinesItems = timelines.Items;
|
||||
for (int i = 0; i < timelineCount; i++) {
|
||||
var timeline = timelinesItems[i];
|
||||
if (timeline is EventTimeline)
|
||||
timeline.Apply(skeleton, animationLast, animationTime, eventBuffer, 0, MixBlend.Setup, MixDirection.Out);
|
||||
}
|
||||
|
||||
if (to.mixDuration > 0) QueueEvents(from, animationTime);
|
||||
this.events.Clear(false);
|
||||
from.nextAnimationLast = animationTime;
|
||||
from.nextTrackLast = from.trackTime;
|
||||
|
||||
return mix;
|
||||
}
|
||||
|
||||
/// <summary> Applies the attachment timeline and sets <see cref="Slot.attachmentState"/>.</summary>
|
||||
/// <param name="attachments">False when: 1) the attachment timeline is mixing out, 2) mix < attachmentThreshold, and 3) the timeline
|
||||
/// is not the last timeline to set the slot's attachment. In that case the timeline is applied only so subsequent
|
||||
|
||||
@ -213,7 +213,10 @@ namespace Spine.Unity {
|
||||
if (_BeforeApply != null)
|
||||
_BeforeApply(this);
|
||||
|
||||
state.Apply(skeleton);
|
||||
if (updateMode != UpdateMode.OnlyEventTimelines)
|
||||
state.Apply(skeleton);
|
||||
else
|
||||
state.ApplyEventTimelinesOnly(skeleton);
|
||||
|
||||
if (_UpdateLocal != null)
|
||||
_UpdateLocal(this);
|
||||
|
||||
@ -62,7 +62,7 @@ namespace Spine.Unity {
|
||||
|
||||
/// <summary>Update mode to optionally limit updates to e.g. only apply animations but not update the mesh.</summary>
|
||||
public UpdateMode UpdateMode { get { return updateMode; } set { updateMode = value; } }
|
||||
[SerializeField] protected UpdateMode updateMode = UpdateMode.FullUpdate;
|
||||
protected UpdateMode updateMode = UpdateMode.FullUpdate;
|
||||
|
||||
/// <summary>Update mode used when the MeshRenderer becomes invisible
|
||||
/// (when <c>OnBecameInvisible()</c> is called). Update mode is automatically
|
||||
@ -263,7 +263,10 @@ namespace Spine.Unity {
|
||||
if (BeforeApply != null)
|
||||
BeforeApply(this);
|
||||
|
||||
state.Apply(skeleton);
|
||||
if (updateMode != UpdateMode.OnlyEventTimelines)
|
||||
state.Apply(skeleton);
|
||||
else
|
||||
state.ApplyEventTimelinesOnly(skeleton);
|
||||
|
||||
if (UpdateLocal != null)
|
||||
UpdateLocal(this);
|
||||
@ -283,7 +286,7 @@ namespace Spine.Unity {
|
||||
// instantiation can happen from Update() after this component, leading to a missing Update() call.
|
||||
if (!wasUpdatedAfterInit) Update(0);
|
||||
if (freeze) return;
|
||||
if (updateMode <= UpdateMode.EverythingExceptMesh) return;
|
||||
if (updateMode != UpdateMode.FullUpdate) return;
|
||||
|
||||
UpdateMesh();
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ namespace Spine.Unity {
|
||||
|
||||
/// <summary>Update mode to optionally limit updates to e.g. only apply animations but not update the mesh.</summary>
|
||||
public UpdateMode UpdateMode { get { return updateMode; } set { updateMode = value; } }
|
||||
[SerializeField] protected UpdateMode updateMode = UpdateMode.FullUpdate;
|
||||
protected UpdateMode updateMode = UpdateMode.FullUpdate;
|
||||
|
||||
/// <summary>Update mode used when the MeshRenderer becomes invisible
|
||||
/// (when <c>OnBecameInvisible()</c> is called). Update mode is automatically
|
||||
@ -381,7 +381,7 @@ namespace Spine.Unity {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (updateMode <= UpdateMode.EverythingExceptMesh) return;
|
||||
if (updateMode != UpdateMode.FullUpdate) return;
|
||||
|
||||
#if SPINE_OPTIONAL_RENDEROVERRIDE
|
||||
bool doMeshOverride = generateMeshOverride != null;
|
||||
|
||||
@ -31,8 +31,10 @@ namespace Spine.Unity {
|
||||
public enum UpdateMode {
|
||||
Nothing = 0,
|
||||
OnlyAnimationStatus,
|
||||
EverythingExceptMesh,
|
||||
FullUpdate
|
||||
OnlyEventTimelines = 4, // added as index 4 to keep scene behavior unchanged.
|
||||
EverythingExceptMesh = 2,
|
||||
FullUpdate,
|
||||
//Reserved 4 for OnlyEventTimelines
|
||||
};
|
||||
|
||||
public delegate void UpdateBonesDelegate (ISkeletonAnimation animated);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user