mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 06:29:02 +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**
|
||||
- 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 new pose system with `spine_bone_local`, `spine_bone_pose`, and related 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
|
||||
- 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 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.
|
||||
|
||||
- **Breaking changes**
|
||||
- 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
|
||||
- Renamed timeline constraint index methods to use unified `getConstraintIndex()`
|
||||
- Changed timeline class hierarchy with new base classes `BoneTimeline`, `SlotCurveTimeline`, and `ConstraintTimeline`
|
||||
@ -598,6 +619,19 @@
|
||||
|
||||
- **Additions**
|
||||
- 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 new pose system with `BoneLocal`, `BonePose`, and related classes
|
||||
- Added `Pose`, `Posed`, and `PosedActive` base classes for unified pose management
|
||||
|
||||
@ -32,8 +32,6 @@
|
||||
|
||||
#include <spine/Array.h>
|
||||
#include <spine/HashMap.h>
|
||||
#include <spine/MixBlend.h>
|
||||
#include <spine/MixDirection.h>
|
||||
#include <spine/SpineObject.h>
|
||||
#include <spine/SpineString.h>
|
||||
#include <spine/Property.h>
|
||||
@ -122,25 +120,28 @@ namespace spine {
|
||||
/// Applies the animation's timelines to the specified skeleton.
|
||||
///
|
||||
/// 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.
|
||||
/// @param lastTime The last time in seconds this animation was applied. Some timelines trigger only at specific times rather
|
||||
/// than every frame. Pass -1 the first time an animation is applied to ensure frame 0 is triggered.
|
||||
/// @param time The time in seconds the skeleton is being posed for. Most timelines find the frame before and the frame after
|
||||
/// this time and interpolate between the frame values. If beyond the getDuration() and loop is
|
||||
/// true then the animation will repeat, else the last frame will be applied.
|
||||
/// @param loop If true, the animation repeats after the getDuration().
|
||||
/// @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 lastTime The last time in seconds this animation was applied. Some timelines trigger only at discrete times, in
|
||||
/// which case all keys are triggered between lastTime (exclusive) and time (inclusive). Pass -1 the first time an
|
||||
/// animation is applied to ensure frame 0 is triggered.
|
||||
/// @param time The time in seconds the skeleton is being posed for. Timelines find the frame before and after this time and
|
||||
/// interpolate between the frame values.
|
||||
/// @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
|
||||
/// fire events.
|
||||
/// @param alpha 0 applies the current or setup values (depending on blend). 1 applies the timeline values. Between
|
||||
/// 0 and 1 applies values between the current or setup values and the timeline values. By adjusting
|
||||
/// alpha over time, an animation can be mixed in or out. alpha can also be useful to apply
|
||||
/// animations on top of each other (layering).
|
||||
/// @param blend Controls how mixing is applied when alpha < 1.
|
||||
/// @param direction Indicates whether the timelines are mixing in or out. Used by timelines which perform instant transitions,
|
||||
/// such as DrawOrderTimeline or AttachmentTimeline.
|
||||
void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose);
|
||||
/// @param alpha 0 applies setup or current values (depending on fromSetup), 1 uses timeline values, and intermediate values
|
||||
/// interpolate between them. Adjusting alpha over time can mix an animation in or out.
|
||||
/// @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.
|
||||
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.
|
||||
const String &getName();
|
||||
|
||||
@ -33,7 +33,6 @@
|
||||
#include <spine/Array.h>
|
||||
#include <spine/Pool.h>
|
||||
#include <spine/Property.h>
|
||||
#include <spine/MixBlend.h>
|
||||
#include <spine/SpineObject.h>
|
||||
#include <spine/SpineString.h>
|
||||
#include <spine/HasRendererObject.h>
|
||||
@ -116,20 +115,11 @@ namespace spine {
|
||||
|
||||
void setLoop(bool inValue);
|
||||
|
||||
/// If true, when mixing from the previous animation to this animation, the previous animation is applied as normal instead
|
||||
/// of being mixed out.
|
||||
///
|
||||
/// 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();
|
||||
/// When true, timelines in this animation that support additive have their values added to the setup or current pose values
|
||||
/// instead of replacing them. Additive can be set for a new track entry only before AnimationState::apply() is next called.
|
||||
bool getAdditive();
|
||||
|
||||
void setHoldPrevious(bool inValue);
|
||||
void setAdditive(bool inValue);
|
||||
|
||||
bool getReverse();
|
||||
|
||||
@ -285,16 +275,12 @@ namespace spine {
|
||||
/// entry is looping, its next loop completion is used instead of its duration.
|
||||
void setMixDuration(float mixDuration, float delay);
|
||||
|
||||
MixBlend getMixBlend();
|
||||
|
||||
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.
|
||||
/// 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.
|
||||
TrackEntry *getMixingFrom();
|
||||
|
||||
/// The track entry for the next animation when mixing from this animation, or NULL if no mixing is currently occuring.
|
||||
/// When mixing from multiple animations, MixingTo makes up a double linked list with MixingFrom.
|
||||
/// The track entry for the next animation when mixing from this animation, or NULL if no mixing is currently occurring.
|
||||
/// When mixing to multiple animations, MixingTo makes up a doubly linked list with MixingFrom.
|
||||
TrackEntry *getMixingTo();
|
||||
|
||||
/// 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;
|
||||
int _trackIndex;
|
||||
|
||||
bool _loop, _holdPrevious, _reverse, _shortestRotation;
|
||||
bool _loop, _additive, _reverse, _shortestRotation, _keepHold;
|
||||
float _eventThreshold, _mixAttachmentThreshold, _alphaAttachmentThreshold, _mixDrawOrderThreshold;
|
||||
float _animationStart, _animationEnd, _animationLast, _nextAnimationLast;
|
||||
float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale;
|
||||
float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha;
|
||||
MixBlend _mixBlend;
|
||||
float _alpha, _mixTime, _mixDuration, _totalAlpha;
|
||||
Array<int> _timelineMode;
|
||||
Array<TrackEntry *> _timelineHoldMix;
|
||||
Array<float> _timelinesRotation;
|
||||
@ -551,9 +536,8 @@ namespace spine {
|
||||
private:
|
||||
static const int Subsequent = 0;
|
||||
static const int First = 1;
|
||||
static const int HoldSubsequent = 2;
|
||||
static const int Hold = 2;
|
||||
static const int HoldFirst = 3;
|
||||
static const int HoldMix = 4;
|
||||
|
||||
static const int Setup = 1;
|
||||
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
|
||||
/// 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);
|
||||
|
||||
/// 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
|
||||
/// 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.
|
||||
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);
|
||||
|
||||
/// Returns true when all mixing from entries are complete.
|
||||
|
||||
@ -41,7 +41,7 @@ namespace spine {
|
||||
|
||||
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 {
|
||||
friend class AnimationState;
|
||||
|
||||
@ -63,7 +63,7 @@ namespace spine {
|
||||
/// See TrackEntry.MixDuration.
|
||||
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.
|
||||
float getMix(Animation &from, Animation &to);
|
||||
|
||||
|
||||
@ -33,8 +33,6 @@
|
||||
#include <spine/Timeline.h>
|
||||
#include <spine/SpineObject.h>
|
||||
#include <spine/Array.h>
|
||||
#include <spine/MixBlend.h>
|
||||
#include <spine/MixDirection.h>
|
||||
#include <spine/SpineString.h>
|
||||
#include <spine/SlotTimeline.h>
|
||||
|
||||
@ -60,8 +58,8 @@ namespace spine {
|
||||
|
||||
virtual ~AttachmentTimeline();
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
/// Sets the time and attachment name for the specified frame.
|
||||
/// @param frame Between 0 and frameCount, inclusive.
|
||||
|
||||
@ -38,11 +38,12 @@
|
||||
#include <spine/Array.h>
|
||||
|
||||
namespace spine {
|
||||
/// The current pose for a bone, before constraints are applied.
|
||||
///
|
||||
/// A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a
|
||||
/// local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a
|
||||
/// constraint or application code modifies the world transform after it was computed from the local transform.
|
||||
/// A bone has a number of poses:
|
||||
/// - BoneData::getSetupPose(): The setup pose.
|
||||
/// - getPose(): The local pose. Set by animations and app code.
|
||||
/// - getAppliedPose(): The applied local pose. This is the local pose modified by constraints and app code.
|
||||
/// - 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 {
|
||||
friend class AnimationState;
|
||||
friend class RotateTimeline;
|
||||
|
||||
@ -69,10 +69,10 @@ namespace spine {
|
||||
public:
|
||||
BoneData(int index, const String &name, BoneData *parent = NULL);
|
||||
|
||||
/// The index of the bone in Skeleton.Bones
|
||||
/// The Skeleton::getBones() index.
|
||||
int getIndex();
|
||||
|
||||
/// May be NULL.
|
||||
/// The parent bone, or NULL if this bone is the root.
|
||||
BoneData *getParent();
|
||||
|
||||
float getLength();
|
||||
@ -81,6 +81,7 @@ namespace spine {
|
||||
|
||||
Color &getColor();
|
||||
|
||||
/// The bone icon name as it was in Spine, or empty if nonessential data was not exported.
|
||||
const String &getIcon();
|
||||
|
||||
void setIcon(const String &icon);
|
||||
|
||||
@ -38,8 +38,15 @@ namespace spine {
|
||||
class Bone;
|
||||
class Skeleton;
|
||||
|
||||
/// The applied pose for a bone. This is the Bone pose with constraints applied and the world transform computed by
|
||||
/// Skeleton::updateWorldTransform(Physics).
|
||||
/// The applied local pose and world transform for a bone. This is the Bone::getPose() with constraints applied and the
|
||||
/// 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 {
|
||||
friend class IkConstraint;
|
||||
friend class PathConstraint;
|
||||
@ -72,7 +79,8 @@ namespace spine {
|
||||
/// Called by Skeleton::updateCache() to compute the world transform, if needed.
|
||||
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
|
||||
/// Runtimes Guide.
|
||||
@ -80,42 +88,40 @@ namespace spine {
|
||||
|
||||
/// 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
|
||||
/// calling this method is equivalent to the local transform used to compute the world transform, but may not be identical.
|
||||
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 modifyLocal(Skeleton &skeleton);
|
||||
void modifyWorld(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();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
void setD(float d);
|
||||
|
||||
/// The world X position. If changed, updateLocalTransform() should be called.
|
||||
/// The world X position.
|
||||
float getWorldX();
|
||||
void setWorldX(float worldX);
|
||||
|
||||
/// The world Y position. If changed, updateLocalTransform() should be called.
|
||||
/// The world Y position.
|
||||
float getWorldY();
|
||||
void setWorldY(float worldY);
|
||||
|
||||
@ -150,9 +156,6 @@ namespace spine {
|
||||
float localToWorldRotation(float localRotation);
|
||||
|
||||
/// 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);
|
||||
|
||||
protected:
|
||||
|
||||
@ -66,8 +66,8 @@ namespace spine {
|
||||
public:
|
||||
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,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
virtual int getBoneIndex() const override {
|
||||
return _boneIndex;
|
||||
@ -79,7 +79,7 @@ namespace spine {
|
||||
|
||||
protected:
|
||||
/// 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;
|
||||
};
|
||||
@ -95,8 +95,8 @@ namespace spine {
|
||||
public:
|
||||
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,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
virtual int getBoneIndex() const override {
|
||||
return _boneIndex;
|
||||
@ -110,7 +110,7 @@ namespace spine {
|
||||
|
||||
protected:
|
||||
/// 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;
|
||||
|
||||
|
||||
@ -48,6 +48,8 @@ namespace spine {
|
||||
public:
|
||||
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();
|
||||
|
||||
void setEndSlot(SlotData *inValue);
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
#include <spine/SlotTimeline.h>
|
||||
|
||||
namespace spine {
|
||||
/// Changes a slot's SlotPose::getColor().
|
||||
/// Changes SlotPose::getColor().
|
||||
class SP_API RGBATimeline : public SlotCurveTimeline {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
@ -53,7 +53,7 @@ namespace spine {
|
||||
void setFrame(int frame, float time, float r, float g, float b, float a);
|
||||
|
||||
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 R = 1;
|
||||
@ -62,7 +62,7 @@ namespace spine {
|
||||
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 {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
@ -81,7 +81,7 @@ namespace spine {
|
||||
void setFrame(int frame, float time, float r, float g, float b);
|
||||
|
||||
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 R = 1;
|
||||
@ -101,8 +101,8 @@ namespace spine {
|
||||
|
||||
virtual ~AlphaTimeline();
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
virtual int getSlotIndex() override;
|
||||
|
||||
@ -112,7 +112,7 @@ namespace spine {
|
||||
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 {
|
||||
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);
|
||||
|
||||
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 R = 1;
|
||||
@ -143,7 +143,7 @@ namespace spine {
|
||||
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 {
|
||||
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);
|
||||
|
||||
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 R = 1;
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
#include <spine/Property.h>
|
||||
|
||||
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 {
|
||||
RTTI_DECL
|
||||
|
||||
|
||||
@ -82,13 +82,13 @@ namespace spine {
|
||||
/// Returns the interpolated value for the specified 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:
|
||||
static const int ENTRIES = 2;
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
namespace spine {
|
||||
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 {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
@ -67,7 +67,7 @@ namespace spine {
|
||||
}
|
||||
|
||||
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:
|
||||
Array<Array<float>> _vertices;
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
#include <spine/Timeline.h>
|
||||
|
||||
namespace spine {
|
||||
/// Changes a subset of a skeleton's Skeleton::getDrawOrder().
|
||||
/// Changes a subset of Skeleton::getDrawOrder().
|
||||
class SP_API DrawOrderFolderTimeline : public Timeline {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
@ -44,8 +44,8 @@ namespace spine {
|
||||
public:
|
||||
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,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
size_t getFrameCount();
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
#include <spine/Timeline.h>
|
||||
|
||||
namespace spine {
|
||||
/// Changes a skeleton's Skeleton::getDrawOrder().
|
||||
/// Changes Skeleton::getDrawOrder().
|
||||
class SP_API DrawOrderTimeline : public Timeline {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
@ -46,8 +46,8 @@ namespace spine {
|
||||
|
||||
explicit DrawOrderTimeline(size_t frameCount);
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
size_t getFrameCount();
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ namespace spine {
|
||||
/// Stores the current pose values for an Event.
|
||||
///
|
||||
/// 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 {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ namespace spine {
|
||||
public:
|
||||
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;
|
||||
|
||||
int getInt() const;
|
||||
|
||||
@ -47,8 +47,8 @@ namespace spine {
|
||||
~EventTimeline();
|
||||
|
||||
/// Fires events for frames > lastTime and <= time.
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
size_t getFrameCount();
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
|
||||
namespace spine {
|
||||
|
||||
/// Changes an IK constraint's IkConstraintPose::getMix(), IkConstraintPose::getSoftness(),
|
||||
/// Changes IkConstraintPose::getMix(), IkConstraintPose::getSoftness(),
|
||||
/// IkConstraintPose::getBendDirection(), IkConstraintPose::getStretch(), and IkConstraintPose::getCompress().
|
||||
class SP_API IkConstraintTimeline : public CurveTimeline, public ConstraintTimeline {
|
||||
friend class SkeletonBinary;
|
||||
@ -49,8 +49,8 @@ namespace spine {
|
||||
|
||||
virtual ~IkConstraintTimeline();
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
/// Sets the time, mix, softness, bend direction, compress, and stretch for the specified frame.
|
||||
/// @param frame Between 0 and frameCount, inclusive.
|
||||
|
||||
@ -56,8 +56,8 @@ namespace spine {
|
||||
/// @param time The frame time in seconds.
|
||||
void setFrame(int frame, float time, Inherit inherit);
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
|
||||
virtual int getBoneIndex() const override {
|
||||
|
||||
@ -74,9 +74,14 @@ namespace spine {
|
||||
|
||||
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();
|
||||
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();
|
||||
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);
|
||||
|
||||
/// 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();
|
||||
|
||||
void setConstantSpeed(bool inValue);
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
|
||||
namespace spine {
|
||||
|
||||
/// Changes a path constraint's PathConstraintPose::getMixRotate(), PathConstraintPose::getMixX(), and
|
||||
/// Changes PathConstraintPose::getMixRotate(), PathConstraintPose::getMixX(), and
|
||||
/// PathConstraintPose::getMixY().
|
||||
class SP_API PathConstraintMixTimeline : public CurveTimeline, public ConstraintTimeline {
|
||||
friend class SkeletonBinary;
|
||||
@ -49,8 +49,8 @@ namespace spine {
|
||||
|
||||
virtual ~PathConstraintMixTimeline();
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
/// Sets the time and color for the specified frame.
|
||||
/// @param frame Between 0 and frameCount, inclusive.
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
namespace spine {
|
||||
|
||||
/// Changes a path constraint's PathConstraintPose::getPosition().
|
||||
/// Changes PathConstraintPose::getPosition().
|
||||
class SP_API PathConstraintPositionTimeline : public ConstraintTimeline1 {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
@ -49,8 +49,8 @@ namespace spine {
|
||||
|
||||
virtual ~PathConstraintPositionTimeline();
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
};
|
||||
}// namespace spine
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
#include <spine/ConstraintTimeline1.h>
|
||||
|
||||
namespace spine {
|
||||
/// Changes a path constraint's PathConstraintPose::getSpacing().
|
||||
/// Changes PathConstraintPose::getSpacing().
|
||||
class SP_API PathConstraintSpacingTimeline : public ConstraintTimeline1 {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
@ -46,8 +46,8 @@ namespace spine {
|
||||
|
||||
virtual ~PathConstraintSpacingTimeline();
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -50,8 +50,8 @@ namespace spine {
|
||||
/// @param constraintIndex -1 for all physics constraints in the skeleton.
|
||||
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,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
virtual int getConstraintIndex() const override {
|
||||
return _constraintIndex;
|
||||
@ -67,10 +67,9 @@ namespace spine {
|
||||
virtual bool global(PhysicsConstraintData &constraintData) = 0;
|
||||
|
||||
int _constraintIndex;
|
||||
bool _additive;
|
||||
};
|
||||
|
||||
/// Changes a physics constraint's PhysicsConstraintPose::getInertia().
|
||||
/// Changes PhysicsConstraintPose::getInertia().
|
||||
class SP_API PhysicsConstraintInertiaTimeline : public PhysicsConstraintTimeline {
|
||||
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 {
|
||||
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 {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
@ -148,8 +147,7 @@ namespace spine {
|
||||
}
|
||||
};
|
||||
|
||||
/// Changes a physics constraint's PhysicsConstraintPose::getMassInverse(). The
|
||||
/// timeline values are not inverted.
|
||||
/// Changes PhysicsConstraintPose::getMassInverse(). The timeline values are not inverted.
|
||||
class SP_API PhysicsConstraintMassTimeline : public PhysicsConstraintTimeline {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
@ -271,10 +269,11 @@ namespace spine {
|
||||
: Timeline(frameCount, 1), ConstraintTimeline(), _constraintIndex(constraintIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_PhysicsConstraintReset) << 32};
|
||||
setPropertyIds(ids, 1);
|
||||
_instant = true;
|
||||
}
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
int getFrameCount() {
|
||||
return (int) _frames.size();
|
||||
|
||||
@ -53,22 +53,27 @@ namespace spine {
|
||||
public:
|
||||
explicit PointAttachment(const String &name);
|
||||
|
||||
/// The local X position.
|
||||
float getX();
|
||||
|
||||
void setX(float inValue);
|
||||
|
||||
/// The local Y position.
|
||||
float getY();
|
||||
|
||||
void setY(float inValue);
|
||||
|
||||
/// The local rotation in degrees, counter clockwise.
|
||||
float getRotation();
|
||||
|
||||
void setRotation(float inValue);
|
||||
|
||||
Color &getColor();
|
||||
|
||||
/// Computes the world position from the local position.
|
||||
void computeWorldPosition(BonePose &bone, float &ox, float &oy);
|
||||
|
||||
/// Computes the world rotation from the local rotation.
|
||||
float computeWorldRotation(BonePose &bone);
|
||||
|
||||
virtual Attachment ©() override;
|
||||
|
||||
@ -44,6 +44,9 @@ namespace spine {
|
||||
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 {
|
||||
return _active;
|
||||
}
|
||||
|
||||
@ -66,7 +66,6 @@ namespace spine {
|
||||
PosedData(const String &name);
|
||||
virtual ~PosedData();
|
||||
|
||||
/// The constraint's name, which is unique across all constraints in the skeleton of the same type.
|
||||
const String &getName() const {
|
||||
return _name;
|
||||
};
|
||||
|
||||
@ -79,6 +79,7 @@ namespace spine {
|
||||
float getScaleY();
|
||||
void setScaleY(float inValue);
|
||||
|
||||
/// The local rotation in degrees, counter clockwise.
|
||||
float getRotation();
|
||||
void setRotation(float inValue);
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ namespace spine {
|
||||
explicit RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
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);
|
||||
|
||||
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().
|
||||
@ -60,7 +60,7 @@ namespace spine {
|
||||
explicit ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
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().
|
||||
@ -75,7 +75,7 @@ namespace spine {
|
||||
explicit ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
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 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 {
|
||||
friend class SkeletonBinary;
|
||||
|
||||
@ -51,8 +51,8 @@ namespace spine {
|
||||
|
||||
virtual ~SequenceTimeline();
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
/// Sets the time, mode, index, and frame time for the specified frame.
|
||||
/// @param frame Between 0 and frameCount, inclusive.
|
||||
|
||||
@ -45,7 +45,7 @@ namespace spine {
|
||||
explicit ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
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().
|
||||
@ -60,7 +60,7 @@ namespace spine {
|
||||
explicit ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
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().
|
||||
@ -75,7 +75,7 @@ namespace spine {
|
||||
explicit ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
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.
|
||||
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();
|
||||
|
||||
Skin *getSkin();
|
||||
@ -310,6 +311,9 @@ namespace spine {
|
||||
/// Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */
|
||||
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();
|
||||
|
||||
void setTime(float time);
|
||||
|
||||
@ -171,9 +171,9 @@ namespace spine {
|
||||
}
|
||||
|
||||
inline long long readLong() {
|
||||
unsigned long long result = (unsigned long long) readInt();
|
||||
unsigned long long result = (unsigned int) readInt();
|
||||
result <<= 32;
|
||||
result |= (unsigned long long) readInt();
|
||||
result |= (unsigned int) readInt();
|
||||
return (long long) result;
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ namespace spine {
|
||||
|
||||
class ConstraintData;
|
||||
|
||||
/// Stores attachments by slot index and attachment name.
|
||||
/// Stores attachments by slot index and placeholder name.
|
||||
/// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and
|
||||
/// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide.
|
||||
class SP_API Skin : public SpineObject {
|
||||
@ -56,10 +56,11 @@ namespace spine {
|
||||
public:
|
||||
struct SP_API Entry {
|
||||
size_t _slotIndex;
|
||||
String _name;
|
||||
String _placeholderName;
|
||||
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;
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
@ -107,7 +108,7 @@ namespace spine {
|
||||
AttachmentMap();
|
||||
|
||||
private:
|
||||
int findInBucket(Array<Entry> &, const String &attachmentName);
|
||||
int findInBucket(Array<Entry> &, const String &placeholderName);
|
||||
|
||||
Array<Array<Entry>> _buckets;
|
||||
};
|
||||
@ -116,19 +117,19 @@ namespace spine {
|
||||
|
||||
~Skin();
|
||||
|
||||
/// Adds an attachment to the skin for the specified slot index and name.
|
||||
/// If the name already exists for the slot, the previous value is replaced.
|
||||
void setAttachment(size_t slotIndex, const String &name, Attachment *attachment);
|
||||
/// Adds an attachment to the skin for the specified slot index and placeholder name.
|
||||
/// If the placeholder name already exists for the slot, the previous value is replaced.
|
||||
void setAttachment(size_t slotIndex, const String &placeholderName, Attachment *attachment);
|
||||
|
||||
/// Returns the attachment for the specified slot index and name, or NULL.
|
||||
Attachment *getAttachment(size_t slotIndex, const String &name);
|
||||
/// Returns the attachment for the specified slot index and placeholder name, or NULL.
|
||||
Attachment *getAttachment(size_t slotIndex, const String &placeholderName);
|
||||
|
||||
// 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 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);
|
||||
|
||||
/// 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>
|
||||
|
||||
namespace spine {
|
||||
/// Changes a slider's SliderPose::getMix().
|
||||
/// Changes SliderPose::getMix().
|
||||
class SP_API SliderMixTimeline : public ConstraintTimeline1 {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
@ -45,8 +45,8 @@ namespace spine {
|
||||
|
||||
virtual ~SliderMixTimeline();
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
#include <spine/ConstraintTimeline1.h>
|
||||
|
||||
namespace spine {
|
||||
/// Changes a slider's SliderPose::getTime().
|
||||
/// Changes SliderPose::getTime().
|
||||
class SP_API SliderTimeline : public ConstraintTimeline1 {
|
||||
friend class SkeletonBinary;
|
||||
friend class SkeletonJson;
|
||||
@ -45,8 +45,8 @@ namespace spine {
|
||||
|
||||
virtual ~SliderTimeline();
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -49,8 +49,8 @@ namespace spine {
|
||||
|
||||
virtual ~SlotCurveTimeline();
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
virtual int getSlotIndex() override;
|
||||
|
||||
@ -58,7 +58,7 @@ namespace spine {
|
||||
|
||||
protected:
|
||||
/// 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;
|
||||
};
|
||||
|
||||
@ -67,7 +67,7 @@ namespace spine {
|
||||
public:
|
||||
SlotData(int index, const String &name, BoneData &boneData);
|
||||
|
||||
/// The index of the slot in Skeleton::getSlots().
|
||||
/// The Skeleton::getSlots() index.
|
||||
int getIndex();
|
||||
|
||||
/// The bone this slot belongs to.
|
||||
|
||||
@ -32,8 +32,6 @@
|
||||
|
||||
#include <spine/RTTI.h>
|
||||
#include <spine/Array.h>
|
||||
#include <spine/MixBlend.h>
|
||||
#include <spine/MixDirection.h>
|
||||
#include <spine/SpineObject.h>
|
||||
#include <spine/Property.h>
|
||||
|
||||
@ -50,19 +48,38 @@ namespace spine {
|
||||
|
||||
virtual ~Timeline();
|
||||
|
||||
/// Sets the value(s) for the specified time.
|
||||
/// @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 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).
|
||||
/// @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 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.
|
||||
/// @param alpha alpha 0 applies the current or setup pose value (depending on pose parameter). 1 applies the timeline
|
||||
/// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting alpha over
|
||||
/// time, an animation can be mixed in or out. alpha can also be useful to apply animations on top of each other (layered).
|
||||
/// @param blend Controls how mixing is applied when alpha is than 1.
|
||||
/// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline.
|
||||
/// @param appliedPose True to modify the applied pose.
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) = 0;
|
||||
/// Applies this timeline to the skeleton.
|
||||
/// @param skeleton The skeleton the timeline is applied to. This provides access to the bones, slots, and other skeleton
|
||||
/// components the timelines may change.
|
||||
/// @param lastTime The last time in seconds this timeline was applied. Some timelines trigger only at discrete times, in
|
||||
/// which case all keys are triggered between lastTime (exclusive) and time (inclusive). Pass -1 the first time a
|
||||
/// timeline is applied to ensure frame 0 is triggered.
|
||||
/// @param time The time in seconds the skeleton is being posed for. Timelines find the frame before and after this time and
|
||||
/// interpolate between the frame values.
|
||||
/// @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.
|
||||
/// @param alpha 0 applies setup or current values (depending on fromSetup), 1 uses timeline values, and intermediate values
|
||||
/// interpolate between them. Adjusting alpha over time can mix a timeline in or out.
|
||||
/// @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();
|
||||
|
||||
@ -80,6 +97,8 @@ namespace spine {
|
||||
Array<PropertyId> _propertyIds;
|
||||
Array<float> _frames;
|
||||
size_t _frameEntries;
|
||||
bool _additive;
|
||||
bool _instant;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
|
||||
namespace spine {
|
||||
|
||||
/// Changes a transform constraint's TransformConstraintPose::getMixRotate(), TransformConstraintPose::getMixX(),
|
||||
/// Changes TransformConstraintPose::getMixRotate(), TransformConstraintPose::getMixX(),
|
||||
/// TransformConstraintPose::getMixY(), TransformConstraintPose::getMixScaleX(),
|
||||
/// TransformConstraintPose::getMixScaleY(), and TransformConstraintPose::getMixShearY().
|
||||
class SP_API TransformConstraintTimeline : public CurveTimeline, public ConstraintTimeline {
|
||||
@ -50,8 +50,8 @@ namespace spine {
|
||||
|
||||
virtual ~TransformConstraintTimeline();
|
||||
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) override;
|
||||
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) override;
|
||||
|
||||
/// Sets the time, rotate mix, translate mix, scale mix, and shear mix for the specified frame.
|
||||
/// @param frame Between 0 and frameCount, inclusive.
|
||||
|
||||
@ -46,7 +46,7 @@ namespace spine {
|
||||
explicit TranslateTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
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.
|
||||
@ -61,7 +61,7 @@ namespace spine {
|
||||
explicit TranslateXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
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.
|
||||
@ -76,7 +76,7 @@ namespace spine {
|
||||
explicit TranslateYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
|
||||
|
||||
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 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().
|
||||
class SP_API VertexAttachment : public Attachment {
|
||||
friend class SkeletonBinary;
|
||||
@ -55,8 +55,8 @@ namespace spine {
|
||||
virtual ~VertexAttachment();
|
||||
|
||||
|
||||
/// Transforms the attachment's local vertices to world coordinates. If the slot's SlotPose::getDeform()
|
||||
/// is not empty, it is used to deform the vertices.
|
||||
/// Transforms the attachment's local vertices to world coordinates. If the SlotPose::getDeform() is not
|
||||
/// empty, it is used to deform the vertices.
|
||||
///
|
||||
/// See https://esotericsoftware.com/spine-runtime-skeletons#World-transforms World transforms in the Spine
|
||||
/// Runtimes Guide.
|
||||
@ -74,10 +74,16 @@ namespace spine {
|
||||
/// Gets a unique ID for this attachment.
|
||||
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();
|
||||
|
||||
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();
|
||||
|
||||
void setVertices(Array<float> &vertices);
|
||||
|
||||
@ -73,8 +73,6 @@
|
||||
#include <spine/LinkedMesh.h>
|
||||
#include <spine/MathUtil.h>
|
||||
#include <spine/MeshAttachment.h>
|
||||
#include <spine/MixBlend.h>
|
||||
#include <spine/MixDirection.h>
|
||||
#include <spine/PathAttachment.h>
|
||||
#include <spine/PathConstraint.h>
|
||||
#include <spine/PathConstraintData.h>
|
||||
|
||||
@ -57,8 +57,8 @@ Animation::~Animation() {
|
||||
ArrayUtils::deleteElements(_timelines);
|
||||
}
|
||||
|
||||
void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void Animation::apply(Skeleton &skeleton, float lastTime, float time, bool loop, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
if (loop && _duration != 0) {
|
||||
time = MathUtil::fmod(time, _duration);
|
||||
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) {
|
||||
_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
|
||||
|
||||
TrackEntry::TrackEntry()
|
||||
: _animation(NULL), _previous(NULL), _next(NULL), _mixingFrom(NULL), _mixingTo(0), _trackIndex(0), _loop(false), _holdPrevious(false),
|
||||
_reverse(false), _shortestRotation(false), _eventThreshold(0), _mixAttachmentThreshold(0), _alphaAttachmentThreshold(0),
|
||||
: _animation(NULL), _previous(NULL), _next(NULL), _mixingFrom(NULL), _mixingTo(0), _trackIndex(0), _loop(false), _additive(false),
|
||||
_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),
|
||||
_trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), _mixDuration(0), _interruptAlpha(0), _totalAlpha(0),
|
||||
_mixBlend(MixBlend_Replace), _listener(dummyOnAnimationEventFunc), SP_ANIMATION_LISTENER_USER_DATA_CTOR _listenerObject(NULL), _state(NULL) {
|
||||
_trackLast(0), _nextTrackLast(0), _trackEnd(0), _timeScale(1.0f), _alpha(0), _mixTime(0), _mixDuration(0), _totalAlpha(0),
|
||||
_listener(dummyOnAnimationEventFunc), SP_ANIMATION_LISTENER_USER_DATA_CTOR _listenerObject(NULL), _state(NULL) {
|
||||
}
|
||||
|
||||
TrackEntry::~TrackEntry() {
|
||||
@ -107,12 +107,12 @@ void TrackEntry::setLoop(bool inValue) {
|
||||
_loop = inValue;
|
||||
}
|
||||
|
||||
bool TrackEntry::getHoldPrevious() {
|
||||
return _holdPrevious;
|
||||
bool TrackEntry::getAdditive() {
|
||||
return _additive;
|
||||
}
|
||||
|
||||
void TrackEntry::setHoldPrevious(bool inValue) {
|
||||
_holdPrevious = inValue;
|
||||
void TrackEntry::setAdditive(bool inValue) {
|
||||
_additive = inValue;
|
||||
}
|
||||
|
||||
bool TrackEntry::getReverse() {
|
||||
@ -267,12 +267,7 @@ void TrackEntry::setMixDuration(float inValue) {
|
||||
|
||||
void TrackEntry::setMixDuration(float mixDuration, float delay) {
|
||||
_mixDuration = mixDuration;
|
||||
if (delay <= 0) {
|
||||
if (_previous != nullptr)
|
||||
delay = MathUtil::max(delay + _previous->getTrackComplete() - mixDuration, 0.0f);
|
||||
else
|
||||
delay = 0;
|
||||
}
|
||||
if (delay <= 0) delay = _previous == nullptr ? 0 : MathUtil::max(delay + _previous->getTrackComplete() - mixDuration, 0.0f);
|
||||
this->_delay = delay;
|
||||
}
|
||||
|
||||
@ -284,14 +279,6 @@ TrackEntry *TrackEntry::getMixingTo() {
|
||||
return _mixingTo;
|
||||
}
|
||||
|
||||
void TrackEntry::setMixBlend(MixBlend blend) {
|
||||
_mixBlend = blend;
|
||||
}
|
||||
|
||||
MixBlend TrackEntry::getMixBlend() {
|
||||
return _mixBlend;
|
||||
}
|
||||
|
||||
void TrackEntry::resetRotationDirections() {
|
||||
_timelinesRotation.clear();
|
||||
}
|
||||
@ -569,20 +556,15 @@ bool AnimationState::apply(Skeleton &skeleton) {
|
||||
|
||||
applied = true;
|
||||
|
||||
// Track 0 animations aren't for layering, so never use current values before the first key.
|
||||
MixBlend blend = i == 0 ? MixBlend_First : current._mixBlend;
|
||||
|
||||
// apply mixing from entries first.
|
||||
// Apply mixing from entries first.
|
||||
float alpha = current._alpha;
|
||||
if (current._mixingFrom != NULL) {
|
||||
alpha *= applyMixingFrom(currentP, skeleton);
|
||||
} else if (current._trackTime >= current._trackEnd && current._next == NULL) {
|
||||
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 applyTime = animationTime;
|
||||
Array<Event *> *applyEvents = &_events;
|
||||
@ -592,19 +574,18 @@ bool AnimationState::apply(Skeleton &skeleton) {
|
||||
}
|
||||
size_t timelineCount = current._animation->_timelines.size();
|
||||
Array<Timeline *> &timelines = current._animation->_timelines;
|
||||
if ((i == 0 && alpha == 1) || blend == MixBlend_Add) {
|
||||
if (i == 0) attachments = true;
|
||||
if (i == 0 && alpha == 1) {
|
||||
for (size_t ii = 0; ii < timelineCount; ++ii) {
|
||||
Timeline *timeline = timelines[ii];
|
||||
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
|
||||
timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, blend, MixDirection_In, false);
|
||||
timeline->apply(skeleton, animationLast, applyTime, applyEvents, alpha, true, false, false, false);
|
||||
}
|
||||
} else {
|
||||
Array<int> &timelineMode = current._timelineMode;
|
||||
|
||||
bool shortestRotation = current._shortestRotation;
|
||||
bool attachments = alpha >= current._alphaAttachmentThreshold;
|
||||
bool add = current._additive, shortestRotation = add || current._shortestRotation;
|
||||
bool firstFrame = !shortestRotation && current._timelinesRotation.size() != timelines.size() << 1;
|
||||
if (firstFrame) current._timelinesRotation.setSize(timelines.size() << 1, 0);
|
||||
Array<float> &timelinesRotation = current._timelinesRotation;
|
||||
@ -613,15 +594,15 @@ bool AnimationState::apply(Skeleton &skeleton) {
|
||||
Timeline *timeline = timelines[ii];
|
||||
assert(timeline);
|
||||
|
||||
MixBlend timelineBlend = timelineMode[ii] == Subsequent ? current._mixBlend : MixBlend_Setup;
|
||||
bool fromSetup = (timelineMode[ii] & First) != 0;
|
||||
|
||||
if (!shortestRotation && timeline->getRTTI().isExactly(RotateTimeline::rtti))
|
||||
applyRotateTimeline(static_cast<RotateTimeline *>(timeline), skeleton, applyTime, alpha, timelineBlend, timelinesRotation,
|
||||
ii << 1, firstFrame);
|
||||
applyRotateTimeline(static_cast<RotateTimeline *>(timeline), skeleton, applyTime, alpha, fromSetup, timelinesRotation, ii << 1,
|
||||
firstFrame);
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
Slot *slot = skeleton.getSlots()[attachmentTimeline->getSlotIndex()];
|
||||
if (!slot->getBone().isActive()) return;
|
||||
|
||||
Array<float> &frames = attachmentTimeline->getFrames();
|
||||
if (out) {
|
||||
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);
|
||||
if (out || time < attachmentTimeline->getFrames()[0]) {
|
||||
if (fromSetup) setAttachment(skeleton, *slot, slot->getData().getAttachmentName(), attachments);
|
||||
} 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.*/
|
||||
@ -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) {
|
||||
if (firstFrame) timelinesRotation[i] = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -866,21 +845,12 @@ void AnimationState::applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleto
|
||||
BoneLocal &pose = bone->_pose;
|
||||
BoneLocal &setup = bone->_data._setup;
|
||||
Array<float> &frames = rotateTimeline->_frames;
|
||||
float r1, r2;
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
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);
|
||||
if (fromSetup) pose._rotation = setup._rotation;
|
||||
return;
|
||||
}
|
||||
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.
|
||||
float total, diff = r2 - r1;
|
||||
@ -934,7 +904,9 @@ bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) {
|
||||
if (from->_totalAlpha == 0 || to->_mixDuration == 0) {
|
||||
to->_mixingFrom = from->_mixingFrom;
|
||||
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);
|
||||
}
|
||||
return finished;
|
||||
@ -948,86 +920,53 @@ bool AnimationState::updateMixingFrom(TrackEntry *to, float delta) {
|
||||
|
||||
float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton) {
|
||||
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;
|
||||
if (to->_mixDuration == 0)// Single frame mix to undo mixingFrom changes.
|
||||
mix = 1;
|
||||
else {
|
||||
mix = to->_mixTime / to->_mixDuration;
|
||||
if (mix > 1) {
|
||||
mix = 1;
|
||||
}
|
||||
}
|
||||
float a = from->_alpha * fromMix, keep = 1 - mix * to->_alpha;
|
||||
float alphaMix = a * (1 - mix), alphaHold = keep > 0 ? alphaMix / keep : a;
|
||||
|
||||
bool attachments = mix < from->_mixAttachmentThreshold, drawOrder = mix < from->_mixDrawOrderThreshold;
|
||||
Array<Timeline *> &timelines = from->_animation->_timelines;
|
||||
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 applyTime = animationTime;
|
||||
Array<Event *> *events = NULL;
|
||||
if (from->_reverse) {
|
||||
if (from->_reverse)
|
||||
applyTime = from->_animation->_duration - applyTime;
|
||||
} else {
|
||||
if (mix < from->_eventThreshold) events = &_events;
|
||||
}
|
||||
else if (mix < from->_eventThreshold)
|
||||
events = &_events;
|
||||
|
||||
MixBlend blend = from->_mixBlend;
|
||||
if (blend == MixBlend_Add) {
|
||||
for (size_t i = 0; i < timelineCount; i++)
|
||||
timelines[i]->apply(skeleton, animationLast, applyTime, events, alphaMix, blend, MixDirection_Out, false);
|
||||
} else {
|
||||
Array<int> &timelineMode = from->_timelineMode;
|
||||
Array<TrackEntry *> &timelineHoldMix = from->_timelineHoldMix;
|
||||
|
||||
bool shortestRotation = 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;
|
||||
|
||||
from->_totalAlpha = 0;
|
||||
for (size_t i = 0; i < timelineCount; i++) {
|
||||
Timeline *timeline = timelines[i];
|
||||
MixDirection direction = MixDirection_Out;
|
||||
MixBlend timelineBlend;
|
||||
float alpha;
|
||||
switch (timelineMode[i]) {
|
||||
case Subsequent:
|
||||
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);
|
||||
}
|
||||
from->_totalAlpha = 0;
|
||||
for (size_t i = 0; i < timelineCount; i++) {
|
||||
Timeline *timeline = timelines[i];
|
||||
int mode = timelineMode[i];
|
||||
float alpha;
|
||||
if ((mode & Hold) != 0) {
|
||||
TrackEntry *holdMix = timelineHoldMix[i];
|
||||
alpha = holdMix == NULL ? alphaHold : alphaHold * MathUtil::max(0.0f, 1.0f - holdMix->_mixTime / holdMix->_mixDuration);
|
||||
} else {
|
||||
if (!drawOrder && timeline->getRTTI().isExactly(DrawOrderTimeline::rtti)) continue;
|
||||
alpha = alphaMix;
|
||||
}
|
||||
from->_totalAlpha += alpha;
|
||||
bool fromSetup = (mode & First) != 0;
|
||||
if (!shortestRotation && timeline->getRTTI().isExactly(RotateTimeline::rtti)) {
|
||||
applyRotateTimeline((RotateTimeline *) timeline, skeleton, applyTime, alpha, fromSetup, timelinesRotation, i << 1, firstFrame);
|
||||
} else if (timeline->getRTTI().isExactly(AttachmentTimeline::rtti)) {
|
||||
applyAttachmentTimeline(static_cast<AttachmentTimeline *>(timeline), skeleton, applyTime, fromSetup, true,
|
||||
attachments && alpha >= from->_alphaAttachmentThreshold);
|
||||
} else {
|
||||
bool out = !drawOrder || !timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) || !fromSetup;
|
||||
timeline->apply(skeleton, animationLast, applyTime, events, alpha, fromSetup, add, out, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1036,9 +975,9 @@ float AnimationState::applyMixingFrom(TrackEntry *to, Skeleton &skeleton) {
|
||||
}
|
||||
|
||||
_events.clear();
|
||||
|
||||
from->_nextAnimationLast = animationTime;
|
||||
from->_nextTrackLast = from->_trackTime;
|
||||
|
||||
return mix;
|
||||
}
|
||||
|
||||
@ -1094,12 +1033,6 @@ void AnimationState::setCurrent(size_t index, TrackEntry *current, bool interrup
|
||||
current->_mixingFrom = from;
|
||||
from->_mixingTo = current;
|
||||
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.
|
||||
}
|
||||
|
||||
@ -1120,8 +1053,8 @@ TrackEntry *AnimationState::newTrackEntry(size_t trackIndex, Animation *animatio
|
||||
entry._trackIndex = (int) trackIndex;
|
||||
entry._animation = animation;
|
||||
entry._loop = loop;
|
||||
entry._holdPrevious = 0;
|
||||
|
||||
entry._additive = false;
|
||||
entry._reverse = false;
|
||||
entry._shortestRotation = false;
|
||||
|
||||
@ -1145,9 +1078,8 @@ TrackEntry *AnimationState::newTrackEntry(size_t trackIndex, Animation *animatio
|
||||
entry._alpha = 1;
|
||||
entry._mixTime = 0;
|
||||
entry._mixDuration = (last == NULL) ? 0 : _data->getMix(*last->_animation, *animation);
|
||||
entry._interruptAlpha = 1;
|
||||
entry._totalAlpha = 0;
|
||||
entry._mixBlend = MixBlend_Replace;
|
||||
entry._keepHold = false;
|
||||
|
||||
return entryP;
|
||||
}
|
||||
@ -1164,8 +1096,6 @@ void AnimationState::clearNext(TrackEntry *entry) {
|
||||
void AnimationState::animationsChanged() {
|
||||
_animationsChanged = false;
|
||||
|
||||
_propertyIDs.clear();
|
||||
|
||||
for (size_t i = 0, n = _tracks.size(); i < n; ++i) {
|
||||
TrackEntry *entry = _tracks[i];
|
||||
if (!entry) continue;
|
||||
@ -1173,60 +1103,62 @@ void AnimationState::animationsChanged() {
|
||||
while (entry->_mixingFrom != NULL) entry = entry->_mixingFrom;
|
||||
|
||||
do {
|
||||
if (entry->_mixingTo == NULL || entry->_mixBlend != MixBlend_Add) computeHold(entry);
|
||||
computeHold(entry);
|
||||
entry = entry->_mixingTo;
|
||||
} while (entry != NULL);
|
||||
}
|
||||
_propertyIDs.clear();
|
||||
}
|
||||
|
||||
void AnimationState::computeHold(TrackEntry *entry) {
|
||||
TrackEntry *to = entry->_mixingTo;
|
||||
Array<Timeline *> &timelines = entry->_animation->_timelines;
|
||||
size_t timelinesCount = timelines.size();
|
||||
Array<int> &timelineMode = entry->_timelineMode;
|
||||
timelineMode.setSize(timelinesCount, 0);
|
||||
entry->_timelineHoldMix.clear();
|
||||
Array<TrackEntry *> &timelineHoldMix = entry->_timelineHoldMix;
|
||||
timelineHoldMix.setSize(timelinesCount, 0);
|
||||
timelineHoldMix.setSize(timelinesCount, NULL);
|
||||
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++) {
|
||||
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) {
|
||||
for (size_t i = 0; i < timelinesCount; ++i) {
|
||||
Timeline *timeline = timelines[i];
|
||||
Array<PropertyId> &ids = timeline->getPropertyIds();
|
||||
if (!_propertyIDs.addAll(ids, true)) {
|
||||
timelineMode[i] = Subsequent;
|
||||
} else if (timeline->getRTTI().isExactly(DrawOrderFolderTimeline::rtti) && _propertyIDs.containsKey(drawOrderPropertyId)) {
|
||||
timelineMode[i] = Subsequent;
|
||||
} else {
|
||||
if (to == NULL || timeline->getRTTI().isExactly(AttachmentTimeline::rtti) || timeline->getRTTI().isExactly(DrawOrderTimeline::rtti) ||
|
||||
timeline->getRTTI().isExactly(DrawOrderFolderTimeline::rtti) || timeline->getRTTI().isExactly(EventTimeline::rtti) ||
|
||||
!to->_animation->hasTimeline(ids)) {
|
||||
timelineMode[i] = First;
|
||||
} else {
|
||||
for (TrackEntry *next = to->_mixingTo; next != NULL; next = next->_mixingTo) {
|
||||
if (next->_animation->hasTimeline(ids)) continue;
|
||||
if (next->_mixDuration > 0) {
|
||||
timelineMode[i] = HoldMix;
|
||||
timelineHoldMix[i] = next;
|
||||
i++;
|
||||
goto continue_outer;// continue outer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
timelineMode[i] = HoldFirst;
|
||||
bool first = _propertyIDs.addAll(ids, true) &&
|
||||
!(timeline->getRTTI().isExactly(DrawOrderFolderTimeline::rtti) && _propertyIDs.containsKey(drawOrderPropertyId));
|
||||
|
||||
if (add && timeline->getAdditive()) {
|
||||
timelineMode[i] = first ? First : Subsequent;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if an earlier entry on this track keys this property.
|
||||
bool found = false;
|
||||
for (TrackEntry *from = entry->_mixingFrom; from != NULL; from = from->_mixingFrom) {
|
||||
if (from->_animation->hasTimeline(ids)) {
|
||||
timelineMode[i] = Subsequent;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Attachment << 32) | slotIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_instant = true;
|
||||
|
||||
_attachmentNames.ensureCapacity(frameCount);
|
||||
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));
|
||||
}
|
||||
|
||||
void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void AttachmentTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(alpha);
|
||||
SP_UNUSED(add);
|
||||
|
||||
Slot *slot = skeleton._slots[_slotIndex];
|
||||
if (!slot->_bone.isActive()) return;
|
||||
SlotPose &pose = appliedPose ? *slot->_applied : slot->_pose;
|
||||
|
||||
if (direction == MixDirection_Out) {
|
||||
if (blend == MixBlend_Setup) setAttachment(skeleton, pose, &slot->_data._attachmentName);
|
||||
} else if (time < _frames[0]) {
|
||||
if (blend == MixBlend_Setup || blend == MixBlend_First) setAttachment(skeleton, pose, &slot->_data._attachmentName);
|
||||
if (out || time < _frames[0]) {
|
||||
if (fromSetup) setAttachment(skeleton, pose, &slot->_data._attachmentName);
|
||||
} else {
|
||||
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) {
|
||||
PropertyId ids[] = {((PropertyId) property << 32) | boneIndex};
|
||||
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) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
|
||||
Bone *bone = skeleton._bones[_boneIndex];
|
||||
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) {
|
||||
PropertyId ids[] = {((PropertyId) property1 << 32) | boneIndex, ((PropertyId) property2 << 32) | boneIndex};
|
||||
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) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
|
||||
Bone *bone = skeleton._bones[_boneIndex];
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
if (time < _frames[0]) {
|
||||
Color &setup = slot._data._setup._color;
|
||||
switch (blend) {
|
||||
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;
|
||||
}
|
||||
if (fromSetup) color.set(slot._data._setup._color);
|
||||
return;
|
||||
}
|
||||
|
||||
float r, g, b, a;
|
||||
@ -111,8 +103,12 @@ void RGBATimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, M
|
||||
if (alpha == 1)
|
||||
color.set(r, g, b, a);
|
||||
else {
|
||||
if (blend == MixBlend_Setup) color.set(slot._data._setup._color);
|
||||
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
|
||||
if (fromSetup) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
float r, g, b;
|
||||
if (time < _frames[0]) {
|
||||
Color &setup = slot._data._setup._color;
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
color.r = setup.r;
|
||||
color.g = setup.g;
|
||||
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;
|
||||
}
|
||||
if (fromSetup) {
|
||||
Color &setup = slot._data._setup._color;
|
||||
color.r = setup.r;
|
||||
color.g = setup.g;
|
||||
color.b = setup.b;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (alpha != 1) {
|
||||
if (blend == MixBlend_Setup) {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@ -219,38 +208,29 @@ void AlphaTimeline::setSlotIndex(int 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) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(direction);
|
||||
SP_UNUSED(add);
|
||||
SP_UNUSED(out);
|
||||
|
||||
Slot *slot = skeleton._slots[_slotIndex];
|
||||
if (!slot->_bone._active) return;
|
||||
|
||||
Color &color = (appliedPose ? *slot->_applied : slot->_pose)._color;
|
||||
float a;
|
||||
if (time < _frames[0]) {
|
||||
Color &setup = slot->_data._setup._color;
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
color.a = setup.a;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
a = color.a + (setup.a - color.a) * alpha;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
if (fromSetup) color.a = slot->_data._setup._color.a;
|
||||
return;
|
||||
}
|
||||
|
||||
float a = getCurveValue(time);
|
||||
if (alpha != 1) {
|
||||
if (fromSetup) {
|
||||
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);
|
||||
}
|
||||
@ -278,93 +258,84 @@ void RGBA2Timeline::setFrame(int frame, float time, float r, float g, float b, f
|
||||
_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 &dark = pose._darkColor;
|
||||
float r2, g2, b2;
|
||||
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;
|
||||
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;
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
light.set(setupLight);
|
||||
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;
|
||||
}
|
||||
r2 = setupDark.r + (r2 - setupDark.r) * alpha;
|
||||
g2 = setupDark.g + (g2 - setupDark.g) * alpha;
|
||||
b2 = setupDark.b + (b2 - setupDark.b) * alpha;
|
||||
} else {
|
||||
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 (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;
|
||||
}
|
||||
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);
|
||||
@ -393,93 +364,84 @@ void RGB2Timeline::setFrame(int frame, float time, float r, float g, float b, fl
|
||||
_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 &dark = pose._darkColor;
|
||||
float r, g, b, r2, g2, b2;
|
||||
if (time < _frames[0]) {
|
||||
SlotPose &setup = slot._data._setup;
|
||||
Color &setupLight = setup._color;
|
||||
Color &setupDark = setup._darkColor;
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
light.r = setupLight.r;
|
||||
light.g = setupLight.g;
|
||||
light.b = setupLight.b;
|
||||
dark.r = setupDark.r;
|
||||
dark.g = setupDark.g;
|
||||
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;
|
||||
}
|
||||
if (fromSetup) {
|
||||
SlotPose &setup = slot._data._setup;
|
||||
Color &setupLight = setup._color;
|
||||
Color &setupDark = setup._darkColor;
|
||||
light.r = setupLight.r;
|
||||
light.g = setupLight.g;
|
||||
light.b = setupLight.b;
|
||||
dark.r = setupDark.r;
|
||||
dark.g = setupDark.g;
|
||||
dark.b = setupDark.b;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (alpha != 1) {
|
||||
if (blend == MixBlend_Setup) {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
float CurveTimeline1::getRelativeValue(float time, float alpha, MixBlend blend, float current, float setup) {
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
return setup;
|
||||
case MixBlend_First:
|
||||
return current + (setup - current) * alpha;
|
||||
default:
|
||||
return current;
|
||||
}
|
||||
}
|
||||
float CurveTimeline1::getRelativeValue(float time, float alpha, bool fromSetup, bool add, float current, float setup) {
|
||||
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||
float value = getCurveValue(time);
|
||||
switch (blend) {
|
||||
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;
|
||||
return fromSetup ? setup + value * alpha : current + (add ? value : value + setup - current) * alpha;
|
||||
}
|
||||
|
||||
float CurveTimeline1::getAbsoluteValue(float time, float alpha, MixBlend blend, float current, float setup) {
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
return setup;
|
||||
case MixBlend_First:
|
||||
return current + (setup - current) * alpha;
|
||||
default:
|
||||
return current;
|
||||
}
|
||||
}
|
||||
float CurveTimeline1::getAbsoluteValue(float time, float alpha, bool fromSetup, bool add, float current, float setup) {
|
||||
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||
float value = getCurveValue(time);
|
||||
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;
|
||||
return fromSetup ? setup + (value - setup) * alpha : current + (add ? value : value - current) * alpha;
|
||||
}
|
||||
|
||||
float CurveTimeline1::getAbsoluteValue(float time, float alpha, MixBlend blend, float current, float setup, float value) {
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
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::getAbsoluteValue(float time, float alpha, bool fromSetup, bool add, float current, float setup, float value) {
|
||||
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||
return fromSetup ? setup + (value - setup) * alpha : current + (add ? value : value - current) * alpha;
|
||||
}
|
||||
|
||||
float CurveTimeline1::getScaleValue(float time, float alpha, MixBlend blend, MixDirection direction, float current, float setup) {
|
||||
if (time < _frames[0]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
return setup;
|
||||
case MixBlend_First:
|
||||
return current + (setup - current) * alpha;
|
||||
default:
|
||||
return current;
|
||||
}
|
||||
}
|
||||
float CurveTimeline1::getScaleValue(float time, float alpha, bool fromSetup, bool add, bool out, float current, float setup) {
|
||||
if (time < _frames[0]) return fromSetup ? setup : current;
|
||||
float value = getCurveValue(time) * setup;
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend_Add) return current + value - setup;
|
||||
return value;
|
||||
}
|
||||
// Mixing out uses sign of setup or current pose, else use sign of key.
|
||||
if (direction == MixDirection_Out) {
|
||||
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;
|
||||
if (alpha == 1 && !add) return value;
|
||||
float base = fromSetup ? setup : current;
|
||||
if (add) return base + (value - setup) * alpha;
|
||||
if (out) return base + (MathUtil::abs(value) * MathUtil::sign(base) - base) * alpha;
|
||||
base = MathUtil::abs(base) * MathUtil::sign(value);
|
||||
return base + (value - base) * alpha;
|
||||
}
|
||||
|
||||
@ -47,6 +47,7 @@ DeformTimeline::DeformTimeline(size_t frameCount, size_t bezierCount, int slotIn
|
||||
: SlotCurveTimeline(frameCount, 1, bezierCount, slotIndex), _attachment(&attachment) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Deform << 32) | ((slotIndex << 16 | attachment._id) & 0xffffffff)};
|
||||
setPropertyIds(ids, 1);
|
||||
_additive = true;
|
||||
|
||||
_vertices.ensureCapacity(frameCount);
|
||||
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;
|
||||
if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti)) {
|
||||
return;
|
||||
@ -68,41 +70,14 @@ void DeformTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha,
|
||||
}
|
||||
|
||||
Array<float> &deformArray = pose._deform;
|
||||
if (deformArray.size() == 0) {
|
||||
blend = MixBlend_Setup;
|
||||
}
|
||||
if (deformArray.size() == 0) fromSetup = true;
|
||||
|
||||
Array<Array<float>> &vertices = _vertices;
|
||||
size_t vertexCount = vertices[0].size();
|
||||
|
||||
Array<float> &frames = _frames;
|
||||
if (time < frames[0]) {
|
||||
switch (blend) {
|
||||
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;
|
||||
}
|
||||
if (fromSetup) deformArray.clear();
|
||||
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.
|
||||
Array<float> &lastVertices = vertices[frames.size() - 1];
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend_Add) {
|
||||
if (add && !fromSetup) {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, no alpha.
|
||||
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.
|
||||
memcpy(deform.buffer(), lastVertices.buffer(), vertexCount * sizeof(float));
|
||||
}
|
||||
} else {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup: {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, with alpha.
|
||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
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;
|
||||
} else if (fromSetup) {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, with alpha.
|
||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
float setup = setupVertices[i];
|
||||
deform[i] = setup + (lastVertices[i] - setup) * alpha;
|
||||
}
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
// Vertex positions or deform offsets, with 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 {
|
||||
// Weighted deform offsets, with alpha.
|
||||
for (size_t i = 0; i < vertexCount; i++) deform[i] = lastVertices[i] * alpha;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
@ -168,7 +135,7 @@ void DeformTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha,
|
||||
Array<float> &nextVertices = vertices[frame + 1];
|
||||
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend_Add) {
|
||||
if (add && !fromSetup) {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, no alpha.
|
||||
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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup: {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, with alpha.
|
||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
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;
|
||||
} else if (fromSetup) {
|
||||
if (vertexAttachment->getBones().size() == 0) {
|
||||
// Unweighted vertex positions, with alpha.
|
||||
Array<float> &setupVertices = vertexAttachment->getVertices();
|
||||
for (size_t i = 0; i < vertexCount; i++) {
|
||||
float prev = prevVertices[i], setup = setupVertices[i];
|
||||
deform[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha;
|
||||
}
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
// 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;
|
||||
}
|
||||
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++) {
|
||||
float prev = prevVertices[i];
|
||||
deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * 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;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
} 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++) {
|
||||
float prev = prevVertices[i];
|
||||
deform[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * 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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 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);
|
||||
_inFolder.setSize(slotCount, false);
|
||||
for (size_t i = 0; i < _slots.size(); ++i) _inFolder[_slots[i]] = true;
|
||||
_instant = true;
|
||||
for (size_t i = 0; i < frameCount; ++i) {
|
||||
Array<int> vec;
|
||||
_drawOrders.add(vec);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawOrderFolderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void DrawOrderFolderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(alpha);
|
||||
SP_UNUSED(add);
|
||||
SP_UNUSED(appliedPose);
|
||||
|
||||
if (direction == MixDirection_Out) {
|
||||
if (blend == MixBlend_Setup) setup(skeleton);
|
||||
} else if (time < _frames[0]) {
|
||||
if (blend == MixBlend_Setup || blend == MixBlend_First) setup(skeleton);
|
||||
if (out || time < _frames[0]) {
|
||||
if (fromSetup) setup(skeleton);
|
||||
} else {
|
||||
Array<int> &drawOrder = _drawOrders[Animation::search(_frames, time)];
|
||||
if (drawOrder.size() == 0)
|
||||
|
||||
@ -48,6 +48,7 @@ PropertyId DrawOrderTimeline::getPropertyId() {
|
||||
DrawOrderTimeline::DrawOrderTimeline(size_t frameCount) : Timeline(frameCount, 1) {
|
||||
PropertyId ids[] = {getPropertyId()};
|
||||
setPropertyIds(ids, 1);
|
||||
_instant = true;
|
||||
|
||||
_drawOrders.ensureCapacity(frameCount);
|
||||
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,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void DrawOrderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(appliedPose);
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(alpha);
|
||||
SP_UNUSED(add);
|
||||
|
||||
Array<Slot *> &drawOrder = skeleton._drawOrder;
|
||||
Array<Slot *> &slots = skeleton._slots;
|
||||
if (direction == MixDirection_Out) {
|
||||
if (blend == MixBlend_Setup) {
|
||||
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) {
|
||||
if (out || time < _frames[0]) {
|
||||
if (fromSetup) {
|
||||
drawOrder.clear();
|
||||
drawOrder.ensureCapacity(slots.size());
|
||||
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)};
|
||||
setPropertyIds(ids, 1);
|
||||
_events.setSize(frameCount, NULL);
|
||||
_instant = true;
|
||||
}
|
||||
|
||||
EventTimeline::~EventTimeline() {
|
||||
ArrayUtils::deleteElements(_events);
|
||||
}
|
||||
|
||||
void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *pEvents, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *pEvents, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(skeleton);
|
||||
if (pEvents == NULL) return;
|
||||
|
||||
Array<Event *> &events = *pEvents;
|
||||
@ -65,7 +67,7 @@ void EventTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<
|
||||
|
||||
if (lastTime > time) {
|
||||
// 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;
|
||||
} else if (lastTime >= _frames[frameCount - 1]) {
|
||||
// Last time is after last frame.
|
||||
|
||||
@ -53,35 +53,26 @@ IkConstraintTimeline::IkConstraintTimeline(size_t frameCount, size_t bezierCount
|
||||
IkConstraintTimeline::~IkConstraintTimeline() {
|
||||
}
|
||||
|
||||
void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(add);
|
||||
|
||||
IkConstraint *constraint = (IkConstraint *) skeleton._constraints[_constraintIndex];
|
||||
if (!constraint->isActive()) return;
|
||||
IkConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
IkConstraintPose &setup = constraint->_data._setup;
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
pose._mix = setup._mix;
|
||||
pose._softness = setup._softness;
|
||||
pose._bendDirection = setup._bendDirection;
|
||||
pose._compress = setup._compress;
|
||||
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;
|
||||
if (fromSetup) {
|
||||
IkConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mix = setup._mix;
|
||||
pose._softness = setup._softness;
|
||||
pose._bendDirection = setup._bendDirection;
|
||||
pose._compress = setup._compress;
|
||||
pose._stretch = setup._stretch;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float mix = 0, softness = 0;
|
||||
@ -108,24 +99,20 @@ void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time,
|
||||
}
|
||||
}
|
||||
|
||||
if (blend == MixBlend_Setup) {
|
||||
IkConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mix = setup._mix + (mix - setup._mix) * alpha;
|
||||
pose._softness = setup._softness + (softness - setup._softness) * alpha;
|
||||
if (direction == MixDirection_Out) {
|
||||
pose._bendDirection = setup._bendDirection;
|
||||
pose._compress = setup._compress;
|
||||
pose._stretch = setup._stretch;
|
||||
return;
|
||||
IkConstraintPose &base = fromSetup ? constraint->_data._setup : pose;
|
||||
pose._mix = base._mix + (mix - base._mix) * alpha;
|
||||
pose._softness = base._softness + (softness - base._softness) * alpha;
|
||||
if (out) {
|
||||
if (fromSetup) {
|
||||
pose._bendDirection = base._bendDirection;
|
||||
pose._compress = base._compress;
|
||||
pose._stretch = base._stretch;
|
||||
}
|
||||
} else {
|
||||
pose._mix += (mix - pose._mix) * alpha;
|
||||
pose._softness += (softness - pose._softness) * alpha;
|
||||
if (direction == MixDirection_Out) return;
|
||||
pose._bendDirection = (int) _frames[i + BEND_DIRECTION];
|
||||
pose._compress = _frames[i + COMPRESS] != 0;
|
||||
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) {
|
||||
|
||||
@ -45,6 +45,7 @@ RTTI_IMPL_MULTI(InheritTimeline, Timeline, BoneTimeline)
|
||||
InheritTimeline::InheritTimeline(size_t frameCount, int boneIndex) : Timeline(frameCount, ENTRIES), BoneTimeline(boneIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_Inherit << 32) | boneIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_instant = true;
|
||||
}
|
||||
|
||||
InheritTimeline::~InheritTimeline() {
|
||||
@ -56,26 +57,25 @@ void InheritTimeline::setFrame(int frame, float time, Inherit inherit) {
|
||||
_frames[frame + INHERIT] = (float) inherit;
|
||||
}
|
||||
|
||||
|
||||
void InheritTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void InheritTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(alpha);
|
||||
SP_UNUSED(add);
|
||||
|
||||
Bone *bone = skeleton._bones[_boneIndex];
|
||||
if (!bone->isActive()) return;
|
||||
BoneLocal &pose = appliedPose ? *bone->_applied : bone->_pose;
|
||||
|
||||
if (direction == MixDirection_Out) {
|
||||
if (blend == MixBlend_Setup) pose._inherit = bone->_data._setup._inherit;
|
||||
return;
|
||||
}
|
||||
|
||||
if (time < _frames[0]) {
|
||||
if (blend == MixBlend_Setup || blend == MixBlend_First) pose._inherit = bone->_data._setup._inherit;
|
||||
if (out) {
|
||||
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]);
|
||||
if (time < _frames[0]) {
|
||||
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) {
|
||||
PropertyId ids[] = {((PropertyId) Property_PathConstraintMix << 32) | constraintIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
PathConstraintMixTimeline::~PathConstraintMixTimeline() {
|
||||
}
|
||||
|
||||
void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(direction);
|
||||
SP_UNUSED(out);
|
||||
|
||||
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
||||
if (!constraint->isActive()) return;
|
||||
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
PathConstraintPose &setup = constraint->_data._setup;
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
pose._mixRotate = setup._mixRotate;
|
||||
pose._mixX = setup._mixX;
|
||||
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;
|
||||
if (fromSetup) {
|
||||
PathConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mixRotate = setup._mixRotate;
|
||||
pose._mixX = setup._mixX;
|
||||
pose._mixY = setup._mixY;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float rotate, x, y;
|
||||
@ -109,15 +102,15 @@ void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float
|
||||
}
|
||||
}
|
||||
|
||||
if (blend == MixBlend_Setup) {
|
||||
PathConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mixRotate = setup._mixRotate + (rotate - setup._mixRotate) * alpha;
|
||||
pose._mixX = setup._mixX + (x - setup._mixX) * alpha;
|
||||
pose._mixY = setup._mixY + (y - setup._mixY) * alpha;
|
||||
PathConstraintPose &base = fromSetup ? constraint->_data._setup : pose;
|
||||
if (add) {
|
||||
pose._mixRotate = base._mixRotate + rotate * alpha;
|
||||
pose._mixX = base._mixX + x * alpha;
|
||||
pose._mixY = base._mixY + y * alpha;
|
||||
} else {
|
||||
pose._mixRotate += (rotate - pose._mixRotate) * alpha;
|
||||
pose._mixX += (x - pose._mixX) * alpha;
|
||||
pose._mixY += (y - pose._mixY) * alpha;
|
||||
pose._mixRotate = base._mixRotate + (rotate - base._mixRotate) * alpha;
|
||||
pose._mixX = base._mixX + (x - base._mixX) * 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)
|
||||
: ConstraintTimeline1(frameCount, bezierCount, constraintIndex, Property_PathConstraintPosition) {
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
PathConstraintPositionTimeline::~PathConstraintPositionTimeline() {
|
||||
}
|
||||
|
||||
void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void PathConstraintPositionTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup,
|
||||
bool add, bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(direction);
|
||||
SP_UNUSED(out);
|
||||
|
||||
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
||||
if (constraint->isActive()) {
|
||||
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
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() {
|
||||
}
|
||||
|
||||
void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup,
|
||||
bool add, bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(direction);
|
||||
SP_UNUSED(out);
|
||||
|
||||
PathConstraint *constraint = (PathConstraint *) skeleton._constraints[_constraintIndex];
|
||||
if (constraint->isActive()) {
|
||||
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
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)
|
||||
|
||||
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};
|
||||
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) {
|
||||
if (blend == MixBlend_Add && !_additive) blend = MixBlend_Replace;
|
||||
SP_UNUSED(out);
|
||||
if (add && !_additive) add = false;
|
||||
if (_constraintIndex == -1) {
|
||||
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];
|
||||
if (constraint->isActive() && global(constraint->_data)) {
|
||||
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 {
|
||||
PhysicsConstraint *constraint = static_cast<PhysicsConstraint *>(skeleton.getConstraints()[_constraintIndex]);
|
||||
if (constraint->isActive()) {
|
||||
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,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void PhysicsConstraintResetTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
PhysicsConstraint *constraint = nullptr;
|
||||
if (_constraintIndex != -1) {
|
||||
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.
|
||||
apply(skeleton, lastTime, FLT_MAX, nullptr, alpha, blend, direction, appliedPose);
|
||||
apply(skeleton, lastTime, FLT_MAX, nullptr, alpha, false, false, false, false);
|
||||
lastTime = -1;
|
||||
} else if (lastTime >= _frames[_frames.size() - 1])// Last time is after last frame.
|
||||
return;
|
||||
|
||||
@ -39,7 +39,7 @@ RotateTimeline::RotateTimeline(size_t frameCount, size_t bezierCount, int boneIn
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Rotate) {
|
||||
}
|
||||
|
||||
void RotateTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
SP_UNUSED(direction);
|
||||
pose._rotation = getRelativeValue(time, alpha, blend, pose._rotation, setup._rotation);
|
||||
void RotateTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
SP_UNUSED(out);
|
||||
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) {
|
||||
}
|
||||
|
||||
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]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
pose._scaleX = setup._scaleX;
|
||||
pose._scaleY = setup._scaleY;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
pose._scaleX += (setup._scaleX - pose._scaleX) * alpha;
|
||||
pose._scaleY += (setup._scaleY - pose._scaleY) * alpha;
|
||||
default: {
|
||||
}
|
||||
if (fromSetup) {
|
||||
pose._scaleX = setup._scaleX;
|
||||
pose._scaleY = setup._scaleY;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -88,54 +81,29 @@ void ScaleTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float
|
||||
x *= setup._scaleX;
|
||||
y *= setup._scaleY;
|
||||
|
||||
if (alpha == 1) {
|
||||
if (blend == MixBlend_Add) {
|
||||
pose._scaleX += x - setup._scaleX;
|
||||
pose._scaleY += y - setup._scaleY;
|
||||
} else {
|
||||
pose._scaleX = x;
|
||||
pose._scaleY = y;
|
||||
}
|
||||
if (alpha == 1 && !add) {
|
||||
pose._scaleX = x;
|
||||
pose._scaleY = y;
|
||||
} else {
|
||||
float bx, by;
|
||||
if (direction == MixDirection_Out) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
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;
|
||||
}
|
||||
if (fromSetup) {
|
||||
bx = setup._scaleX;
|
||||
by = setup._scaleY;
|
||||
} else {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
bx = MathUtil::abs(setup._scaleX) * MathUtil::sign(x);
|
||||
by = MathUtil::abs(setup._scaleY) * MathUtil::sign(y);
|
||||
pose._scaleX = bx + (x - bx) * alpha;
|
||||
pose._scaleY = by + (y - by) * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
bx = MathUtil::abs(pose._scaleX) * MathUtil::sign(x);
|
||||
by = MathUtil::abs(pose._scaleY) * MathUtil::sign(y);
|
||||
pose._scaleX = bx + (x - bx) * alpha;
|
||||
pose._scaleY = by + (y - by) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
pose._scaleX += (x - setup._scaleX) * alpha;
|
||||
pose._scaleY += (y - setup._scaleY) * alpha;
|
||||
}
|
||||
bx = pose._scaleX;
|
||||
by = pose._scaleY;
|
||||
}
|
||||
if (add) {
|
||||
pose._scaleX = bx + (x - setup._scaleX) * alpha;
|
||||
pose._scaleY = by + (y - setup._scaleY) * alpha;
|
||||
} else if (out) {
|
||||
pose._scaleX = bx + (MathUtil::abs(x) * MathUtil::sign(bx) - bx) * alpha;
|
||||
pose._scaleY = by + (MathUtil::abs(y) * MathUtil::sign(by) - by) * alpha;
|
||||
} else {
|
||||
bx = MathUtil::abs(bx) * MathUtil::sign(x);
|
||||
by = MathUtil::abs(by) * MathUtil::sign(y);
|
||||
pose._scaleX = bx + (x - bx) * alpha;
|
||||
pose._scaleY = by + (y - by) * alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -146,8 +114,8 @@ ScaleXTimeline::ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIn
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleX) {
|
||||
}
|
||||
|
||||
void ScaleXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose._scaleX = getScaleValue(time, alpha, blend, direction, pose._scaleX, setup._scaleX);
|
||||
void ScaleXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
pose._scaleX = getScaleValue(time, alpha, fromSetup, add, out, pose._scaleX, setup._scaleX);
|
||||
}
|
||||
|
||||
RTTI_IMPL(ScaleYTimeline, BoneTimeline1)
|
||||
@ -156,6 +124,6 @@ ScaleYTimeline::ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIn
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ScaleY) {
|
||||
}
|
||||
|
||||
void ScaleYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose._scaleY = getScaleValue(time, alpha, blend, direction, pose._scaleY, setup._scaleY);
|
||||
void ScaleYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
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)
|
||||
: Timeline(frameCount, ENTRIES), SlotTimeline(), _slotIndex(slotIndex), _attachment((HasTextureRegion *) &attachment) {
|
||||
_instant = true;
|
||||
int sequenceId = 0;
|
||||
if (attachment.getRTTI().instanceOf(RegionAttachment::rtti)) sequenceId = ((RegionAttachment *) &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;
|
||||
}
|
||||
|
||||
void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(alpha);
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(add);
|
||||
|
||||
Slot *slot = skeleton.getSlots()[getSlotIndex()];
|
||||
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 (!sequence) return;
|
||||
|
||||
if (direction == MixDirection_Out) {
|
||||
if (blend == MixBlend_Setup) pose.setSequenceIndex(-1);
|
||||
if (out) {
|
||||
if (fromSetup) pose.setSequenceIndex(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
Array<float> &frames = this->_frames;
|
||||
if (time < frames[0]) {
|
||||
if (blend == MixBlend_Setup || blend == MixBlend_First) pose.setSequenceIndex(-1);
|
||||
if (fromSetup) pose.setSequenceIndex(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -46,18 +46,12 @@ ShearTimeline::ShearTimeline(size_t frameCount, size_t bezierCount, int boneInde
|
||||
: 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]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
pose._shearX = setup._shearX;
|
||||
pose._shearY = setup._shearY;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
pose._shearX += (setup._shearX - pose._shearX) * alpha;
|
||||
pose._shearY += (setup._shearY - pose._shearY) * alpha;
|
||||
default: {
|
||||
}
|
||||
if (fromSetup) {
|
||||
pose._shearX = setup._shearX;
|
||||
pose._shearY = setup._shearY;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -86,19 +80,15 @@ void ShearTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float
|
||||
}
|
||||
}
|
||||
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
pose._shearX = setup._shearX + x * alpha;
|
||||
pose._shearY = setup._shearY + y * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
pose._shearX += (setup._shearX + x - pose._shearX) * alpha;
|
||||
pose._shearY += (setup._shearY + y - pose._shearY) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
pose._shearX += x * alpha;
|
||||
pose._shearY += y * alpha;
|
||||
if (fromSetup) {
|
||||
pose._shearX = setup._shearX + x * alpha;
|
||||
pose._shearY = setup._shearY + y * alpha;
|
||||
} else if (add) {
|
||||
pose._shearX += x * alpha;
|
||||
pose._shearY += y * alpha;
|
||||
} else {
|
||||
pose._shearX += (setup._shearX + x - pose._shearX) * alpha;
|
||||
pose._shearY += (setup._shearY + y - pose._shearY) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,8 +98,9 @@ ShearXTimeline::ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIn
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearX) {
|
||||
}
|
||||
|
||||
void ShearXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose._shearX = getRelativeValue(time, alpha, blend, pose._shearX, setup._shearX);
|
||||
void ShearXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
SP_UNUSED(out);
|
||||
pose._shearX = getRelativeValue(time, alpha, fromSetup, add, pose._shearX, setup._shearX);
|
||||
}
|
||||
|
||||
RTTI_IMPL(ShearYTimeline, BoneTimeline1)
|
||||
@ -118,6 +109,7 @@ ShearYTimeline::ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIn
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_ShearY) {
|
||||
}
|
||||
|
||||
void ShearYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose._shearY = getRelativeValue(time, alpha, blend, pose._shearY, setup._shearY);
|
||||
void ShearYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
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;
|
||||
}
|
||||
|
||||
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>());
|
||||
Array<Entry> &bucket = _buckets[slotIndex];
|
||||
int existing = findInBucket(bucket, attachmentName);
|
||||
int existing = findInBucket(bucket, placeholderName);
|
||||
attachment->reference();
|
||||
if (existing >= 0) {
|
||||
disposeAttachment(bucket[existing]._attachment);
|
||||
bucket[existing]._attachment = attachment;
|
||||
} 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;
|
||||
int existing = findInBucket(_buckets[slotIndex], attachmentName);
|
||||
int existing = findInBucket(_buckets[slotIndex], placeholderName);
|
||||
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;
|
||||
int existing = findInBucket(_buckets[slotIndex], attachmentName);
|
||||
int existing = findInBucket(_buckets[slotIndex], placeholderName);
|
||||
if (existing >= 0) {
|
||||
disposeAttachment(_buckets[slotIndex][existing]._attachment);
|
||||
_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++)
|
||||
if (bucket[i]._name == attachmentName) return (int) i;
|
||||
if (bucket[i]._placeholderName == placeholderName) return (int) i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -99,16 +99,16 @@ Skin::~Skin() {
|
||||
}
|
||||
}
|
||||
|
||||
void Skin::setAttachment(size_t slotIndex, const String &name, Attachment *attachment) {
|
||||
_attachments.put(slotIndex, name, attachment);
|
||||
void Skin::setAttachment(size_t slotIndex, const String &placeholderName, Attachment *attachment) {
|
||||
_attachments.put(slotIndex, placeholderName, attachment);
|
||||
}
|
||||
|
||||
Attachment *Skin::getAttachment(size_t slotIndex, const String &name) {
|
||||
return _attachments.get(slotIndex, name);
|
||||
Attachment *Skin::getAttachment(size_t slotIndex, const String &placeholderName) {
|
||||
return _attachments.get(slotIndex, placeholderName);
|
||||
}
|
||||
|
||||
void Skin::removeAttachment(size_t slotIndex, const String &name) {
|
||||
_attachments.remove(slotIndex, name);
|
||||
void Skin::removeAttachment(size_t slotIndex, const String &placeholderName) {
|
||||
_attachments.remove(slotIndex, placeholderName);
|
||||
}
|
||||
|
||||
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()) {
|
||||
Skin::AttachmentMap::Entry &entry = entries.next();
|
||||
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];
|
||||
|
||||
if (slot->getPose().getAttachment() == entry._attachment) {
|
||||
Attachment *attachment = getAttachment(slotIndex, entry._name);
|
||||
Attachment *attachment = getAttachment(slotIndex, entry._placeholderName);
|
||||
if (attachment) slot->getPose().setAttachment(attachment);
|
||||
}
|
||||
}
|
||||
@ -162,7 +162,7 @@ void Skin::addSkin(Skin &other) {
|
||||
AttachmentMap::Entries entries = other.getAttachments();
|
||||
while (entries.hasNext()) {
|
||||
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()) {
|
||||
AttachmentMap::Entry &entry = entries.next();
|
||||
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
|
||||
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();
|
||||
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) {
|
||||
|
||||
@ -46,21 +46,22 @@ SliderMixTimeline::SliderMixTimeline(size_t frameCount, size_t bezierCount, int
|
||||
: ConstraintTimeline1(frameCount, bezierCount, sliderIndex, Property_SliderMix) {
|
||||
PropertyId ids[] = {((PropertyId) Property_SliderMix << 32) | sliderIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
SliderMixTimeline::~SliderMixTimeline() {
|
||||
}
|
||||
|
||||
void SliderMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void SliderMixTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(direction);
|
||||
SP_UNUSED(out);
|
||||
|
||||
Slider *constraint = (Slider *) skeleton._constraints[_constraintIndex];
|
||||
if (constraint->isActive()) {
|
||||
SliderPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
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) {
|
||||
PropertyId ids[] = {((PropertyId) Property_SliderTime << 32) | sliderIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
SliderTimeline::~SliderTimeline() {
|
||||
}
|
||||
|
||||
void SliderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void SliderTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(direction);
|
||||
SP_UNUSED(out);
|
||||
|
||||
Slider *constraint = (Slider *) skeleton._constraints[_constraintIndex];
|
||||
if (constraint->isActive()) {
|
||||
SliderPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
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;
|
||||
}
|
||||
|
||||
void SlotCurveTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void SlotCurveTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add, bool out,
|
||||
bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(direction);
|
||||
SP_UNUSED(out);
|
||||
|
||||
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)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -48,43 +48,33 @@ TransformConstraintTimeline::TransformConstraintTimeline(size_t frameCount, size
|
||||
: CurveTimeline(frameCount, TransformConstraintTimeline::ENTRIES, bezierCount), ConstraintTimeline(), _constraintIndex(transformConstraintIndex) {
|
||||
PropertyId ids[] = {((PropertyId) Property_TransformConstraint << 32) | transformConstraintIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
_additive = true;
|
||||
}
|
||||
|
||||
TransformConstraintTimeline::~TransformConstraintTimeline() {
|
||||
}
|
||||
|
||||
void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixBlend blend,
|
||||
MixDirection direction, bool appliedPose) {
|
||||
void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, bool fromSetup, bool add,
|
||||
bool out, bool appliedPose) {
|
||||
SP_UNUSED(lastTime);
|
||||
SP_UNUSED(events);
|
||||
SP_UNUSED(direction);
|
||||
SP_UNUSED(out);
|
||||
|
||||
TransformConstraint *constraint = (TransformConstraint *) skeleton._constraints[_constraintIndex];
|
||||
if (!constraint->isActive()) return;
|
||||
TransformConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
|
||||
if (time < _frames[0]) {
|
||||
TransformConstraintPose &setup = constraint->_data._setup;
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
pose._mixRotate = setup._mixRotate;
|
||||
pose._mixX = setup._mixX;
|
||||
pose._mixY = setup._mixY;
|
||||
pose._mixScaleX = setup._mixScaleX;
|
||||
pose._mixScaleY = setup._mixScaleY;
|
||||
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;
|
||||
if (fromSetup) {
|
||||
TransformConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mixRotate = setup._mixRotate;
|
||||
pose._mixX = setup._mixX;
|
||||
pose._mixY = setup._mixY;
|
||||
pose._mixScaleX = setup._mixScaleX;
|
||||
pose._mixScaleY = setup._mixScaleY;
|
||||
pose._mixShearY = setup._mixShearY;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float rotate, x, y, scaleX, scaleY, shearY;
|
||||
@ -127,34 +117,21 @@ void TransformConstraintTimeline::apply(Skeleton &skeleton, float lastTime, floa
|
||||
}
|
||||
}
|
||||
|
||||
switch (blend) {
|
||||
case MixBlend_Setup: {
|
||||
TransformConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mixRotate = setup._mixRotate + (rotate - setup._mixRotate) * alpha;
|
||||
pose._mixX = setup._mixX + (x - setup._mixX) * alpha;
|
||||
pose._mixY = setup._mixY + (y - setup._mixY) * alpha;
|
||||
pose._mixScaleX = setup._mixScaleX + (scaleX - setup._mixScaleX) * alpha;
|
||||
pose._mixScaleY = setup._mixScaleY + (scaleY - setup._mixScaleY) * alpha;
|
||||
pose._mixShearY = setup._mixShearY + (shearY - setup._mixShearY) * alpha;
|
||||
break;
|
||||
}
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
pose._mixRotate += (rotate - pose._mixRotate) * alpha;
|
||||
pose._mixX += (x - pose._mixX) * 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;
|
||||
TransformConstraintPose &base = fromSetup ? constraint->_data._setup : pose;
|
||||
if (add) {
|
||||
pose._mixRotate = base._mixRotate + rotate * alpha;
|
||||
pose._mixX = base._mixX + x * alpha;
|
||||
pose._mixY = base._mixY + y * alpha;
|
||||
pose._mixScaleX = base._mixScaleX + scaleX * alpha;
|
||||
pose._mixScaleY = base._mixScaleY + scaleY * alpha;
|
||||
pose._mixShearY = base._mixShearY + shearY * alpha;
|
||||
} else {
|
||||
pose._mixRotate = base._mixRotate + (rotate - base._mixRotate) * alpha;
|
||||
pose._mixX = base._mixX + (x - base._mixX) * alpha;
|
||||
pose._mixY = base._mixY + (y - base._mixY) * alpha;
|
||||
pose._mixScaleX = base._mixScaleX + (scaleX - base._mixScaleX) * alpha;
|
||||
pose._mixScaleY = base._mixScaleY + (scaleY - base._mixScaleY) * alpha;
|
||||
pose._mixShearY = base._mixShearY + (shearY - base._mixShearY) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -46,18 +46,12 @@ TranslateTimeline::TranslateTimeline(size_t frameCount, size_t bezierCount, int
|
||||
: 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]) {
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
pose._x = setup._x;
|
||||
pose._y = setup._y;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
pose._x += (setup._x - pose._x) * alpha;
|
||||
pose._y += (setup._y - pose._y) * alpha;
|
||||
default: {
|
||||
}
|
||||
if (fromSetup) {
|
||||
pose._x = setup._x;
|
||||
pose._y = setup._y;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -86,19 +80,15 @@ void TranslateTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, fl
|
||||
}
|
||||
}
|
||||
|
||||
switch (blend) {
|
||||
case MixBlend_Setup:
|
||||
pose._x = setup._x + x * alpha;
|
||||
pose._y = setup._y + y * alpha;
|
||||
break;
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
pose._x += (setup._x + x - pose._x) * alpha;
|
||||
pose._y += (setup._y + y - pose._y) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
pose._x += x * alpha;
|
||||
pose._y += y * alpha;
|
||||
if (fromSetup) {
|
||||
pose._x = setup._x + x * alpha;
|
||||
pose._y = setup._y + y * alpha;
|
||||
} else if (add) {
|
||||
pose._x += x * alpha;
|
||||
pose._y += y * alpha;
|
||||
} else {
|
||||
pose._x += (setup._x + x - pose._x) * alpha;
|
||||
pose._y += (setup._y + y - pose._y) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,8 +98,9 @@ TranslateXTimeline::TranslateXTimeline(size_t frameCount, size_t bezierCount, in
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_X) {
|
||||
}
|
||||
|
||||
void TranslateXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose._x = getRelativeValue(time, alpha, blend, pose._x, setup._x);
|
||||
void TranslateXTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
SP_UNUSED(out);
|
||||
pose._x = getRelativeValue(time, alpha, fromSetup, add, pose._x, setup._x);
|
||||
}
|
||||
|
||||
RTTI_IMPL(TranslateYTimeline, BoneTimeline1)
|
||||
@ -118,6 +109,7 @@ TranslateYTimeline::TranslateYTimeline(size_t frameCount, size_t bezierCount, in
|
||||
: BoneTimeline1(frameCount, bezierCount, boneIndex, Property_Y) {
|
||||
}
|
||||
|
||||
void TranslateYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, MixBlend blend, MixDirection direction) {
|
||||
pose._y = getRelativeValue(time, alpha, blend, pose._y, setup._y);
|
||||
void TranslateYTimeline::_apply(BoneLocal &pose, BoneLocal &setup, float time, float alpha, bool fromSetup, bool add, bool out) {
|
||||
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");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -81,6 +81,7 @@ int main(int argc, char *argv[]) {
|
||||
const char *skeletonPath = argv[1];
|
||||
const char *atlasPath = argv[2];
|
||||
const char *animationName = argc >= 4 ? argv[3] : nullptr;
|
||||
const char *animationName2 = argc >= 5 ? argv[4] : nullptr;
|
||||
|
||||
// Load atlas with headless texture loader
|
||||
HeadlessTextureLoader textureLoader;
|
||||
@ -147,6 +148,47 @@ int main(int argc, char *argv[]) {
|
||||
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
|
||||
if (state != nullptr) {
|
||||
delete state;
|
||||
|
||||
@ -1864,21 +1864,8 @@ namespace spine {
|
||||
_json.writeName("mixDuration");
|
||||
_json.writeValue(obj->getMixDuration());
|
||||
|
||||
_json.writeName("mixBlend");
|
||||
_json.writeValue([&]() -> String {
|
||||
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("additive");
|
||||
_json.writeValue(obj->getAdditive());
|
||||
|
||||
_json.writeName("mixingFrom");
|
||||
if (obj->getMixingFrom() == nullptr) {
|
||||
@ -1894,8 +1881,6 @@ namespace spine {
|
||||
writeTrackEntry(obj->getMixingTo());
|
||||
}
|
||||
|
||||
_json.writeName("holdPrevious");
|
||||
_json.writeValue(obj->getHoldPrevious());
|
||||
|
||||
_json.writeName("shortestRotation");
|
||||
_json.writeValue(obj->getShortestRotation());
|
||||
@ -2208,11 +2193,15 @@ namespace spine {
|
||||
writeColor(obj->getColor());
|
||||
|
||||
_json.writeName("bones");
|
||||
_json.writeArrayStart();
|
||||
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
||||
_json.writeValue(obj->getBones()[i]);
|
||||
if (obj->getBones().size() == 0) {
|
||||
_json.writeNull();
|
||||
} 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.writeArrayStart();
|
||||
@ -2271,11 +2260,15 @@ namespace spine {
|
||||
writeColor(obj->getColor());
|
||||
|
||||
_json.writeName("bones");
|
||||
_json.writeArrayStart();
|
||||
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
||||
_json.writeValue(obj->getBones()[i]);
|
||||
if (obj->getBones().size() == 0) {
|
||||
_json.writeNull();
|
||||
} 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.writeArrayStart();
|
||||
@ -2605,11 +2598,7 @@ namespace spine {
|
||||
_json.writeValue(obj->getHeight());
|
||||
|
||||
_json.writeName("sequence");
|
||||
if (!obj->getSequence().hasPathSuffix()) {
|
||||
_json.writeNull();
|
||||
} else {
|
||||
writeSequence(&obj->getSequence());
|
||||
}
|
||||
writeSequence(&obj->getSequence());
|
||||
|
||||
_json.writeName("parentMesh");
|
||||
if (obj->getParentMesh() == nullptr) {
|
||||
@ -2619,11 +2608,15 @@ namespace spine {
|
||||
}
|
||||
|
||||
_json.writeName("bones");
|
||||
_json.writeArrayStart();
|
||||
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
||||
_json.writeValue(obj->getBones()[i]);
|
||||
if (obj->getBones().size() == 0) {
|
||||
_json.writeNull();
|
||||
} 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.writeArrayStart();
|
||||
@ -2688,11 +2681,15 @@ namespace spine {
|
||||
writeColor(obj->getColor());
|
||||
|
||||
_json.writeName("bones");
|
||||
_json.writeArrayStart();
|
||||
for (size_t i = 0; i < obj->getBones().size(); i++) {
|
||||
_json.writeValue(obj->getBones()[i]);
|
||||
if (obj->getBones().size() == 0) {
|
||||
_json.writeNull();
|
||||
} 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.writeArrayStart();
|
||||
@ -3128,11 +3125,7 @@ namespace spine {
|
||||
_json.writeValue(obj->getPath());
|
||||
|
||||
_json.writeName("sequence");
|
||||
if (!obj->getSequence().hasPathSuffix()) {
|
||||
_json.writeNull();
|
||||
} else {
|
||||
writeSequence(&obj->getSequence());
|
||||
}
|
||||
writeSequence(&obj->getSequence());
|
||||
|
||||
_json.writeName("name");
|
||||
_json.writeValue(obj->getName());
|
||||
@ -3440,10 +3433,10 @@ namespace spine {
|
||||
|
||||
void writeSkinEntry(Skin::AttachmentMap::Entry *obj) {
|
||||
_json.writeObjectStart();
|
||||
String name = obj->_name;
|
||||
String placeholderName = obj->_placeholderName;
|
||||
String refString;
|
||||
if (!name.isEmpty()) {
|
||||
refString.append("<SkinEntry-").append(name).append(">");
|
||||
if (!placeholderName.isEmpty()) {
|
||||
refString.append("<SkinEntry-").append(placeholderName).append(">");
|
||||
} else {
|
||||
refString.append("<SkinEntry-").append(_nextId++).append(">");
|
||||
}
|
||||
@ -3454,7 +3447,7 @@ namespace spine {
|
||||
_json.writeName("slotIndex");
|
||||
_json.writeValue((int) obj->_slotIndex);
|
||||
_json.writeName("name");
|
||||
_json.writeValue(obj->_name);
|
||||
_json.writeValue(obj->_placeholderName);
|
||||
_json.writeName("attachment");
|
||||
writeAttachment(obj->_attachment);
|
||||
_json.writeObjectEnd();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user