Merge pull request #63802 from TokageItLab/curve-transition

This commit is contained in:
Rémi Verschelde 2022-08-22 22:30:09 +02:00 committed by GitHub
commit 9c567a0604
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 63 additions and 17 deletions

View File

@ -37,6 +37,9 @@
<member name="switch_mode" type="int" setter="set_switch_mode" getter="get_switch_mode" enum="AnimationNodeStateMachineTransition.SwitchMode" default="0"> <member name="switch_mode" type="int" setter="set_switch_mode" getter="get_switch_mode" enum="AnimationNodeStateMachineTransition.SwitchMode" default="0">
The transition type. The transition type.
</member> </member>
<member name="xfade_curve" type="Curve" setter="set_xfade_curve" getter="get_xfade_curve">
Ease curve for better control over cross-fade between this state and the next.
</member>
<member name="xfade_time" type="float" setter="set_xfade_time" getter="get_xfade_time" default="0.0"> <member name="xfade_time" type="float" setter="set_xfade_time" getter="get_xfade_time" default="0.0">
The time to cross-fade between this state and the next. The time to cross-fade between this state and the next.
</member> </member>

View File

@ -46,7 +46,9 @@
<member name="input_count" type="int" setter="set_enabled_inputs" getter="get_enabled_inputs" default="0"> <member name="input_count" type="int" setter="set_enabled_inputs" getter="get_enabled_inputs" default="0">
The number of available input ports for this node. The number of available input ports for this node.
</member> </member>
<member name="xfade_time" type="float" setter="set_cross_fade_time" getter="get_cross_fade_time" default="0.0"> <member name="xfade_curve" type="Curve" setter="set_xfade_curve" getter="get_xfade_curve">
</member>
<member name="xfade_time" type="float" setter="set_xfade_time" getter="get_xfade_time" default="0.0">
Cross-fading time (in seconds) between each animation connected to the inputs. Cross-fading time (in seconds) between each animation connected to the inputs.
</member> </member>
</members> </members>

View File

