Spine: add feature to insert/remove interpolates while updating

This commit is contained in:
sanikoyes 2015-05-05 11:12:17 +08:00
parent dce8a6c251
commit 6d0914dfc5
2 changed files with 226 additions and 11 deletions

View File

@ -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;

View File

@ -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];