mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[cpp] Port AnimationState additive/hold rework, Skin placeholder rename, timeline API changes from spine-libgdx
- Replace MixBlend/MixDirection with bool fromSetup/add/out in all timeline apply() signatures - Remove MixBlend.h and MixDirection.h (no longer used) - Add Timeline::_additive and _instant fields - Replace TrackEntry holdPrevious/interruptAlpha/mixBlend with additive/keepHold - Rewrite AnimationState hold system with bitmask (Subsequent/First/Hold/HoldFirst) - Rewrite applyMixingFrom alpha computation - Rename Skin::AttachmentMap::Entry::_name to _placeholderName - Fix SkeletonBinary::readLong() sign extension bug truncating 64-bit hashes - Fix SkeletonSerializer sequence and bones null/empty parity with Java - Add transition frame testing to HeadlessTest - Port all doc updates from spine-libgdx
This commit is contained in:
parent
41b743e73d
commit
7b0bf128ff
36
CHANGELOG.md
36
CHANGELOG.md
@ -4,6 +4,15 @@
|
|||||||
|
|
||||||
- **Additions**
|
- **Additions**
|
||||||
- Added `spine_slider` and `spine_slider_data` types for slider constraints
|
- Added `spine_slider` and `spine_slider_data` types for slider constraints
|
||||||
|
- Regenerated C bindings for the AnimationState additive/hold rework and Skin placeholder name rename in spine-cpp.
|
||||||
|
|
||||||
|
- **Breaking changes**
|
||||||
|
- `spine_track_entry_get_mix_blend()` / `spine_track_entry_set_mix_blend()` removed. Use `spine_track_entry_get_additive()` / `spine_track_entry_set_additive()` instead.
|
||||||
|
- `spine_track_entry_get_hold_previous()` / `spine_track_entry_set_hold_previous()` removed.
|
||||||
|
- `spine_skin_entry_get_name()` renamed to `spine_skin_entry_get_placeholder_name()`.
|
||||||
|
- Timeline `apply()` signature changed: `spine_mix_blend` and `spine_mix_direction` parameters replaced with `bool fromSetup, bool add, bool out`.
|
||||||
|
- `spine_animation_apply()` signature changed to match.
|
||||||
|
- `spine_curve_timeline1_get_absolute_value()`, `spine_curve_timeline1_get_relative_value()`, `spine_curve_timeline1_get_scale_value()` signatures changed.
|
||||||
- Added `spine_slider_timeline` and `spine_slider_mix_timeline` for animating sliders
|
- Added `spine_slider_timeline` and `spine_slider_mix_timeline` for animating sliders
|
||||||
- Added new pose system with `spine_bone_local`, `spine_bone_pose`, and related types
|
- Added new pose system with `spine_bone_local`, `spine_bone_pose`, and related types
|
||||||
- Added `spine_pose`, `spine_posed`, and `spine_posed_active` base types
|
- Added `spine_pose`, `spine_posed`, and `spine_posed_active` base types
|
||||||
@ -77,11 +86,23 @@
|
|||||||
- Added `HasRendererObject` interface for attachments with renderer-specific data
|
- Added `HasRendererObject` interface for attachments with renderer-specific data
|
||||||
- Ported the latest parser fixes from spine-libgdx, including the 4.3 path constraint flag fix and the weighted mesh binary vertex allocation/count fix.
|
- Ported the latest parser fixes from spine-libgdx, including the 4.3 path constraint flag fix and the weighted mesh binary vertex allocation/count fix.
|
||||||
- Ported the latest additive timeline updates and alpha/RGB timeline flicker fixes from spine-libgdx.
|
- Ported the latest additive timeline updates and alpha/RGB timeline flicker fixes from spine-libgdx.
|
||||||
|
- Ported the AnimationState additive/hold rework from spine-libgdx. `MixBlend` and `MixDirection` are no longer used by timelines. The new system uses `bool fromSetup, bool add, bool out` parameters and a bitmask-based hold system that replaces `holdPrevious` and `interruptAlpha`.
|
||||||
|
- Added `Timeline::getAdditive()` and `Timeline::getInstant()` to query timeline blending capabilities.
|
||||||
|
- Added `TrackEntry::getAdditive()` / `TrackEntry::setAdditive()` to control additive blending per track entry.
|
||||||
|
- Ported the Skin placeholder name rename from spine-libgdx. `Skin::AttachmentMap::Entry::_name` renamed to `_placeholderName`.
|
||||||
|
- Fixed `SkeletonBinary::readLong()` sign extension bug that truncated 64-bit hash values to 32 bits.
|
||||||
- Ported the sequence attachment refactor from spine-libgdx. `Sequence` now precomputes per-frame regions, UVs, and region offsets, and `RegionAttachment` / `MeshAttachment` now mirror the libgdx implementation.
|
- Ported the sequence attachment refactor from spine-libgdx. `Sequence` now precomputes per-frame regions, UVs, and region offsets, and `RegionAttachment` / `MeshAttachment` now mirror the libgdx implementation.
|
||||||
|
|
||||||
- **Breaking changes**
|
- **Breaking changes**
|
||||||
- Headers reorganized from `spine-cpp/spine-cpp/include/spine/` to `spine-cpp/include/spine/`
|
- Headers reorganized from `spine-cpp/spine-cpp/include/spine/` to `spine-cpp/include/spine/`
|
||||||
- Timeline `apply()` methods now take an additional `appliedPose` parameter
|
- Timeline `apply()` signature changed: `MixBlend blend, MixDirection direction` replaced with `bool fromSetup, bool add, bool out`. All timeline subclasses updated.
|
||||||
|
- `Animation::apply()` signature changed to match the new timeline parameters.
|
||||||
|
- `CurveTimeline1::getRelativeValue()`, `getAbsoluteValue()`, and `getScaleValue()` signatures changed from `MixBlend`/`MixDirection` to `bool fromSetup, bool add, bool out`.
|
||||||
|
- `TrackEntry::getHoldPrevious()` / `setHoldPrevious()` removed. Use `TrackEntry::getAdditive()` / `setAdditive()` instead for additive blending.
|
||||||
|
- `TrackEntry::getMixBlend()` / `setMixBlend()` removed.
|
||||||
|
- `TrackEntry::_interruptAlpha` removed.
|
||||||
|
- `Skin::AttachmentMap::Entry::_name` renamed to `_placeholderName`. All `Skin` methods use `placeholderName` parameter names instead of `name`/`attachmentName`.
|
||||||
|
- `AnimationState` hold constants changed: `HoldSubsequent` and `HoldMix` removed, replaced with bitmask system (`Subsequent=0, First=1, Hold=2, HoldFirst=3`).
|
||||||
- `Bone` now extends `PosedActive` with separate pose, constrained, and applied states
|
- `Bone` now extends `PosedActive` with separate pose, constrained, and applied states
|
||||||
- Renamed timeline constraint index methods to use unified `getConstraintIndex()`
|
- Renamed timeline constraint index methods to use unified `getConstraintIndex()`
|
||||||
- Changed timeline class hierarchy with new base classes `BoneTimeline`, `SlotCurveTimeline`, and `ConstraintTimeline`
|
- Changed timeline class hierarchy with new base classes `BoneTimeline`, `SlotCurveTimeline`, and `ConstraintTimeline`
|
||||||
@ -598,6 +619,19 @@
|
|||||||
|
|
||||||
- **Additions**
|
- **Additions**
|
||||||
- Added `Slider` and `SliderData` classes for slider constraints
|
- Added `Slider` and `SliderData` classes for slider constraints
|
||||||
|
- Reworked AnimationState hold system. Replaced `MixBlend`/`MixDirection` in timeline `apply()` with `boolean fromSetup, boolean add, boolean out`. The new bitmask-based hold system prevents dipping during crossfades without requiring `holdPrevious`.
|
||||||
|
- Added `Timeline.getAdditive()` and `Timeline.getInstant()` to query timeline blending capabilities.
|
||||||
|
- Added `TrackEntry.getAdditive()` / `TrackEntry.setAdditive()` for additive blending per track entry.
|
||||||
|
- Renamed `Skin.SkinEntry.getName()` to `getPlaceholderName()`. All `Skin` methods now use `placeholderName` parameter names.
|
||||||
|
|
||||||
|
- **Breaking changes (since previous 4.3 beta)**
|
||||||
|
- `TrackEntry.getHoldPrevious()` / `setHoldPrevious()` removed.
|
||||||
|
- `TrackEntry.getMixBlend()` / `setMixBlend()` removed. Use `TrackEntry.getAdditive()` / `setAdditive()` for additive blending.
|
||||||
|
- `MixBlend` and `MixDirection` enums removed from `Animation`.
|
||||||
|
- Timeline `apply()` signature changed: `MixBlend blend, MixDirection direction` replaced with `boolean fromSetup, boolean add, boolean out`.
|
||||||
|
- `Animation.apply()` signature changed to match.
|
||||||
|
- `CurveTimeline1.getRelativeValue()`, `getAbsoluteValue()`, `getScaleValue()` signatures changed.
|
||||||
|
- `Skin.SkinEntry.getName()` renamed to `getPlaceholderName()`.
|
||||||
- Added `SliderTimeline` and `SliderMixTimeline` for animating sliders
|
- Added `SliderTimeline` and `SliderMixTimeline` for animating sliders
|
||||||
- Added new pose system with `BoneLocal`, `BonePose`, and related classes
|
- Added new pose system with `BoneLocal`, `BonePose`, and related classes
|
||||||
- Added `Pose`, `Posed`, and `PosedActive` base classes for unified pose management
|
- Added `Pose`, `Posed`, and `PosedActive` base classes for unified pose management
|
||||||
|
|||||||
@ -32,8 +32,6 @@
|
|||||||
|
|
||||||
#include <spine/Array.h>
|
#include <spine/Array.h>
|
||||||
#include <spine/HashMap.h>
|
#include <spine/HashMap.h>
|
||||||
#include <spine/MixBlend.h>
|
|
||||||
#include <spine/MixDirection.h>
|
|
||||||
#include <spine/SpineObject.h>
|
#include <spine/SpineObject.h>
|
||||||
#include <spine/SpineString.h>
|
#include <spine/SpineString.h>
|
||||||
#include <spine/Property.h>
|
#include <spine/Property.h>
|
||||||
@ -122,25 +120,28 @@ namespace spine {
|
|||||||
/// Applies the animation's timelines to the specified skeleton.
|
/// Applies the animation's timelines to the specified skeleton.
|
||||||
///
|
///
|
||||||
/// See Timeline::apply().
|
/// See Timeline::apply().
|
||||||
/// @param skeleton The skeleton the animation is being applied to. This provides access to the bones, slots, and other skeleton
|
/// @param skeleton The skeleton the animation is applied to. This provides access to the bones, slots, and other skeleton
|
||||||
/// components the timelines may change.
|
/// components the timelines may change.
|
||||||
/// @param lastTime The last time in seconds this animation was applied. Some timelines trigger only at specific times rather
|
/// @param lastTime The last time in seconds this animation was applied. Some timelines trigger only at discrete times, in
|
||||||
/// than every frame. Pass -1 the first time an animation is applied to ensure frame 0 is triggered.
|
/// which case all keys are triggered between lastTime (exclusive) and time (inclusive). Pass -1 the first time an
|
||||||
/// @param time The time in seconds the skeleton is being posed for. Most timelines find the frame before and the frame after
|
/// animation is applied to ensure frame 0 is triggered.
|
||||||
/// this time and interpolate between the frame values. If beyond the getDuration() and loop is
|
/// @param time The time in seconds the skeleton is being posed for. Timelines find the frame before and after this time and
|
||||||
/// true then the animation will repeat, else the last frame will be applied.
|
/// interpolate between the frame values.
|
||||||
/// @param loop If true, the animation repeats after the getDuration().
|
/// @param loop True if time beyond the getDuration() repeats the animation, else the last frame is used.
|
||||||
/// @param events If any events are fired, they are added to this list. Can be null to ignore fired events or if no timelines
|
/// @param events If any events are fired, they are added to this list. Can be NULL to ignore fired events or if no timelines
|
||||||
/// fire events.
|
/// fire events.
|
||||||
/// @param alpha 0 applies the current or setup values (depending on blend). 1 applies the timeline values. Between
|
/// @param alpha 0 applies setup or current values (depending on fromSetup), 1 uses timeline values, and intermediate values
|
||||||
/// 0 and 1 applies values between the current or setup values and the timeline values. By adjusting
|
/// interpolate between them. Adjusting alpha over time can mix an animation in or out.
|
||||||
/// alpha over time, an animation can be mixed in or out. alpha can also be useful to apply
|
/// @param fromSetup If true, alpha transitions between setup and timeline values, setup values are used before the first
|
||||||
/// animations on top of each other (layering).
|
/// frame (current values are not used). If false, alpha transitions between current and timeline values, no change
|
||||||
/// @param blend Controls how mixing is applied when alpha < 1.
|
/// is made before the first frame.
|
||||||
/// @param direction Indicates whether the timelines are mixing in or out. Used by timelines which perform instant transitions,
|
/// @param add If true, for timelines that support it, their values are added to the setup or current values (depending on
|
||||||
/// such as DrawOrderTimeline or AttachmentTimeline.
|
/// fromSetup).
|
||||||
void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Array<Event *> *events, float alpha, MixBlend blend,
|
/// @param out True when the animation is mixing out, else it is mixing in. Used by timelines that perform instant
|
||||||
MixDirection direction, bool appliedPose);
|
/// transitions.
|
||||||
|
/// @param appliedPose True to modify the applied pose, else the pose is modified.
|
||||||
|
void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
|
bool appliedPose);
|
||||||
|
|
||||||
/// The animation's name, which is unique across all animations in the skeleton.
|
/// The animation's name, which is unique across all animations in the skeleton.
|
||||||
const String &getName();
|
const String &getName();
|
||||||
|
|||||||
@ -33,7 +33,6 @@
|
|||||||
#include <spine/Array.h>
|
#include <spine/Array.h>
|
||||||
#include <spine/Pool.h>
|
#include <spine/Pool.h>
|
||||||
#include <spine/Property.h>
|
#include <spine/Property.h>
|
||||||
#include <spine/MixBlend.h>
|
|
||||||
#include <spine/SpineObject.h>
|
#include <spine/SpineObject.h>
|
||||||
#include <spine/SpineString.h>
|
#include <spine/SpineString.h>
|
||||||
#include <spine/HasRendererObject.h>
|
#include <spine/HasRendererObject.h>
|
||||||
@ -116,20 +115,11 @@ namespace spine {
|
|||||||
|
|
||||||
void setLoop(bool inValue);
|
void setLoop(bool inValue);
|
||||||
|
|
||||||
/// If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead
|
/// When true, timelines in this animation that support additive have their values added to the setup or current pose values
|
||||||
/// of being mixed out.
|
/// instead of replacing them. Additive can be set for a new track entry only before AnimationState::apply() is next called.
|
||||||
///
|
bool getAdditive();
|
||||||
/// When mixing between animations that key the same property, if a lower track also keys that property then the value will
|
|
||||||
/// briefly dip toward the lower track value during the mix. This happens because the first animation mixes from 100% to 0%
|
|
||||||
/// while the second animation mixes from 0% to 100%. Setting holdPrevious to true applies the first animation
|
|
||||||
/// at 100% during the mix so the lower track value is overwritten. Such dipping does not occur on the lowest track which
|
|
||||||
/// keys the property, only when a higher track also keys the property.
|
|
||||||
///
|
|
||||||
/// Snapping will occur if holdPrevious is true and this animation does not key all the same properties as the
|
|
||||||
/// previous animation.
|
|
||||||
bool getHoldPrevious();
|
|
||||||
|
|
||||||
void setHoldPrevious(bool inValue);
|
void setAdditive(bool inValue);
|
||||||
|
|
||||||
bool getReverse();
|
bool getReverse();
|
||||||
|
|
||||||
@ -285,16 +275,12 @@ namespace spine {
|
|||||||
/// entry is looping, its next loop completion is used instead of its duration.
|
/// entry is looping, its next loop completion is used instead of its duration.
|
||||||
void setMixDuration(float mixDuration, float delay);
|
void setMixDuration(float mixDuration, float delay);
|
||||||
|
|
||||||
MixBlend getMixBlend();
|
/// The track entry for the previous animation when mixing to this animation, or NULL if no mixing is currently occurring.
|
||||||
|
/// When mixing from multiple animations, MixingFrom makes up a doubly linked list with MixingTo.
|
||||||
void setMixBlend(MixBlend blend);
|
|
||||||
|
|
||||||
/// The track entry for the previous animation when mixing from the previous animation to this animation, or NULL if no
|
|
||||||
/// mixing is currently occuring. When mixing from multiple animations, MixingFrom makes up a double linked list with MixingTo.
|
|
||||||
TrackEntry *getMixingFrom();
|
TrackEntry *getMixingFrom();
|
||||||
|
|
||||||
/// The track entry for the next animation when mixing from this animation, or NULL if no mixing is currently occuring.
|
/// The track entry for the next animation when mixing from this animation, or NULL if no mixing is currently occurring.
|
||||||
/// When mixing from multiple animations, MixingTo makes up a double linked list with MixingFrom.
|
/// When mixing to multiple animations, MixingTo makes up a doubly linked list with MixingFrom.
|
||||||
TrackEntry *getMixingTo();
|
TrackEntry *getMixingTo();
|
||||||
|
|
||||||
/// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the
|
/// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the
|
||||||
@ -347,12 +333,11 @@ namespace spine {
|
|||||||
TrackEntry *_mixingTo;
|
TrackEntry *_mixingTo;
|
||||||
int _trackIndex;
|
int _trackIndex;
|
||||||
|
|
||||||
bool _loop, _holdPrevious, _reverse, _shortestRotation;
|
bool _loop, _additive, _reverse, _shortestRotation, _keepHold;
|
||||||
float _eventThreshold, _mixAttachmentThreshold, _alphaAttachmentThreshold, _mixDrawOrderThreshold;
|
float _eventThreshold, _mixAttachmentThreshold, _alphaAttachmentThreshold, _mixDrawOrderThreshold;
|
||||||
float _animationStart, _animationEnd, _animationLast, _nextAnimationLast;
|
float _animationStart, _animationEnd, _animationLast, _nextAnimationLast;
|
||||||
float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale;
|
float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale;
|
||||||
float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha;
|
float _alpha, _mixTime, _mixDuration, _totalAlpha;
|
||||||
MixBlend _mixBlend;
|
|
||||||
Array<int> _timelineMode;
|
Array<int> _timelineMode;
|
||||||
Array<TrackEntry *> _timelineHoldMix;
|
Array<TrackEntry *> _timelineHoldMix;
|
||||||
Array<float> _timelinesRotation;
|
Array<float> _timelinesRotation;
|
||||||
@ -551,9 +536,8 @@ namespace spine {
|
|||||||
private:
|
private:
|
||||||
static const int Subsequent = 0;
|
static const int Subsequent = 0;
|
||||||
static const int First = 1;
|
static const int First = 1;
|
||||||
static const int HoldSubsequent = 2;
|
static const int Hold = 2;
|
||||||
static const int HoldFirst = 3;
|
static const int HoldFirst = 3;
|
||||||
static const int HoldMix = 4;
|
|
||||||
|
|
||||||
static const int Setup = 1;
|
static const int Setup = 1;
|
||||||
static const int Current = 2;
|
static const int Current = 2;
|
||||||
@ -584,14 +568,14 @@ namespace spine {
|
|||||||
|
|
||||||
/// Applies the rotate timeline, mixing with the current pose while keeping the same rotation direction chosen as the shortest
|
/// Applies the rotate timeline, mixing with the current pose while keeping the same rotation direction chosen as the shortest
|
||||||
/// the first time the mixing was applied.
|
/// the first time the mixing was applied.
|
||||||
static void applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, MixBlend pose,
|
static void applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, bool fromSetup,
|
||||||
Array<float> &timelinesRotation, size_t i, bool firstFrame);
|
Array<float> &timelinesRotation, size_t i, bool firstFrame);
|
||||||
|
|
||||||
/// Applies the attachment timeline and sets Slot::attachmentState.
|
/// Applies the attachment timeline and sets Slot::attachmentState.
|
||||||
/// @param attachments False when: 1) the attachment timeline is mixing out, 2) mix < attachmentThreshold, and 3) the timeline
|
/// @param 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
|
/// is not the last timeline to set the slot's attachment. In that case the timeline is applied only so subsequent
|
||||||
/// timelines see any deform.
|
/// timelines see any deform.
|
||||||
void applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float animationTime, MixBlend pose, bool out,
|
void applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float animationTime, bool fromSetup, bool out,
|
||||||
bool attachments);
|
bool attachments);
|
||||||
|
|
||||||
/// Returns true when all mixing from entries are complete.
|
/// Returns true when all mixing from entries are complete.
|
||||||
|
|||||||
@ -41,7 +41,7 @@ namespace spine {
|
|||||||
|
|
||||||
class Animation;
|
class Animation;
|
||||||
|
|
||||||
/// Stores mix (crossfade) durations to be applied when AnimationState animations are changed.
|
/// Stores mix (crossfade) durations to be applied when AnimationState animations are changed on the same track.
|
||||||
class SP_API AnimationStateData : public SpineObject {
|
class SP_API AnimationStateData : public SpineObject {
|
||||||
friend class AnimationState;
|
friend class AnimationState;
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ namespace spine {
|
|||||||
/// See TrackEntry.MixDuration.
|
/// See TrackEntry.MixDuration.
|
||||||
void setMix(Animation &from, Animation &to, float duration);
|
void setMix(Animation &from, Animation &to, float duration);
|
||||||
|
|
||||||
/// The mix duration to use when changing from the specified animation to the other,
|
/// Returns the mix duration to use when changing from the specified animation to the other on the same track,
|
||||||
/// or the DefaultMix if no mix duration has been set.
|
/// or the DefaultMix if no mix duration has been set.
|
||||||
float getMix(Animation &from, Animation &to);
|
float getMix(Animation &from, Animation &to);
|
||||||
|
|
||||||
|
|||||||
@ -33,8 +33,6 @@
|
|||||||
#include <spine/Timeline.h>
|
#include <spine/Timeline.h>
|
||||||
#include <spine/SpineObject.h>
|
#include <spine/SpineObject.h>
|
||||||
#include <spine/Array.h>
|
#include <spine/Array.h>
|
||||||
#include <spine/MixBlend.h>
|
|
||||||
#include <spine/MixDirection.h>
|
|
||||||
#include <spine/SpineString.h>
|
#include <spine/SpineString.h>
|
||||||
#include <spine/SlotTimeline.h>
|
#include <spine/SlotTimeline.h>
|
||||||
|
|
||||||
@ -60,8 +58,8 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~AttachmentTimeline();
|
virtual ~AttachmentTimeline();
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
/// Sets the time and attachment name for the specified frame.
|
/// Sets the time and attachment name for the specified frame.
|
||||||
/// @param frame Between 0 and frameCount, inclusive.
|
/// @param frame Between 0 and frameCount, inclusive.
|
||||||
|
|||||||
@ -38,11 +38,12 @@
|
|||||||
#include <spine/Array.h>
|
#include <spine/Array.h>
|
||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
/// The current pose for a bone, before constraints are applied.
|
/// A bone has a number of poses:
|
||||||
///
|
/// - BoneData::getSetupPose(): The setup pose.
|
||||||
/// A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a
|
/// - getPose(): The local pose. Set by animations and app code.
|
||||||
/// local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a
|
/// - getAppliedPose(): The applied local pose. This is the local pose modified by constraints and app code.
|
||||||
/// constraint or application code modifies the world transform after it was computed from the local transform.
|
/// - The world transform on the applied pose, computed by Skeleton::updateWorldTransform(Physics) and
|
||||||
|
/// BonePose::updateWorldTransform(Skeleton).
|
||||||
class SP_API Bone : public PosedGeneric<BoneData, BoneLocal, BonePose>, public PosedActive, public Update {
|
class SP_API Bone : public PosedGeneric<BoneData, BoneLocal, BonePose>, public PosedActive, public Update {
|
||||||
friend class AnimationState;
|
friend class AnimationState;
|
||||||
friend class RotateTimeline;
|
friend class RotateTimeline;
|
||||||
|
|||||||
@ -69,10 +69,10 @@ namespace spine {
|
|||||||
public:
|
public:
|
||||||
BoneData(int index, const String &name, BoneData *parent = NULL);
|
BoneData(int index, const String &name, BoneData *parent = NULL);
|
||||||
|
|
||||||
/// The index of the bone in Skeleton.Bones
|
/// The Skeleton::getBones() index.
|
||||||
int getIndex();
|
int getIndex();
|
||||||
|
|
||||||
/// May be NULL.
|
/// The parent bone, or NULL if this bone is the root.
|
||||||
BoneData *getParent();
|
BoneData *getParent();
|
||||||
|
|
||||||
float getLength();
|
float getLength();
|
||||||
@ -81,6 +81,7 @@ namespace spine {
|
|||||||
|
|
||||||
Color &getColor();
|
Color &getColor();
|
||||||
|
|
||||||
|
/// The bone icon name as it was in Spine, or empty if nonessential data was not exported.
|
||||||
const String &getIcon();
|
const String &getIcon();
|
||||||
|
|
||||||
void setIcon(const String &icon);
|
void setIcon(const String &icon);
|
||||||
|
|||||||
@ -38,8 +38,15 @@ namespace spine {
|
|||||||
class Bone;
|
class Bone;
|
||||||
class Skeleton;
|
class Skeleton;
|
||||||
|
|
||||||
/// The applied pose for a bone. This is the Bone pose with constraints applied and the world transform computed by
|
/// The applied local pose and world transform for a bone. This is the Bone::getPose() with constraints applied and the
|
||||||
/// Skeleton::updateWorldTransform(Physics).
|
/// world transform computed by Skeleton::updateWorldTransform(Physics) and updateWorldTransform(Skeleton).
|
||||||
|
///
|
||||||
|
/// If the world transform is changed, call updateLocalTransform(Skeleton) before using the local transform. The local
|
||||||
|
/// transform may be needed by other code (eg to apply another constraint).
|
||||||
|
///
|
||||||
|
/// After changing the world transform, call updateWorldTransform(Skeleton) on every descendant bone. It may be more
|
||||||
|
/// convenient to modify the local transform instead, then call Skeleton::updateWorldTransform(Physics) to update the world
|
||||||
|
/// transforms for all bones and apply constraints.
|
||||||
class SP_API BonePose : public BoneLocal, public Update {
|
class SP_API BonePose : public BoneLocal, public Update {
|
||||||
friend class IkConstraint;
|
friend class IkConstraint;
|
||||||
friend class PathConstraint;
|
friend class PathConstraint;
|
||||||
@ -72,7 +79,8 @@ namespace spine {
|
|||||||
/// Called by Skeleton::updateCache() to compute the world transform, if needed.
|
/// Called by Skeleton::updateCache() to compute the world transform, if needed.
|
||||||
virtual void update(Skeleton &skeleton, Physics physics) override;
|
virtual void update(Skeleton &skeleton, Physics physics) override;
|
||||||
|
|
||||||
/// Computes the world transform using the parent bone's applied pose and this pose. Child bones are not updated.
|
/// Computes the world transform using the parent bone's world transform and this applied local pose. Child bones are not
|
||||||
|
/// updated.
|
||||||
///
|
///
|
||||||
/// See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
|
/// See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
|
||||||
/// Runtimes Guide.
|
/// Runtimes Guide.
|
||||||
@ -80,42 +88,40 @@ namespace spine {
|
|||||||
|
|
||||||
/// Computes the local transform values from the world transform.
|
/// Computes the local transform values from the world transform.
|
||||||
///
|
///
|
||||||
/// If the world transform is modified (by a constraint, rotateWorld(), etc) then this method should be called so
|
|
||||||
/// the local transform matches the world transform. The local transform may be needed by other code (eg to apply another
|
|
||||||
/// constraint).
|
|
||||||
///
|
|
||||||
/// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The local transform after
|
/// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The local transform after
|
||||||
/// calling this method is equivalent to the local transform used to compute the world transform, but may not be identical.
|
/// calling this method is equivalent to the local transform used to compute the world transform, but may not be identical.
|
||||||
void updateLocalTransform(Skeleton &skeleton);
|
void updateLocalTransform(Skeleton &skeleton);
|
||||||
|
|
||||||
/// If the world transform has been modified and the local transform no longer matches, updateLocalTransform() is called.
|
/// If the world transform has been modified by constraints and the local transform no longer matches,
|
||||||
|
/// updateLocalTransform() is called. Call this after Skeleton::updateWorldTransform(Physics) before using the applied
|
||||||
|
/// local transform.
|
||||||
void validateLocalTransform(Skeleton &skeleton);
|
void validateLocalTransform(Skeleton &skeleton);
|
||||||
|
|
||||||
void modifyLocal(Skeleton &skeleton);
|
void modifyLocal(Skeleton &skeleton);
|
||||||
void modifyWorld(int update);
|
void modifyWorld(int update);
|
||||||
void resetWorld(int update);
|
void resetWorld(int update);
|
||||||
|
|
||||||
/// Part of the world transform matrix for the X axis. If changed, updateLocalTransform() should be called.
|
/// Part of the world transform matrix for the X axis.
|
||||||
float getA();
|
float getA();
|
||||||
void setA(float a);
|
void setA(float a);
|
||||||
|
|
||||||
/// Part of the world transform matrix for the Y axis. If changed, updateLocalTransform() should be called.
|
/// Part of the world transform matrix for the Y axis.
|
||||||
float getB();
|
float getB();
|
||||||
void setB(float b);
|
void setB(float b);
|
||||||
|
|
||||||
/// Part of the world transform matrix for the X axis. If changed, updateLocalTransform() should be called.
|
/// Part of the world transform matrix for the X axis.
|
||||||
float getC();
|
float getC();
|
||||||
void setC(float c);
|
void setC(float c);
|
||||||
|
|
||||||
/// Part of the world transform matrix for the Y axis. If changed, updateLocalTransform() should be called.
|
/// Part of the world transform matrix for the Y axis.
|
||||||
float getD();
|
float getD();
|
||||||
void setD(float d);
|
void setD(float d);
|
||||||
|
|
||||||
/// The world X position. If changed, updateLocalTransform() should be called.
|
/// The world X position.
|
||||||
float getWorldX();
|
float getWorldX();
|
||||||
void setWorldX(float worldX);
|
void setWorldX(float worldX);
|
||||||
|
|
||||||
/// The world Y position. If changed, updateLocalTransform() should be called.
|
/// The world Y position.
|
||||||
float getWorldY();
|
float getWorldY();
|
||||||
void setWorldY(float worldY);
|
void setWorldY(float worldY);
|
||||||
|
|
||||||
@ -150,9 +156,6 @@ namespace spine {
|
|||||||
float localToWorldRotation(float localRotation);
|
float localToWorldRotation(float localRotation);
|
||||||
|
|
||||||
/// Rotates the world transform the specified amount.
|
/// Rotates the world transform the specified amount.
|
||||||
///
|
|
||||||
/// After changes are made to the world transform, updateLocalTransform() should be called on this bone and any
|
|
||||||
/// child bones, recursively.
|
|
||||||
void rotateWorld(float degrees);
|
void rotateWorld(float degrees);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@ -66,8 +66,8 @@ namespace spine {
|
|||||||
public:
|
public:
|
||||||
BoneTimeline1(size_t frameCount, size_t bezierCount, int boneIndex, Property property);
|
BoneTimeline1(size_t frameCount, size_t bezierCount, int boneIndex, Property property);
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
virtual int getBoneIndex() const override {
|
virtual int getBoneIndex() const override {
|
||||||
return _boneIndex;
|
return _boneIndex;
|
||||||
@ -79,7 +79,7 @@ namespace spine {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Applies changes to the pose based on the timeline values.
|
/// Applies changes to the pose based on the timeline values.
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) = 0;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) = 0;
|
||||||
|
|
||||||
int _boneIndex;
|
int _boneIndex;
|
||||||
};
|
};
|
||||||
@ -95,8 +95,8 @@ namespace spine {
|
|||||||
public:
|
public:
|
||||||
BoneTimeline2(size_t frameCount, size_t bezierCount, int boneIndex, Property property1, Property property2);
|
BoneTimeline2(size_t frameCount, size_t bezierCount, int boneIndex, Property property1, Property property2);
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
virtual int getBoneIndex() const override {
|
virtual int getBoneIndex() const override {
|
||||||
return _boneIndex;
|
return _boneIndex;
|
||||||
@ -110,7 +110,7 @@ namespace spine {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Applies changes to the pose based on the timeline values.
|
/// Applies changes to the pose based on the timeline values.
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) = 0;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) = 0;
|
||||||
|
|
||||||
int _boneIndex;
|
int _boneIndex;
|
||||||
|
|
||||||
|
|||||||
@ -48,6 +48,8 @@ namespace spine {
|
|||||||
public:
|
public:
|
||||||
explicit ClippingAttachment(const String &name);
|
explicit ClippingAttachment(const String &name);
|
||||||
|
|
||||||
|
/// Clipping is performed between the clipping attachment's slot and the end slot. If NULL, clipping is done until
|
||||||
|
/// the end of the skeleton's rendering.
|
||||||
SlotData *getEndSlot();
|
SlotData *getEndSlot();
|
||||||
|
|
||||||
void setEndSlot(SlotData *inValue);
|
void setEndSlot(SlotData *inValue);
|
||||||
|
|||||||
@ -34,7 +34,7 @@
|
|||||||
#include <spine/SlotTimeline.h>
|
#include <spine/SlotTimeline.h>
|
||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
/// Changes a slot's SlotPose::getColor().
|
/// Changes SlotPose::getColor().
|
||||||
class SP_API RGBATimeline : public SlotCurveTimeline {
|
class SP_API RGBATimeline : public SlotCurveTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ namespace spine {
|
|||||||
void setFrame(int frame, float time, float r, float g, float b, float a);
|
void setFrame(int frame, float time, float r, float g, float b, float a);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) override;
|
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) override;
|
||||||
|
|
||||||
static const int ENTRIES = 5;
|
static const int ENTRIES = 5;
|
||||||
static const int R = 1;
|
static const int R = 1;
|
||||||
@ -62,7 +62,7 @@ namespace spine {
|
|||||||
static const int A = 4;
|
static const int A = 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes the RGB for a slot's SlotPose::getColor().
|
/// Changes RGB for a slot's SlotPose::getColor().
|
||||||
class SP_API RGBTimeline : public SlotCurveTimeline {
|
class SP_API RGBTimeline : public SlotCurveTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ namespace spine {
|
|||||||
void setFrame(int frame, float time, float r, float g, float b);
|
void setFrame(int frame, float time, float r, float g, float b);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) override;
|
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) override;
|
||||||
|
|
||||||
static const int ENTRIES = 4;
|
static const int ENTRIES = 4;
|
||||||
static const int R = 1;
|
static const int R = 1;
|
||||||
@ -101,8 +101,8 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~AlphaTimeline();
|
virtual ~AlphaTimeline();
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
virtual int getSlotIndex() override;
|
virtual int getSlotIndex() override;
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ namespace spine {
|
|||||||
int _slotIndex;
|
int _slotIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a slot's SlotPose::getColor() and SlotPose::getDarkColor() for two color tinting.
|
/// Changes SlotPose::getColor() and SlotPose::getDarkColor() for two color tinting.
|
||||||
class SP_API RGBA2Timeline : public SlotCurveTimeline {
|
class SP_API RGBA2Timeline : public SlotCurveTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ namespace spine {
|
|||||||
void setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2);
|
void setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) override;
|
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) override;
|
||||||
|
|
||||||
static const int ENTRIES = 8;
|
static const int ENTRIES = 8;
|
||||||
static const int R = 1;
|
static const int R = 1;
|
||||||
@ -143,7 +143,7 @@ namespace spine {
|
|||||||
static const int B2 = 7;
|
static const int B2 = 7;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes the RGB for a slot's SlotPose::getColor() and SlotPose::getDarkColor() for two color tinting.
|
/// Changes RGB for a slot's SlotPose::getColor() and SlotPose::getDarkColor() for two color tinting.
|
||||||
class SP_API RGB2Timeline : public SlotCurveTimeline {
|
class SP_API RGB2Timeline : public SlotCurveTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -162,7 +162,7 @@ namespace spine {
|
|||||||
void setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2);
|
void setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) override;
|
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) override;
|
||||||
|
|
||||||
static const int ENTRIES = 7;
|
static const int ENTRIES = 7;
|
||||||
static const int R = 1;
|
static const int R = 1;
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
#include <spine/Property.h>
|
#include <spine/Property.h>
|
||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
/// Base class for single-value constraint timelines.
|
/// The base class for timelines that change 1 constraint property with a curve.
|
||||||
class SP_API ConstraintTimeline1 : public CurveTimeline1, public ConstraintTimeline {
|
class SP_API ConstraintTimeline1 : public CurveTimeline1, public ConstraintTimeline {
|
||||||
RTTI_DECL
|
RTTI_DECL
|
||||||
|
|
||||||
|
|||||||
@ -82,13 +82,13 @@ namespace spine {
|
|||||||
/// Returns the interpolated value for the specified time.
|
/// Returns the interpolated value for the specified time.
|
||||||
float getCurveValue(float time);
|
float getCurveValue(float time);
|
||||||
|
|
||||||
float getRelativeValue(float time, float alpha, MixBlend blend, float current, float setup);
|
float getRelativeValue(float time, float alpha, bool fromSetup, bool add, float current, float setup);
|
||||||
|
|
||||||
float getAbsoluteValue(float time, float alpha, MixBlend blend, float current, float setup);
|
float getAbsoluteValue(float time, float alpha, bool fromSetup, bool add, float current, float setup);
|
||||||
|
|
||||||
float getAbsoluteValue(float time, float alpha, MixBlend blend, float current, float setup, float value);
|
float getAbsoluteValue(float time, float alpha, bool fromSetup, bool add, float current, float setup, float value);
|
||||||
|
|
||||||
float getScaleValue(float time, float alpha, MixBlend blend, MixDirection direction, float current, float setup);
|
float getScaleValue(float time, float alpha, bool fromSetup, bool add, bool out, float current, float setup);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const int ENTRIES = 2;
|
static const int ENTRIES = 2;
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
namespace spine {
|
namespace spine {
|
||||||
class VertexAttachment;
|
class VertexAttachment;
|
||||||
|
|
||||||
/// Changes a slot's SlotPose::getDeform() to deform a VertexAttachment.
|
/// Changes SlotPose::getDeform() to deform a VertexAttachment.
|
||||||
class SP_API DeformTimeline : public SlotCurveTimeline {
|
class SP_API DeformTimeline : public SlotCurveTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) override;
|
void _apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Array<Array<float>> _vertices;
|
Array<Array<float>> _vertices;
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
#include <spine/Timeline.h>
|
#include <spine/Timeline.h>
|
||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
/// Changes a subset of a skeleton's Skeleton::getDrawOrder().
|
/// Changes a subset of Skeleton::getDrawOrder().
|
||||||
class SP_API DrawOrderFolderTimeline : public Timeline {
|
class SP_API DrawOrderFolderTimeline : public Timeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -44,8 +44,8 @@ namespace spine {
|
|||||||
public:
|
public:
|
||||||
DrawOrderFolderTimeline(size_t frameCount, Array<int> &slots, size_t slotCount);
|
DrawOrderFolderTimeline(size_t frameCount, Array<int> &slots, size_t slotCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
size_t getFrameCount();
|
size_t getFrameCount();
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
#include <spine/Timeline.h>
|
#include <spine/Timeline.h>
|
||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
/// Changes a skeleton's Skeleton::getDrawOrder().
|
/// Changes Skeleton::getDrawOrder().
|
||||||
class SP_API DrawOrderTimeline : public Timeline {
|
class SP_API DrawOrderTimeline : public Timeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -46,8 +46,8 @@ namespace spine {
|
|||||||
|
|
||||||
explicit DrawOrderTimeline(size_t frameCount);
|
explicit DrawOrderTimeline(size_t frameCount);
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
size_t getFrameCount();
|
size_t getFrameCount();
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,7 @@ namespace spine {
|
|||||||
/// Stores the current pose values for an Event.
|
/// Stores the current pose values for an Event.
|
||||||
///
|
///
|
||||||
/// See Timeline::apply(), AnimationStateListener::event(), and
|
/// See Timeline::apply(), AnimationStateListener::event(), and
|
||||||
/// @see https://esotericsoftware.com/spine-events Events in the Spine User Guide.
|
/// https://esotericsoftware.com/spine-events Events in the Spine User Guide.
|
||||||
class SP_API Event : public SpineObject {
|
class SP_API Event : public SpineObject {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,7 @@ namespace spine {
|
|||||||
public:
|
public:
|
||||||
explicit EventData(const String &name);
|
explicit EventData(const String &name);
|
||||||
|
|
||||||
/// The name of the event, which is unique within the skeleton.
|
/// The name of the event, unique across all events in the skeleton.
|
||||||
const String &getName() const;
|
const String &getName() const;
|
||||||
|
|
||||||
int getInt() const;
|
int getInt() const;
|
||||||
|
|||||||
@ -47,8 +47,8 @@ namespace spine {
|
|||||||
~EventTimeline();
|
~EventTimeline();
|
||||||
|
|
||||||
/// Fires events for frames > lastTime and <= time.
|
/// Fires events for frames > lastTime and <= time.
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
size_t getFrameCount();
|
size_t getFrameCount();
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
|
|
||||||
/// Changes an IK constraint's IkConstraintPose::getMix(), IkConstraintPose::getSoftness(),
|
/// Changes IkConstraintPose::getMix(), IkConstraintPose::getSoftness(),
|
||||||
/// IkConstraintPose::getBendDirection(), IkConstraintPose::getStretch(), and IkConstraintPose::getCompress().
|
/// IkConstraintPose::getBendDirection(), IkConstraintPose::getStretch(), and IkConstraintPose::getCompress().
|
||||||
class SP_API IkConstraintTimeline : public CurveTimeline, public ConstraintTimeline {
|
class SP_API IkConstraintTimeline : public CurveTimeline, public ConstraintTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
@ -49,8 +49,8 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~IkConstraintTimeline();
|
virtual ~IkConstraintTimeline();
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
/// Sets the time, mix, softness, bend direction, compress, and stretch for the specified frame.
|
/// Sets the time, mix, softness, bend direction, compress, and stretch for the specified frame.
|
||||||
/// @param frame Between 0 and frameCount, inclusive.
|
/// @param frame Between 0 and frameCount, inclusive.
|
||||||
|
|||||||
@ -56,8 +56,8 @@ namespace spine {
|
|||||||
/// @param time The frame time in seconds.
|
/// @param time The frame time in seconds.
|
||||||
void setFrame(int frame, float time, Inherit inherit);
|
void setFrame(int frame, float time, Inherit inherit);
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
|
|
||||||
virtual int getBoneIndex() const override {
|
virtual int getBoneIndex() const override {
|
||||||
|
|||||||
@ -74,9 +74,14 @@ namespace spine {
|
|||||||
|
|
||||||
Color &getColor();
|
Color &getColor();
|
||||||
|
|
||||||
|
/// The parent mesh if this is a linked mesh, else NULL. A linked mesh shares the bones, vertices, regionUVs,
|
||||||
|
/// triangles, hullLength, edges, width, and height with the parent mesh, but may have a different name or path,
|
||||||
|
/// and therefore a different texture region.
|
||||||
MeshAttachment *getParentMesh();
|
MeshAttachment *getParentMesh();
|
||||||
void setParentMesh(MeshAttachment *inValue);
|
void setParentMesh(MeshAttachment *inValue);
|
||||||
|
|
||||||
|
/// Vertex index pairs describing edges for controlling triangulation, or empty if nonessential data was not
|
||||||
|
/// exported. Mesh triangles do not cross edges. Triangulation is not performed at runtime.
|
||||||
Array<unsigned short> &getEdges();
|
Array<unsigned short> &getEdges();
|
||||||
void setEdges(Array<unsigned short> &inValue);
|
void setEdges(Array<unsigned short> &inValue);
|
||||||
|
|
||||||
|
|||||||
@ -1,65 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Spine Runtimes License Agreement
|
|
||||||
* Last updated April 5, 2025. Replaces all prior versions.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013-2025, 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef Spine_MixPose_h
|
|
||||||
#define Spine_MixPose_h
|
|
||||||
|
|
||||||
namespace spine {
|
|
||||||
|
|
||||||
/// Controls how timeline values are mixed with setup pose values or current pose values when a timeline is applied with
|
|
||||||
/// alpha < 1.
|
|
||||||
///
|
|
||||||
/// See Timeline::apply().
|
|
||||||
enum MixBlend {
|
|
||||||
/// Transitions between the setup and timeline values (the current value is not used). Before the first frame, the setup
|
|
||||||
/// value is used.
|
|
||||||
///
|
|
||||||
/// MixBlend_Setup is intended to transition to or from the setup pose, not for animations layered on top of others.
|
|
||||||
MixBlend_Setup = 0,
|
|
||||||
/// Transitions between the current and timeline values. Before the first frame, transitions between the current and setup
|
|
||||||
/// values. Timelines which perform instant transitions, such as DrawOrderTimeline or AttachmentTimeline, use
|
|
||||||
/// the setup value before the first frame.
|
|
||||||
///
|
|
||||||
/// MixBlend_First is intended for the first animations applied, not for animations layered on top of others.
|
|
||||||
MixBlend_First,
|
|
||||||
/// Transitions between the current and timeline values. No change is made before the first frame.
|
|
||||||
///
|
|
||||||
/// MixBlend_Replace is intended for animations layered on top of others, not for the first animations applied.
|
|
||||||
MixBlend_Replace,
|
|
||||||
/// Transitions between the current value and the current plus timeline values. No change is made before the first frame.
|
|
||||||
///
|
|
||||||
/// MixBlend_Add is intended for animations layered on top of others, not for the first animations applied.
|
|
||||||
///
|
|
||||||
/// Properties set by additive animations must be set manually or by another animation before applying the additive
|
|
||||||
/// animations, else the property values will increase each time the additive animations are applied.
|
|
||||||
MixBlend_Add
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* Spine_MixPose_h */
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Spine Runtimes License Agreement
|
|
||||||
* Last updated April 5, 2025. Replaces all prior versions.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013-2025, 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef Spine_MixDirection_h
|
|
||||||
#define Spine_MixDirection_h
|
|
||||||
|
|
||||||
namespace spine {
|
|
||||||
|
|
||||||
/// Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose value) or
|
|
||||||
/// mixing in toward 1 (the timeline's value). Some timelines use this to decide how values are applied.
|
|
||||||
///
|
|
||||||
/// See Timeline::apply().
|
|
||||||
enum MixDirection {
|
|
||||||
MixDirection_In = 0,
|
|
||||||
MixDirection_Out
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* Spine_MixDirection_h */
|
|
||||||
@ -53,6 +53,8 @@ namespace spine {
|
|||||||
|
|
||||||
void setClosed(bool inValue);
|
void setClosed(bool inValue);
|
||||||
|
|
||||||
|
/// If true, additional calculations are performed to make computing positions along the path more accurate so
|
||||||
|
/// movement along the path has a constant speed.
|
||||||
bool getConstantSpeed();
|
bool getConstantSpeed();
|
||||||
|
|
||||||
void setConstantSpeed(bool inValue);
|
void setConstantSpeed(bool inValue);
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
|
|
||||||
/// Changes a path constraint's PathConstraintPose::getMixRotate(), PathConstraintPose::getMixX(), and
|
/// Changes PathConstraintPose::getMixRotate(), PathConstraintPose::getMixX(), and
|
||||||
/// PathConstraintPose::getMixY().
|
/// PathConstraintPose::getMixY().
|
||||||
class SP_API PathConstraintMixTimeline : public CurveTimeline, public ConstraintTimeline {
|
class SP_API PathConstraintMixTimeline : public CurveTimeline, public ConstraintTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
@ -49,8 +49,8 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~PathConstraintMixTimeline();
|
virtual ~PathConstraintMixTimeline();
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
/// Sets the time and color for the specified frame.
|
/// Sets the time and color for the specified frame.
|
||||||
/// @param frame Between 0 and frameCount, inclusive.
|
/// @param frame Between 0 and frameCount, inclusive.
|
||||||
|
|||||||
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
|
|
||||||
/// Changes a path constraint's PathConstraintPose::getPosition().
|
/// Changes PathConstraintPose::getPosition().
|
||||||
class SP_API PathConstraintPositionTimeline : public ConstraintTimeline1 {
|
class SP_API PathConstraintPositionTimeline : public ConstraintTimeline1 {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -49,8 +49,8 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~PathConstraintPositionTimeline();
|
virtual ~PathConstraintPositionTimeline();
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
};
|
};
|
||||||
}// namespace spine
|
}// namespace spine
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
#include <spine/ConstraintTimeline1.h>
|
#include <spine/ConstraintTimeline1.h>
|
||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
/// Changes a path constraint's PathConstraintPose::getSpacing().
|
/// Changes PathConstraintPose::getSpacing().
|
||||||
class SP_API PathConstraintSpacingTimeline : public ConstraintTimeline1 {
|
class SP_API PathConstraintSpacingTimeline : public ConstraintTimeline1 {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -46,8 +46,8 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~PathConstraintSpacingTimeline();
|
virtual ~PathConstraintSpacingTimeline();
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,8 +50,8 @@ namespace spine {
|
|||||||
/// @param constraintIndex -1 for all physics constraints in the skeleton.
|
/// @param constraintIndex -1 for all physics constraints in the skeleton.
|
||||||
explicit PhysicsConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex, Property property);
|
explicit PhysicsConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex, Property property);
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
virtual int getConstraintIndex() const override {
|
virtual int getConstraintIndex() const override {
|
||||||
return _constraintIndex;
|
return _constraintIndex;
|
||||||
@ -67,10 +67,9 @@ namespace spine {
|
|||||||
virtual bool global(PhysicsConstraintData &constraintData) = 0;
|
virtual bool global(PhysicsConstraintData &constraintData) = 0;
|
||||||
|
|
||||||
int _constraintIndex;
|
int _constraintIndex;
|
||||||
bool _additive;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a physics constraint's PhysicsConstraintPose::getInertia().
|
/// Changes PhysicsConstraintPose::getInertia().
|
||||||
class SP_API PhysicsConstraintInertiaTimeline : public PhysicsConstraintTimeline {
|
class SP_API PhysicsConstraintInertiaTimeline : public PhysicsConstraintTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -96,7 +95,7 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a physics constraint's PhysicsConstraintPose::getStrength().
|
/// Changes PhysicsConstraintPose::getStrength().
|
||||||
class SP_API PhysicsConstraintStrengthTimeline : public PhysicsConstraintTimeline {
|
class SP_API PhysicsConstraintStrengthTimeline : public PhysicsConstraintTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -122,7 +121,7 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a physics constraint's PhysicsConstraintPose::getDamping().
|
/// Changes PhysicsConstraintPose::getDamping().
|
||||||
class SP_API PhysicsConstraintDampingTimeline : public PhysicsConstraintTimeline {
|
class SP_API PhysicsConstraintDampingTimeline : public PhysicsConstraintTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -148,8 +147,7 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a physics constraint's PhysicsConstraintPose::getMassInverse(). The
|
/// Changes PhysicsConstraintPose::getMassInverse(). The timeline values are not inverted.
|
||||||
/// timeline values are not inverted.
|
|
||||||
class SP_API PhysicsConstraintMassTimeline : public PhysicsConstraintTimeline {
|
class SP_API PhysicsConstraintMassTimeline : public PhysicsConstraintTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -175,7 +173,7 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a physics constraint's PhysicsConstraintPose::getWind().
|
/// Changes PhysicsConstraintPose::getWind().
|
||||||
class SP_API PhysicsConstraintWindTimeline : public PhysicsConstraintTimeline {
|
class SP_API PhysicsConstraintWindTimeline : public PhysicsConstraintTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -203,7 +201,7 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a physics constraint's PhysicsConstraintPose::getGravity().
|
/// Changes PhysicsConstraintPose::getGravity().
|
||||||
class SP_API PhysicsConstraintGravityTimeline : public PhysicsConstraintTimeline {
|
class SP_API PhysicsConstraintGravityTimeline : public PhysicsConstraintTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -231,7 +229,7 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a physics constraint's PhysicsConstraintPose::getMix().
|
/// Changes PhysicsConstraintPose::getMix().
|
||||||
class SP_API PhysicsConstraintMixTimeline : public PhysicsConstraintTimeline {
|
class SP_API PhysicsConstraintMixTimeline : public PhysicsConstraintTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -271,10 +269,11 @@ namespace spine {
|
|||||||
: Timeline(frameCount, 1), ConstraintTimeline(), _constraintIndex(constraintIndex) {
|
: Timeline(frameCount, 1), ConstraintTimeline(), _constraintIndex(constraintIndex) {
|
||||||
PropertyId ids[] = {((PropertyId) Property_PhysicsConstraintReset) << 32};
|
PropertyId ids[] = {((PropertyId) Property_PhysicsConstraintReset) << 32};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
|
_instant = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
int getFrameCount() {
|
int getFrameCount() {
|
||||||
return (int) _frames.size();
|
return (int) _frames.size();
|
||||||
|
|||||||
@ -53,22 +53,27 @@ namespace spine {
|
|||||||
public:
|
public:
|
||||||
explicit PointAttachment(const String &name);
|
explicit PointAttachment(const String &name);
|
||||||
|
|
||||||
|
/// The local X position.
|
||||||
float getX();
|
float getX();
|
||||||
|
|
||||||
void setX(float inValue);
|
void setX(float inValue);
|
||||||
|
|
||||||
|
/// The local Y position.
|
||||||
float getY();
|
float getY();
|
||||||
|
|
||||||
void setY(float inValue);
|
void setY(float inValue);
|
||||||
|
|
||||||
|
/// The local rotation in degrees, counter clockwise.
|
||||||
float getRotation();
|
float getRotation();
|
||||||
|
|
||||||
void setRotation(float inValue);
|
void setRotation(float inValue);
|
||||||
|
|
||||||
Color &getColor();
|
Color &getColor();
|
||||||
|
|
||||||
|
/// Computes the world position from the local position.
|
||||||
void computeWorldPosition(BonePose &bone, float &ox, float &oy);
|
void computeWorldPosition(BonePose &bone, float &ox, float &oy);
|
||||||
|
|
||||||
|
/// Computes the world rotation from the local rotation.
|
||||||
float computeWorldRotation(BonePose &bone);
|
float computeWorldRotation(BonePose &bone);
|
||||||
|
|
||||||
virtual Attachment ©() override;
|
virtual Attachment ©() override;
|
||||||
|
|||||||
@ -44,6 +44,9 @@ namespace spine {
|
|||||||
virtual ~PosedActive() {
|
virtual ~PosedActive() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns false when this won't be updated by Skeleton::updateWorldTransform(Physics) because a skin is
|
||||||
|
/// required and the active skin does not contain this item. See Skin::getBones(), Skin::getConstraints(),
|
||||||
|
/// PosedData::getSkinRequired(), and Skeleton::updateCache().
|
||||||
bool isActive() const {
|
bool isActive() const {
|
||||||
return _active;
|
return _active;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,7 +66,6 @@ namespace spine {
|
|||||||
PosedData(const String &name);
|
PosedData(const String &name);
|
||||||
virtual ~PosedData();
|
virtual ~PosedData();
|
||||||
|
|
||||||
/// The constraint's name, which is unique across all constraints in the skeleton of the same type.
|
|
||||||
const String &getName() const {
|
const String &getName() const {
|
||||||
return _name;
|
return _name;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -79,6 +79,7 @@ namespace spine {
|
|||||||
float getScaleY();
|
float getScaleY();
|
||||||
void setScaleY(float inValue);
|
void setScaleY(float inValue);
|
||||||
|
|
||||||
|
/// The local rotation in degrees, counter clockwise.
|
||||||
float getRotation();
|
float getRotation();
|
||||||
void setRotation(float inValue);
|
void setRotation(float inValue);
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace spine {
|
|||||||
explicit RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
explicit RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) override;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,7 @@ namespace spine {
|
|||||||
explicit ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
explicit ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) override;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a bone's local BoneLocal::getScaleX().
|
/// Changes a bone's local BoneLocal::getScaleX().
|
||||||
@ -60,7 +60,7 @@ namespace spine {
|
|||||||
explicit ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
explicit ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) override;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a bone's local BoneLocal::getScaleY().
|
/// Changes a bone's local BoneLocal::getScaleY().
|
||||||
@ -75,7 +75,7 @@ namespace spine {
|
|||||||
explicit ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
explicit ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) override;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@ namespace spine {
|
|||||||
class Attachment;
|
class Attachment;
|
||||||
class HasTextureRegion;
|
class HasTextureRegion;
|
||||||
|
|
||||||
/// Changes a slot's SlotPose::getSequenceIndex() for an attachment's Sequence.
|
/// Changes SlotPose::getSequenceIndex() for an attachment's Sequence.
|
||||||
class SP_API SequenceTimeline : public Timeline, public SlotTimeline {
|
class SP_API SequenceTimeline : public Timeline, public SlotTimeline {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
|
|
||||||
@ -51,8 +51,8 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~SequenceTimeline();
|
virtual ~SequenceTimeline();
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
/// Sets the time, mode, index, and frame time for the specified frame.
|
/// Sets the time, mode, index, and frame time for the specified frame.
|
||||||
/// @param frame Between 0 and frameCount, inclusive.
|
/// @param frame Between 0 and frameCount, inclusive.
|
||||||
|
|||||||
@ -45,7 +45,7 @@ namespace spine {
|
|||||||
explicit ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
explicit ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) override;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a bone's local BoneLocal::getShearX().
|
/// Changes a bone's local BoneLocal::getShearX().
|
||||||
@ -60,7 +60,7 @@ namespace spine {
|
|||||||
explicit ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
explicit ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) override;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a bone's local BoneLocal::getShearY().
|
/// Changes a bone's local BoneLocal::getShearY().
|
||||||
@ -75,7 +75,7 @@ namespace spine {
|
|||||||
explicit ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
explicit ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) override;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -200,6 +200,7 @@ namespace spine {
|
|||||||
/// @return May be NULL.
|
/// @return May be NULL.
|
||||||
Slot *findSlot(const String &slotName);
|
Slot *findSlot(const String &slotName);
|
||||||
|
|
||||||
|
/// The skeleton's slots in the order they should be drawn. The returned array may be modified to change the draw order.
|
||||||
Array<Slot *> &getDrawOrder();
|
Array<Slot *> &getDrawOrder();
|
||||||
|
|
||||||
Skin *getSkin();
|
Skin *getSkin();
|
||||||
@ -310,6 +311,9 @@ namespace spine {
|
|||||||
/// Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */
|
/// Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */
|
||||||
void physicsRotate(float x, float y, float degrees);
|
void physicsRotate(float x, float y, float degrees);
|
||||||
|
|
||||||
|
/// Returns the skeleton's time, used for time-based manipulations, such as PhysicsConstraint.
|
||||||
|
///
|
||||||
|
/// See update().
|
||||||
float getTime();
|
float getTime();
|
||||||
|
|
||||||
void setTime(float time);
|
void setTime(float time);
|
||||||
|
|||||||
@ -171,9 +171,9 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline long long readLong() {
|
inline long long readLong() {
|
||||||
unsigned long long result = (unsigned long long) readInt();
|
unsigned long long result = (unsigned int) readInt();
|
||||||
result <<= 32;
|
result <<= 32;
|
||||||
result |= (unsigned long long) readInt();
|
result |= (unsigned int) readInt();
|
||||||
return (long long) result;
|
return (long long) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,7 @@ namespace spine {
|
|||||||
|
|
||||||
class ConstraintData;
|
class ConstraintData;
|
||||||
|
|
||||||
/// Stores attachments by slot index and attachment name.
|
/// Stores attachments by slot index and placeholder name.
|
||||||
/// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and
|
/// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and
|
||||||
/// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide.
|
/// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide.
|
||||||
class SP_API Skin : public SpineObject {
|
class SP_API Skin : public SpineObject {
|
||||||
@ -56,10 +56,11 @@ namespace spine {
|
|||||||
public:
|
public:
|
||||||
struct SP_API Entry {
|
struct SP_API Entry {
|
||||||
size_t _slotIndex;
|
size_t _slotIndex;
|
||||||
String _name;
|
String _placeholderName;
|
||||||
Attachment *_attachment;
|
Attachment *_attachment;
|
||||||
|
|
||||||
Entry(size_t slotIndex, const String &name, Attachment *attachment) : _slotIndex(slotIndex), _name(name), _attachment(attachment) {
|
Entry(size_t slotIndex, const String &placeholderName, Attachment *attachment)
|
||||||
|
: _slotIndex(slotIndex), _placeholderName(placeholderName), _attachment(attachment) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -95,11 +96,11 @@ namespace spine {
|
|||||||
size_t _bucketIndex;
|
size_t _bucketIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
void put(size_t slotIndex, const String &attachmentName, Attachment *attachment);
|
void put(size_t slotIndex, const String &placeholderName, Attachment *attachment);
|
||||||
|
|
||||||
Attachment *get(size_t slotIndex, const String &attachmentName);
|
Attachment *get(size_t slotIndex, const String &placeholderName);
|
||||||
|
|
||||||
void remove(size_t slotIndex, const String &attachmentName);
|
void remove(size_t slotIndex, const String &placeholderName);
|
||||||
|
|
||||||
Entries getEntries();
|
Entries getEntries();
|
||||||
|
|
||||||
@ -107,7 +108,7 @@ namespace spine {
|
|||||||
AttachmentMap();
|
AttachmentMap();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int findInBucket(Array<Entry> &, const String &attachmentName);
|
int findInBucket(Array<Entry> &, const String &placeholderName);
|
||||||
|
|
||||||
Array<Array<Entry>> _buckets;
|
Array<Array<Entry>> _buckets;
|
||||||
};
|
};
|
||||||
@ -116,19 +117,19 @@ namespace spine {
|
|||||||
|
|
||||||
~Skin();
|
~Skin();
|
||||||
|
|
||||||
/// Adds an attachment to the skin for the specified slot index and name.
|
/// Adds an attachment to the skin for the specified slot index and placeholder name.
|
||||||
/// If the name already exists for the slot, the previous value is replaced.
|
/// If the placeholder name already exists for the slot, the previous value is replaced.
|
||||||
void setAttachment(size_t slotIndex, const String &name, Attachment *attachment);
|
void setAttachment(size_t slotIndex, const String &placeholderName, Attachment *attachment);
|
||||||
|
|
||||||
/// Returns the attachment for the specified slot index and name, or NULL.
|
/// Returns the attachment for the specified slot index and placeholder name, or NULL.
|
||||||
Attachment *getAttachment(size_t slotIndex, const String &name);
|
Attachment *getAttachment(size_t slotIndex, const String &placeholderName);
|
||||||
|
|
||||||
// Removes the attachment from the skin.
|
// Removes the attachment from the skin.
|
||||||
void removeAttachment(size_t slotIndex, const String &name);
|
void removeAttachment(size_t slotIndex, const String &placeholderName);
|
||||||
|
|
||||||
/// Finds the skin keys for a given slot. The results are added to the passed array of names.
|
/// Finds the placeholder names for a given slot. The results are added to the passed array.
|
||||||
/// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex.
|
/// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex.
|
||||||
/// @param names Found skin key names will be added to this array.
|
/// @param names Found placeholder names will be added to this array.
|
||||||
void findNamesForSlot(size_t slotIndex, Array<String> &names);
|
void findNamesForSlot(size_t slotIndex, Array<String> &names);
|
||||||
|
|
||||||
/// Finds the attachments for a given slot. The results are added to the passed array of Attachments.
|
/// Finds the attachments for a given slot. The results are added to the passed array of Attachments.
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
#include <spine/ConstraintTimeline1.h>
|
#include <spine/ConstraintTimeline1.h>
|
||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
/// Changes a slider's SliderPose::getMix().
|
/// Changes SliderPose::getMix().
|
||||||
class SP_API SliderMixTimeline : public ConstraintTimeline1 {
|
class SP_API SliderMixTimeline : public ConstraintTimeline1 {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
friend class SkeletonJson;
|
friend class SkeletonJson;
|
||||||
@ -45,8 +45,8 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~SliderMixTimeline();
|
virtual ~SliderMixTimeline();
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
#include <spine/ConstraintTimeline1.h>
|
#include <spine/ConstraintTimeline1.h>
|
||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
/// Changes a slider's SliderPose::getTime().
|
/// Changes SliderPose::getTime().
|
||||||
class SP_API SliderTimeline : public ConstraintTimeline1 {
|
class SP_API SliderTimeline : public ConstraintTimeline1 {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
friend class SkeletonJson;
|
friend class SkeletonJson;
|
||||||
@ -45,8 +45,8 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~SliderTimeline();
|
virtual ~SliderTimeline();
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -49,8 +49,8 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~SlotCurveTimeline();
|
virtual ~SlotCurveTimeline();
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
virtual int getSlotIndex() override;
|
virtual int getSlotIndex() override;
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ namespace spine {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Applies the timeline to the slot pose.
|
/// Applies the timeline to the slot pose.
|
||||||
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) = 0;
|
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) = 0;
|
||||||
|
|
||||||
int _slotIndex;
|
int _slotIndex;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -67,7 +67,7 @@ namespace spine {
|
|||||||
public:
|
public:
|
||||||
SlotData(int index, const String &name, BoneData &boneData);
|
SlotData(int index, const String &name, BoneData &boneData);
|
||||||
|
|
||||||
/// The index of the slot in Skeleton::getSlots().
|
/// The Skeleton::getSlots() index.
|
||||||
int getIndex();
|
int getIndex();
|
||||||
|
|
||||||
/// The bone this slot belongs to.
|
/// The bone this slot belongs to.
|
||||||
|
|||||||
@ -32,8 +32,6 @@
|
|||||||
|
|
||||||
#include <spine/RTTI.h>
|
#include <spine/RTTI.h>
|
||||||
#include <spine/Array.h>
|
#include <spine/Array.h>
|
||||||
#include <spine/MixBlend.h>
|
|
||||||
#include <spine/MixDirection.h>
|
|
||||||
#include <spine/SpineObject.h>
|
#include <spine/SpineObject.h>
|
||||||
#include <spine/Property.h>
|
#include <spine/Property.h>
|
||||||
|
|
||||||
@ -50,19 +48,38 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~Timeline();
|
virtual ~Timeline();
|
||||||
|
|
||||||
/// Sets the value(s) for the specified time.
|
/// Applies this timeline to the skeleton.
|
||||||
/// @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other skeleton components the timeline may change.
|
/// @param skeleton The skeleton the timeline is applied to. This provides access to the bones, slots, and other skeleton
|
||||||
/// @param lastTime lastTime The time this timeline was last applied. Timelines such as EventTimeline trigger only at specific times rather than every frame. In that case, the timeline triggers everything between lastTime (exclusive) and time (inclusive).
|
/// components the timelines may change.
|
||||||
/// @param time The time within the animation. Most timelines find the key before and the key after this time so they can interpolate between the keys.
|
/// @param lastTime The last time in seconds this timeline was applied. Some timelines trigger only at discrete times, in
|
||||||
/// @param events If any events are fired, they are added to this array. Can be NULL to ignore firing events or if the timeline does not fire events. May be NULL.
|
/// which case all keys are triggered between lastTime (exclusive) and time (inclusive). Pass -1 the first time a
|
||||||
/// @param alpha alpha 0 applies the current or setup pose value (depending on pose parameter). 1 applies the timeline
|
/// timeline is applied to ensure frame 0 is triggered.
|
||||||
/// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting alpha over
|
/// @param time The time in seconds the skeleton is being posed for. Timelines find the frame before and after this time and
|
||||||
/// time, an animation can be mixed in or out. alpha can also be useful to apply animations on top of each other (layered).
|
/// interpolate between the frame values.
|
||||||
/// @param blend Controls how mixing is applied when alpha is than 1.
|
/// @param events If any events are fired, they are added to this list. Can be NULL to ignore fired events or if no timelines
|
||||||
/// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline.
|
/// fire events.
|
||||||
/// @param appliedPose True to modify the applied pose.
|
/// @param alpha 0 applies setup or current values (depending on fromSetup), 1 uses timeline values, and intermediate values
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
/// interpolate between them. Adjusting alpha over time can mix a timeline in or out.
|
||||||
MixDirection direction, bool appliedPose) = 0;
|
/// @param fromSetup If true, alpha transitions between setup and timeline values, setup values are used before the first
|
||||||
|
/// frame (current values are not used). If false, alpha transitions between current and timeline values, no change
|
||||||
|
/// is made before the first frame.
|
||||||
|
/// @param add If true, for timelines that support it, their values are added to the setup or current values (depending on
|
||||||
|
/// fromSetup).
|
||||||
|
/// @param out True when the animation is mixing out, else it is mixing in. Used by timelines that perform instant
|
||||||
|
/// transitions.
|
||||||
|
/// @param appliedPose True to modify the applied pose, else the pose is modified.
|
||||||
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
|
bool appliedPose) = 0;
|
||||||
|
|
||||||
|
/// True if this timeline supports additive blending.
|
||||||
|
bool getAdditive() {
|
||||||
|
return _additive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// True if this timeline sets values instantaneously and does not support interpolation between frames.
|
||||||
|
bool getInstant() {
|
||||||
|
return _instant;
|
||||||
|
}
|
||||||
|
|
||||||
size_t getFrameEntries();
|
size_t getFrameEntries();
|
||||||
|
|
||||||
@ -80,6 +97,8 @@ namespace spine {
|
|||||||
Array<PropertyId> _propertyIds;
|
Array<PropertyId> _propertyIds;
|
||||||
Array<float> _frames;
|
Array<float> _frames;
|
||||||
size_t _frameEntries;
|
size_t _frameEntries;
|
||||||
|
bool _additive;
|
||||||
|
bool _instant;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
|
|
||||||
/// Changes a transform constraint's TransformConstraintPose::getMixRotate(), TransformConstraintPose::getMixX(),
|
/// Changes TransformConstraintPose::getMixRotate(), TransformConstraintPose::getMixX(),
|
||||||
/// TransformConstraintPose::getMixY(), TransformConstraintPose::getMixScaleX(),
|
/// TransformConstraintPose::getMixY(), TransformConstraintPose::getMixScaleX(),
|
||||||
/// TransformConstraintPose::getMixScaleY(), and TransformConstraintPose::getMixShearY().
|
/// TransformConstraintPose::getMixScaleY(), and TransformConstraintPose::getMixShearY().
|
||||||
class SP_API TransformConstraintTimeline : public CurveTimeline, public ConstraintTimeline {
|
class SP_API TransformConstraintTimeline : public CurveTimeline, public ConstraintTimeline {
|
||||||
@ -50,8 +50,8 @@ namespace spine {
|
|||||||
|
|
||||||
virtual ~TransformConstraintTimeline();
|
virtual ~TransformConstraintTimeline();
|
||||||
|
|
||||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) override;
|
bool appliedPose) override;
|
||||||
|
|
||||||
/// Sets the time, rotate mix, translate mix, scale mix, and shear mix for the specified frame.
|
/// Sets the time, rotate mix, translate mix, scale mix, and shear mix for the specified frame.
|
||||||
/// @param frame Between 0 and frameCount, inclusive.
|
/// @param frame Between 0 and frameCount, inclusive.
|
||||||
|
|||||||
@ -46,7 +46,7 @@ namespace spine {
|
|||||||
explicit TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
explicit TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) override;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a bone's local X translation.
|
/// Changes a bone's local X translation.
|
||||||
@ -61,7 +61,7 @@ namespace spine {
|
|||||||
explicit TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
explicit TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) override;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Changes a bone's local Y translation.
|
/// Changes a bone's local Y translation.
|
||||||
@ -76,7 +76,7 @@ namespace spine {
|
|||||||
explicit TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
explicit TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) override;
|
virtual void _apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@ namespace spine {
|
|||||||
class Slot;
|
class Slot;
|
||||||
class Skeleton;
|
class Skeleton;
|
||||||
|
|
||||||
/// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's
|
/// An attachment with vertices that are transformed by one or more bones and can be deformed by
|
||||||
/// SlotPose::getDeform().
|
/// SlotPose::getDeform().
|
||||||
class SP_API VertexAttachment : public Attachment {
|
class SP_API VertexAttachment : public Attachment {
|
||||||
friend class SkeletonBinary;
|
friend class SkeletonBinary;
|
||||||
@ -55,8 +55,8 @@ namespace spine {
|
|||||||
virtual ~VertexAttachment();
|
virtual ~VertexAttachment();
|
||||||
|
|
||||||
|
|
||||||
/// Transforms the attachment's local vertices to world coordinates. If the slot's SlotPose::getDeform()
|
/// Transforms the attachment's local vertices to world coordinates. If the SlotPose::getDeform() is not
|
||||||
/// is not empty, it is used to deform the vertices.
|
/// empty, it is used to deform the vertices.
|
||||||
///
|
///
|
||||||
/// See https://esotericsoftware.com/spine-runtime-skeletons#World-transforms World transforms in the Spine
|
/// See https://esotericsoftware.com/spine-runtime-skeletons#World-transforms World transforms in the Spine
|
||||||
/// Runtimes Guide.
|
/// Runtimes Guide.
|
||||||
@ -74,10 +74,16 @@ namespace spine {
|
|||||||
/// Gets a unique ID for this attachment.
|
/// Gets a unique ID for this attachment.
|
||||||
int getId();
|
int getId();
|
||||||
|
|
||||||
|
/// The bones that affect the vertices. The entries are, for each vertex, the number of bones affecting the
|
||||||
|
/// vertex followed by that many bone indices, which is the Skeleton::getBones() index. Empty if this attachment
|
||||||
|
/// has no weights.
|
||||||
Array<int> &getBones();
|
Array<int> &getBones();
|
||||||
|
|
||||||
void setBones(Array<int> &bones);
|
void setBones(Array<int> &bones);
|
||||||
|
|
||||||
|
/// The vertex positions in the bone's coordinate system. For a non-weighted attachment, the values are x,y pairs
|
||||||
|
/// for each vertex. For a weighted attachment, the values are x,y,weight triplets for each bone affecting each
|
||||||
|
/// vertex.
|
||||||
Array<float> &getVertices();
|
Array<float> &getVertices();
|
||||||
|
|
||||||
void setVertices(Array<float> &vertices);
|
void setVertices(Array<float> &vertices);
|
||||||
|
|||||||
@ -73,8 +73,6 @@
|
|||||||
#include <spine/LinkedMesh.h>
|
#include <spine/LinkedMesh.h>
|
||||||
#include <spine/MathUtil.h>
|
#include <spine/MathUtil.h>
|
||||||
#include <spine/MeshAttachment.h>
|
#include <spine/MeshAttachment.h>
|
||||||
#include <spine/MixBlend.h>
|
|
||||||
#include <spine/MixDirection.h>
|
|
||||||
#include <spine/PathAttachment.h>
|
#include <spine/PathAttachment.h>
|
||||||
#include <spine/PathConstraint.h>
|
#include <spine/PathConstraint.h>
|
||||||
#include <spine/PathConstraintData.h>
|
#include <spine/PathConstraintData.h>
|
||||||
|
|||||||
@ -57,8 +57,8 @@ Animation::~Animation() {
|
|||||||
ArrayUtils::deleteElements(_timelines);
|
ArrayUtils::deleteElements(_timelines);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Array<Event *> *events, float alpha, MixBlend blend,
|
void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool out, bool appliedPose) {
|
||||||
if (loop && _duration != 0) {
|
if (loop && _duration != 0) {
|
||||||
time = MathUtil::fmod(time, _duration);
|
time = MathUtil::fmod(time, _duration);
|
||||||
if (lastTime > 0) {
|
if (lastTime > 0) {
|
||||||
@ -67,7 +67,7 @@ void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0, n = _timelines.size(); i < n; ++i) {
|
for (size_t i = 0, n = _timelines.size(); i < n; ++i) {
|
||||||
_timelines[i]->apply(skeleton, lastTime, time, events, alpha, blend, direction, appliedPose);
|
_timelines[i]->apply(skeleton, lastTime, time, events, alpha, fromSetup, add, out, appliedPose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -73,11 +73,11 @@ void dummyOnAnimationEventFunc(AnimationState *state, spine::EventType type, Tra
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
TrackEntry::TrackEntry()
|
TrackEntry::TrackEntry()
|
||||||
: _animation(NULL), _previous(NULL), _next(NULL), _mixingFrom(NULL), _mixingTo(0), _trackIndex(0), _loop(false), _holdPrevious(false),
|
: _animation(NULL), _previous(NULL), _next(NULL), _mixingFrom(NULL), _mixingTo(0), _trackIndex(0), _loop(false), _additive(false),
|
||||||
_reverse(false), _shortestRotation(false), _eventThreshold(0), _mixAttachmentThreshold(0), _alphaAttachmentThreshold(0),
|
_reverse(false), _shortestRotation(false), _keepHold(false), _eventThreshold(0), _mixAttachmentThreshold(0), _alphaAttachmentThreshold(0),
|
||||||
_mixDrawOrderThreshold(0), _animationStart(0), _animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(0),
|
_mixDrawOrderThreshold(0), _animationStart(0), _animationEnd(0), _animationLast(0), _nextAnimationLast(0), _delay(0), _trackTime(0),
|
||||||
_trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), _mixDuration(0), _interruptAlpha(0), _totalAlpha(0),
|
_trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), _mixDuration(0), _totalAlpha(0),
|
||||||
_mixBlend(MixBlend_Replace), _listener(dummyOnAnimationEventFunc), SP_ANIMATION_LISTENER_USER_DATA_CTOR _listenerObject(NULL), _state(NULL) {
|
_listener(dummyOnAnimationEventFunc), SP_ANIMATION_LISTENER_USER_DATA_CTOR _listenerObject(NULL), _state(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackEntry::~TrackEntry() {
|
TrackEntry::~TrackEntry() {
|
||||||
@ -107,12 +107,12 @@ void TrackEntry::setLoop(bool inValue) {
|
|||||||
_loop = inValue;
|
_loop = inValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TrackEntry::getHoldPrevious() {
|
bool TrackEntry::getAdditive() {
|
||||||
return _holdPrevious;
|
return _additive;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackEntry::setHoldPrevious(bool inValue) {
|
void TrackEntry::setAdditive(bool inValue) {
|
||||||
_holdPrevious = inValue;
|
_additive = inValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TrackEntry::getReverse() {
|
bool TrackEntry::getReverse() {
|
||||||
@ -267,12 +267,7 @@ void TrackEntry::setMixDuration(float inValue) {
|
|||||||
|
|
||||||
void TrackEntry::setMixDuration(float mixDuration, float delay) {
|
void TrackEntry::setMixDuration(float mixDuration, float delay) {
|
||||||
_mixDuration = mixDuration;
|
_mixDuration = mixDuration;
|
||||||
if (delay <= 0) {
|
if (delay <= 0) delay = _previous == nullptr ? 0 : MathUtil::max(delay + _previous->getTrackComplete() - mixDuration, 0.0f);
|
||||||
if (_previous != nullptr)
|
|
||||||
delay = MathUtil::max(delay + _previous->getTrackComplete() - mixDuration, 0.0f);
|
|
||||||
else
|
|
||||||
delay = 0;
|
|
||||||
}
|
|
||||||
this->_delay = delay;
|
this->_delay = delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,14 +279,6 @@ TrackEntry *TrackEntry::getMixingTo() {
|
|||||||
return _mixingTo;
|
return _mixingTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackEntry::setMixBlend(MixBlend blend) {
|
|
||||||
_mixBlend = blend;
|
|
||||||
}
|
|
||||||
|
|
||||||
MixBlend TrackEntry::getMixBlend() {
|
|
||||||
return _mixBlend;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TrackEntry::resetRotationDirections() {
|
void TrackEntry::resetRotationDirections() {
|
||||||
_timelinesRotation.clear();
|
_timelinesRotation.clear();
|
||||||
}
|
}
|
||||||
@ -569,20 +556,15 @@ bool AnimationState::apply(Skeleton &skeleton) {
|
|||||||
|
|
||||||
applied = true;
|
applied = true;
|
||||||
|
|
||||||
// Track 0 animations aren't for layering, so never use current values before the first key.
|
// Apply mixing from entries first.
|
||||||
MixBlend blend = i == 0 ? MixBlend_First : current._mixBlend;
|
|
||||||
|
|
||||||
// apply mixing from entries first.
|
|
||||||
float alpha = current._alpha;
|
float alpha = current._alpha;
|
||||||
if (current._mixingFrom != NULL) {
|
if (current._mixingFrom != NULL) {
|
||||||
alpha *= applyMixingFrom(currentP, skeleton);
|
alpha *= applyMixingFrom(currentP, skeleton);
|
||||||
} else if (current._trackTime >= current._trackEnd && current._next == NULL) {
|
} else if (current._trackTime >= current._trackEnd && current._next == NULL) {
|
||||||
alpha = 0;// Set to setup pose the last time the entry will be applied.
|
alpha = 0;// Set to setup pose the last time the entry will be applied.
|
||||||
}
|
}
|
||||||
bool attachments = alpha >= current._alphaAttachmentThreshold;
|
|
||||||
|
|
||||||
|
// Apply current entry.
|
||||||
// apply current entry.
|
|
||||||
float animationLast = current._animationLast, animationTime = current.getAnimationTime();
|
float animationLast = current._animationLast, animationTime = current.getAnimationTime();
|
||||||
float applyTime = animationTime;
|
float applyTime = animationTime;
|
||||||
Array<Event *> *applyEvents = &_events;
|
Array<Event *> *applyEvents = &_events;
|
||||||
@ -592,19 +574,18 @@ bool AnimationState::apply(Skeleton &skeleton) {
|
|||||||
}
|
}
|
||||||
size_t timelineCount = current._animation->_timelines.size();
|
size_t timelineCount = current._animation->_timelines.size();
|
||||||
Array<Timeline *> &timelines = current._animation->_timelines;
|
Array<Timeline *> &timelines = current._animation->_timelines;
|
||||||
if ((i == 0 && alpha == 1) || blend == MixBlend_Add) {
|
if (i == 0 && alpha == 1) {
|
||||||
if (i == 0) attachments = true;
|
|
||||||
for (size_t ii = 0; ii < timelineCount; ++ii) {
|
for (size_t ii = 0; ii < timelineCount; ++ii) {
|
||||||
Timeline *timeline = timelines[ii];
|
Timeline *timeline = timelines[ii];
|
||||||
if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti))
|
if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti))
|
||||||
applyAttachmentTimeline(static_cast<AttachmentTimeline *>(timeline), skeleton, applyTime, blend, false, attachments);
|
applyAttachmentTimeline(static_cast<AttachmentTimeline *>(timeline), skeleton, applyTime, true, false, true);
|
||||||
else
|
else
|
||||||
timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection_In, false);
|
timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, true, false, false, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Array<int> &timelineMode = current._timelineMode;
|
Array<int> &timelineMode = current._timelineMode;
|
||||||
|
bool attachments = alpha >= current._alphaAttachmentThreshold;
|
||||||
bool shortestRotation = current._shortestRotation;
|
bool add = current._additive, shortestRotation = add || current._shortestRotation;
|
||||||
bool firstFrame = !shortestRotation && current._timelinesRotation.size() != timelines.size() << 1;
|
bool firstFrame = !shortestRotation && current._timelinesRotation.size() != timelines.size() << 1;
|
||||||
if (firstFrame) current._timelinesRotation.setSize(timelines.size() << 1, 0);
|
if (firstFrame) current._timelinesRotation.setSize(timelines.size() << 1, 0);
|
||||||
Array<float> &timelinesRotation = current._timelinesRotation;
|
Array<float> &timelinesRotation = current._timelinesRotation;
|
||||||
@ -613,15 +594,15 @@ bool AnimationState::apply(Skeleton &skeleton) {
|
|||||||
Timeline *timeline = timelines[ii];
|
Timeline *timeline = timelines[ii];
|
||||||
assert(timeline);
|
assert(timeline);
|
||||||
|
|
||||||
MixBlend timelineBlend = timelineMode[ii] == Subsequent ? current._mixBlend : MixBlend_Setup;
|
bool fromSetup = (timelineMode[ii] & First) != 0;
|
||||||
|
|
||||||
if (!shortestRotation && timeline->getRTTI().isExactly(RotateTimeline::rtti))
|
if (!shortestRotation && timeline->getRTTI().isExactly(RotateTimeline::rtti))
|
||||||
applyRotateTimeline(static_cast<RotateTimeline *>(timeline), skeleton, applyTime, alpha, timelineBlend, timelinesRotation,
|
applyRotateTimeline(static_cast<RotateTimeline *>(timeline), skeleton, applyTime, alpha, fromSetup, timelinesRotation, ii << 1,
|
||||||
ii << 1, firstFrame);
|
firstFrame);
|
||||||
else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti))
|
else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti))
|
||||||
applyAttachmentTimeline(static_cast<AttachmentTimeline *>(timeline), skeleton, applyTime, blend, false, attachments);
|
applyAttachmentTimeline(static_cast<AttachmentTimeline *>(timeline), skeleton, applyTime, fromSetup, false, attachments);
|
||||||
else
|
else
|
||||||
timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, timelineBlend, MixDirection_In, false);
|
timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, fromSetup, add, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -833,18 +814,16 @@ Animation *AnimationState::getEmptyAnimation() {
|
|||||||
return &ret;
|
return &ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationState::applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float time, MixBlend blend, bool out,
|
void AnimationState::applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float time, bool fromSetup, bool out,
|
||||||
bool attachments) {
|
bool attachments) {
|
||||||
Slot *slot = skeleton.getSlots()[attachmentTimeline->getSlotIndex()];
|
Slot *slot = skeleton.getSlots()[attachmentTimeline->getSlotIndex()];
|
||||||
if (!slot->getBone().isActive()) return;
|
if (!slot->getBone().isActive()) return;
|
||||||
|
|
||||||
Array<float> &frames = attachmentTimeline->getFrames();
|
if (out || time < attachmentTimeline->getFrames()[0]) {
|
||||||
if (out) {
|
if (fromSetup) setAttachment(skeleton, *slot, slot->getData().getAttachmentName(), attachments);
|
||||||
if (blend == MixBlend_Setup) setAttachment(skeleton, *slot, slot->getData().getAttachmentName(), attachments);
|
|
||||||
} else if (time < frames[0]) {
|
|
||||||
if (blend == MixBlend_Setup || blend == MixBlend_First) setAttachment(skeleton, *slot, slot->getData().getAttachmentName(), attachments);
|
|
||||||
} else {
|
} else {
|
||||||
setAttachment(skeleton, *slot, attachmentTimeline->getAttachmentNames()[Animation::search(frames, time)], attachments);
|
setAttachment(skeleton, *slot, attachmentTimeline->getAttachmentNames()[Animation::search(attachmentTimeline->getFrames(), time)],
|
||||||
|
attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.*/
|
/* If an attachment wasn't set (ie before the first frame or attachments is false), set the setup attachment later.*/
|
||||||
@ -852,12 +831,12 @@ void AnimationState::applyAttachmentTimeline(AttachmentTimeline *attachmentTimel
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, MixBlend blend,
|
void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, bool fromSetup,
|
||||||
Array<float> &timelinesRotation, size_t i, bool firstFrame) {
|
Array<float> &timelinesRotation, size_t i, bool firstFrame) {
|
||||||
if (firstFrame) timelinesRotation[i] = 0;
|
if (firstFrame) timelinesRotation[i] = 0;
|
||||||
|
|
||||||
if (alpha == 1) {
|
if (alpha == 1) {
|
||||||
static_cast<Timeline *>(rotateTimeline)->apply(skeleton, 0, time, NULL, 1, blend, MixDirection_In, false);
|
static_cast<Timeline *>(rotateTimeline)->apply(skeleton, 0, time, NULL, 1, fromSetup, false, false, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -866,21 +845,12 @@ void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleto
|
|||||||
BoneLocal &pose = bone->_pose;
|
BoneLocal &pose = bone->_pose;
|
||||||
BoneLocal &setup = bone->_data._setup;
|
BoneLocal &setup = bone->_data._setup;
|
||||||
Array<float> &frames = rotateTimeline->_frames;
|
Array<float> &frames = rotateTimeline->_frames;
|
||||||
float r1, r2;
|
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
switch (blend) {
|
if (fromSetup) pose._rotation = setup._rotation;
|
||||||
case MixBlend_Setup:
|
return;
|
||||||
pose._rotation = setup._rotation;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
case MixBlend_First:
|
|
||||||
r1 = pose._rotation;
|
|
||||||
r2 = setup._rotation;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r1 = blend == MixBlend_Setup ? setup._rotation : pose._rotation;
|
|
||||||
r2 = setup._rotation + rotateTimeline->getCurveValue(time);
|
|
||||||
}
|
}
|
||||||
|
float r1 = fromSetup ? setup._rotation : pose._rotation;
|
||||||
|
float r2 = setup._rotation + rotateTimeline->getCurveValue(time);
|
||||||
|
|
||||||
// Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
|
// Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
|
||||||
float total, diff = r2 - r1;
|
float total, diff = r2 - r1;
|
||||||
@ -934,7 +904,9 @@ bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) {
|
|||||||
if (from->_totalAlpha == 0 || to->_mixDuration == 0) {
|
if (from->_totalAlpha == 0 || to->_mixDuration == 0) {
|
||||||
to->_mixingFrom = from->_mixingFrom;
|
to->_mixingFrom = from->_mixingFrom;
|
||||||
if (from->_mixingFrom) from->_mixingFrom->_mixingTo = to;
|
if (from->_mixingFrom) from->_mixingFrom->_mixingTo = to;
|
||||||
to->_interruptAlpha = from->_interruptAlpha;
|
if (from->_totalAlpha == 0) {
|
||||||
|
for (TrackEntry *next = to; next->_mixingTo != NULL; next = next->_mixingTo) next->_keepHold = true;
|
||||||
|
}
|
||||||
_queue->end(from);
|
_queue->end(from);
|
||||||
}
|
}
|
||||||
return finished;
|
return finished;
|
||||||
@ -948,86 +920,53 @@ bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) {
|
|||||||
|
|
||||||
float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton) {
|
float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton) {
|
||||||
TrackEntry *from = to->_mixingFrom;
|
TrackEntry *from = to->_mixingFrom;
|
||||||
if (from->_mixingFrom != NULL) applyMixingFrom(from, skeleton);
|
float fromMix = from->_mixingFrom != NULL ? applyMixingFrom(from, skeleton) : 1;
|
||||||
|
float mix = to->_mixDuration == 0 ? 1 : MathUtil::min(1.0f, to->_mixTime / to->_mixDuration);
|
||||||
|
|
||||||
float mix;
|
float a = from->_alpha * fromMix, keep = 1 - mix * to->_alpha;
|
||||||
if (to->_mixDuration == 0)// Single frame mix to undo mixingFrom changes.
|
float alphaMix = a * (1 - mix), alphaHold = keep > 0 ? alphaMix / keep : a;
|
||||||
mix = 1;
|
|
||||||
else {
|
|
||||||
mix = to->_mixTime / to->_mixDuration;
|
|
||||||
if (mix > 1) {
|
|
||||||
mix = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool attachments = mix < from->_mixAttachmentThreshold, drawOrder = mix < from->_mixDrawOrderThreshold;
|
|
||||||
Array<Timeline *> &timelines = from->_animation->_timelines;
|
Array<Timeline *> &timelines = from->_animation->_timelines;
|
||||||
size_t timelineCount = timelines.size();
|
size_t timelineCount = timelines.size();
|
||||||
float alphaHold = from->_alpha * to->_interruptAlpha, alphaMix = alphaHold * (1 - mix);
|
Array<int> &timelineMode = from->_timelineMode;
|
||||||
|
Array<TrackEntry *> &timelineHoldMix = from->_timelineHoldMix;
|
||||||
|
|
||||||
|
bool attachments = mix < from->_mixAttachmentThreshold, drawOrder = mix < from->_mixDrawOrderThreshold;
|
||||||
|
bool add = from->_additive, shortestRotation = add || from->_shortestRotation;
|
||||||
|
bool firstFrame = !shortestRotation && from->_timelinesRotation.size() != timelines.size() << 1;
|
||||||
|
if (firstFrame) from->_timelinesRotation.setSize(timelines.size() << 1, 0);
|
||||||
|
Array<float> &timelinesRotation = from->_timelinesRotation;
|
||||||
|
|
||||||
float animationLast = from->_animationLast, animationTime = from->getAnimationTime();
|
float animationLast = from->_animationLast, animationTime = from->getAnimationTime();
|
||||||
float applyTime = animationTime;
|
float applyTime = animationTime;
|
||||||
Array<Event *> *events = NULL;
|
Array<Event *> *events = NULL;
|
||||||
if (from->_reverse) {
|
if (from->_reverse)
|
||||||
applyTime = from->_animation->_duration - applyTime;
|
applyTime = from->_animation->_duration - applyTime;
|
||||||
} else {
|
else if (mix < from->_eventThreshold)
|
||||||
if (mix < from->_eventThreshold) events = &_events;
|
events = &_events;
|
||||||
}
|
|
||||||
|
|
||||||
MixBlend blend = from->_mixBlend;
|
from->_totalAlpha = 0;
|
||||||
if (blend == MixBlend_Add) {
|
for (size_t i = 0; i < timelineCount; i++) {
|
||||||
for (size_t i = 0; i < timelineCount; i++)
|
Timeline *timeline = timelines[i];
|
||||||
timelines[i]->apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection_Out, false);
|
int mode = timelineMode[i];
|
||||||
} else {
|
float alpha;
|
||||||
Array<int> &timelineMode = from->_timelineMode;
|
if ((mode & Hold) != 0) {
|
||||||
Array<TrackEntry *> &timelineHoldMix = from->_timelineHoldMix;
|
TrackEntry *holdMix = timelineHoldMix[i];
|
||||||
|
alpha = holdMix == NULL ? alphaHold : alphaHold * MathUtil::max(0.0f, 1.0f - holdMix->_mixTime / holdMix->_mixDuration);
|
||||||
bool shortestRotation = from->_shortestRotation;
|
} else {
|
||||||
bool firstFrame = !shortestRotation && from->_timelinesRotation.size() != timelines.size() << 1;
|
if (!drawOrder && timeline->getRTTI().isExactly(DrawOrderTimeline::rtti)) continue;
|
||||||
if (firstFrame) from->_timelinesRotation.setSize(timelines.size() << 1, 0);
|
alpha = alphaMix;
|
||||||
|
}
|
||||||
Array<float> &timelinesRotation = from->_timelinesRotation;
|
from->_totalAlpha += alpha;
|
||||||
|
bool fromSetup = (mode & First) != 0;
|
||||||
from->_totalAlpha = 0;
|
if (!shortestRotation && timeline->getRTTI().isExactly(RotateTimeline::rtti)) {
|
||||||
for (size_t i = 0; i < timelineCount; i++) {
|
applyRotateTimeline((RotateTimeline *) timeline, skeleton, applyTime, alpha, fromSetup, timelinesRotation, i << 1, firstFrame);
|
||||||
Timeline *timeline = timelines[i];
|
} else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) {
|
||||||
MixDirection direction = MixDirection_Out;
|
applyAttachmentTimeline(static_cast<AttachmentTimeline *>(timeline), skeleton, applyTime, fromSetup, true,
|
||||||
MixBlend timelineBlend;
|
attachments && alpha >= from->_alphaAttachmentThreshold);
|
||||||
float alpha;
|
} else {
|
||||||
switch (timelineMode[i]) {
|
bool out = !drawOrder || !timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) || !fromSetup;
|
||||||
case Subsequent:
|
timeline->apply(skeleton, animationLast, applyTime, events, alpha, fromSetup, add, out, false);
|
||||||
if (!drawOrder && (timeline->getRTTI().isExactly(DrawOrderTimeline::rtti))) continue;
|
|
||||||
timelineBlend = blend;
|
|
||||||
alpha = alphaMix;
|
|
||||||
break;
|
|
||||||
case First:
|
|
||||||
timelineBlend = MixBlend_Setup;
|
|
||||||
alpha = alphaMix;
|
|
||||||
break;
|
|
||||||
case HoldSubsequent:
|
|
||||||
timelineBlend = blend;
|
|
||||||
alpha = alphaHold;
|
|
||||||
break;
|
|
||||||
case HoldFirst:
|
|
||||||
timelineBlend = MixBlend_Setup;
|
|
||||||
alpha = alphaHold;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
timelineBlend = MixBlend_Setup;
|
|
||||||
TrackEntry *holdMix = timelineHoldMix[i];
|
|
||||||
alpha = alphaHold * MathUtil::max(0.0f, 1.0f - holdMix->_mixTime / holdMix->_mixDuration);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
from->_totalAlpha += alpha;
|
|
||||||
if (!shortestRotation && (timeline->getRTTI().isExactly(RotateTimeline::rtti))) {
|
|
||||||
applyRotateTimeline((RotateTimeline *) timeline, skeleton, applyTime, alpha, timelineBlend, timelinesRotation, i << 1, firstFrame);
|
|
||||||
} else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) {
|
|
||||||
applyAttachmentTimeline(static_cast<AttachmentTimeline *>(timeline), skeleton, applyTime, timelineBlend, true,
|
|
||||||
attachments && alpha >= from->_alphaAttachmentThreshold);
|
|
||||||
} else {
|
|
||||||
if (drawOrder && timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) && timelineBlend == MixBlend_Setup)
|
|
||||||
direction = MixDirection_In;
|
|
||||||
timeline->apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1036,9 +975,9 @@ float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_events.clear();
|
_events.clear();
|
||||||
|
|
||||||
from->_nextAnimationLast = animationTime;
|
from->_nextAnimationLast = animationTime;
|
||||||
from->_nextTrackLast = from->_trackTime;
|
from->_nextTrackLast = from->_trackTime;
|
||||||
|
|
||||||
return mix;
|
return mix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1094,12 +1033,6 @@ void AnimationState::setCurrent(size_t index, TrackEntry *current, bool interrup
|
|||||||
current->_mixingFrom = from;
|
current->_mixingFrom = from;
|
||||||
from->_mixingTo = current;
|
from->_mixingTo = current;
|
||||||
current->_mixTime = 0;
|
current->_mixTime = 0;
|
||||||
|
|
||||||
// Store interrupted mix percentage.
|
|
||||||
if (from->_mixingFrom != NULL && from->_mixDuration > 0) {
|
|
||||||
current->_interruptAlpha *= MathUtil::min(1.0f, from->_mixTime / from->_mixDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
from->_timelinesRotation.clear();// Reset rotation for mixing out, in case entry was mixed in.
|
from->_timelinesRotation.clear();// Reset rotation for mixing out, in case entry was mixed in.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1120,8 +1053,8 @@ TrackEntry *AnimationState::newTrackEntry(size_t trackIndex, Animation *animatio
|
|||||||
entry._trackIndex = (int) trackIndex;
|
entry._trackIndex = (int) trackIndex;
|
||||||
entry._animation = animation;
|
entry._animation = animation;
|
||||||
entry._loop = loop;
|
entry._loop = loop;
|
||||||
entry._holdPrevious = 0;
|
|
||||||
|
|
||||||
|
entry._additive = false;
|
||||||
entry._reverse = false;
|
entry._reverse = false;
|
||||||
entry._shortestRotation = false;
|
entry._shortestRotation = false;
|
||||||
|
|
||||||
@ -1145,9 +1078,8 @@ TrackEntry *AnimationState::newTrackEntry(size_t trackIndex, Animation *animatio
|
|||||||
entry._alpha = 1;
|
entry._alpha = 1;
|
||||||
entry._mixTime = 0;
|
entry._mixTime = 0;
|
||||||
entry._mixDuration = (last == NULL) ? 0 : _data->getMix(*last->_animation, *animation);
|
entry._mixDuration = (last == NULL) ? 0 : _data->getMix(*last->_animation, *animation);
|
||||||
entry._interruptAlpha = 1;
|
|
||||||
entry._totalAlpha = 0;
|
entry._totalAlpha = 0;
|
||||||
entry._mixBlend = MixBlend_Replace;
|
entry._keepHold = false;
|
||||||
|
|
||||||
return entryP;
|
return entryP;
|
||||||
}
|
}
|
||||||
@ -1164,8 +1096,6 @@ void AnimationState::clearNext(TrackEntry *entry) {
|
|||||||
void AnimationState::animationsChanged() {
|
void AnimationState::animationsChanged() {
|
||||||
_animationsChanged = false;
|
_animationsChanged = false;
|
||||||
|
|
||||||
_propertyIDs.clear();
|
|
||||||
|
|
||||||
for (size_t i = 0, n = _tracks.size(); i < n; ++i) {
|
for (size_t i = 0, n = _tracks.size(); i < n; ++i) {
|
||||||
TrackEntry *entry = _tracks[i];
|
TrackEntry *entry = _tracks[i];
|
||||||
if (!entry) continue;
|
if (!entry) continue;
|
||||||
@ -1173,60 +1103,62 @@ void AnimationState::animationsChanged() {
|
|||||||
while (entry->_mixingFrom != NULL) entry = entry->_mixingFrom;
|
while (entry->_mixingFrom != NULL) entry = entry->_mixingFrom;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (entry->_mixingTo == NULL || entry->_mixBlend != MixBlend_Add) computeHold(entry);
|
computeHold(entry);
|
||||||
entry = entry->_mixingTo;
|
entry = entry->_mixingTo;
|
||||||
} while (entry != NULL);
|
} while (entry != NULL);
|
||||||
}
|
}
|
||||||
|
_propertyIDs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationState::computeHold(TrackEntry *entry) {
|
void AnimationState::computeHold(TrackEntry *entry) {
|
||||||
TrackEntry *to = entry->_mixingTo;
|
|
||||||
Array<Timeline *> &timelines = entry->_animation->_timelines;
|
Array<Timeline *> &timelines = entry->_animation->_timelines;
|
||||||
size_t timelinesCount = timelines.size();
|
size_t timelinesCount = timelines.size();
|
||||||
Array<int> &timelineMode = entry->_timelineMode;
|
Array<int> &timelineMode = entry->_timelineMode;
|
||||||
timelineMode.setSize(timelinesCount, 0);
|
timelineMode.setSize(timelinesCount, 0);
|
||||||
|
entry->_timelineHoldMix.clear();
|
||||||
Array<TrackEntry *> &timelineHoldMix = entry->_timelineHoldMix;
|
Array<TrackEntry *> &timelineHoldMix = entry->_timelineHoldMix;
|
||||||
timelineHoldMix.setSize(timelinesCount, 0);
|
timelineHoldMix.setSize(timelinesCount, NULL);
|
||||||
PropertyId drawOrderPropertyId = DrawOrderTimeline::getPropertyId();
|
PropertyId drawOrderPropertyId = DrawOrderTimeline::getPropertyId();
|
||||||
|
bool add = entry->_additive, keepHold = entry->_keepHold;
|
||||||
|
TrackEntry *to = entry->_mixingTo;
|
||||||
|
|
||||||
if (to != NULL && to->_holdPrevious) {
|
for (size_t i = 0; i < timelinesCount; ++i) {
|
||||||
for (size_t i = 0; i < timelinesCount; i++) {
|
|
||||||
bool first = _propertyIDs.addAll(timelines[i]->getPropertyIds(), true);
|
|
||||||
if (first && timelines[i]->getRTTI().isExactly(DrawOrderFolderTimeline::rtti) && _propertyIDs.containsKey(drawOrderPropertyId))
|
|
||||||
first = false;
|
|
||||||
timelineMode[i] = first ? HoldFirst : HoldSubsequent;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// outer:
|
|
||||||
size_t i = 0;
|
|
||||||
continue_outer:
|
|
||||||
for (; i < timelinesCount; ++i) {
|
|
||||||
Timeline *timeline = timelines[i];
|
Timeline *timeline = timelines[i];
|
||||||
Array<PropertyId> &ids = timeline->getPropertyIds();
|
Array<PropertyId> &ids = timeline->getPropertyIds();
|
||||||
if (!_propertyIDs.addAll(ids, true)) {
|
bool first = _propertyIDs.addAll(ids, true) &&
|
||||||
timelineMode[i] = Subsequent;
|
!(timeline->getRTTI().isExactly(DrawOrderFolderTimeline::rtti) && _propertyIDs.containsKey(drawOrderPropertyId));
|
||||||
} else if (timeline->getRTTI().isExactly(DrawOrderFolderTimeline::rtti) && _propertyIDs.containsKey(drawOrderPropertyId)) {
|
|
||||||
timelineMode[i] = Subsequent;
|
if (add && timeline->getAdditive()) {
|
||||||
} else {
|
timelineMode[i] = first ? First : Subsequent;
|
||||||
if (to == NULL || timeline->getRTTI().isExactly(AttachmentTimeline::rtti) || timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) ||
|
continue;
|
||||||
timeline->getRTTI().isExactly(DrawOrderFolderTimeline::rtti) || timeline->getRTTI().isExactly(EventTimeline::rtti) ||
|
}
|
||||||
!to->_animation->hasTimeline(ids)) {
|
|
||||||
timelineMode[i] = First;
|
// Check if an earlier entry on this track keys this property.
|
||||||
} else {
|
bool found = false;
|
||||||
for (TrackEntry *next = to->_mixingTo; next != NULL; next = next->_mixingTo) {
|
for (TrackEntry *from = entry->_mixingFrom; from != NULL; from = from->_mixingFrom) {
|
||||||
if (next->_animation->hasTimeline(ids)) continue;
|
if (from->_animation->hasTimeline(ids)) {
|
||||||
if (next->_mixDuration > 0) {
|
timelineMode[i] = Subsequent;
|
||||||
timelineMode[i] = HoldMix;
|
found = true;
|
||||||
timelineHoldMix[i] = next;
|
break;
|
||||||
i++;
|
|
||||||
goto continue_outer;// continue outer;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
timelineMode[i] = HoldFirst;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (found) continue;
|
||||||
|
|
||||||
|
// Hold if the next entry will overwrite this property.
|
||||||
|
int mode;
|
||||||
|
if (to == NULL || timeline->getInstant() || (to->_additive && timeline->getAdditive()) || !to->_animation->hasTimeline(ids))
|
||||||
|
mode = first ? First : Subsequent;
|
||||||
|
else {
|
||||||
|
mode = first ? HoldFirst : Hold;
|
||||||
|
// Find next entry that doesn't overwrite this property. Its mix fades out the hold.
|
||||||
|
for (TrackEntry *next = to->_mixingTo; next != NULL; next = next->_mixingTo) {
|
||||||
|
if ((next->_additive && timeline->getAdditive()) || !next->_animation->hasTimeline(ids)) {
|
||||||
|
if (next->_mixDuration > 0) timelineHoldMix[i] = next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keepHold) mode = (mode & ~Hold) | (timelineMode[i] & Hold);
|
||||||
|
timelineMode[i] = mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,6 +46,7 @@ RTTI_IMPL_MULTI(AttachmentTimeline, Timeline, SlotTimeline)
|
|||||||
AttachmentTimeline::AttachmentTimeline(size_t frameCount, int slotIndex) : Timeline(frameCount, 1), SlotTimeline(), _slotIndex(slotIndex) {
|
AttachmentTimeline::AttachmentTimeline(size_t frameCount, int slotIndex) : Timeline(frameCount, 1), SlotTimeline(), _slotIndex(slotIndex) {
|
||||||
PropertyId ids[] = {((PropertyId) Property_Attachment << 32) | slotIndex};
|
PropertyId ids[] = {((PropertyId) Property_Attachment << 32) | slotIndex};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
|
_instant = true;
|
||||||
|
|
||||||
_attachmentNames.ensureCapacity(frameCount);
|
_attachmentNames.ensureCapacity(frameCount);
|
||||||
for (size_t i = 0; i < frameCount; ++i) {
|
for (size_t i = 0; i < frameCount; ++i) {
|
||||||
@ -60,20 +61,19 @@ void AttachmentTimeline::setAttachment(Skeleton &skeleton, SlotPose &pose, Strin
|
|||||||
pose.setAttachment(attachmentName == NULL || attachmentName->isEmpty() ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName));
|
pose.setAttachment(attachmentName == NULL || attachmentName->isEmpty() ? NULL : skeleton.getAttachment(_slotIndex, *attachmentName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool out, bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(alpha);
|
SP_UNUSED(alpha);
|
||||||
|
SP_UNUSED(add);
|
||||||
|
|
||||||
Slot *slot = skeleton._slots[_slotIndex];
|
Slot *slot = skeleton._slots[_slotIndex];
|
||||||
if (!slot->_bone.isActive()) return;
|
if (!slot->_bone.isActive()) return;
|
||||||
SlotPose &pose = appliedPose ? *slot->_applied : slot->_pose;
|
SlotPose &pose = appliedPose ? *slot->_applied : slot->_pose;
|
||||||
|
|
||||||
if (direction == MixDirection_Out) {
|
if (out || time < _frames[0]) {
|
||||||
if (blend == MixBlend_Setup) setAttachment(skeleton, pose, &slot->_data._attachmentName);
|
if (fromSetup) setAttachment(skeleton, pose, &slot->_data._attachmentName);
|
||||||
} else if (time < _frames[0]) {
|
|
||||||
if (blend == MixBlend_Setup || blend == MixBlend_First) setAttachment(skeleton, pose, &slot->_data._attachmentName);
|
|
||||||
} else {
|
} else {
|
||||||
setAttachment(skeleton, pose, &_attachmentNames[Animation::search(_frames, time)]);
|
setAttachment(skeleton, pose, &_attachmentNames[Animation::search(_frames, time)]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,16 +51,17 @@ BoneTimeline1::BoneTimeline1(size_t frameCount, size_t bezierCount, int boneInde
|
|||||||
: CurveTimeline1(frameCount, bezierCount), BoneTimeline(boneIndex), _boneIndex(boneIndex) {
|
: CurveTimeline1(frameCount, bezierCount), BoneTimeline(boneIndex), _boneIndex(boneIndex) {
|
||||||
PropertyId ids[] = {((PropertyId) property << 32) | boneIndex};
|
PropertyId ids[] = {((PropertyId) property << 32) | boneIndex};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
|
_additive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoneTimeline1::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend, MixDirection direction,
|
void BoneTimeline1::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
bool appliedPose) {
|
bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
|
|
||||||
Bone *bone = skeleton._bones[_boneIndex];
|
Bone *bone = skeleton._bones[_boneIndex];
|
||||||
if (bone->isActive()) {
|
if (bone->isActive()) {
|
||||||
_apply(appliedPose ? *bone->_applied : bone->_pose, bone->_data._setup, time, alpha, blend, direction);
|
_apply(appliedPose ? *bone->_applied : bone->_pose, bone->_data._setup, time, alpha, fromSetup, add, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,16 +71,17 @@ BoneTimeline2::BoneTimeline2(size_t frameCount, size_t bezierCount, int boneInde
|
|||||||
: CurveTimeline(frameCount, BoneTimeline2::ENTRIES, bezierCount), BoneTimeline(boneIndex), _boneIndex(boneIndex) {
|
: CurveTimeline(frameCount, BoneTimeline2::ENTRIES, bezierCount), BoneTimeline(boneIndex), _boneIndex(boneIndex) {
|
||||||
PropertyId ids[] = {((PropertyId) property1 << 32) | boneIndex, ((PropertyId) property2 << 32) | boneIndex};
|
PropertyId ids[] = {((PropertyId) property1 << 32) | boneIndex, ((PropertyId) property2 << 32) | boneIndex};
|
||||||
setPropertyIds(ids, 2);
|
setPropertyIds(ids, 2);
|
||||||
|
_additive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoneTimeline2::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend, MixDirection direction,
|
void BoneTimeline2::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
bool appliedPose) {
|
bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
|
|
||||||
Bone *bone = skeleton._bones[_boneIndex];
|
Bone *bone = skeleton._bones[_boneIndex];
|
||||||
if (bone->isActive()) {
|
if (bone->isActive()) {
|
||||||
_apply(appliedPose ? *bone->_applied : bone->_pose, bone->_data._setup, time, alpha, blend, direction);
|
_apply(appliedPose ? *bone->_applied : bone->_pose, bone->_data._setup, time, alpha, fromSetup, add, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,20 +59,12 @@ void RGBATimeline::setFrame(int frame, float time, float r, float g, float b, fl
|
|||||||
_frames[frame + A] = a;
|
_frames[frame + A] = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RGBATimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) {
|
void RGBATimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) {
|
||||||
|
SP_UNUSED(add);
|
||||||
Color &color = pose._color;
|
Color &color = pose._color;
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) {
|
||||||
Color &setup = slot._data._setup._color;
|
if (fromSetup) color.set(slot._data._setup._color);
|
||||||
switch (blend) {
|
return;
|
||||||
case MixBlend_Setup:
|
|
||||||
color.set(setup);
|
|
||||||
return;
|
|
||||||
case MixBlend_First:
|
|
||||||
color.add((setup.r - color.r) * alpha, (setup.g - color.g) * alpha, (setup.b - color.b) * alpha, (setup.a - color.a) * alpha);
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float r, g, b, a;
|
float r, g, b, a;
|
||||||
@ -111,8 +103,12 @@ void RGBATimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, M
|
|||||||
if (alpha == 1)
|
if (alpha == 1)
|
||||||
color.set(r, g, b, a);
|
color.set(r, g, b, a);
|
||||||
else {
|
else {
|
||||||
if (blend == MixBlend_Setup) color.set(slot._data._setup._color);
|
if (fromSetup) {
|
||||||
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
|
Color &setup = slot._data._setup._color;
|
||||||
|
color.set(setup.r + (r - setup.r) * alpha, setup.g + (g - setup.g) * alpha, setup.b + (b - setup.b) * alpha,
|
||||||
|
setup.a + (a - setup.a) * alpha);
|
||||||
|
} else
|
||||||
|
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,65 +130,58 @@ void RGBTimeline::setFrame(int frame, float time, float r, float g, float b) {
|
|||||||
_frames[frame + B] = b;
|
_frames[frame + B] = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RGBTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) {
|
void RGBTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) {
|
||||||
|
SP_UNUSED(add);
|
||||||
Color &color = pose._color;
|
Color &color = pose._color;
|
||||||
float r, g, b;
|
float r, g, b;
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) {
|
||||||
Color &setup = slot._data._setup._color;
|
if (fromSetup) {
|
||||||
switch (blend) {
|
Color &setup = slot._data._setup._color;
|
||||||
case MixBlend_Setup:
|
color.r = setup.r;
|
||||||
color.r = setup.r;
|
color.g = setup.g;
|
||||||
color.g = setup.g;
|
color.b = setup.b;
|
||||||
color.b = setup.b;
|
|
||||||
return;
|
|
||||||
case MixBlend_First:
|
|
||||||
r = color.r + (setup.r - color.r) * alpha;
|
|
||||||
g = color.g + (setup.g - color.g) * alpha;
|
|
||||||
b = color.b + (setup.b - color.b) * alpha;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int i = Animation::search(_frames, time, ENTRIES);
|
|
||||||
int curveType = (int) _curves[i >> 2];
|
|
||||||
switch (curveType) {
|
|
||||||
case LINEAR: {
|
|
||||||
float before = _frames[i];
|
|
||||||
r = _frames[i + R];
|
|
||||||
g = _frames[i + G];
|
|
||||||
b = _frames[i + B];
|
|
||||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
|
||||||
r += (_frames[i + ENTRIES + R] - r) * t;
|
|
||||||
g += (_frames[i + ENTRIES + G] - g) * t;
|
|
||||||
b += (_frames[i + ENTRIES + B] - b) * t;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STEPPED: {
|
|
||||||
r = _frames[i + R];
|
|
||||||
g = _frames[i + G];
|
|
||||||
b = _frames[i + B];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
r = getBezierValue(time, i, R, curveType - BEZIER);
|
|
||||||
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
|
||||||
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (alpha != 1) {
|
int i = Animation::search(_frames, time, ENTRIES);
|
||||||
if (blend == MixBlend_Setup) {
|
int curveType = (int) _curves[i >> 2];
|
||||||
Color &setup = slot._data._setup._color;
|
switch (curveType) {
|
||||||
r = setup.r + (r - setup.r) * alpha;
|
case LINEAR: {
|
||||||
g = setup.g + (g - setup.g) * alpha;
|
float before = _frames[i];
|
||||||
b = setup.b + (b - setup.b) * alpha;
|
r = _frames[i + R];
|
||||||
} else {
|
g = _frames[i + G];
|
||||||
r = color.r + (r - color.r) * alpha;
|
b = _frames[i + B];
|
||||||
g = color.g + (g - color.g) * alpha;
|
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||||
b = color.b + (b - color.b) * alpha;
|
r += (_frames[i + ENTRIES + R] - r) * t;
|
||||||
}
|
g += (_frames[i + ENTRIES + G] - g) * t;
|
||||||
|
b += (_frames[i + ENTRIES + B] - b) * t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STEPPED: {
|
||||||
|
r = _frames[i + R];
|
||||||
|
g = _frames[i + G];
|
||||||
|
b = _frames[i + B];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
r = getBezierValue(time, i, R, curveType - BEZIER);
|
||||||
|
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
||||||
|
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alpha != 1) {
|
||||||
|
if (fromSetup) {
|
||||||
|
Color &setup = slot._data._setup._color;
|
||||||
|
r = setup.r + (r - setup.r) * alpha;
|
||||||
|
g = setup.g + (g - setup.g) * alpha;
|
||||||
|
b = setup.b + (b - setup.b) * alpha;
|
||||||
|
} else {
|
||||||
|
r = color.r + (r - color.r) * alpha;
|
||||||
|
g = color.g + (g - color.g) * alpha;
|
||||||
|
b = color.b + (b - color.b) * alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
color.r = r < 0 ? 0 : (r > 1 ? 1 : r);
|
color.r = r < 0 ? 0 : (r > 1 ? 1 : r);
|
||||||
@ -219,38 +208,29 @@ void AlphaTimeline::setSlotIndex(int inValue) {
|
|||||||
_slotIndex = inValue;
|
_slotIndex = inValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlphaTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend, MixDirection direction,
|
void AlphaTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
bool appliedPose) {
|
bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(direction);
|
SP_UNUSED(add);
|
||||||
|
SP_UNUSED(out);
|
||||||
|
|
||||||
Slot *slot = skeleton._slots[_slotIndex];
|
Slot *slot = skeleton._slots[_slotIndex];
|
||||||
if (!slot->_bone._active) return;
|
if (!slot->_bone._active) return;
|
||||||
|
|
||||||
Color &color = (appliedPose ? *slot->_applied : slot->_pose)._color;
|
Color &color = (appliedPose ? *slot->_applied : slot->_pose)._color;
|
||||||
float a;
|
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) {
|
||||||
Color &setup = slot->_data._setup._color;
|
if (fromSetup) color.a = slot->_data._setup._color.a;
|
||||||
switch (blend) {
|
return;
|
||||||
case MixBlend_Setup:
|
}
|
||||||
color.a = setup.a;
|
|
||||||
return;
|
float a = getCurveValue(time);
|
||||||
case MixBlend_First:
|
if (alpha != 1) {
|
||||||
a = color.a + (setup.a - color.a) * alpha;
|
if (fromSetup) {
|
||||||
break;
|
Color &setup = slot->_data._setup._color;
|
||||||
default:
|
a = setup.a + (a - setup.a) * alpha;
|
||||||
return;
|
} else
|
||||||
}
|
a = color.a + (a - color.a) * alpha;
|
||||||
} else {
|
|
||||||
a = getCurveValue(time);
|
|
||||||
if (alpha != 1) {
|
|
||||||
if (blend == MixBlend_Setup) {
|
|
||||||
Color &setup = slot->_data._setup._color;
|
|
||||||
a = setup.a + (a - setup.a) * alpha;
|
|
||||||
} else
|
|
||||||
a = color.a + (a - color.a) * alpha;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
color.a = a < 0 ? 0 : (a > 1 ? 1 : a);
|
color.a = a < 0 ? 0 : (a > 1 ? 1 : a);
|
||||||
}
|
}
|
||||||
@ -278,93 +258,84 @@ void RGBA2Timeline::setFrame(int frame, float time, float r, float g, float b, f
|
|||||||
_frames[frame + B2] = b2;
|
_frames[frame + B2] = b2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RGBA2Timeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) {
|
void RGBA2Timeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) {
|
||||||
|
SP_UNUSED(add);
|
||||||
Color &light = pose._color;
|
Color &light = pose._color;
|
||||||
Color &dark = pose._darkColor;
|
Color &dark = pose._darkColor;
|
||||||
float r2, g2, b2;
|
float r2, g2, b2;
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) {
|
||||||
|
if (fromSetup) {
|
||||||
|
SlotPose &setup = slot._data._setup;
|
||||||
|
light.set(setup._color);
|
||||||
|
Color &setupDark = setup._darkColor;
|
||||||
|
dark.r = setupDark.r;
|
||||||
|
dark.g = setupDark.g;
|
||||||
|
dark.b = setupDark.b;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float r, g, b, a;
|
||||||
|
int i = Animation::search(_frames, time, ENTRIES);
|
||||||
|
int curveType = (int) _curves[i >> 3];
|
||||||
|
switch (curveType) {
|
||||||
|
case LINEAR: {
|
||||||
|
float before = _frames[i];
|
||||||
|
r = _frames[i + R];
|
||||||
|
g = _frames[i + G];
|
||||||
|
b = _frames[i + B];
|
||||||
|
a = _frames[i + A];
|
||||||
|
r2 = _frames[i + R2];
|
||||||
|
g2 = _frames[i + G2];
|
||||||
|
b2 = _frames[i + B2];
|
||||||
|
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||||
|
r += (_frames[i + ENTRIES + R] - r) * t;
|
||||||
|
g += (_frames[i + ENTRIES + G] - g) * t;
|
||||||
|
b += (_frames[i + ENTRIES + B] - b) * t;
|
||||||
|
a += (_frames[i + ENTRIES + A] - a) * t;
|
||||||
|
r2 += (_frames[i + ENTRIES + R2] - r2) * t;
|
||||||
|
g2 += (_frames[i + ENTRIES + G2] - g2) * t;
|
||||||
|
b2 += (_frames[i + ENTRIES + B2] - b2) * t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STEPPED: {
|
||||||
|
r = _frames[i + R];
|
||||||
|
g = _frames[i + G];
|
||||||
|
b = _frames[i + B];
|
||||||
|
a = _frames[i + A];
|
||||||
|
r2 = _frames[i + R2];
|
||||||
|
g2 = _frames[i + G2];
|
||||||
|
b2 = _frames[i + B2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
r = getBezierValue(time, i, R, curveType - BEZIER);
|
||||||
|
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
||||||
|
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||||
|
a = getBezierValue(time, i, A, curveType + BEZIER_SIZE * 3 - BEZIER);
|
||||||
|
r2 = getBezierValue(time, i, R2, curveType + BEZIER_SIZE * 4 - BEZIER);
|
||||||
|
g2 = getBezierValue(time, i, G2, curveType + BEZIER_SIZE * 5 - BEZIER);
|
||||||
|
b2 = getBezierValue(time, i, B2, curveType + BEZIER_SIZE * 6 - BEZIER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alpha == 1)
|
||||||
|
light.set(r, g, b, a);
|
||||||
|
else if (fromSetup) {
|
||||||
SlotPose &setup = slot._data._setup;
|
SlotPose &setup = slot._data._setup;
|
||||||
Color &setupLight = setup._color;
|
Color &setupLight = setup._color;
|
||||||
|
light.set(setupLight.r + (r - setupLight.r) * alpha, setupLight.g + (g - setupLight.g) * alpha, setupLight.b + (b - setupLight.b) * alpha,
|
||||||
|
setupLight.a + (a - setupLight.a) * alpha);
|
||||||
Color &setupDark = setup._darkColor;
|
Color &setupDark = setup._darkColor;
|
||||||
switch (blend) {
|
r2 = setupDark.r + (r2 - setupDark.r) * alpha;
|
||||||
case MixBlend_Setup:
|
g2 = setupDark.g + (g2 - setupDark.g) * alpha;
|
||||||
light.set(setupLight);
|
b2 = setupDark.b + (b2 - setupDark.b) * alpha;
|
||||||
dark.r = setupDark.r;
|
|
||||||
dark.g = setupDark.g;
|
|
||||||
dark.b = setupDark.b;
|
|
||||||
/* Fall through. */
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
case MixBlend_First:
|
|
||||||
light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha,
|
|
||||||
(setupLight.a - light.a) * alpha);
|
|
||||||
r2 = dark.r + (setupDark.r - dark.r) * alpha;
|
|
||||||
g2 = dark.g + (setupDark.g - dark.g) * alpha;
|
|
||||||
b2 = dark.b + (setupDark.b - dark.b) * alpha;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
float r, g, b, a;
|
light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);
|
||||||
int i = Animation::search(_frames, time, ENTRIES);
|
r2 = dark.r + (r2 - dark.r) * alpha;
|
||||||
int curveType = (int) _curves[i >> 3];
|
g2 = dark.g + (g2 - dark.g) * alpha;
|
||||||
switch (curveType) {
|
b2 = dark.b + (b2 - dark.b) * alpha;
|
||||||
case LINEAR: {
|
|
||||||
float before = _frames[i];
|
|
||||||
r = _frames[i + R];
|
|
||||||
g = _frames[i + G];
|
|
||||||
b = _frames[i + B];
|
|
||||||
a = _frames[i + A];
|
|
||||||
r2 = _frames[i + R2];
|
|
||||||
g2 = _frames[i + G2];
|
|
||||||
b2 = _frames[i + B2];
|
|
||||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
|
||||||
r += (_frames[i + ENTRIES + R] - r) * t;
|
|
||||||
g += (_frames[i + ENTRIES + G] - g) * t;
|
|
||||||
b += (_frames[i + ENTRIES + B] - b) * t;
|
|
||||||
a += (_frames[i + ENTRIES + A] - a) * t;
|
|
||||||
r2 += (_frames[i + ENTRIES + R2] - r2) * t;
|
|
||||||
g2 += (_frames[i + ENTRIES + G2] - g2) * t;
|
|
||||||
b2 += (_frames[i + ENTRIES + B2] - b2) * t;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STEPPED: {
|
|
||||||
r = _frames[i + R];
|
|
||||||
g = _frames[i + G];
|
|
||||||
b = _frames[i + B];
|
|
||||||
a = _frames[i + A];
|
|
||||||
r2 = _frames[i + R2];
|
|
||||||
g2 = _frames[i + G2];
|
|
||||||
b2 = _frames[i + B2];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
r = getBezierValue(time, i, R, curveType - BEZIER);
|
|
||||||
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
|
||||||
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
|
||||||
a = getBezierValue(time, i, A, curveType + BEZIER_SIZE * 3 - BEZIER);
|
|
||||||
r2 = getBezierValue(time, i, R2, curveType + BEZIER_SIZE * 4 - BEZIER);
|
|
||||||
g2 = getBezierValue(time, i, G2, curveType + BEZIER_SIZE * 5 - BEZIER);
|
|
||||||
b2 = getBezierValue(time, i, B2, curveType + BEZIER_SIZE * 6 - BEZIER);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alpha == 1)
|
|
||||||
light.set(r, g, b, a);
|
|
||||||
else if (blend == MixBlend_Setup) {
|
|
||||||
SlotPose &setup = slot._data._setup;
|
|
||||||
Color &setupLight = setup._color;
|
|
||||||
light.set(setupLight.r + (r - setupLight.r) * alpha, setupLight.g + (g - setupLight.g) * alpha, setupLight.b + (b - setupLight.b) * alpha,
|
|
||||||
setupLight.a + (a - setupLight.a) * alpha);
|
|
||||||
Color &setupDark = setup._darkColor;
|
|
||||||
r2 = setupDark.r + (r2 - setupDark.r) * alpha;
|
|
||||||
g2 = setupDark.g + (g2 - setupDark.g) * alpha;
|
|
||||||
b2 = setupDark.b + (b2 - setupDark.b) * alpha;
|
|
||||||
} else {
|
|
||||||
light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);
|
|
||||||
r2 = dark.r + (r2 - dark.r) * alpha;
|
|
||||||
g2 = dark.g + (g2 - dark.g) * alpha;
|
|
||||||
b2 = dark.b + (b2 - dark.b) * alpha;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dark.r = r2 < 0 ? 0 : (r2 > 1 ? 1 : r2);
|
dark.r = r2 < 0 ? 0 : (r2 > 1 ? 1 : r2);
|
||||||
@ -393,93 +364,84 @@ void RGB2Timeline::setFrame(int frame, float time, float r, float g, float b, fl
|
|||||||
_frames[frame + B2] = b2;
|
_frames[frame + B2] = b2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RGB2Timeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) {
|
void RGB2Timeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) {
|
||||||
|
SP_UNUSED(add);
|
||||||
Color &light = pose._color;
|
Color &light = pose._color;
|
||||||
Color &dark = pose._darkColor;
|
Color &dark = pose._darkColor;
|
||||||
float r, g, b, r2, g2, b2;
|
float r, g, b, r2, g2, b2;
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) {
|
||||||
SlotPose &setup = slot._data._setup;
|
if (fromSetup) {
|
||||||
Color &setupLight = setup._color;
|
SlotPose &setup = slot._data._setup;
|
||||||
Color &setupDark = setup._darkColor;
|
Color &setupLight = setup._color;
|
||||||
switch (blend) {
|
Color &setupDark = setup._darkColor;
|
||||||
case MixBlend_Setup:
|
light.r = setupLight.r;
|
||||||
light.r = setupLight.r;
|
light.g = setupLight.g;
|
||||||
light.g = setupLight.g;
|
light.b = setupLight.b;
|
||||||
light.b = setupLight.b;
|
dark.r = setupDark.r;
|
||||||
dark.r = setupDark.r;
|
dark.g = setupDark.g;
|
||||||
dark.g = setupDark.g;
|
dark.b = setupDark.b;
|
||||||
dark.b = setupDark.b;
|
|
||||||
/* Fall through. */
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
case MixBlend_First:
|
|
||||||
r = light.r + (setupLight.r - light.r) * alpha;
|
|
||||||
g = light.g + (setupLight.g - light.g) * alpha;
|
|
||||||
b = light.b + (setupLight.b - light.b) * alpha;
|
|
||||||
r2 = dark.r + (setupDark.r - dark.r) * alpha;
|
|
||||||
g2 = dark.g + (setupDark.g - dark.g) * alpha;
|
|
||||||
b2 = dark.b + (setupDark.b - dark.b) * alpha;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int i = Animation::search(_frames, time, ENTRIES);
|
|
||||||
int curveType = (int) _curves[i / ENTRIES];
|
|
||||||
switch (curveType) {
|
|
||||||
case LINEAR: {
|
|
||||||
float before = _frames[i];
|
|
||||||
r = _frames[i + R];
|
|
||||||
g = _frames[i + G];
|
|
||||||
b = _frames[i + B];
|
|
||||||
r2 = _frames[i + R2];
|
|
||||||
g2 = _frames[i + G2];
|
|
||||||
b2 = _frames[i + B2];
|
|
||||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
|
||||||
r += (_frames[i + ENTRIES + R] - r) * t;
|
|
||||||
g += (_frames[i + ENTRIES + G] - g) * t;
|
|
||||||
b += (_frames[i + ENTRIES + B] - b) * t;
|
|
||||||
r2 += (_frames[i + ENTRIES + R2] - r2) * t;
|
|
||||||
g2 += (_frames[i + ENTRIES + G2] - g2) * t;
|
|
||||||
b2 += (_frames[i + ENTRIES + B2] - b2) * t;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STEPPED: {
|
|
||||||
r = _frames[i + R];
|
|
||||||
g = _frames[i + G];
|
|
||||||
b = _frames[i + B];
|
|
||||||
r2 = _frames[i + R2];
|
|
||||||
g2 = _frames[i + G2];
|
|
||||||
b2 = _frames[i + B2];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
r = getBezierValue(time, i, R, curveType - BEZIER);
|
|
||||||
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
|
||||||
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
|
||||||
r2 = getBezierValue(time, i, R2, curveType + BEZIER_SIZE * 3 - BEZIER);
|
|
||||||
g2 = getBezierValue(time, i, G2, curveType + BEZIER_SIZE * 4 - BEZIER);
|
|
||||||
b2 = getBezierValue(time, i, B2, curveType + BEZIER_SIZE * 5 - BEZIER);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (alpha != 1) {
|
int i = Animation::search(_frames, time, ENTRIES);
|
||||||
if (blend == MixBlend_Setup) {
|
int curveType = (int) _curves[i / ENTRIES];
|
||||||
SlotPose &setup = slot._data._setup;
|
switch (curveType) {
|
||||||
Color &setupLight = setup._color;
|
case LINEAR: {
|
||||||
r = setupLight.r + (r - setupLight.r) * alpha;
|
float before = _frames[i];
|
||||||
g = setupLight.g + (g - setupLight.g) * alpha;
|
r = _frames[i + R];
|
||||||
b = setupLight.b + (b - setupLight.b) * alpha;
|
g = _frames[i + G];
|
||||||
Color &setupDark = setup._darkColor;
|
b = _frames[i + B];
|
||||||
r2 = setupDark.r + (r2 - setupDark.r) * alpha;
|
r2 = _frames[i + R2];
|
||||||
g2 = setupDark.g + (g2 - setupDark.g) * alpha;
|
g2 = _frames[i + G2];
|
||||||
b2 = setupDark.b + (b2 - setupDark.b) * alpha;
|
b2 = _frames[i + B2];
|
||||||
} else {
|
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||||
r = light.r + (r - light.r) * alpha;
|
r += (_frames[i + ENTRIES + R] - r) * t;
|
||||||
g = light.g + (g - light.g) * alpha;
|
g += (_frames[i + ENTRIES + G] - g) * t;
|
||||||
b = light.b + (b - light.b) * alpha;
|
b += (_frames[i + ENTRIES + B] - b) * t;
|
||||||
r2 = dark.r + (r2 - dark.r) * alpha;
|
r2 += (_frames[i + ENTRIES + R2] - r2) * t;
|
||||||
g2 = dark.g + (g2 - dark.g) * alpha;
|
g2 += (_frames[i + ENTRIES + G2] - g2) * t;
|
||||||
b2 = dark.b + (b2 - dark.b) * alpha;
|
b2 += (_frames[i + ENTRIES + B2] - b2) * t;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
case STEPPED: {
|
||||||
|
r = _frames[i + R];
|
||||||
|
g = _frames[i + G];
|
||||||
|
b = _frames[i + B];
|
||||||
|
r2 = _frames[i + R2];
|
||||||
|
g2 = _frames[i + G2];
|
||||||
|
b2 = _frames[i + B2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
r = getBezierValue(time, i, R, curveType - BEZIER);
|
||||||
|
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
||||||
|
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||||
|
r2 = getBezierValue(time, i, R2, curveType + BEZIER_SIZE * 3 - BEZIER);
|
||||||
|
g2 = getBezierValue(time, i, G2, curveType + BEZIER_SIZE * 4 - BEZIER);
|
||||||
|
b2 = getBezierValue(time, i, B2, curveType + BEZIER_SIZE * 5 - BEZIER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alpha != 1) {
|
||||||
|
if (fromSetup) {
|
||||||
|
SlotPose &setup = slot._data._setup;
|
||||||
|
Color &setupLight = setup._color;
|
||||||
|
r = setupLight.r + (r - setupLight.r) * alpha;
|
||||||
|
g = setupLight.g + (g - setupLight.g) * alpha;
|
||||||
|
b = setupLight.b + (b - setupLight.b) * alpha;
|
||||||
|
Color &setupDark = setup._darkColor;
|
||||||
|
r2 = setupDark.r + (r2 - setupDark.r) * alpha;
|
||||||
|
g2 = setupDark.g + (g2 - setupDark.g) * alpha;
|
||||||
|
b2 = setupDark.b + (b2 - setupDark.b) * alpha;
|
||||||
|
} else {
|
||||||
|
r = light.r + (r - light.r) * alpha;
|
||||||
|
g = light.g + (g - light.g) * alpha;
|
||||||
|
b = light.b + (b - light.b) * alpha;
|
||||||
|
r2 = dark.r + (r2 - dark.r) * alpha;
|
||||||
|
g2 = dark.g + (g2 - dark.g) * alpha;
|
||||||
|
b2 = dark.b + (b2 - dark.b) * alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -130,117 +130,30 @@ float CurveTimeline1::getCurveValue(float time) {
|
|||||||
return getBezierValue(time, i, CurveTimeline1::VALUE, curveType - CurveTimeline1::BEZIER);
|
return getBezierValue(time, i, CurveTimeline1::VALUE, curveType - CurveTimeline1::BEZIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
float CurveTimeline1::getRelativeValue(float time, float alpha, MixBlend blend, float current, float setup) {
|
float CurveTimeline1::getRelativeValue(float time, float alpha, bool fromSetup, bool add, float current, float setup) {
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||||
switch (blend) {
|
|
||||||
case MixBlend_Setup:
|
|
||||||
return setup;
|
|
||||||
case MixBlend_First:
|
|
||||||
return current + (setup - current) * alpha;
|
|
||||||
default:
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
float value = getCurveValue(time);
|
float value = getCurveValue(time);
|
||||||
switch (blend) {
|
return fromSetup ? setup + value * alpha : current + (add ? value : value + setup - current) * alpha;
|
||||||
case MixBlend_Setup:
|
|
||||||
return setup + value * alpha;
|
|
||||||
case MixBlend_First:
|
|
||||||
case MixBlend_Replace:
|
|
||||||
return current + (value + setup - current) * alpha;
|
|
||||||
case MixBlend_Add:
|
|
||||||
return current + value * alpha;
|
|
||||||
}
|
|
||||||
return current;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float CurveTimeline1::getAbsoluteValue(float time, float alpha, MixBlend blend, float current, float setup) {
|
float CurveTimeline1::getAbsoluteValue(float time, float alpha, bool fromSetup, bool add, float current, float setup) {
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||||
switch (blend) {
|
|
||||||
case MixBlend_Setup:
|
|
||||||
return setup;
|
|
||||||
case MixBlend_First:
|
|
||||||
return current + (setup - current) * alpha;
|
|
||||||
default:
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
float value = getCurveValue(time);
|
float value = getCurveValue(time);
|
||||||
switch (blend) {
|
return fromSetup ? setup + (value - setup) * alpha : current + (add ? value : value - current) * alpha;
|
||||||
case MixBlend_Setup:
|
|
||||||
return setup + (value - setup) * alpha;
|
|
||||||
case MixBlend_First:
|
|
||||||
case MixBlend_Replace:
|
|
||||||
return current + (value - current) * alpha;
|
|
||||||
case MixBlend_Add:
|
|
||||||
return current + value * alpha;
|
|
||||||
}
|
|
||||||
return current;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float CurveTimeline1::getAbsoluteValue(float time, float alpha, MixBlend blend, float current, float setup, float value) {
|
float CurveTimeline1::getAbsoluteValue(float time, float alpha, bool fromSetup, bool add, float current, float setup, float value) {
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||||
switch (blend) {
|
return fromSetup ? setup + (value - setup) * alpha : current + (add ? value : value - current) * alpha;
|
||||||
case MixBlend_Setup:
|
|
||||||
return setup;
|
|
||||||
case MixBlend_First:
|
|
||||||
return current + (setup - current) * alpha;
|
|
||||||
default:
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (blend) {
|
|
||||||
case MixBlend_Setup:
|
|
||||||
return setup + (value - setup) * alpha;
|
|
||||||
case MixBlend_First:
|
|
||||||
case MixBlend_Replace:
|
|
||||||
return current + (value - current) * alpha;
|
|
||||||
case MixBlend_Add:
|
|
||||||
return current + value * alpha;
|
|
||||||
}
|
|
||||||
return current;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float CurveTimeline1::getScaleValue(float time, float alpha, MixBlend blend, MixDirection direction, float current, float setup) {
|
float CurveTimeline1::getScaleValue(float time, float alpha, bool fromSetup, bool add, bool out, float current, float setup) {
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||||
switch (blend) {
|
|
||||||
case MixBlend_Setup:
|
|
||||||
return setup;
|
|
||||||
case MixBlend_First:
|
|
||||||
return current + (setup - current) * alpha;
|
|
||||||
default:
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
float value = getCurveValue(time) * setup;
|
float value = getCurveValue(time) * setup;
|
||||||
if (alpha == 1) {
|
if (alpha == 1 && !add) return value;
|
||||||
if (blend == MixBlend_Add) return current + value - setup;
|
float base = fromSetup ? setup : current;
|
||||||
return value;
|
if (add) return base + (value - setup) * alpha;
|
||||||
}
|
if (out) return base + (MathUtil::abs(value) * MathUtil::sign(base) - base) * alpha;
|
||||||
// Mixing out uses sign of setup or current pose, else use sign of key.
|
base = MathUtil::abs(base) * MathUtil::sign(value);
|
||||||
if (direction == MixDirection_Out) {
|
return base + (value - base) * alpha;
|
||||||
switch (blend) {
|
|
||||||
case MixBlend_Setup:
|
|
||||||
return setup + (MathUtil::abs(value) * MathUtil::sign(setup) - setup) * alpha;
|
|
||||||
case MixBlend_First:
|
|
||||||
case MixBlend_Replace:
|
|
||||||
return current + (MathUtil::abs(value) * MathUtil::sign(current) - current) * alpha;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
float s;
|
|
||||||
switch (blend) {
|
|
||||||
case MixBlend_Setup:
|
|
||||||
s = MathUtil::abs(setup) * MathUtil::sign(value);
|
|
||||||
return s + (value - s) * alpha;
|
|
||||||
case MixBlend_First:
|
|
||||||
case MixBlend_Replace:
|
|
||||||
s = MathUtil::abs(current) * MathUtil::sign(value);
|
|
||||||
return s + (value - s) * alpha;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return current + (value - setup) * alpha;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,7 @@ DeformTimeline::DeformTimeline(size_t frameCount, size_t bezierCount, int slotIn
|
|||||||
: SlotCurveTimeline(frameCount, 1, bezierCount, slotIndex), _attachment(&attachment) {
|
: SlotCurveTimeline(frameCount, 1, bezierCount, slotIndex), _attachment(&attachment) {
|
||||||
PropertyId ids[] = {((PropertyId) Property_Deform << 32) | ((slotIndex << 16 | attachment._id) & 0xffffffff)};
|
PropertyId ids[] = {((PropertyId) Property_Deform << 32) | ((slotIndex << 16 | attachment._id) & 0xffffffff)};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
|
_additive = true;
|
||||||
|
|
||||||
_vertices.ensureCapacity(frameCount);
|
_vertices.ensureCapacity(frameCount);
|
||||||
for (size_t i = 0; i < frameCount; ++i) {
|
for (size_t i = 0; i < frameCount; ++i) {
|
||||||
@ -56,7 +57,8 @@ DeformTimeline::DeformTimeline(size_t frameCount, size_t bezierCount, int slotIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DeformTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) {
|
void DeformTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, bool fromSetup, bool add) {
|
||||||
|
SP_UNUSED(slot);
|
||||||
Attachment *slotAttachment = pose._attachment;
|
Attachment *slotAttachment = pose._attachment;
|
||||||
if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) {
|
if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) {
|
||||||
return;
|
return;
|
||||||
@ -68,41 +70,14 @@ void DeformTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Array<float> &deformArray = pose._deform;
|
Array<float> &deformArray = pose._deform;
|
||||||
if (deformArray.size() == 0) {
|
if (deformArray.size() == 0) fromSetup = true;
|
||||||
blend = MixBlend_Setup;
|
|
||||||
}
|
|
||||||
|
|
||||||
Array<Array<float>> &vertices = _vertices;
|
Array<Array<float>> &vertices = _vertices;
|
||||||
size_t vertexCount = vertices[0].size();
|
size_t vertexCount = vertices[0].size();
|
||||||
|
|
||||||
Array<float> &frames = _frames;
|
Array<float> &frames = _frames;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
switch (blend) {
|
if (fromSetup) deformArray.clear();
|
||||||
case MixBlend_Setup:
|
|
||||||
deformArray.clear();
|
|
||||||
return;
|
|
||||||
case MixBlend_First: {
|
|
||||||
if (alpha == 1) {
|
|
||||||
deformArray.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
deformArray.setSize(vertexCount, 0);
|
|
||||||
Array<float> &deform = deformArray;
|
|
||||||
if (vertexAttachment->getBones().size() == 0) {
|
|
||||||
// Unweighted vertex positions.
|
|
||||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
|
||||||
for (size_t i = 0; i < vertexCount; i++) deform[i] += (setupVertices[i] - deform[i]) * alpha;
|
|
||||||
} else {
|
|
||||||
// Weighted deform offsets.
|
|
||||||
alpha = 1 - alpha;
|
|
||||||
for (size_t i = 0; i < vertexCount; i++) deform[i] *= alpha;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MixBlend_Replace:
|
|
||||||
case MixBlend_Add:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +87,7 @@ void DeformTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha,
|
|||||||
if (time >= frames[frames.size() - 1]) {// Time is after last frame.
|
if (time >= frames[frames.size() - 1]) {// Time is after last frame.
|
||||||
Array<float> &lastVertices = vertices[frames.size() - 1];
|
Array<float> &lastVertices = vertices[frames.size() - 1];
|
||||||
if (alpha == 1) {
|
if (alpha == 1) {
|
||||||
if (blend == MixBlend_Add) {
|
if (add && !fromSetup) {
|
||||||
if (vertexAttachment->getBones().size() == 0) {
|
if (vertexAttachment->getBones().size() == 0) {
|
||||||
// Unweighted vertex positions, no alpha.
|
// Unweighted vertex positions, no alpha.
|
||||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||||
@ -125,38 +100,30 @@ void DeformTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha,
|
|||||||
// Vertex positions or deform offsets, no alpha.
|
// Vertex positions or deform offsets, no alpha.
|
||||||
memcpy(deform.buffer(), lastVertices.buffer(), vertexCount * sizeof(float));
|
memcpy(deform.buffer(), lastVertices.buffer(), vertexCount * sizeof(float));
|
||||||
}
|
}
|
||||||
} else {
|
} else if (fromSetup) {
|
||||||
switch (blend) {
|
if (vertexAttachment->getBones().size() == 0) {
|
||||||
case MixBlend_Setup: {
|
// Unweighted vertex positions, with alpha.
|
||||||
if (vertexAttachment->getBones().size() == 0) {
|
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||||
// Unweighted vertex positions, with alpha.
|
for (size_t i = 0; i < vertexCount; i++) {
|
||||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
float setup = setupVertices[i];
|
||||||
for (size_t i = 0; i < vertexCount; i++) {
|
deform[i] = setup + (lastVertices[i] - setup) * alpha;
|
||||||
float setup = setupVertices[i];
|
|
||||||
deform[i] = setup + (lastVertices[i] - setup) * alpha;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Weighted deform offsets, with alpha.
|
|
||||||
for (size_t i = 0; i < vertexCount; i++) deform[i] = lastVertices[i] * alpha;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case MixBlend_First:
|
} else {
|
||||||
case MixBlend_Replace:
|
// Weighted deform offsets, with alpha.
|
||||||
// Vertex positions or deform offsets, with alpha.
|
for (size_t i = 0; i < vertexCount; i++) deform[i] = lastVertices[i] * alpha;
|
||||||
for (size_t i = 0; i < vertexCount; i++) deform[i] += (lastVertices[i] - deform[i]) * alpha;
|
|
||||||
break;
|
|
||||||
case MixBlend_Add:
|
|
||||||
if (vertexAttachment->getBones().size() == 0) {
|
|
||||||
// Unweighted vertex positions, with alpha.
|
|
||||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
|
||||||
for (size_t i = 0; i < vertexCount; i++) deform[i] += (lastVertices[i] - setupVertices[i]) * alpha;
|
|
||||||
} else {
|
|
||||||
// Weighted deform offsets, alpha.
|
|
||||||
for (size_t i = 0; i < vertexCount; i++) deform[i] += lastVertices[i] * alpha;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} else if (add) {
|
||||||
|
if (vertexAttachment->getBones().size() == 0) {
|
||||||
|
// Unweighted vertex positions, with alpha.
|
||||||
|
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||||
|
for (size_t i = 0; i < vertexCount; i++) deform[i] += (lastVertices[i] - setupVertices[i]) * alpha;
|
||||||
|
} else {
|
||||||
|
// Weighted deform offsets, with alpha.
|
||||||
|
for (size_t i = 0; i < vertexCount; i++) deform[i] += lastVertices[i] * alpha;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Vertex positions or deform offsets, with alpha.
|
||||||
|
for (size_t i = 0; i < vertexCount; i++) deform[i] += (lastVertices[i] - deform[i]) * alpha;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -168,7 +135,7 @@ void DeformTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha,
|
|||||||
Array<float> &nextVertices = vertices[frame + 1];
|
Array<float> &nextVertices = vertices[frame + 1];
|
||||||
|
|
||||||
if (alpha == 1) {
|
if (alpha == 1) {
|
||||||
if (blend == MixBlend_Add) {
|
if (add && !fromSetup) {
|
||||||
if (vertexAttachment->getBones().size() == 0) {
|
if (vertexAttachment->getBones().size() == 0) {
|
||||||
// Unweighted vertex positions, no alpha.
|
// Unweighted vertex positions, no alpha.
|
||||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||||
@ -192,49 +159,41 @@ void DeformTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha,
|
|||||||
deform[i] = prev + (nextVertices[i] - prev) * percent;
|
deform[i] = prev + (nextVertices[i] - prev) * percent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if (fromSetup) {
|
||||||
switch (blend) {
|
if (vertexAttachment->getBones().size() == 0) {
|
||||||
case MixBlend_Setup: {
|
// Unweighted vertex positions, with alpha.
|
||||||
if (vertexAttachment->getBones().size() == 0) {
|
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||||
// Unweighted vertex positions, with alpha.
|
for (size_t i = 0; i < vertexCount; i++) {
|
||||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
float prev = prevVertices[i], setup = setupVertices[i];
|
||||||
for (size_t i = 0; i < vertexCount; i++) {
|
deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
|
||||||
float prev = prevVertices[i], setup = setupVertices[i];
|
|
||||||
deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Weighted deform offsets, with alpha.
|
|
||||||
for (size_t i = 0; i < vertexCount; i++) {
|
|
||||||
float prev = prevVertices[i];
|
|
||||||
deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case MixBlend_First:
|
} else {
|
||||||
case MixBlend_Replace:
|
// Weighted deform offsets, with alpha.
|
||||||
// Vertex positions or deform offsets, with alpha.
|
for (size_t i = 0; i < vertexCount; i++) {
|
||||||
for (size_t i = 0; i < vertexCount; i++) {
|
float prev = prevVertices[i];
|
||||||
float prev = prevVertices[i];
|
deform[i] = (prev + (nextVertices[i] - prev) * percent) * alpha;
|
||||||
deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha;
|
}
|
||||||
}
|
}
|
||||||
break;
|
} else if (add) {
|
||||||
case MixBlend_Add:
|
if (vertexAttachment->getBones().size() == 0) {
|
||||||
if (vertexAttachment->getBones().size() == 0) {
|
// Unweighted vertex positions, with alpha.
|
||||||
// Unweighted vertex positions, with alpha.
|
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
for (size_t i = 0; i < vertexCount; i++) {
|
||||||
for (size_t i = 0; i < vertexCount; i++) {
|
float prev = prevVertices[i];
|
||||||
float prev = prevVertices[i];
|
deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha;
|
||||||
deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha;
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
// Weighted deform offsets, with alpha.
|
||||||
// Weighted deform offsets, with alpha.
|
for (size_t i = 0; i < vertexCount; i++) {
|
||||||
for (size_t i = 0; i < vertexCount; i++) {
|
float prev = prevVertices[i];
|
||||||
float prev = prevVertices[i];
|
deform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha;
|
||||||
deform[i] += (prev + (nextVertices[i] - prev) * percent) * alpha;
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
break;
|
// Vertex positions or deform offsets, with alpha.
|
||||||
|
for (size_t i = 0; i < vertexCount; i++) {
|
||||||
|
float prev = prevVertices[i];
|
||||||
|
deform[i] += (prev + (nextVertices[i] - prev) * percent - deform[i]) * alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,23 +49,23 @@ DrawOrderFolderTimeline::DrawOrderFolderTimeline(size_t frameCount, Array<int> &
|
|||||||
_drawOrders.ensureCapacity(frameCount);
|
_drawOrders.ensureCapacity(frameCount);
|
||||||
_inFolder.setSize(slotCount, false);
|
_inFolder.setSize(slotCount, false);
|
||||||
for (size_t i = 0; i < _slots.size(); ++i) _inFolder[_slots[i]] = true;
|
for (size_t i = 0; i < _slots.size(); ++i) _inFolder[_slots[i]] = true;
|
||||||
|
_instant = true;
|
||||||
for (size_t i = 0; i < frameCount; ++i) {
|
for (size_t i = 0; i < frameCount; ++i) {
|
||||||
Array<int> vec;
|
Array<int> vec;
|
||||||
_drawOrders.add(vec);
|
_drawOrders.add(vec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawOrderFolderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void DrawOrderFolderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool out, bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(alpha);
|
SP_UNUSED(alpha);
|
||||||
|
SP_UNUSED(add);
|
||||||
SP_UNUSED(appliedPose);
|
SP_UNUSED(appliedPose);
|
||||||
|
|
||||||
if (direction == MixDirection_Out) {
|
if (out || time < _frames[0]) {
|
||||||
if (blend == MixBlend_Setup) setup(skeleton);
|
if (fromSetup) setup(skeleton);
|
||||||
} else if (time < _frames[0]) {
|
|
||||||
if (blend == MixBlend_Setup || blend == MixBlend_First) setup(skeleton);
|
|
||||||
} else {
|
} else {
|
||||||
Array<int> &drawOrder = _drawOrders[Animation::search(_frames, time)];
|
Array<int> &drawOrder = _drawOrders[Animation::search(_frames, time)];
|
||||||
if (drawOrder.size() == 0)
|
if (drawOrder.size() == 0)
|
||||||
|
|||||||
@ -48,6 +48,7 @@ PropertyId DrawOrderTimeline::getPropertyId() {
|
|||||||
DrawOrderTimeline::DrawOrderTimeline(size_t frameCount) : Timeline(frameCount, 1) {
|
DrawOrderTimeline::DrawOrderTimeline(size_t frameCount) : Timeline(frameCount, 1) {
|
||||||
PropertyId ids[] = {getPropertyId()};
|
PropertyId ids[] = {getPropertyId()};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
|
_instant = true;
|
||||||
|
|
||||||
_drawOrders.ensureCapacity(frameCount);
|
_drawOrders.ensureCapacity(frameCount);
|
||||||
for (size_t i = 0; i < frameCount; ++i) {
|
for (size_t i = 0; i < frameCount; ++i) {
|
||||||
@ -56,26 +57,18 @@ DrawOrderTimeline::DrawOrderTimeline(size_t frameCount) : Timeline(frameCount, 1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool appliedPose) {
|
||||||
SP_UNUSED(appliedPose);
|
SP_UNUSED(appliedPose);
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(alpha);
|
SP_UNUSED(alpha);
|
||||||
|
SP_UNUSED(add);
|
||||||
|
|
||||||
Array<Slot *> &drawOrder = skeleton._drawOrder;
|
Array<Slot *> &drawOrder = skeleton._drawOrder;
|
||||||
Array<Slot *> &slots = skeleton._slots;
|
Array<Slot *> &slots = skeleton._slots;
|
||||||
if (direction == MixDirection_Out) {
|
if (out || time < _frames[0]) {
|
||||||
if (blend == MixBlend_Setup) {
|
if (fromSetup) {
|
||||||
drawOrder.clear();
|
|
||||||
drawOrder.ensureCapacity(slots.size());
|
|
||||||
for (size_t i = 0, n = slots.size(); i < n; ++i) drawOrder.add(slots[i]);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time < _frames[0]) {
|
|
||||||
if (blend == MixBlend_Setup || blend == MixBlend_First) {
|
|
||||||
drawOrder.clear();
|
drawOrder.clear();
|
||||||
drawOrder.ensureCapacity(slots.size());
|
drawOrder.ensureCapacity(slots.size());
|
||||||
for (size_t i = 0, n = slots.size(); i < n; ++i) drawOrder.add(slots[i]);
|
for (size_t i = 0, n = slots.size(); i < n; ++i) drawOrder.add(slots[i]);
|
||||||
|
|||||||
@ -49,14 +49,16 @@ EventTimeline::EventTimeline(size_t frameCount) : Timeline(frameCount, 1) {
|
|||||||
PropertyId ids[] = {((PropertyId) Property_Event << 32)};
|
PropertyId ids[] = {((PropertyId) Property_Event << 32)};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
_events.setSize(frameCount, NULL);
|
_events.setSize(frameCount, NULL);
|
||||||
|
_instant = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventTimeline::~EventTimeline() {
|
EventTimeline::~EventTimeline() {
|
||||||
ArrayUtils::deleteElements(_events);
|
ArrayUtils::deleteElements(_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *pEvents, float alpha, MixBlend blend,
|
void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *pEvents, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool appliedPose) {
|
||||||
|
SP_UNUSED(skeleton);
|
||||||
if (pEvents == NULL) return;
|
if (pEvents == NULL) return;
|
||||||
|
|
||||||
Array<Event *> &events = *pEvents;
|
Array<Event *> &events = *pEvents;
|
||||||
@ -65,7 +67,7 @@ void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<
|
|||||||
|
|
||||||
if (lastTime > time) {
|
if (lastTime > time) {
|
||||||
// Apply after lastTime for looped animations.
|
// Apply after lastTime for looped animations.
|
||||||
apply(skeleton, lastTime, FLT_MAX, pEvents, alpha, blend, direction, appliedPose);
|
apply(skeleton, lastTime, FLT_MAX, pEvents, 0, false, false, false, false);
|
||||||
lastTime = -1.0f;
|
lastTime = -1.0f;
|
||||||
} else if (lastTime >= _frames[frameCount - 1]) {
|
} else if (lastTime >= _frames[frameCount - 1]) {
|
||||||
// Last time is after last frame.
|
// Last time is after last frame.
|
||||||
|
|||||||
@ -53,35 +53,26 @@ IkConstraintTimeline::IkConstraintTimeline(size_t frameCount, size_t bezierCount
|
|||||||
IkConstraintTimeline::~IkConstraintTimeline() {
|
IkConstraintTimeline::~IkConstraintTimeline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool out, bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
|
SP_UNUSED(add);
|
||||||
|
|
||||||
IkConstraint *constraint = (IkConstraint *) skeleton._constraints[_constraintIndex];
|
IkConstraint *constraint = (IkConstraint *) skeleton._constraints[_constraintIndex];
|
||||||
if (!constraint->isActive()) return;
|
if (!constraint->isActive()) return;
|
||||||
IkConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
IkConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||||
|
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) {
|
||||||
IkConstraintPose &setup = constraint->_data._setup;
|
if (fromSetup) {
|
||||||
switch (blend) {
|
IkConstraintPose &setup = constraint->_data._setup;
|
||||||
case MixBlend_Setup:
|
pose._mix = setup._mix;
|
||||||
pose._mix = setup._mix;
|
pose._softness = setup._softness;
|
||||||
pose._softness = setup._softness;
|
pose._bendDirection = setup._bendDirection;
|
||||||
pose._bendDirection = setup._bendDirection;
|
pose._compress = setup._compress;
|
||||||
pose._compress = setup._compress;
|
pose._stretch = setup._stretch;
|
||||||
pose._stretch = setup._stretch;
|
|
||||||
return;
|
|
||||||
case MixBlend_First:
|
|
||||||
pose._mix += (setup._mix - pose._mix) * alpha;
|
|
||||||
pose._softness += (setup._softness - pose._softness) * alpha;
|
|
||||||
pose._bendDirection = setup._bendDirection;
|
|
||||||
pose._compress = setup._compress;
|
|
||||||
pose._stretch = setup._stretch;
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float mix = 0, softness = 0;
|
float mix = 0, softness = 0;
|
||||||
@ -108,24 +99,20 @@ void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blend == MixBlend_Setup) {
|
IkConstraintPose &base = fromSetup ? constraint->_data._setup : pose;
|
||||||
IkConstraintPose &setup = constraint->_data._setup;
|
pose._mix = base._mix + (mix - base._mix) * alpha;
|
||||||
pose._mix = setup._mix + (mix - setup._mix) * alpha;
|
pose._softness = base._softness + (softness - base._softness) * alpha;
|
||||||
pose._softness = setup._softness + (softness - setup._softness) * alpha;
|
if (out) {
|
||||||
if (direction == MixDirection_Out) {
|
if (fromSetup) {
|
||||||
pose._bendDirection = setup._bendDirection;
|
pose._bendDirection = base._bendDirection;
|
||||||
pose._compress = setup._compress;
|
pose._compress = base._compress;
|
||||||
pose._stretch = setup._stretch;
|
pose._stretch = base._stretch;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pose._mix += (mix - pose._mix) * alpha;
|
pose._bendDirection = (int) _frames[i + BEND_DIRECTION];
|
||||||
pose._softness += (softness - pose._softness) * alpha;
|
pose._compress = _frames[i + COMPRESS] != 0;
|
||||||
if (direction == MixDirection_Out) return;
|
pose._stretch = _frames[i + STRETCH] != 0;
|
||||||
}
|
}
|
||||||
pose._bendDirection = (int) _frames[i + BEND_DIRECTION];
|
|
||||||
pose._compress = _frames[i + COMPRESS] != 0;
|
|
||||||
pose._stretch = _frames[i + STRETCH] != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IkConstraintTimeline::setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, bool stretch) {
|
void IkConstraintTimeline::setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, bool stretch) {
|
||||||
|
|||||||
@ -45,6 +45,7 @@ RTTI_IMPL_MULTI(InheritTimeline, Timeline, BoneTimeline)
|
|||||||
InheritTimeline::InheritTimeline(size_t frameCount, int boneIndex) : Timeline(frameCount, ENTRIES), BoneTimeline(boneIndex) {
|
InheritTimeline::InheritTimeline(size_t frameCount, int boneIndex) : Timeline(frameCount, ENTRIES), BoneTimeline(boneIndex) {
|
||||||
PropertyId ids[] = {((PropertyId) Property_Inherit << 32) | boneIndex};
|
PropertyId ids[] = {((PropertyId) Property_Inherit << 32) | boneIndex};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
|
_instant = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
InheritTimeline::~InheritTimeline() {
|
InheritTimeline::~InheritTimeline() {
|
||||||
@ -56,26 +57,25 @@ void InheritTimeline::setFrame(int frame, float time, Inherit inherit) {
|
|||||||
_frames[frame + INHERIT] = (float) inherit;
|
_frames[frame + INHERIT] = (float) inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InheritTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
void InheritTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
bool appliedPose) {
|
||||||
MixDirection direction, bool appliedPose) {
|
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(alpha);
|
SP_UNUSED(alpha);
|
||||||
|
SP_UNUSED(add);
|
||||||
|
|
||||||
Bone *bone = skeleton._bones[_boneIndex];
|
Bone *bone = skeleton._bones[_boneIndex];
|
||||||
if (!bone->isActive()) return;
|
if (!bone->isActive()) return;
|
||||||
BoneLocal &pose = appliedPose ? *bone->_applied : bone->_pose;
|
BoneLocal &pose = appliedPose ? *bone->_applied : bone->_pose;
|
||||||
|
|
||||||
if (direction == MixDirection_Out) {
|
if (out) {
|
||||||
if (blend == MixBlend_Setup) pose._inherit = bone->_data._setup._inherit;
|
if (fromSetup) pose._inherit = bone->_data._setup._inherit;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time < _frames[0]) {
|
|
||||||
if (blend == MixBlend_Setup || blend == MixBlend_First) pose._inherit = bone->_data._setup._inherit;
|
|
||||||
} else {
|
} else {
|
||||||
int idx = Animation::search(_frames, time, ENTRIES) + INHERIT;
|
if (time < _frames[0]) {
|
||||||
pose._inherit = static_cast<Inherit>((int) _frames[idx]);
|
if (fromSetup) pose._inherit = bone->_data._setup._inherit;
|
||||||
|
} else {
|
||||||
|
int idx = Animation::search(_frames, time, ENTRIES) + INHERIT;
|
||||||
|
pose._inherit = static_cast<Inherit>((int) _frames[idx]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,37 +48,30 @@ PathConstraintMixTimeline::PathConstraintMixTimeline(size_t frameCount, size_t b
|
|||||||
: CurveTimeline(frameCount, PathConstraintMixTimeline::ENTRIES, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) {
|
: CurveTimeline(frameCount, PathConstraintMixTimeline::ENTRIES, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) {
|
||||||
PropertyId ids[] = {((PropertyId) Property_PathConstraintMix << 32) | constraintIndex};
|
PropertyId ids[] = {((PropertyId) Property_PathConstraintMix << 32) | constraintIndex};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
|
_additive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PathConstraintMixTimeline::~PathConstraintMixTimeline() {
|
PathConstraintMixTimeline::~PathConstraintMixTimeline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool out, bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(direction);
|
SP_UNUSED(out);
|
||||||
|
|
||||||
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
||||||
if (!constraint->isActive()) return;
|
if (!constraint->isActive()) return;
|
||||||
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||||
|
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) {
|
||||||
PathConstraintPose &setup = constraint->_data._setup;
|
if (fromSetup) {
|
||||||
switch (blend) {
|
PathConstraintPose &setup = constraint->_data._setup;
|
||||||
case MixBlend_Setup:
|
pose._mixRotate = setup._mixRotate;
|
||||||
pose._mixRotate = setup._mixRotate;
|
pose._mixX = setup._mixX;
|
||||||
pose._mixX = setup._mixX;
|
pose._mixY = setup._mixY;
|
||||||
pose._mixY = setup._mixY;
|
|
||||||
return;
|
|
||||||
case MixBlend_First:
|
|
||||||
pose._mixRotate += (setup._mixRotate - pose._mixRotate) * alpha;
|
|
||||||
pose._mixX += (setup._mixX - pose._mixX) * alpha;
|
|
||||||
pose._mixY += (setup._mixY - pose._mixY) * alpha;
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float rotate, x, y;
|
float rotate, x, y;
|
||||||
@ -109,15 +102,15 @@ void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blend == MixBlend_Setup) {
|
PathConstraintPose &base = fromSetup ? constraint->_data._setup : pose;
|
||||||
PathConstraintPose &setup = constraint->_data._setup;
|
if (add) {
|
||||||
pose._mixRotate = setup._mixRotate + (rotate - setup._mixRotate) * alpha;
|
pose._mixRotate = base._mixRotate + rotate * alpha;
|
||||||
pose._mixX = setup._mixX + (x - setup._mixX) * alpha;
|
pose._mixX = base._mixX + x * alpha;
|
||||||
pose._mixY = setup._mixY + (y - setup._mixY) * alpha;
|
pose._mixY = base._mixY + y * alpha;
|
||||||
} else {
|
} else {
|
||||||
pose._mixRotate += (rotate - pose._mixRotate) * alpha;
|
pose._mixRotate = base._mixRotate + (rotate - base._mixRotate) * alpha;
|
||||||
pose._mixX += (x - pose._mixX) * alpha;
|
pose._mixX = base._mixX + (x - base._mixX) * alpha;
|
||||||
pose._mixY += (y - pose._mixY) * alpha;
|
pose._mixY = base._mixY + (y - base._mixY) * alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,21 +45,22 @@ RTTI_IMPL(PathConstraintPositionTimeline, ConstraintTimeline1)
|
|||||||
|
|
||||||
PathConstraintPositionTimeline::PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int constraintIndex)
|
PathConstraintPositionTimeline::PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int constraintIndex)
|
||||||
: ConstraintTimeline1(frameCount, bezierCount, constraintIndex, Property_PathConstraintPosition) {
|
: ConstraintTimeline1(frameCount, bezierCount, constraintIndex, Property_PathConstraintPosition) {
|
||||||
|
_additive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PathConstraintPositionTimeline::~PathConstraintPositionTimeline() {
|
PathConstraintPositionTimeline::~PathConstraintPositionTimeline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool add, bool out, bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(direction);
|
SP_UNUSED(out);
|
||||||
|
|
||||||
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
||||||
if (constraint->isActive()) {
|
if (constraint->isActive()) {
|
||||||
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||||
PathConstraintData &data = constraint->_data;
|
PathConstraintData &data = constraint->_data;
|
||||||
pose._position = getAbsoluteValue(time, alpha, blend, pose._position, data._setup._position);
|
pose._position = getAbsoluteValue(time, alpha, fromSetup, add, pose._position, data._setup._position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,16 +50,16 @@ PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(size_t frameCount,
|
|||||||
PathConstraintSpacingTimeline::~PathConstraintSpacingTimeline() {
|
PathConstraintSpacingTimeline::~PathConstraintSpacingTimeline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool add, bool out, bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(direction);
|
SP_UNUSED(out);
|
||||||
|
|
||||||
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
||||||
if (constraint->isActive()) {
|
if (constraint->isActive()) {
|
||||||
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||||
PathConstraintData &data = constraint->_data;
|
PathConstraintData &data = constraint->_data;
|
||||||
pose._spacing = getAbsoluteValue(time, alpha, blend == MixBlend_Add ? MixBlend_Replace : blend, pose._spacing, data._setup._spacing);
|
pose._spacing = getAbsoluteValue(time, alpha, fromSetup, false, pose._spacing, data._setup._spacing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,14 +52,15 @@ RTTI_IMPL(PhysicsConstraintMixTimeline, PhysicsConstraintTimeline)
|
|||||||
RTTI_IMPL_MULTI(PhysicsConstraintResetTimeline, Timeline, ConstraintTimeline)
|
RTTI_IMPL_MULTI(PhysicsConstraintResetTimeline, Timeline, ConstraintTimeline)
|
||||||
|
|
||||||
PhysicsConstraintTimeline::PhysicsConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex, Property property)
|
PhysicsConstraintTimeline::PhysicsConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex, Property property)
|
||||||
: CurveTimeline1(frameCount, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex), _additive(false) {
|
: CurveTimeline1(frameCount, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) {
|
||||||
PropertyId ids[] = {((PropertyId) property << 32) | constraintIndex};
|
PropertyId ids[] = {((PropertyId) property << 32) | constraintIndex};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsConstraintTimeline::apply(Skeleton &skeleton, float, float time, Array<Event *> *, float alpha, MixBlend blend, MixDirection direction,
|
void PhysicsConstraintTimeline::apply(Skeleton &skeleton, float, float time, Array<Event *> *, float alpha, bool fromSetup, bool add, bool out,
|
||||||
bool appliedPose) {
|
bool appliedPose) {
|
||||||
if (blend == MixBlend_Add && !_additive) blend = MixBlend_Replace;
|
SP_UNUSED(out);
|
||||||
|
if (add && !_additive) add = false;
|
||||||
if (_constraintIndex == -1) {
|
if (_constraintIndex == -1) {
|
||||||
float value = time >= _frames[0] ? getCurveValue(time) : 0;
|
float value = time >= _frames[0] ? getCurveValue(time) : 0;
|
||||||
|
|
||||||
@ -68,20 +69,20 @@ void PhysicsConstraintTimeline::apply(Skeleton &skeleton, float, float time, Arr
|
|||||||
PhysicsConstraint *constraint = physicsConstraints[i];
|
PhysicsConstraint *constraint = physicsConstraints[i];
|
||||||
if (constraint->isActive() && global(constraint->_data)) {
|
if (constraint->isActive() && global(constraint->_data)) {
|
||||||
PhysicsConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
PhysicsConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||||
set(pose, getAbsoluteValue(time, alpha, blend, get(pose), get(constraint->_data._setup), value));
|
set(pose, getAbsoluteValue(time, alpha, fromSetup, add, get(pose), get(constraint->_data._setup), value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PhysicsConstraint *constraint = static_cast<PhysicsConstraint *>(skeleton.getConstraints()[_constraintIndex]);
|
PhysicsConstraint *constraint = static_cast<PhysicsConstraint *>(skeleton.getConstraints()[_constraintIndex]);
|
||||||
if (constraint->isActive()) {
|
if (constraint->isActive()) {
|
||||||
PhysicsConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
PhysicsConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||||
set(pose, getAbsoluteValue(time, alpha, blend, get(pose), get(constraint->_data._setup)));
|
set(pose, getAbsoluteValue(time, alpha, fromSetup, add, get(pose), get(constraint->_data._setup)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsConstraintResetTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *, float alpha, MixBlend blend,
|
void PhysicsConstraintResetTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *, float alpha, bool fromSetup, bool add,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool out, bool appliedPose) {
|
||||||
PhysicsConstraint *constraint = nullptr;
|
PhysicsConstraint *constraint = nullptr;
|
||||||
if (_constraintIndex != -1) {
|
if (_constraintIndex != -1) {
|
||||||
constraint = static_cast<PhysicsConstraint *>(skeleton.getConstraints()[_constraintIndex]);
|
constraint = static_cast<PhysicsConstraint *>(skeleton.getConstraints()[_constraintIndex]);
|
||||||
@ -89,7 +90,7 @@ void PhysicsConstraintResetTimeline::apply(Skeleton &skeleton, float lastTime, f
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lastTime > time) {// Apply after lastTime for looped animations.
|
if (lastTime > time) {// Apply after lastTime for looped animations.
|
||||||
apply(skeleton, lastTime, FLT_MAX, nullptr, alpha, blend, direction, appliedPose);
|
apply(skeleton, lastTime, FLT_MAX, nullptr, alpha, false, false, false, false);
|
||||||
lastTime = -1;
|
lastTime = -1;
|
||||||
} else if (lastTime >= _frames[_frames.size() - 1])// Last time is after last frame.
|
} else if (lastTime >= _frames[_frames.size() - 1])// Last time is after last frame.
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -39,7 +39,7 @@ RotateTimeline::RotateTimeline(size_t frameCount, size_t bezierCount, int boneIn
|
|||||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Rotate) {
|
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Rotate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RotateTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
void RotateTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||||
SP_UNUSED(direction);
|
SP_UNUSED(out);
|
||||||
pose._rotation = getRelativeValue(time, alpha, blend, pose._rotation, setup._rotation);
|
pose._rotation = getRelativeValue(time, alpha, fromSetup, add, pose._rotation, setup._rotation);
|
||||||
}
|
}
|
||||||
@ -46,18 +46,11 @@ ScaleTimeline::ScaleTimeline(size_t frameCount, size_t bezierCount, int boneInde
|
|||||||
: BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ScaleX, Property_ScaleY) {
|
: BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ScaleX, Property_ScaleY) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
void ScaleTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) {
|
||||||
switch (blend) {
|
if (fromSetup) {
|
||||||
case MixBlend_Setup:
|
pose._scaleX = setup._scaleX;
|
||||||
pose._scaleX = setup._scaleX;
|
pose._scaleY = setup._scaleY;
|
||||||
pose._scaleY = setup._scaleY;
|
|
||||||
return;
|
|
||||||
case MixBlend_First:
|
|
||||||
pose._scaleX += (setup._scaleX - pose._scaleX) * alpha;
|
|
||||||
pose._scaleY += (setup._scaleY - pose._scaleY) * alpha;
|
|
||||||
default: {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -88,54 +81,29 @@ void ScaleTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float
|
|||||||
x *= setup._scaleX;
|
x *= setup._scaleX;
|
||||||
y *= setup._scaleY;
|
y *= setup._scaleY;
|
||||||
|
|
||||||
if (alpha == 1) {
|
if (alpha == 1 && !add) {
|
||||||
if (blend == MixBlend_Add) {
|
pose._scaleX = x;
|
||||||
pose._scaleX += x - setup._scaleX;
|
pose._scaleY = y;
|
||||||
pose._scaleY += y - setup._scaleY;
|
|
||||||
} else {
|
|
||||||
pose._scaleX = x;
|
|
||||||
pose._scaleY = y;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
float bx, by;
|
float bx, by;
|
||||||
if (direction == MixDirection_Out) {
|
if (fromSetup) {
|
||||||
switch (blend) {
|
bx = setup._scaleX;
|
||||||
case MixBlend_Setup:
|
by = setup._scaleY;
|
||||||
bx = setup._scaleX;
|
|
||||||
by = setup._scaleY;
|
|
||||||
pose._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
|
|
||||||
pose._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
|
|
||||||
break;
|
|
||||||
case MixBlend_First:
|
|
||||||
case MixBlend_Replace:
|
|
||||||
bx = pose._scaleX;
|
|
||||||
by = pose._scaleY;
|
|
||||||
pose._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
|
|
||||||
pose._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
|
|
||||||
break;
|
|
||||||
case MixBlend_Add:
|
|
||||||
pose._scaleX += (x - setup._scaleX) * alpha;
|
|
||||||
pose._scaleY += (y - setup._scaleY) * alpha;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
switch (blend) {
|
bx = pose._scaleX;
|
||||||
case MixBlend_Setup:
|
by = pose._scaleY;
|
||||||
bx = MathUtil::abs(setup._scaleX) * MathUtil::sign(x);
|
}
|
||||||
by = MathUtil::abs(setup._scaleY) * MathUtil::sign(y);
|
if (add) {
|
||||||
pose._scaleX = bx + (x - bx) * alpha;
|
pose._scaleX = bx + (x - setup._scaleX) * alpha;
|
||||||
pose._scaleY = by + (y - by) * alpha;
|
pose._scaleY = by + (y - setup._scaleY) * alpha;
|
||||||
break;
|
} else if (out) {
|
||||||
case MixBlend_First:
|
pose._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
|
||||||
case MixBlend_Replace:
|
pose._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
|
||||||
bx = MathUtil::abs(pose._scaleX) * MathUtil::sign(x);
|
} else {
|
||||||
by = MathUtil::abs(pose._scaleY) * MathUtil::sign(y);
|
bx = MathUtil::abs(bx) * MathUtil::sign(x);
|
||||||
pose._scaleX = bx + (x - bx) * alpha;
|
by = MathUtil::abs(by) * MathUtil::sign(y);
|
||||||
pose._scaleY = by + (y - by) * alpha;
|
pose._scaleX = bx + (x - bx) * alpha;
|
||||||
break;
|
pose._scaleY = by + (y - by) * alpha;
|
||||||
case MixBlend_Add:
|
|
||||||
pose._scaleX += (x - setup._scaleX) * alpha;
|
|
||||||
pose._scaleY += (y - setup._scaleY) * alpha;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,8 +114,8 @@ ScaleXTimeline::ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIn
|
|||||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleX) {
|
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleX) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
void ScaleXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||||
pose._scaleX = getScaleValue(time, alpha, blend, direction, pose._scaleX, setup._scaleX);
|
pose._scaleX = getScaleValue(time, alpha, fromSetup, add, out, pose._scaleX, setup._scaleX);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTTI_IMPL(ScaleYTimeline, BoneTimeline1)
|
RTTI_IMPL(ScaleYTimeline, BoneTimeline1)
|
||||||
@ -156,6 +124,6 @@ ScaleYTimeline::ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIn
|
|||||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleY) {
|
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleY) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
void ScaleYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||||
pose._scaleY = getScaleValue(time, alpha, blend, direction, pose._scaleY, setup._scaleY);
|
pose._scaleY = getScaleValue(time, alpha, fromSetup, add, out, pose._scaleY, setup._scaleY);
|
||||||
}
|
}
|
||||||
@ -45,6 +45,7 @@ RTTI_IMPL_MULTI(SequenceTimeline, Timeline, SlotTimeline)
|
|||||||
|
|
||||||
SequenceTimeline::SequenceTimeline(size_t frameCount, int slotIndex, Attachment &attachment)
|
SequenceTimeline::SequenceTimeline(size_t frameCount, int slotIndex, Attachment &attachment)
|
||||||
: Timeline(frameCount, ENTRIES), SlotTimeline(), _slotIndex(slotIndex), _attachment((HasTextureRegion *) &attachment) {
|
: Timeline(frameCount, ENTRIES), SlotTimeline(), _slotIndex(slotIndex), _attachment((HasTextureRegion *) &attachment) {
|
||||||
|
_instant = true;
|
||||||
int sequenceId = 0;
|
int sequenceId = 0;
|
||||||
if (attachment.getRTTI().instanceOf(RegionAttachment::rtti)) sequenceId = ((RegionAttachment *) &attachment)->getSequence().getId();
|
if (attachment.getRTTI().instanceOf(RegionAttachment::rtti)) sequenceId = ((RegionAttachment *) &attachment)->getSequence().getId();
|
||||||
if (attachment.getRTTI().instanceOf(MeshAttachment::rtti)) sequenceId = ((MeshAttachment *) &attachment)->getSequence().getId();
|
if (attachment.getRTTI().instanceOf(MeshAttachment::rtti)) sequenceId = ((MeshAttachment *) &attachment)->getSequence().getId();
|
||||||
@ -71,11 +72,12 @@ void SequenceTimeline::setSlotIndex(int inValue) {
|
|||||||
_slotIndex = inValue;
|
_slotIndex = inValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool appliedPose) {
|
||||||
SP_UNUSED(alpha);
|
SP_UNUSED(alpha);
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
|
SP_UNUSED(add);
|
||||||
|
|
||||||
Slot *slot = skeleton.getSlots()[getSlotIndex()];
|
Slot *slot = skeleton.getSlots()[getSlotIndex()];
|
||||||
if (!slot->getBone().isActive()) return;
|
if (!slot->getBone().isActive()) return;
|
||||||
@ -90,14 +92,14 @@ void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Arr
|
|||||||
if (((Attachment *) _attachment)->getRTTI().instanceOf(MeshAttachment::rtti)) sequence = &((MeshAttachment *) _attachment)->getSequence();
|
if (((Attachment *) _attachment)->getRTTI().instanceOf(MeshAttachment::rtti)) sequence = &((MeshAttachment *) _attachment)->getSequence();
|
||||||
if (!sequence) return;
|
if (!sequence) return;
|
||||||
|
|
||||||
if (direction == MixDirection_Out) {
|
if (out) {
|
||||||
if (blend == MixBlend_Setup) pose.setSequenceIndex(-1);
|
if (fromSetup) pose.setSequenceIndex(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array<float> &frames = this->_frames;
|
Array<float> &frames = this->_frames;
|
||||||
if (time < frames[0]) {
|
if (time < frames[0]) {
|
||||||
if (blend == MixBlend_Setup || blend == MixBlend_First) pose.setSequenceIndex(-1);
|
if (fromSetup) pose.setSequenceIndex(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,18 +46,12 @@ ShearTimeline::ShearTimeline(size_t frameCount, size_t bezierCount, int boneInde
|
|||||||
: BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ShearX, Property_ShearY) {
|
: BoneTimeline2(frameCount, bezierCount, boneIndex, Property_ShearX, Property_ShearY) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShearTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
void ShearTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||||
|
SP_UNUSED(out);
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) {
|
||||||
switch (blend) {
|
if (fromSetup) {
|
||||||
case MixBlend_Setup:
|
pose._shearX = setup._shearX;
|
||||||
pose._shearX = setup._shearX;
|
pose._shearY = setup._shearY;
|
||||||
pose._shearY = setup._shearY;
|
|
||||||
return;
|
|
||||||
case MixBlend_First:
|
|
||||||
pose._shearX += (setup._shearX - pose._shearX) * alpha;
|
|
||||||
pose._shearY += (setup._shearY - pose._shearY) * alpha;
|
|
||||||
default: {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -86,19 +80,15 @@ void ShearTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (blend) {
|
if (fromSetup) {
|
||||||
case MixBlend_Setup:
|
pose._shearX = setup._shearX + x * alpha;
|
||||||
pose._shearX = setup._shearX + x * alpha;
|
pose._shearY = setup._shearY + y * alpha;
|
||||||
pose._shearY = setup._shearY + y * alpha;
|
} else if (add) {
|
||||||
break;
|
pose._shearX += x * alpha;
|
||||||
case MixBlend_First:
|
pose._shearY += y * alpha;
|
||||||
case MixBlend_Replace:
|
} else {
|
||||||
pose._shearX += (setup._shearX + x - pose._shearX) * alpha;
|
pose._shearX += (setup._shearX + x - pose._shearX) * alpha;
|
||||||
pose._shearY += (setup._shearY + y - pose._shearY) * alpha;
|
pose._shearY += (setup._shearY + y - pose._shearY) * alpha;
|
||||||
break;
|
|
||||||
case MixBlend_Add:
|
|
||||||
pose._shearX += x * alpha;
|
|
||||||
pose._shearY += y * alpha;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,8 +98,9 @@ ShearXTimeline::ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIn
|
|||||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearX) {
|
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearX) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShearXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
void ShearXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||||
pose._shearX = getRelativeValue(time, alpha, blend, pose._shearX, setup._shearX);
|
SP_UNUSED(out);
|
||||||
|
pose._shearX = getRelativeValue(time, alpha, fromSetup, add, pose._shearX, setup._shearX);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTTI_IMPL(ShearYTimeline, BoneTimeline1)
|
RTTI_IMPL(ShearYTimeline, BoneTimeline1)
|
||||||
@ -118,6 +109,7 @@ ShearYTimeline::ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIn
|
|||||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearY) {
|
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearY) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShearYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
void ShearYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||||
pose._shearY = getRelativeValue(time, alpha, blend, pose._shearY, setup._shearY);
|
SP_UNUSED(out);
|
||||||
|
pose._shearY = getRelativeValue(time, alpha, fromSetup, add, pose._shearY, setup._shearY);
|
||||||
}
|
}
|
||||||
@ -49,37 +49,37 @@ static void disposeAttachment(Attachment *attachment) {
|
|||||||
if (attachment->getRefCount() == 0) delete attachment;
|
if (attachment->getRefCount() == 0) delete attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skin::AttachmentMap::put(size_t slotIndex, const String &attachmentName, Attachment *attachment) {
|
void Skin::AttachmentMap::put(size_t slotIndex, const String &placeholderName, Attachment *attachment) {
|
||||||
if (slotIndex >= _buckets.size()) _buckets.setSize(slotIndex + 1, Array<Entry>());
|
if (slotIndex >= _buckets.size()) _buckets.setSize(slotIndex + 1, Array<Entry>());
|
||||||
Array<Entry> &bucket = _buckets[slotIndex];
|
Array<Entry> &bucket = _buckets[slotIndex];
|
||||||
int existing = findInBucket(bucket, attachmentName);
|
int existing = findInBucket(bucket, placeholderName);
|
||||||
attachment->reference();
|
attachment->reference();
|
||||||
if (existing >= 0) {
|
if (existing >= 0) {
|
||||||
disposeAttachment(bucket[existing]._attachment);
|
disposeAttachment(bucket[existing]._attachment);
|
||||||
bucket[existing]._attachment = attachment;
|
bucket[existing]._attachment = attachment;
|
||||||
} else {
|
} else {
|
||||||
bucket.add(Entry(slotIndex, attachmentName, attachment));
|
bucket.add(Entry(slotIndex, placeholderName, attachment));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Attachment *Skin::AttachmentMap::get(size_t slotIndex, const String &attachmentName) {
|
Attachment *Skin::AttachmentMap::get(size_t slotIndex, const String &placeholderName) {
|
||||||
if (slotIndex >= _buckets.size()) return NULL;
|
if (slotIndex >= _buckets.size()) return NULL;
|
||||||
int existing = findInBucket(_buckets[slotIndex], attachmentName);
|
int existing = findInBucket(_buckets[slotIndex], placeholderName);
|
||||||
return existing >= 0 ? _buckets[slotIndex][existing]._attachment : NULL;
|
return existing >= 0 ? _buckets[slotIndex][existing]._attachment : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skin::AttachmentMap::remove(size_t slotIndex, const String &attachmentName) {
|
void Skin::AttachmentMap::remove(size_t slotIndex, const String &placeholderName) {
|
||||||
if (slotIndex >= _buckets.size()) return;
|
if (slotIndex >= _buckets.size()) return;
|
||||||
int existing = findInBucket(_buckets[slotIndex], attachmentName);
|
int existing = findInBucket(_buckets[slotIndex], placeholderName);
|
||||||
if (existing >= 0) {
|
if (existing >= 0) {
|
||||||
disposeAttachment(_buckets[slotIndex][existing]._attachment);
|
disposeAttachment(_buckets[slotIndex][existing]._attachment);
|
||||||
_buckets[slotIndex].removeAt(existing);
|
_buckets[slotIndex].removeAt(existing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Skin::AttachmentMap::findInBucket(Array<Entry> &bucket, const String &attachmentName) {
|
int Skin::AttachmentMap::findInBucket(Array<Entry> &bucket, const String &placeholderName) {
|
||||||
for (size_t i = 0; i < bucket.size(); i++)
|
for (size_t i = 0; i < bucket.size(); i++)
|
||||||
if (bucket[i]._name == attachmentName) return (int) i;
|
if (bucket[i]._placeholderName == placeholderName) return (int) i;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,16 +99,16 @@ Skin::~Skin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skin::setAttachment(size_t slotIndex, const String &name, Attachment *attachment) {
|
void Skin::setAttachment(size_t slotIndex, const String &placeholderName, Attachment *attachment) {
|
||||||
_attachments.put(slotIndex, name, attachment);
|
_attachments.put(slotIndex, placeholderName, attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
Attachment *Skin::getAttachment(size_t slotIndex, const String &name) {
|
Attachment *Skin::getAttachment(size_t slotIndex, const String &placeholderName) {
|
||||||
return _attachments.get(slotIndex, name);
|
return _attachments.get(slotIndex, placeholderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skin::removeAttachment(size_t slotIndex, const String &name) {
|
void Skin::removeAttachment(size_t slotIndex, const String &placeholderName) {
|
||||||
_attachments.remove(slotIndex, name);
|
_attachments.remove(slotIndex, placeholderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Skin::findNamesForSlot(size_t slotIndex, Array<String> &names) {
|
void Skin::findNamesForSlot(size_t slotIndex, Array<String> &names) {
|
||||||
@ -116,7 +116,7 @@ void Skin::findNamesForSlot(size_t slotIndex, Array<String> &names) {
|
|||||||
while (entries.hasNext()) {
|
while (entries.hasNext()) {
|
||||||
Skin::AttachmentMap::Entry &entry = entries.next();
|
Skin::AttachmentMap::Entry &entry = entries.next();
|
||||||
if (entry._slotIndex == slotIndex) {
|
if (entry._slotIndex == slotIndex) {
|
||||||
names.add(entry._name);
|
names.add(entry._placeholderName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ void Skin::attachAll(Skeleton &skeleton, Skin &oldSkin) {
|
|||||||
Slot *slot = slots[slotIndex];
|
Slot *slot = slots[slotIndex];
|
||||||
|
|
||||||
if (slot->getPose().getAttachment() == entry._attachment) {
|
if (slot->getPose().getAttachment() == entry._attachment) {
|
||||||
Attachment *attachment = getAttachment(slotIndex, entry._name);
|
Attachment *attachment = getAttachment(slotIndex, entry._placeholderName);
|
||||||
if (attachment) slot->getPose().setAttachment(attachment);
|
if (attachment) slot->getPose().setAttachment(attachment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ void Skin::addSkin(Skin &other) {
|
|||||||
AttachmentMap::Entries entries = other.getAttachments();
|
AttachmentMap::Entries entries = other.getAttachments();
|
||||||
while (entries.hasNext()) {
|
while (entries.hasNext()) {
|
||||||
AttachmentMap::Entry &entry = entries.next();
|
AttachmentMap::Entry &entry = entries.next();
|
||||||
setAttachment(entry._slotIndex, entry._name, entry._attachment);
|
setAttachment(entry._slotIndex, entry._placeholderName, entry._attachment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,9 +177,9 @@ void Skin::copySkin(Skin &other) {
|
|||||||
while (entries.hasNext()) {
|
while (entries.hasNext()) {
|
||||||
AttachmentMap::Entry &entry = entries.next();
|
AttachmentMap::Entry &entry = entries.next();
|
||||||
if (entry._attachment->getRTTI().isExactly(MeshAttachment::rtti))
|
if (entry._attachment->getRTTI().isExactly(MeshAttachment::rtti))
|
||||||
setAttachment(entry._slotIndex, entry._name, &static_cast<MeshAttachment *>(entry._attachment)->newLinkedMesh());
|
setAttachment(entry._slotIndex, entry._placeholderName, &static_cast<MeshAttachment *>(entry._attachment)->newLinkedMesh());
|
||||||
else
|
else
|
||||||
setAttachment(entry._slotIndex, entry._name, &entry._attachment->copy());
|
setAttachment(entry._slotIndex, entry._placeholderName, &entry._attachment->copy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -82,7 +82,7 @@ void Slider::update(Skeleton &skeleton, Physics physics) {
|
|||||||
const Array<int> &indices = animation->getBones();
|
const Array<int> &indices = animation->getBones();
|
||||||
for (size_t i = 0, n = indices.size(); i < n; i++) bones[indices[i]]->_applied->modifyLocal(skeleton);
|
for (size_t i = 0, n = indices.size(); i < n; i++) bones[indices[i]]->_applied->modifyLocal(skeleton);
|
||||||
|
|
||||||
animation->apply(skeleton, p._time, p._time, _data._loop, NULL, p._mix, _data._additive ? MixBlend_Add : MixBlend_Replace, MixDirection_In, true);
|
animation->apply(skeleton, p._time, p._time, _data._loop, NULL, p._mix, false, _data._additive, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Slider::sort(Skeleton &skeleton) {
|
void Slider::sort(Skeleton &skeleton) {
|
||||||
|
|||||||
@ -46,21 +46,22 @@ SliderMixTimeline::SliderMixTimeline(size_t frameCount, size_t bezierCount, int
|
|||||||
: ConstraintTimeline1(frameCount, bezierCount, sliderIndex, Property_SliderMix) {
|
: ConstraintTimeline1(frameCount, bezierCount, sliderIndex, Property_SliderMix) {
|
||||||
PropertyId ids[] = {((PropertyId) Property_SliderMix << 32) | sliderIndex};
|
PropertyId ids[] = {((PropertyId) Property_SliderMix << 32) | sliderIndex};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
|
_additive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SliderMixTimeline::~SliderMixTimeline() {
|
SliderMixTimeline::~SliderMixTimeline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SliderMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void SliderMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(direction);
|
SP_UNUSED(out);
|
||||||
|
|
||||||
Slider *constraint = (Slider *) skeleton._constraints[_constraintIndex];
|
Slider *constraint = (Slider *) skeleton._constraints[_constraintIndex];
|
||||||
if (constraint->isActive()) {
|
if (constraint->isActive()) {
|
||||||
SliderPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
SliderPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||||
SliderData &data = constraint->_data;
|
SliderData &data = constraint->_data;
|
||||||
pose._mix = getAbsoluteValue(time, alpha, blend, pose._mix, data._setup._mix);
|
pose._mix = getAbsoluteValue(time, alpha, fromSetup, add, pose._mix, data._setup._mix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,21 +46,22 @@ SliderTimeline::SliderTimeline(size_t frameCount, size_t bezierCount, int slider
|
|||||||
: ConstraintTimeline1(frameCount, bezierCount, sliderIndex, Property_SliderTime) {
|
: ConstraintTimeline1(frameCount, bezierCount, sliderIndex, Property_SliderTime) {
|
||||||
PropertyId ids[] = {((PropertyId) Property_SliderTime << 32) | sliderIndex};
|
PropertyId ids[] = {((PropertyId) Property_SliderTime << 32) | sliderIndex};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
|
_additive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SliderTimeline::~SliderTimeline() {
|
SliderTimeline::~SliderTimeline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SliderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void SliderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(direction);
|
SP_UNUSED(out);
|
||||||
|
|
||||||
Slider *constraint = (Slider *) skeleton._constraints[_constraintIndex];
|
Slider *constraint = (Slider *) skeleton._constraints[_constraintIndex];
|
||||||
if (constraint->isActive()) {
|
if (constraint->isActive()) {
|
||||||
SliderPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
SliderPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||||
SliderData &data = constraint->_data;
|
SliderData &data = constraint->_data;
|
||||||
pose._time = getAbsoluteValue(time, alpha, blend, pose._time, data._setup._time);
|
pose._time = getAbsoluteValue(time, alpha, fromSetup, add, pose._time, data._setup._time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,12 +53,12 @@ void SlotCurveTimeline::setSlotIndex(int inValue) {
|
|||||||
_slotIndex = inValue;
|
_slotIndex = inValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlotCurveTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void SlotCurveTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(direction);
|
SP_UNUSED(out);
|
||||||
|
|
||||||
Slot *slot = skeleton._slots[_slotIndex];
|
Slot *slot = skeleton._slots[_slotIndex];
|
||||||
if (slot->_bone.isActive()) _apply(*slot, appliedPose ? *slot->_applied : slot->_pose, time, alpha, blend);
|
if (slot->_bone.isActive()) _apply(*slot, appliedPose ? *slot->_applied : slot->_pose, time, alpha, fromSetup, add);
|
||||||
}
|
}
|
||||||
@ -36,7 +36,8 @@ using namespace spine;
|
|||||||
|
|
||||||
RTTI_IMPL_NOPARENT(Timeline)
|
RTTI_IMPL_NOPARENT(Timeline)
|
||||||
|
|
||||||
Timeline::Timeline(size_t frameCount, size_t frameEntries) : _propertyIds(), _frames(), _frameEntries(frameEntries) {
|
Timeline::Timeline(size_t frameCount, size_t frameEntries)
|
||||||
|
: _propertyIds(), _frames(), _frameEntries(frameEntries), _additive(false), _instant(false) {
|
||||||
_frames.setSize(frameCount * frameEntries, 0);
|
_frames.setSize(frameCount * frameEntries, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -48,43 +48,33 @@ TransformConstraintTimeline::TransformConstraintTimeline(size_t frameCount, size
|
|||||||
: CurveTimeline(frameCount, TransformConstraintTimeline::ENTRIES, bezierCount), ConstraintTimeline(), _constraintIndex(transformConstraintIndex) {
|
: CurveTimeline(frameCount, TransformConstraintTimeline::ENTRIES, bezierCount), ConstraintTimeline(), _constraintIndex(transformConstraintIndex) {
|
||||||
PropertyId ids[] = {((PropertyId) Property_TransformConstraint << 32) | transformConstraintIndex};
|
PropertyId ids[] = {((PropertyId) Property_TransformConstraint << 32) | transformConstraintIndex};
|
||||||
setPropertyIds(ids, 1);
|
setPropertyIds(ids, 1);
|
||||||
|
_additive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransformConstraintTimeline::~TransformConstraintTimeline() {
|
TransformConstraintTimeline::~TransformConstraintTimeline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||||
MixDirection direction, bool appliedPose) {
|
bool out, bool appliedPose) {
|
||||||
SP_UNUSED(lastTime);
|
SP_UNUSED(lastTime);
|
||||||
SP_UNUSED(events);
|
SP_UNUSED(events);
|
||||||
SP_UNUSED(direction);
|
SP_UNUSED(out);
|
||||||
|
|
||||||
TransformConstraint *constraint = (TransformConstraint *) skeleton._constraints[_constraintIndex];
|
TransformConstraint *constraint = (TransformConstraint *) skeleton._constraints[_constraintIndex];
|
||||||
if (!constraint->isActive()) return;
|
if (!constraint->isActive()) return;
|
||||||
TransformConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
TransformConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||||
|
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) {
|
||||||
TransformConstraintPose &setup = constraint->_data._setup;
|
if (fromSetup) {
|
||||||
switch (blend) {
|
TransformConstraintPose &setup = constraint->_data._setup;
|
||||||
case MixBlend_Setup:
|
pose._mixRotate = setup._mixRotate;
|
||||||
pose._mixRotate = setup._mixRotate;
|
pose._mixX = setup._mixX;
|
||||||
pose._mixX = setup._mixX;
|
pose._mixY = setup._mixY;
|
||||||
pose._mixY = setup._mixY;
|
pose._mixScaleX = setup._mixScaleX;
|
||||||
pose._mixScaleX = setup._mixScaleX;
|
pose._mixScaleY = setup._mixScaleY;
|
||||||
pose._mixScaleY = setup._mixScaleY;
|
pose._mixShearY = setup._mixShearY;
|
||||||
pose._mixShearY = setup._mixShearY;
|
|
||||||
return;
|
|
||||||
case MixBlend_First:
|
|
||||||
pose._mixRotate += (setup._mixRotate - pose._mixRotate) * alpha;
|
|
||||||
pose._mixX += (setup._mixX - pose._mixX) * alpha;
|
|
||||||
pose._mixY += (setup._mixY - pose._mixY) * alpha;
|
|
||||||
pose._mixScaleX += (setup._mixScaleX - pose._mixScaleX) * alpha;
|
|
||||||
pose._mixScaleY += (setup._mixScaleY - pose._mixScaleY) * alpha;
|
|
||||||
pose._mixShearY += (setup._mixShearY - pose._mixShearY) * alpha;
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float rotate, x, y, scaleX, scaleY, shearY;
|
float rotate, x, y, scaleX, scaleY, shearY;
|
||||||
@ -127,34 +117,21 @@ void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, floa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (blend) {
|
TransformConstraintPose &base = fromSetup ? constraint->_data._setup : pose;
|
||||||
case MixBlend_Setup: {
|
if (add) {
|
||||||
TransformConstraintPose &setup = constraint->_data._setup;
|
pose._mixRotate = base._mixRotate + rotate * alpha;
|
||||||
pose._mixRotate = setup._mixRotate + (rotate - setup._mixRotate) * alpha;
|
pose._mixX = base._mixX + x * alpha;
|
||||||
pose._mixX = setup._mixX + (x - setup._mixX) * alpha;
|
pose._mixY = base._mixY + y * alpha;
|
||||||
pose._mixY = setup._mixY + (y - setup._mixY) * alpha;
|
pose._mixScaleX = base._mixScaleX + scaleX * alpha;
|
||||||
pose._mixScaleX = setup._mixScaleX + (scaleX - setup._mixScaleX) * alpha;
|
pose._mixScaleY = base._mixScaleY + scaleY * alpha;
|
||||||
pose._mixScaleY = setup._mixScaleY + (scaleY - setup._mixScaleY) * alpha;
|
pose._mixShearY = base._mixShearY + shearY * alpha;
|
||||||
pose._mixShearY = setup._mixShearY + (shearY - setup._mixShearY) * alpha;
|
} else {
|
||||||
break;
|
pose._mixRotate = base._mixRotate + (rotate - base._mixRotate) * alpha;
|
||||||
}
|
pose._mixX = base._mixX + (x - base._mixX) * alpha;
|
||||||
case MixBlend_First:
|
pose._mixY = base._mixY + (y - base._mixY) * alpha;
|
||||||
case MixBlend_Replace:
|
pose._mixScaleX = base._mixScaleX + (scaleX - base._mixScaleX) * alpha;
|
||||||
pose._mixRotate += (rotate - pose._mixRotate) * alpha;
|
pose._mixScaleY = base._mixScaleY + (scaleY - base._mixScaleY) * alpha;
|
||||||
pose._mixX += (x - pose._mixX) * alpha;
|
pose._mixShearY = base._mixShearY + (shearY - base._mixShearY) * alpha;
|
||||||
pose._mixY += (y - pose._mixY) * alpha;
|
|
||||||
pose._mixScaleX += (scaleX - pose._mixScaleX) * alpha;
|
|
||||||
pose._mixScaleY += (scaleY - pose._mixScaleY) * alpha;
|
|
||||||
pose._mixShearY += (shearY - pose._mixShearY) * alpha;
|
|
||||||
break;
|
|
||||||
case MixBlend_Add:
|
|
||||||
pose._mixRotate += rotate * alpha;
|
|
||||||
pose._mixX += x * alpha;
|
|
||||||
pose._mixY += y * alpha;
|
|
||||||
pose._mixScaleX += scaleX * alpha;
|
|
||||||
pose._mixScaleY += scaleY * alpha;
|
|
||||||
pose._mixShearY += shearY * alpha;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,18 +46,12 @@ TranslateTimeline::TranslateTimeline(size_t frameCount, size_t bezierCount, int
|
|||||||
: BoneTimeline2(frameCount, bezierCount, boneIndex, Property_X, Property_Y) {
|
: BoneTimeline2(frameCount, bezierCount, boneIndex, Property_X, Property_Y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranslateTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
void TranslateTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||||
|
SP_UNUSED(out);
|
||||||
if (time < _frames[0]) {
|
if (time < _frames[0]) {
|
||||||
switch (blend) {
|
if (fromSetup) {
|
||||||
case MixBlend_Setup:
|
pose._x = setup._x;
|
||||||
pose._x = setup._x;
|
pose._y = setup._y;
|
||||||
pose._y = setup._y;
|
|
||||||
return;
|
|
||||||
case MixBlend_First:
|
|
||||||
pose._x += (setup._x - pose._x) * alpha;
|
|
||||||
pose._y += (setup._y - pose._y) * alpha;
|
|
||||||
default: {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -86,19 +80,15 @@ void TranslateTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, fl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (blend) {
|
if (fromSetup) {
|
||||||
case MixBlend_Setup:
|
pose._x = setup._x + x * alpha;
|
||||||
pose._x = setup._x + x * alpha;
|
pose._y = setup._y + y * alpha;
|
||||||
pose._y = setup._y + y * alpha;
|
} else if (add) {
|
||||||
break;
|
pose._x += x * alpha;
|
||||||
case MixBlend_First:
|
pose._y += y * alpha;
|
||||||
case MixBlend_Replace:
|
} else {
|
||||||
pose._x += (setup._x + x - pose._x) * alpha;
|
pose._x += (setup._x + x - pose._x) * alpha;
|
||||||
pose._y += (setup._y + y - pose._y) * alpha;
|
pose._y += (setup._y + y - pose._y) * alpha;
|
||||||
break;
|
|
||||||
case MixBlend_Add:
|
|
||||||
pose._x += x * alpha;
|
|
||||||
pose._y += y * alpha;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,8 +98,9 @@ TranslateXTimeline::TranslateXTimeline(size_t frameCount, size_t bezierCount, in
|
|||||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_X) {
|
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_X) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranslateXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
void TranslateXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||||
pose._x = getRelativeValue(time, alpha, blend, pose._x, setup._x);
|
SP_UNUSED(out);
|
||||||
|
pose._x = getRelativeValue(time, alpha, fromSetup, add, pose._x, setup._x);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTTI_IMPL(TranslateYTimeline, BoneTimeline1)
|
RTTI_IMPL(TranslateYTimeline, BoneTimeline1)
|
||||||
@ -118,6 +109,7 @@ TranslateYTimeline::TranslateYTimeline(size_t frameCount, size_t bezierCount, in
|
|||||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Y) {
|
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranslateYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
void TranslateYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||||
pose._y = getRelativeValue(time, alpha, blend, pose._y, setup._y);
|
SP_UNUSED(out);
|
||||||
|
pose._y = getRelativeValue(time, alpha, fromSetup, add, pose._y, setup._y);
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ int main(int argc, char *argv[]) {
|
|||||||
setlocale(LC_ALL, "C");
|
setlocale(LC_ALL, "C");
|
||||||
|
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
fprintf(stderr, "Usage: DebugPrinter <skeleton-path> <atlas-path> [animation-name]\n");
|
fprintf(stderr, "Usage: HeadlessTest <skeleton-path> <atlas-path> [animation-name] [animation-name-2]\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +81,7 @@ int main(int argc, char *argv[]) {
|
|||||||
const char *skeletonPath = argv[1];
|
const char *skeletonPath = argv[1];
|
||||||
const char *atlasPath = argv[2];
|
const char *atlasPath = argv[2];
|
||||||
const char *animationName = argc >= 4 ? argv[3] : nullptr;
|
const char *animationName = argc >= 4 ? argv[3] : nullptr;
|
||||||
|
const char *animationName2 = argc >= 5 ? argv[4] : nullptr;
|
||||||
|
|
||||||
// Load atlas with headless texture loader
|
// Load atlas with headless texture loader
|
||||||
HeadlessTextureLoader textureLoader;
|
HeadlessTextureLoader textureLoader;
|
||||||
@ -147,6 +148,47 @@ int main(int argc, char *argv[]) {
|
|||||||
printf("%s", serializer.serializeAnimationState(state).buffer());
|
printf("%s", serializer.serializeAnimationState(state).buffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transition test: if a second animation is provided, play A for 10 frames, transition to B,
|
||||||
|
// then sample skeleton state at frames 5, 10, 15, 20 during the mix.
|
||||||
|
if (state != nullptr && animationName2 != nullptr) {
|
||||||
|
Animation *animation2 = skeletonData->findAnimation(animationName2);
|
||||||
|
if (!animation2) {
|
||||||
|
fprintf(stderr, "Animation not found: %s\n", animationName2);
|
||||||
|
delete state;
|
||||||
|
delete stateData;
|
||||||
|
delete skeletonData;
|
||||||
|
delete atlas;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset skeleton and state
|
||||||
|
skeleton.setupPose();
|
||||||
|
state->clearTracks();
|
||||||
|
state->setAnimation(0, *skeletonData->findAnimation(animationName), true);
|
||||||
|
|
||||||
|
// Run 10 frames of animation A
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
state->update(1 / 60.0f);
|
||||||
|
state->apply(skeleton);
|
||||||
|
skeleton.updateWorldTransform(Physics_Update);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transition to animation B
|
||||||
|
state->setAnimation(0, *animation2, true);
|
||||||
|
|
||||||
|
// Run 20 frames through the mix, serializing at frames 5, 10, 15, 20
|
||||||
|
for (int i = 1; i <= 20; i++) {
|
||||||
|
state->update(1 / 60.0f);
|
||||||
|
state->apply(skeleton);
|
||||||
|
skeleton.updateWorldTransform(Physics_Update);
|
||||||
|
if (i == 5 || i == 10 || i == 15 || i == 20) {
|
||||||
|
SkeletonSerializer transSerializer;
|
||||||
|
printf("\n=== TRANSITION FRAME %d ===\n", i);
|
||||||
|
printf("%s", transSerializer.serializeSkeleton(&skeleton).buffer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
if (state != nullptr) {
|
if (state != nullptr) {
|
||||||
delete state;
|
delete state;
|
||||||
|
|||||||
@ -1864,21 +1864,8 @@ namespace spine {
|
|||||||
_json.writeName("mixDuration");
|
_json.writeName("mixDuration");
|
||||||
_json.writeValue(obj->getMixDuration());
|
_json.writeValue(obj->getMixDuration());
|
||||||
|
|
||||||
_json.writeName("mixBlend");
|
_json.writeName("additive");
|
||||||
_json.writeValue([&]() -> String {
|
_json.writeValue(obj->getAdditive());
|
||||||
switch (obj->getMixBlend()) {
|
|
||||||
case MixBlend_Setup:
|
|
||||||
return "setup";
|
|
||||||
case MixBlend_First:
|
|
||||||
return "first";
|
|
||||||
case MixBlend_Replace:
|
|
||||||
return "replace";
|
|
||||||
case MixBlend_Add:
|
|
||||||
return "add";
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
|
|
||||||
_json.writeName("mixingFrom");
|
_json.writeName("mixingFrom");
|
||||||
if (obj->getMixingFrom() == nullptr) {
|
if (obj->getMixingFrom() == nullptr) {
|
||||||
@ -1894,8 +1881,6 @@ namespace spine {
|
|||||||
writeTrackEntry(obj->getMixingTo());
|
writeTrackEntry(obj->getMixingTo());
|
||||||
}
|
}
|
||||||
|
|
||||||
_json.writeName("holdPrevious");
|
|
||||||
_json.writeValue(obj->getHoldPrevious());
|
|
||||||
|
|
||||||
_json.writeName("shortestRotation");
|
_json.writeName("shortestRotation");
|
||||||
_json.writeValue(obj->getShortestRotation());
|
_json.writeValue(obj->getShortestRotation());
|
||||||
@ -2208,11 +2193,15 @@ namespace spine {
|
|||||||
writeColor(obj->getColor());
|
writeColor(obj->getColor());
|
||||||
|
|
||||||
_json.writeName("bones");
|
_json.writeName("bones");
|
||||||
_json.writeArrayStart();
|
if (obj->getBones().size() == 0) {
|
||||||
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
_json.writeNull();
|
||||||
_json.writeValue(obj->getBones()[i]);
|
} else {
|
||||||
|
_json.writeArrayStart();
|
||||||
|
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
||||||
|
_json.writeValue(obj->getBones()[i]);
|
||||||
|
}
|
||||||
|
_json.writeArrayEnd();
|
||||||
}
|
}
|
||||||
_json.writeArrayEnd();
|
|
||||||
|
|
||||||
_json.writeName("vertices");
|
_json.writeName("vertices");
|
||||||
_json.writeArrayStart();
|
_json.writeArrayStart();
|
||||||
@ -2271,11 +2260,15 @@ namespace spine {
|
|||||||
writeColor(obj->getColor());
|
writeColor(obj->getColor());
|
||||||
|
|
||||||
_json.writeName("bones");
|
_json.writeName("bones");
|
||||||
_json.writeArrayStart();
|
if (obj->getBones().size() == 0) {
|
||||||
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
_json.writeNull();
|
||||||
_json.writeValue(obj->getBones()[i]);
|
} else {
|
||||||
|
_json.writeArrayStart();
|
||||||
|
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
||||||
|
_json.writeValue(obj->getBones()[i]);
|
||||||
|
}
|
||||||
|
_json.writeArrayEnd();
|
||||||
}
|
}
|
||||||
_json.writeArrayEnd();
|
|
||||||
|
|
||||||
_json.writeName("vertices");
|
_json.writeName("vertices");
|
||||||
_json.writeArrayStart();
|
_json.writeArrayStart();
|
||||||
@ -2605,11 +2598,7 @@ namespace spine {
|
|||||||
_json.writeValue(obj->getHeight());
|
_json.writeValue(obj->getHeight());
|
||||||
|
|
||||||
_json.writeName("sequence");
|
_json.writeName("sequence");
|
||||||
if (!obj->getSequence().hasPathSuffix()) {
|
writeSequence(&obj->getSequence());
|
||||||
_json.writeNull();
|
|
||||||
} else {
|
|
||||||
writeSequence(&obj->getSequence());
|
|
||||||
}
|
|
||||||
|
|
||||||
_json.writeName("parentMesh");
|
_json.writeName("parentMesh");
|
||||||
if (obj->getParentMesh() == nullptr) {
|
if (obj->getParentMesh() == nullptr) {
|
||||||
@ -2619,11 +2608,15 @@ namespace spine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_json.writeName("bones");
|
_json.writeName("bones");
|
||||||
_json.writeArrayStart();
|
if (obj->getBones().size() == 0) {
|
||||||
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
_json.writeNull();
|
||||||
_json.writeValue(obj->getBones()[i]);
|
} else {
|
||||||
|
_json.writeArrayStart();
|
||||||
|
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
||||||
|
_json.writeValue(obj->getBones()[i]);
|
||||||
|
}
|
||||||
|
_json.writeArrayEnd();
|
||||||
}
|
}
|
||||||
_json.writeArrayEnd();
|
|
||||||
|
|
||||||
_json.writeName("vertices");
|
_json.writeName("vertices");
|
||||||
_json.writeArrayStart();
|
_json.writeArrayStart();
|
||||||
@ -2688,11 +2681,15 @@ namespace spine {
|
|||||||
writeColor(obj->getColor());
|
writeColor(obj->getColor());
|
||||||
|
|
||||||
_json.writeName("bones");
|
_json.writeName("bones");
|
||||||
_json.writeArrayStart();
|
if (obj->getBones().size() == 0) {
|
||||||
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
_json.writeNull();
|
||||||
_json.writeValue(obj->getBones()[i]);
|
} else {
|
||||||
|
_json.writeArrayStart();
|
||||||
|
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
||||||
|
_json.writeValue(obj->getBones()[i]);
|
||||||
|
}
|
||||||
|
_json.writeArrayEnd();
|
||||||
}
|
}
|
||||||
_json.writeArrayEnd();
|
|
||||||
|
|
||||||
_json.writeName("vertices");
|
_json.writeName("vertices");
|
||||||
_json.writeArrayStart();
|
_json.writeArrayStart();
|
||||||
@ -3128,11 +3125,7 @@ namespace spine {
|
|||||||
_json.writeValue(obj->getPath());
|
_json.writeValue(obj->getPath());
|
||||||
|
|
||||||
_json.writeName("sequence");
|
_json.writeName("sequence");
|
||||||
if (!obj->getSequence().hasPathSuffix()) {
|
writeSequence(&obj->getSequence());
|
||||||
_json.writeNull();
|
|
||||||
} else {
|
|
||||||
writeSequence(&obj->getSequence());
|
|
||||||
}
|
|
||||||
|
|
||||||
_json.writeName("name");
|
_json.writeName("name");
|
||||||
_json.writeValue(obj->getName());
|
_json.writeValue(obj->getName());
|
||||||
@ -3440,10 +3433,10 @@ namespace spine {
|
|||||||
|
|
||||||
void writeSkinEntry(Skin::AttachmentMap::Entry *obj) {
|
void writeSkinEntry(Skin::AttachmentMap::Entry *obj) {
|
||||||
_json.writeObjectStart();
|
_json.writeObjectStart();
|
||||||
String name = obj->_name;
|
String placeholderName = obj->_placeholderName;
|
||||||
String refString;
|
String refString;
|
||||||
if (!name.isEmpty()) {
|
if (!placeholderName.isEmpty()) {
|
||||||
refString.append("<SkinEntry-").append(name).append(">");
|
refString.append("<SkinEntry-").append(placeholderName).append(">");
|
||||||
} else {
|
} else {
|
||||||
refString.append("<SkinEntry-").append(_nextId++).append(">");
|
refString.append("<SkinEntry-").append(_nextId++).append(">");
|
||||||
}
|
}
|
||||||
@ -3454,7 +3447,7 @@ namespace spine {
|
|||||||
_json.writeName("slotIndex");
|
_json.writeName("slotIndex");
|
||||||
_json.writeValue((int) obj->_slotIndex);
|
_json.writeValue((int) obj->_slotIndex);
|
||||||
_json.writeName("name");
|
_json.writeName("name");
|
||||||
_json.writeValue(obj->_name);
|
_json.writeValue(obj->_placeholderName);
|
||||||
_json.writeName("attachment");
|
_json.writeName("attachment");
|
||||||
writeAttachment(obj->_attachment);
|
writeAttachment(obj->_attachment);
|
||||||
_json.writeObjectEnd();
|
_json.writeObjectEnd();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user