@ -676,12 +676,20 @@ String AnimationNodeTransition::get_input_caption(int p_input) const {
return inputs[p_input].name; return inputs[p_input].name;
} }
void AnimationNodeTransition::set_cross_fade_time(float p_fade) { void AnimationNodeTransition::set_xfade_time(float p_fade) {
xfade = p_fade; xfade_time = p_fade;
} }
float AnimationNodeTransition::get_cross_fade_time() const { float AnimationNodeTransition::get_xfade_time() const {
return xfade; return xfade_time;
}
void AnimationNodeTransition::set_xfade_curve(const Ref<Curve> &p_curve) {
xfade_curve = p_curve;
}
Ref<Curve> AnimationNodeTransition::get_xfade_curve() const {
return xfade_curve;
} }
void AnimationNodeTransition::set_from_start(bool p_from_start) { void AnimationNodeTransition::set_from_start(bool p_from_start) {
@ -707,7 +715,7 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_
set_parameter(this->prev, prev_current); set_parameter(this->prev, prev_current);
prev = prev_current; prev = prev_current;
prev_xfading = xfade; prev_xfading = xfade_time;
time = 0; time = 0;
switched = true; switched = true;
} }
@ -734,13 +742,16 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_seek_
time += p_time; time += p_time;
} }
if (inputs[current].auto_advance && rem <= xfade) { if (inputs[current].auto_advance && rem <= xfade_time) {
set_parameter(this->current, (current + 1) % enabled_inputs); set_parameter(this->current, (current + 1) % enabled_inputs);
} }
} else { // cross-fading from prev to current } else { // cross-fading from prev to current
float blend = xfade == 0 ? 0 : (prev_xfading / xfade); float blend = xfade_time == 0 ? 0 : (prev_xfading / xfade_time);
if (xfade_curve.is_valid()) {
blend = xfade_curve->interpolate(blend);
}
if (from_start && !p_seek && switched) { //just switched, seek to start of current if (from_start && !p_seek && switched) { //just switched, seek to start of current
@ -790,14 +801,18 @@ void AnimationNodeTransition::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_input_caption", "input", "caption"), &AnimationNodeTransition::set_input_caption); ClassDB::bind_method(D_METHOD("set_input_caption", "input", "caption"), &AnimationNodeTransition::set_input_caption);
ClassDB::bind_method(D_METHOD("get_input_caption", "input"), &AnimationNodeTransition::get_input_caption); ClassDB::bind_method(D_METHOD("get_input_caption", "input"), &AnimationNodeTransition::get_input_caption);
ClassDB::bind_method(D_METHOD("set_cross_fade_time", "time"), &AnimationNodeTransition::set_cross_fade_time); ClassDB::bind_method(D_METHOD("set_xfade_time", "time"), &AnimationNodeTransition::set_xfade_time);
ClassDB::bind_method(D_METHOD("get_cross_fade_time"), &AnimationNodeTransition::get_cross_fade_time); ClassDB::bind_method(D_METHOD("get_xfade_time"), &AnimationNodeTransition::get_xfade_time);
ClassDB::bind_method(D_METHOD("set_xfade_curve", "curve"), &AnimationNodeTransition::set_xfade_curve);
ClassDB::bind_method(D_METHOD("get_xfade_curve"), &AnimationNodeTransition::get_xfade_curve);
ClassDB::bind_method(D_METHOD("set_from_start", "from_start"), &AnimationNodeTransition::set_from_start); ClassDB::bind_method(D_METHOD("set_from_start", "from_start"), &AnimationNodeTransition::set_from_start);
ClassDB::bind_method(D_METHOD("is_from_start"), &AnimationNodeTransition::is_from_start); ClassDB::bind_method(D_METHOD("is_from_start"), &AnimationNodeTransition::is_from_start);
ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,64,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_enabled_inputs", "get_enabled_inputs"); ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_RANGE, "0,64,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_enabled_inputs", "get_enabled_inputs");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01,suffix:s"), "set_cross_fade_time", "get_cross_fade_time"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01,suffix:s"), "set_xfade_time", "get_xfade_time");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "xfade_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_xfade_curve", "get_xfade_curve");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "from_start"), "set_from_start", "is_from_start"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "from_start"), "set_from_start", "is_from_start");
for (int i = 0; i < MAX_INPUTS; i++) { for (int i = 0; i < MAX_INPUTS; i++) {

View File

@ -297,7 +297,8 @@ class AnimationNodeTransition : public AnimationNodeSync {
StringName current = PNAME("current"); StringName current = PNAME("current");
StringName prev_current = "prev_current"; StringName prev_current = "prev_current";
float xfade = 0.0; float xfade_time = 0.0;
Ref<Curve> xfade_curve;
bool from_start = true; bool from_start = true;
void _update_inputs(); void _update_inputs();
@ -321,8 +322,11 @@ public:
void set_input_caption(int p_input, const String &p_name); void set_input_caption(int p_input, const String &p_name);
String get_input_caption(int p_input) const; String get_input_caption(int p_input) const;
void set_cross_fade_time(float p_fade); void set_xfade_time(float p_fade);
float get_cross_fade_time() const; float get_xfade_time() const;
void set_xfade_curve(const Ref<Curve> &p_curve);
Ref<Curve> get_xfade_curve() const;
void set_from_start(bool p_from_start); void set_from_start(bool p_from_start);
bool is_from_start() const; bool is_from_start() const;

View File

@ -98,12 +98,20 @@ NodePath AnimationNodeStateMachineTransition::get_advance_expression_base_node()
void AnimationNodeStateMachineTransition::set_xfade_time(float p_xfade) { void AnimationNodeStateMachineTransition::set_xfade_time(float p_xfade) {
ERR_FAIL_COND(p_xfade < 0); ERR_FAIL_COND(p_xfade < 0);
xfade = p_xfade; xfade_time = p_xfade;
emit_changed(); emit_changed();
} }
float AnimationNodeStateMachineTransition::get_xfade_time() const { float AnimationNodeStateMachineTransition::get_xfade_time() const {
return xfade; return xfade_time;
}
void AnimationNodeStateMachineTransition::set_xfade_curve(const Ref<Curve> &p_curve) {
xfade_curve = p_curve;
}
Ref<Curve> AnimationNodeStateMachineTransition::get_xfade_curve() const {
return xfade_curve;
} }
void AnimationNodeStateMachineTransition::set_disabled(bool p_disabled) { void AnimationNodeStateMachineTransition::set_disabled(bool p_disabled) {
@ -137,6 +145,9 @@ void AnimationNodeStateMachineTransition::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_xfade_time", "secs"), &AnimationNodeStateMachineTransition::set_xfade_time); ClassDB::bind_method(D_METHOD("set_xfade_time", "secs"), &AnimationNodeStateMachineTransition::set_xfade_time);
ClassDB::bind_method(D_METHOD("get_xfade_time"), &AnimationNodeStateMachineTransition::get_xfade_time); ClassDB::bind_method(D_METHOD("get_xfade_time"), &AnimationNodeStateMachineTransition::get_xfade_time);
ClassDB::bind_method(D_METHOD("set_xfade_curve", "curve"), &AnimationNodeStateMachineTransition::set_xfade_curve);
ClassDB::bind_method(D_METHOD("get_xfade_curve"), &AnimationNodeStateMachineTransition::get_xfade_curve);
ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &AnimationNodeStateMachineTransition::set_disabled); ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &AnimationNodeStateMachineTransition::set_disabled);
ClassDB::bind_method(D_METHOD("is_disabled"), &AnimationNodeStateMachineTransition::is_disabled); ClassDB::bind_method(D_METHOD("is_disabled"), &AnimationNodeStateMachineTransition::is_disabled);
@ -150,6 +161,7 @@ void AnimationNodeStateMachineTransition::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_advance_expression_base_node"), &AnimationNodeStateMachineTransition::get_advance_expression_base_node); ClassDB::bind_method(D_METHOD("get_advance_expression_base_node"), &AnimationNodeStateMachineTransition::get_advance_expression_base_node);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,240,0.01,suffix:s"), "set_xfade_time", "get_xfade_time"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,240,0.01,suffix:s"), "set_xfade_time", "get_xfade_time");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "xfade_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_xfade_curve", "get_xfade_curve");
ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,32,1"), "set_priority", "get_priority"); ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,32,1"), "set_priority", "get_priority");
ADD_GROUP("Switch", ""); ADD_GROUP("Switch", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "switch_mode", PROPERTY_HINT_ENUM, "Immediate,Sync,At End"), "set_switch_mode", "get_switch_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "switch_mode", PROPERTY_HINT_ENUM, "Immediate,Sync,At End"), "set_switch_mode", "get_switch_mode");
@ -420,6 +432,9 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
} }
} }
if (current_curve.is_valid()) {
fade_blend = current_curve->interpolate(fade_blend);
}
float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_seek_root, fade_blend, AnimationNode::FILTER_IGNORE, true); float rem = p_state_machine->blend_node(current, p_state_machine->states[current].node, p_time, p_seek, p_seek_root, fade_blend, AnimationNode::FILTER_IGNORE, true);
if (fading_from != StringName()) { if (fading_from != StringName()) {
@ -450,6 +465,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
if (p_state_machine->transitions[i].local_from == current && p_state_machine->transitions[i].local_to == path[0]) { if (p_state_machine->transitions[i].local_from == current && p_state_machine->transitions[i].local_to == path[0]) {
next_xfade = p_state_machine->transitions[i].transition->get_xfade_time(); next_xfade = p_state_machine->transitions[i].transition->get_xfade_time();
current_curve = p_state_machine->transitions[i].transition->get_xfade_curve();
switch_mode = p_state_machine->transitions[i].transition->get_switch_mode(); switch_mode = p_state_machine->transitions[i].transition->get_switch_mode();
next = path[0]; next = path[0];
} }
@ -504,6 +520,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s
tr.to = String(p_state_machine->transitions[auto_advance_to].to).replace_first("../", ""); tr.to = String(p_state_machine->transitions[auto_advance_to].to).replace_first("../", "");
tr.next = p_state_machine->transitions[auto_advance_to].to; tr.next = p_state_machine->transitions[auto_advance_to].to;
current_transition = tr; current_transition = tr;
current_curve = p_state_machine->transitions[auto_advance_to].transition->get_xfade_curve();
next_xfade = p_state_machine->transitions[auto_advance_to].transition->get_xfade_time(); next_xfade = p_state_machine->transitions[auto_advance_to].transition->get_xfade_time();
switch_mode = p_state_machine->transitions[auto_advance_to].transition->get_switch_mode(); switch_mode = p_state_machine->transitions[auto_advance_to].transition->get_switch_mode();
} }

View File

@ -49,7 +49,8 @@ private:
bool auto_advance = false; bool auto_advance = false;
StringName advance_condition; StringName advance_condition;
StringName advance_condition_name; StringName advance_condition_name;
float xfade = 0.0; float xfade_time = 0.0;
Ref<Curve> xfade_curve;
bool disabled = false; bool disabled = false;
int priority = 1; int priority = 1;
String advance_expression; String advance_expression;
@ -82,6 +83,9 @@ public:
void set_xfade_time(float p_xfade); void set_xfade_time(float p_xfade);
float get_xfade_time() const; float get_xfade_time() const;
void set_xfade_curve(const Ref<Curve> &p_curve);
Ref<Curve> get_xfade_curve() const;
void set_disabled(bool p_disabled); void set_disabled(bool p_disabled);
bool is_disabled() const; bool is_disabled() const;
@ -117,6 +121,7 @@ class AnimationNodeStateMachinePlayback : public Resource {
StringName current; StringName current;
Transition current_transition; Transition current_transition;
Ref<Curve> current_curve;
bool force_auto_advance = false; bool force_auto_advance = false;
StringName fading_from; StringName fading_from;