[godot] Port AnimationState additive/hold rework, remove MixBlend/MixDirection, Skin placeholder rename

- Remove SpineConstant::MixBlend and SpineConstant::MixDirection enums
- Replace SpineTrackEntry hold_previous/mix_blend with additive
- Replace SpineAnimationTrack hold_previous/mix_blend with additive
- Update SpineTimeline::apply and SpineAnimation::apply signatures
- Update SpineSkin to use _placeholderName
- Sync spine-cpp copy from spine-cpp root
This commit is contained in:
Mario Zechner 2026-03-24 21:26:41 +01:00
parent a9f6c2a402
commit 1d5a11acef
12 changed files with 54 additions and 94 deletions

View File

@ -238,6 +238,15 @@
- **Additions**
- Added `SpineSlider` and `SpineSliderData` classes for slider constraints
- Added `SpineTrackEntry.get_additive()` / `set_additive()` for additive blending per track entry.
- **Breaking changes (since previous 4.3 beta)**
- `SpineTrackEntry.get_hold_previous()` / `set_hold_previous()` removed.
- `SpineTrackEntry.get_mix_blend()` / `set_mix_blend()` removed. Use `get_additive()` / `set_additive()` for additive blending.
- `SpineConstant.MixBlend` and `SpineConstant.MixDirection` enums removed.
- `SpineTimeline.apply()` signature changed: `blend` and `direction` parameters replaced with `from_setup`, `add`, `out`.
- `SpineAnimation.apply()` signature changed to match.
- `SpineAnimationTrack` property `hold_previous` replaced with `additive`, property `mix_blend` removed.
- Added `SpineBoneLocal` and `SpineBonePose` classes for new pose system
- Added pose classes for constraints: `SpineIkConstraintPose`, `SpinePathConstraintPose`, `SpinePhysicsConstraintPose`, `SpineSliderPose`, `SpineTransformConstraintPose`

View File

