Spine: add feature to insert/remove interpolates while updating
This commit is contained in:
parent
dce8a6c251
commit
6d0914dfc5
|
@ -29,6 +29,81 @@
|
|||
#include "tween.h"
|
||||
#include "method_bind_ext.inc"
|
||||
|
||||
void Tween::_add_pending_command(StringName p_key
|
||||
,const Variant& p_arg1 ,const Variant& p_arg2 ,const Variant& p_arg3 ,const Variant& p_arg4 ,const Variant& p_arg5
|
||||
,const Variant& p_arg6 ,const Variant& p_arg7 ,const Variant& p_arg8 ,const Variant& p_arg9 ,const Variant& p_arg10
|
||||
) {
|
||||
|
||||
pending_commands.push_back(PendingCommand());
|
||||
PendingCommand& cmd = pending_commands.back()->get();
|
||||
|
||||
cmd.key = p_key;
|
||||
int& count = cmd.args;
|
||||
if(p_arg10.get_type() != Variant::NIL)
|
||||
count = 10;
|
||||
else if(p_arg9.get_type() != Variant::NIL)
|
||||
count = 9;
|
||||
else if(p_arg8.get_type() != Variant::NIL)
|
||||
count = 8;
|
||||
else if(p_arg7.get_type() != Variant::NIL)
|
||||
count = 7;
|
||||
else if(p_arg6.get_type() != Variant::NIL)
|
||||
count = 6;
|
||||
else if(p_arg5.get_type() != Variant::NIL)
|
||||
count = 5;
|
||||
else if(p_arg4.get_type() != Variant::NIL)
|
||||
count = 4;
|
||||
else if(p_arg3.get_type() != Variant::NIL)
|
||||
count = 3;
|
||||
else if(p_arg2.get_type() != Variant::NIL)
|
||||
count = 2;
|
||||
else if(p_arg1.get_type() != Variant::NIL)
|
||||
count = 1;
|
||||
if(count > 0)
|
||||
cmd.arg[0] = p_arg1;
|
||||
if(count > 1)
|
||||
cmd.arg[1] = p_arg2;
|
||||
if(count > 2)
|
||||
cmd.arg[2] = p_arg3;
|
||||
if(count > 3)
|
||||
cmd.arg[3] = p_arg4;
|
||||
if(count > 4)
|
||||
cmd.arg[4] = p_arg5;
|
||||
if(count > 5)
|
||||
cmd.arg[5] = p_arg6;
|
||||
if(count > 6)
|
||||
cmd.arg[6] = p_arg7;
|
||||
if(count > 7)
|
||||
cmd.arg[7] = p_arg8;
|
||||
if(count > 8)
|
||||
cmd.arg[8] = p_arg9;
|
||||
if(count > 9)
|
||||
cmd.arg[9] = p_arg10;
|
||||
}
|
||||
|
||||
void Tween::_process_pending_commands() {
|
||||
|
||||
for(List<PendingCommand>::Element *E=pending_commands.front();E;E=E->next()) {
|
||||
|
||||
PendingCommand& cmd = E->get();
|
||||
Variant::CallError err;
|
||||
Variant *arg[10] = {
|
||||
&cmd.arg[0],
|
||||
&cmd.arg[1],
|
||||
&cmd.arg[2],
|
||||
&cmd.arg[3],
|
||||
&cmd.arg[4],
|
||||
&cmd.arg[5],
|
||||
&cmd.arg[6],
|
||||
&cmd.arg[7],
|
||||
&cmd.arg[8],
|
||||
&cmd.arg[9],
|
||||
};
|
||||
this->call(cmd.key, (const Variant **) arg, cmd.args, err);
|
||||
}
|
||||
pending_commands.clear();
|
||||
}
|
||||
|
||||
bool Tween::_set(const StringName& p_name, const Variant& p_value) {
|
||||
|
||||
String name=p_name;
|
||||
|
@ -456,6 +531,8 @@ bool Tween::_apply_tween_value(InterpolateData& p_data, Variant& value) {
|
|||
|
||||
void Tween::_tween_process(float p_delta) {
|
||||
|
||||
_process_pending_commands();
|
||||
|
||||
if (speed_scale == 0)
|
||||
return;
|
||||
p_delta *= speed_scale;
|
||||
|
@ -551,8 +628,12 @@ void Tween::_tween_process(float p_delta) {
|
|||
|
||||
_apply_tween_value(data, result);
|
||||
|
||||
if(data.finish)
|
||||
if (data.finish) {
|
||||
emit_signal("tween_complete",object,data.key);
|
||||
// not repeat mode, remove completed action
|
||||
if (!repeat)
|
||||
call_deferred("remove", object, data.key);
|
||||
}
|
||||
}
|
||||
pending_update --;
|
||||
}
|
||||
|
@ -734,7 +815,10 @@ bool Tween::resume_all() {
|
|||
|
||||
bool Tween::remove(Object *p_object, String p_key) {
|
||||
|
||||
ERR_FAIL_COND_V(pending_update != 0, false);
|
||||
if(pending_update != 0) {
|
||||
call_deferred("remove", p_object, p_key);
|
||||
return true;
|
||||
}
|
||||
for(List<InterpolateData>::Element *E=interpolates.front();E;E=E->next()) {
|
||||
|
||||
InterpolateData& data = E->get();
|
||||
|
@ -751,7 +835,10 @@ bool Tween::remove(Object *p_object, String p_key) {
|
|||
|
||||
bool Tween::remove_all() {
|
||||
|
||||
ERR_FAIL_COND_V(pending_update != 0, false);
|
||||
if(pending_update != 0) {
|
||||
call_deferred("remove_all");
|
||||
return true;
|
||||
}
|
||||
set_active(false);
|
||||
_set_process(false);
|
||||
interpolates.clear();
|
||||
|
@ -940,7 +1027,19 @@ bool Tween::interpolate_property(Object *p_object
|
|||
, EaseType p_ease_type
|
||||
, real_t p_delay
|
||||
) {
|
||||
ERR_FAIL_COND_V(pending_update != 0, false);
|
||||
if(pending_update != 0) {
|
||||
_add_pending_command("interpolate_property"
|
||||
, p_object
|
||||
, p_property
|
||||
, p_initial_val
|
||||
, p_final_val
|
||||
, p_times_in_sec
|
||||
, p_trans_type
|
||||
, p_ease_type
|
||||
, p_delay
|
||||
);
|
||||
return true;
|
||||
}
|
||||
// convert INT to REAL is better for interpolaters
|
||||
if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t();
|
||||
if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t();
|
||||
|
@ -987,7 +1086,19 @@ bool Tween::interpolate_method(Object *p_object
|
|||
, EaseType p_ease_type
|
||||
, real_t p_delay
|
||||
) {
|
||||
ERR_FAIL_COND_V(pending_update != 0, false);
|
||||
if(pending_update != 0) {
|
||||
_add_pending_command("interpolate_method"
|
||||
, p_object
|
||||
, p_method
|
||||
, p_initial_val
|
||||
, p_final_val
|
||||
, p_times_in_sec
|
||||
, p_trans_type
|
||||
, p_ease_type
|
||||
, p_delay
|
||||
);
|
||||
return true;
|
||||
}
|
||||
// convert INT to REAL is better for interpolaters
|
||||
if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t();
|
||||
if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t();
|
||||
|
@ -999,6 +1110,7 @@ bool Tween::interpolate_method(Object *p_object
|
|||
ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false);
|
||||
ERR_FAIL_COND_V(p_delay < 0, false);
|
||||
|
||||
ERR_EXPLAIN("Object has no method named: %s" + p_method);
|
||||
ERR_FAIL_COND_V(!p_object->has_method(p_method), false);
|
||||
|
||||
InterpolateData data;
|
||||
|
@ -1029,10 +1141,23 @@ bool Tween::interpolate_callback(Object *p_object
|
|||
, VARIANT_ARG_DECLARE
|
||||
) {
|
||||
|
||||
ERR_FAIL_COND_V(pending_update != 0, false);
|
||||
if(pending_update != 0) {
|
||||
_add_pending_command("interpolate_callback"
|
||||
, p_object
|
||||
, p_times_in_sec
|
||||
, p_callback
|
||||
, p_arg1
|
||||
, p_arg2
|
||||
, p_arg3
|
||||
, p_arg4
|
||||
, p_arg5
|
||||
);
|
||||
return true;
|
||||
}
|
||||
ERR_FAIL_COND_V(p_object == NULL, false);
|
||||
ERR_FAIL_COND_V(p_times_in_sec < 0, false);
|
||||
|
||||
ERR_EXPLAIN("Object has no callback named: %s" + p_callback);
|
||||
ERR_FAIL_COND_V(!p_object->has_method(p_callback), false);
|
||||
|
||||
InterpolateData data;
|
||||
|
@ -1080,10 +1205,23 @@ bool Tween::interpolate_deferred_callback(Object *p_object
|
|||
, VARIANT_ARG_DECLARE
|
||||
) {
|
||||
|
||||
ERR_FAIL_COND_V(pending_update != 0, false);
|
||||
if(pending_update != 0) {
|
||||
_add_pending_command("interpolate_deferred_callback"
|
||||
, p_object
|
||||
, p_times_in_sec
|
||||
, p_callback
|
||||
, p_arg1
|
||||
, p_arg2
|
||||
, p_arg3
|
||||
, p_arg4
|
||||
, p_arg5
|
||||
);
|
||||
return true;
|
||||
}
|
||||
ERR_FAIL_COND_V(p_object == NULL, false);
|
||||
ERR_FAIL_COND_V(p_times_in_sec < 0, false);
|
||||
|
||||
ERR_EXPLAIN("Object has no callback named: %s" + p_callback);
|
||||
ERR_FAIL_COND_V(!p_object->has_method(p_callback), false);
|
||||
|
||||
InterpolateData data;
|
||||
|
@ -1135,7 +1273,20 @@ bool Tween::follow_property(Object *p_object
|
|||
, EaseType p_ease_type
|
||||
, real_t p_delay
|
||||
) {
|
||||
ERR_FAIL_COND_V(pending_update != 0, false);
|
||||
if(pending_update != 0) {
|
||||
_add_pending_command("follow_property"
|
||||
, p_object
|
||||
, p_property
|
||||
, p_initial_val
|
||||
, p_target
|
||||
, p_target_property
|
||||
, p_times_in_sec
|
||||
, p_trans_type
|
||||
, p_ease_type
|
||||
, p_delay
|
||||
);
|
||||
return true;
|
||||
}
|
||||
// convert INT to REAL is better for interpolaters
|
||||
if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t();
|
||||
|
||||
|
@ -1188,7 +1339,20 @@ bool Tween::follow_method(Object *p_object
|
|||
, EaseType p_ease_type
|
||||
, real_t p_delay
|
||||
) {
|
||||
ERR_FAIL_COND_V(pending_update != 0, false);
|
||||
if(pending_update != 0) {
|
||||
_add_pending_command("follow_method"
|
||||
, p_object
|
||||
, p_method
|
||||
, p_initial_val
|
||||
, p_target
|
||||
, p_target_method
|
||||
, p_times_in_sec
|
||||
, p_trans_type
|
||||
, p_ease_type
|
||||
, p_delay
|
||||
);
|
||||
return true;
|
||||
}
|
||||
// convert INT to REAL is better for interpolaters
|
||||
if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t();
|
||||
|
||||
|
@ -1199,7 +1363,9 @@ bool Tween::follow_method(Object *p_object
|
|||
ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false);
|
||||
ERR_FAIL_COND_V(p_delay < 0, false);
|
||||
|
||||
ERR_EXPLAIN("Object has no method named: %s" + p_method);
|
||||
ERR_FAIL_COND_V(!p_object->has_method(p_method), false);
|
||||
ERR_EXPLAIN("Target has no method named: %s" + p_target_method);
|
||||
ERR_FAIL_COND_V(!p_target->has_method(p_target_method), false);
|
||||
|
||||
Variant::CallError error;
|
||||
|
@ -1240,7 +1406,20 @@ bool Tween::targeting_property(Object *p_object
|
|||
, EaseType p_ease_type
|
||||
, real_t p_delay
|
||||
) {
|
||||
ERR_FAIL_COND_V(pending_update != 0, false);
|
||||
if(pending_update != 0) {
|
||||
_add_pending_command("targeting_property"
|
||||
, p_object
|
||||
, p_property
|
||||
, p_initial
|
||||
, p_initial_property
|
||||
, p_final_val
|
||||
, p_times_in_sec
|
||||
, p_trans_type
|
||||
, p_ease_type
|
||||
, p_delay
|
||||
);
|
||||
return true;
|
||||
}
|
||||
// convert INT to REAL is better for interpolaters
|
||||
if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t();
|
||||
|
||||
|
@ -1298,7 +1477,20 @@ bool Tween::targeting_method(Object *p_object
|
|||
, EaseType p_ease_type
|
||||
, real_t p_delay
|
||||
) {
|
||||
ERR_FAIL_COND_V(pending_update != 0, false);
|
||||
if(pending_update != 0) {
|
||||
_add_pending_command("targeting_method"
|
||||
, p_object
|
||||
, p_method
|
||||
, p_initial
|
||||
, p_initial_method
|
||||
, p_final_val
|
||||
, p_times_in_sec
|
||||
, p_trans_type
|
||||
, p_ease_type
|
||||
, p_delay
|
||||
);
|
||||
return true;
|
||||
}
|
||||
// convert INT to REAL is better for interpolaters
|
||||
if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t();
|
||||
|
||||
|
@ -1309,7 +1501,9 @@ bool Tween::targeting_method(Object *p_object
|
|||
ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false);
|
||||
ERR_FAIL_COND_V(p_delay < 0, false);
|
||||
|
||||
ERR_EXPLAIN("Object has no method named: %s" + p_method);
|
||||
ERR_FAIL_COND_V(!p_object->has_method(p_method), false);
|
||||
ERR_EXPLAIN("Initial Object has no method named: %s" + p_initial_method);
|
||||
ERR_FAIL_COND_V(!p_initial->has_method(p_initial_method), false);
|
||||
|
||||
Variant::CallError error;
|
||||
|
|
|
@ -110,6 +110,27 @@ private:
|
|||
|
||||
List<InterpolateData> interpolates;
|
||||
|
||||
struct PendingCommand {
|
||||
StringName key;
|
||||
int args;
|
||||
Variant arg[10];
|
||||
};
|
||||
List<PendingCommand> pending_commands;
|
||||
|
||||
void _add_pending_command(StringName p_key
|
||||
,const Variant& p_arg1=Variant()
|
||||
,const Variant& p_arg2=Variant()
|
||||
,const Variant& p_arg3=Variant()
|
||||
,const Variant& p_arg4=Variant()
|
||||
,const Variant& p_arg5=Variant()
|
||||
,const Variant& p_arg6=Variant()
|
||||
,const Variant& p_arg7=Variant()
|
||||
,const Variant& p_arg8=Variant()
|
||||
,const Variant& p_arg9=Variant()
|
||||
,const Variant& p_arg10=Variant()
|
||||
);
|
||||
void _process_pending_commands();
|
||||
|
||||
typedef real_t (*interpolater)(real_t t, real_t b, real_t c, real_t d);
|
||||
static interpolater interpolaters[TRANS_COUNT][EASE_COUNT];
|
||||
|
||||
|
|
Loading…
Reference in New Issue