@ -40,7 +40,7 @@ void SpineAnimation::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_duration"), &SpineAnimation::get_duration);
ClassDB::bind_method(D_METHOD("set_duration", "duration"), &SpineAnimation::set_duration);
ClassDB::bind_method(D_METHOD("apply", "skeleton", "last_time", "time", "loop", "events", "alpha", "blend", "direction", "appliedPose"),
ClassDB::bind_method(D_METHOD("apply", "skeleton", "last_time", "time", "loop", "events", "alpha", "from_setup", "add", "out", "appliedPose"),
&SpineAnimation::apply);
ClassDB::bind_method(D_METHOD("get_timelines"), &SpineAnimation::get_timelines);
ClassDB::bind_method(D_METHOD("has_timeline", "ids"), &SpineAnimation::has_timeline);
@ -67,12 +67,11 @@ void SpineAnimation::set_duration(float duration) {
get_spine_object()->setDuration(duration);
}
void SpineAnimation::apply(Ref<SpineSkeleton> skeleton, float last_time, float time, bool loop, Array events, float alpha,
SpineConstant::MixBlend blend, SpineConstant::MixDirection direction, bool appliedPose) {
void SpineAnimation::apply(Ref<SpineSkeleton> skeleton, float last_time, float time, bool loop, Array events, float alpha, bool from_setup, bool add,
bool out, bool appliedPose) {
SPINE_CHECK(get_spine_object(), )
spine::Array<spine::Event *> spineEvents;
get_spine_object()->apply(*(skeleton->get_spine_object()), last_time, time, loop, &spineEvents, alpha, (spine::MixBlend) blend,
(spine::MixDirection) direction, appliedPose);
get_spine_object()->apply(*(skeleton->get_spine_object()), last_time, time, loop, &spineEvents, alpha, from_setup, add, out, appliedPose);
for (int i = 0; i < (int) spineEvents.size(); ++i) {
auto event_ref = memnew(SpineEvent);
event_ref->set_spine_object(skeleton->get_spine_owner(), spineEvents[i]);

View File

@ -45,8 +45,8 @@ protected:
static void _bind_methods();
public:
void apply(Ref<SpineSkeleton> skeleton, float last_time, float time, bool loop, Array events, float alpha, SpineConstant::MixBlend blend,
SpineConstant::MixDirection direction, bool appliedPose);
void apply(Ref<SpineSkeleton> skeleton, float last_time, float time, bool loop, Array events, float alpha, bool from_setup, bool add, bool out,
bool appliedPose);
Array get_timelines();

View File

@ -59,8 +59,8 @@ void SpineAnimationTrack::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_track_index"), &SpineAnimationTrack::get_track_index);
ClassDB::bind_method(D_METHOD("set_mix_duration", "mix_duration"), &SpineAnimationTrack::set_mix_duration);
ClassDB::bind_method(D_METHOD("get_mix_duration"), &SpineAnimationTrack::get_mix_duration);
ClassDB::bind_method(D_METHOD("set_hold_previous", "hold_previous"), &SpineAnimationTrack::set_hold_previous);
ClassDB::bind_method(D_METHOD("get_hold_previous"), &SpineAnimationTrack::get_hold_previous);
ClassDB::bind_method(D_METHOD("set_additive", "additive"), &SpineAnimationTrack::set_additive);
ClassDB::bind_method(D_METHOD("get_additive"), &SpineAnimationTrack::get_additive);
ClassDB::bind_method(D_METHOD("set_reverse", "reverse"), &SpineAnimationTrack::set_reverse);
ClassDB::bind_method(D_METHOD("get_reverse"), &SpineAnimationTrack::get_reverse);
ClassDB::bind_method(D_METHOD("set_shortest_rotation", "shortest_rotation"), &SpineAnimationTrack::set_shortest_rotation);
@ -73,8 +73,8 @@ void SpineAnimationTrack::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_mix_attachment_threshold"), &SpineAnimationTrack::get_mix_attachment_threshold);
ClassDB::bind_method(D_METHOD("set_mix_draw_order_threshold", "mix_draw_order_threshold"), &SpineAnimationTrack::set_mix_draw_order_threshold);
ClassDB::bind_method(D_METHOD("get_mix_draw_order_threshold"), &SpineAnimationTrack::get_mix_draw_order_threshold);
ClassDB::bind_method(D_METHOD("set_mix_blend", "mix_blend"), &SpineAnimationTrack::set_mix_blend);
ClassDB::bind_method(D_METHOD("get_mix_blend"), &SpineAnimationTrack::get_mix_blend);
ClassDB::bind_method(D_METHOD("set_blend_tree_mode", "blend_tree_mode_enabled"), &SpineAnimationTrack::set_blend_tree_mode);
ClassDB::bind_method(D_METHOD("get_blend_tree_mode"), &SpineAnimationTrack::get_blend_tree_mode);
ClassDB::bind_method(D_METHOD("set_debug", "debug"), &SpineAnimationTrack::set_debug);
@ -91,22 +91,21 @@ void SpineAnimationTrack::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "track_index", PROPERTY_HINT_RANGE, "0,256,1"), "set_track_index", "get_track_index");
ADD_PROPERTY(PropertyInfo(VARIANT_FLOAT, "mix_duration"), "set_mix_duration", "get_mix_duration");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hold_previous"), "set_hold_previous", "get_hold_previous");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "additive"), "set_additive", "get_additive");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reverse"), "set_reverse", "get_reverse");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortest_rotation"), "set_shortest_rotation", "get_shortest_rotation");
ADD_PROPERTY(PropertyInfo(Variant::VARIANT_FLOAT, "time_scale"), "set_time_scale", "get_time_scale");
ADD_PROPERTY(PropertyInfo(Variant::VARIANT_FLOAT, "alpha"), "set_alpha", "get_alpha");
ADD_PROPERTY(PropertyInfo(Variant::VARIANT_FLOAT, "attachment_threshold"), "set_mix_attachment_threshold", "get_mix_attachment_threshold");
ADD_PROPERTY(PropertyInfo(Variant::VARIANT_FLOAT, "draw_order_threshold"), "set_mix_draw_order_threshold", "get_mix_draw_order_threshold");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_blend", PROPERTY_HINT_ENUM, "Setup,First,Replace,Add"), "set_mix_blend", "get_mix_blend");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "blend_tree_mode"), "set_blend_tree_mode", "get_blend_tree_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug"), "set_debug", "get_debug");
}
SpineAnimationTrack::SpineAnimationTrack()
: loop(false), animation_changed(false), track_index(-1), mix_duration(-1), hold_previous(false), reverse(false), shortest_rotation(false),
time_scale(1), alpha(1), mix_attachment_threshold(0), mix_draw_order_threshold(0), mix_blend(SpineConstant::MixBlend_Replace),
blend_tree_mode(false), debug(false), sprite(nullptr) {
: loop(false), animation_changed(false), track_index(-1), mix_duration(-1), additive(false), reverse(false), shortest_rotation(false),
time_scale(1), alpha(1), mix_attachment_threshold(0), mix_draw_order_threshold(0), blend_tree_mode(false), debug(false), sprite(nullptr) {
}
void SpineAnimationTrack::_notification(int what) {
@ -314,14 +313,14 @@ void SpineAnimationTrack::update_animation_state(const Variant &variant_sprite)
auto &entry = animation_state->setAnimation(track_index, SPINE_STRING(animation_name), loop);
if (should_set_mix) entry.setMixDuration(mix_duration);
entry.setHoldPrevious(hold_previous);
entry.setAdditive(additive);
entry.setReverse(reverse);
entry.setShortestRotation(shortest_rotation);
entry.setTimeScale(time_scale);
entry.setAlpha(alpha);
entry.setMixAttachmentThreshold(mix_attachment_threshold);
entry.setMixDrawOrderThreshold(mix_draw_order_threshold);
entry.setMixBlend((spine::MixBlend) mix_blend);
if (debug)
print_line(String("Setting animation {0} with mix_duration {1} on track {2} on {3}")
@ -428,13 +427,13 @@ void SpineAnimationTrack::update_animation_state(const Variant &variant_sprite)
entry.setMixDuration(0);
entry.setTrackTime(track_time);
entry.setHoldPrevious(hold_previous);
entry.setAdditive(additive);
entry.setReverse(reverse);
entry.setShortestRotation(shortest_rotation);
entry.setAlpha(alpha);
entry.setMixAttachmentThreshold(mix_attachment_threshold);
entry.setMixDrawOrderThreshold(mix_draw_order_threshold);
entry.setMixBlend((spine::MixBlend) mix_blend);
#endif
} else {
if (animation_player->is_playing()) {
@ -454,14 +453,14 @@ void SpineAnimationTrack::update_animation_state(const Variant &variant_sprite)
auto &entry = animation_state->setAnimation(track_index, SPINE_STRING(animation_name), loop);
if (should_set_mix) entry.setMixDuration(mix_duration);
entry.setHoldPrevious(hold_previous);
entry.setAdditive(additive);
entry.setReverse(reverse);
entry.setShortestRotation(shortest_rotation);
entry.setTimeScale(time_scale);
entry.setAlpha(alpha);
entry.setMixAttachmentThreshold(mix_attachment_threshold);
entry.setMixDrawOrderThreshold(mix_draw_order_threshold);
entry.setMixBlend((spine::MixBlend) mix_blend);
if (debug)
print_line(String("Setting animation {0} with mix_duration {1} on track {2} on {3}")
@ -519,12 +518,12 @@ float SpineAnimationTrack::get_mix_duration() {
return mix_duration;
}
void SpineAnimationTrack::set_hold_previous(bool _hold_previous) {
hold_previous = _hold_previous;
void SpineAnimationTrack::set_additive(bool _additive) {
additive = _additive;
}
bool SpineAnimationTrack::get_hold_previous() {
return hold_previous;
bool SpineAnimationTrack::get_additive() {
return additive;
}
void SpineAnimationTrack::set_reverse(bool _reverse) {
@ -575,14 +574,6 @@ float SpineAnimationTrack::get_mix_draw_order_threshold() {
return mix_draw_order_threshold;
}
void SpineAnimationTrack::set_mix_blend(SpineConstant::MixBlend _blend) {
mix_blend = _blend;
}
SpineConstant::MixBlend SpineAnimationTrack::get_mix_blend() {
return mix_blend;
}
void SpineAnimationTrack::set_blend_tree_mode(bool _blend_tree_mode) {
blend_tree_mode = _blend_tree_mode;
}

View File

@ -48,14 +48,14 @@ protected:
// These can be set by the user.
int track_index;
float mix_duration;
bool hold_previous;
bool additive;
bool reverse;
bool shortest_rotation;
float time_scale;
float alpha;
float mix_attachment_threshold;
float mix_draw_order_threshold;
SpineConstant::MixBlend mix_blend;
bool blend_tree_mode;
bool debug;
@ -96,9 +96,9 @@ public:
float get_mix_duration();
void set_hold_previous(bool _hold_previous);
void set_additive(bool _additive);
bool get_hold_previous();
bool get_additive();
void set_reverse(bool _reverse);
@ -124,9 +124,6 @@ public:
float get_mix_draw_order_threshold();
void set_mix_blend(SpineConstant::MixBlend _blend);
SpineConstant::MixBlend get_mix_blend();
void set_blend_tree_mode(bool _blend_tree_mode);

View File

@ -30,14 +30,6 @@
#include "SpineConstant.h"
void SpineConstant::_bind_methods() {
BIND_ENUM_CONSTANT(MixBlend_Setup)
BIND_ENUM_CONSTANT(MixBlend_First)
BIND_ENUM_CONSTANT(MixBlend_Replace)
BIND_ENUM_CONSTANT(MixBlend_Add)
BIND_ENUM_CONSTANT(MixDirection_In)
BIND_ENUM_CONSTANT(MixDirection_Out)
BIND_ENUM_CONSTANT(Property_Rotate)
BIND_ENUM_CONSTANT(Property_X)
BIND_ENUM_CONSTANT(Property_Y)

View File

@ -38,18 +38,6 @@ protected:
static void _bind_methods();
public:
enum MixBlend {
MixBlend_Setup = 0,
MixBlend_First,
MixBlend_Replace,
MixBlend_Add
};
enum MixDirection {
MixDirection_In = 0,
MixDirection_Out
};
enum PropertyId {
Property_Rotate = 1 << 0,
Property_X = 1 << 1,
@ -124,8 +112,6 @@ public:
};
};
VARIANT_ENUM_CAST(SpineConstant::MixBlend)
VARIANT_ENUM_CAST(SpineConstant::MixDirection)
VARIANT_ENUM_CAST(SpineConstant::PropertyId)
VARIANT_ENUM_CAST(SpineConstant::Inherit)
VARIANT_ENUM_CAST(SpineConstant::PositionMode)

View File

@ -163,7 +163,7 @@ Array SpineSkin::get_attachments() {
attachment_ref = Ref<SpineAttachment>(memnew(SpineAttachment));
attachment_ref->set_spine_object(get_spine_owner(), entry._attachment);
}
entry_ref->init(entry._slotIndex, entry._name.buffer(), attachment_ref);
entry_ref->init(entry._slotIndex, entry._placeholderName.buffer(), attachment_ref);
result.push_back(entry_ref);
}
return result;

View File

@ -35,7 +35,8 @@
#endif
void SpineTimeline::_bind_methods() {
ClassDB::bind_method(D_METHOD("apply", "skeleton", "last_time", "time", "events", "alpha", "blend", "direction"), &SpineTimeline::apply);
ClassDB::bind_method(D_METHOD("apply", "skeleton", "last_time", "time", "events", "alpha", "from_setup", "add", "out", "applied_pose"),
&SpineTimeline::apply);
ClassDB::bind_method(D_METHOD("get_frame_entries"), &SpineTimeline::get_frame_entries);
ClassDB::bind_method(D_METHOD("get_frame_count"), &SpineTimeline::get_frame_count);
ClassDB::bind_method(D_METHOD("get_frames"), &SpineTimeline::get_frames);
@ -44,8 +45,8 @@ void SpineTimeline::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_type"), &SpineTimeline::get_type);
}
void SpineTimeline::apply(Ref<SpineSkeleton> skeleton, float last_time, float time, Array events, float alpha, SpineConstant::MixBlend blend,
SpineConstant::MixDirection direction, bool applied_pose) {
void SpineTimeline::apply(Ref<SpineSkeleton> skeleton, float last_time, float time, Array events, float alpha, bool from_setup, bool add, bool out,
bool applied_pose) {
SPINE_CHECK(get_spine_object(), )
if (!skeleton->get_spine_object()) return;
spine::Array<spine::Event *> spine_events;
@ -53,8 +54,7 @@ void SpineTimeline::apply(Ref<SpineSkeleton> skeleton, float last_time, float ti
for (int i = 0; i < events.size(); ++i) {
events[i] = ((Ref<SpineEvent>) spine_events[i])->get_spine_object();
}
get_spine_object()->apply(*(skeleton->get_spine_object()), last_time, time, &spine_events, alpha, (spine::MixBlend) blend,
(spine::MixDirection) direction, applied_pose);
get_spine_object()->apply(*(skeleton->get_spine_object()), last_time, time, &spine_events, alpha, from_setup, add, out, applied_pose);
}
int SpineTimeline::get_frame_entries() {

View File

@ -45,8 +45,8 @@ protected:
static void _bind_methods();
public:
void apply(Ref<SpineSkeleton> skeleton, float last_time, float time, Array events, float alpha, SpineConstant::MixBlend blend,
SpineConstant::MixDirection direction, bool applied_pose);
void apply(Ref<SpineSkeleton> skeleton, float last_time, float time, Array events, float alpha, bool from_setup, bool add, bool out,
bool applied_pose);
int get_frame_entries();

View File

@ -36,8 +36,8 @@ void SpineTrackEntry::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_previous"), &SpineTrackEntry::get_previous);
ClassDB::bind_method(D_METHOD("get_loop"), &SpineTrackEntry::get_loop);
ClassDB::bind_method(D_METHOD("set_loop", "v"), &SpineTrackEntry::set_loop);
ClassDB::bind_method(D_METHOD("get_hold_previous"), &SpineTrackEntry::get_hold_previous);
ClassDB::bind_method(D_METHOD("set_hold_previous", "v"), &SpineTrackEntry::set_hold_previous);
ClassDB::bind_method(D_METHOD("get_additive"), &SpineTrackEntry::get_additive);
ClassDB::bind_method(D_METHOD("set_additive", "v"), &SpineTrackEntry::set_additive);
ClassDB::bind_method(D_METHOD("get_reverse"), &SpineTrackEntry::get_reverse);
ClassDB::bind_method(D_METHOD("set_reverse", "v"), &SpineTrackEntry::set_reverse);
ClassDB::bind_method(D_METHOD("get_shortest_rotation"), &SpineTrackEntry::get_shortest_rotation);
@ -74,8 +74,7 @@ void SpineTrackEntry::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_mix_duration"), &SpineTrackEntry::get_mix_duration);
ClassDB::bind_method(D_METHOD("set_mix_duration", "v"), &SpineTrackEntry::set_mix_duration);
ClassDB::bind_method(D_METHOD("set_mix_duration_and_delay", "v", "delay"), &SpineTrackEntry::set_mix_duration_and_delay);
ClassDB::bind_method(D_METHOD("get_mix_blend"), &SpineTrackEntry::get_mix_blend);
ClassDB::bind_method(D_METHOD("set_mix_blend", "v"), &SpineTrackEntry::set_mix_blend);
ClassDB::bind_method(D_METHOD("get_mixing_from"), &SpineTrackEntry::get_mixing_from);
ClassDB::bind_method(D_METHOD("get_mixing_to"), &SpineTrackEntry::get_mixing_to);
ClassDB::bind_method(D_METHOD("reset_rotation_directions"), &SpineTrackEntry::reset_rotation_directions);
@ -115,14 +114,14 @@ void SpineTrackEntry::set_loop(bool v) {
get_spine_object()->setLoop(v);
}
bool SpineTrackEntry::get_hold_previous() {
bool SpineTrackEntry::get_additive() {
SPINE_CHECK(get_spine_object(), false)
return get_spine_object()->getHoldPrevious();
return get_spine_object()->getAdditive();
}
void SpineTrackEntry::set_hold_previous(bool v) {
void SpineTrackEntry::set_additive(bool v) {
SPINE_CHECK(get_spine_object(), )
get_spine_object()->setHoldPrevious(v);
get_spine_object()->setAdditive(v);
}
bool SpineTrackEntry::get_reverse() {
@ -309,16 +308,6 @@ void SpineTrackEntry::set_mix_duration_and_delay(float v, float delay) {
get_spine_object()->setMixDuration(v, delay);
}
SpineConstant::MixBlend SpineTrackEntry::get_mix_blend() {
SPINE_CHECK(get_spine_object(), SpineConstant::MixBlend_Setup)
return (SpineConstant::MixBlend) get_spine_object()->getMixBlend();
}
void SpineTrackEntry::set_mix_blend(SpineConstant::MixBlend v) {
SPINE_CHECK(get_spine_object(), )
get_spine_object()->setMixBlend((spine::MixBlend) v);
}
Ref<SpineTrackEntry> SpineTrackEntry::get_mixing_from() {
SPINE_CHECK(get_spine_object(), nullptr)
auto mixing_from = get_spine_object()->getMixingFrom();

View File

@ -53,9 +53,9 @@ public:
void set_loop(bool v);
bool get_hold_previous();
bool get_additive();
void set_hold_previous(bool v);
void set_additive(bool v);
bool get_reverse();
@ -129,9 +129,6 @@ public:
void set_mix_duration_and_delay(float v, float delay);
SpineConstant::MixBlend get_mix_blend();
void set_mix_blend(SpineConstant::MixBlend v);
Ref<SpineTrackEntry> get_mixing_from();