You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-07 12:30:27 +00:00
-Display on animation editor which keys are invalid and which tracks are unresolved
-Added a tool to clean up unresolved tracks and unused keys
This commit is contained in:
@@ -207,6 +207,11 @@ extern bool _err_error_exists;
|
|||||||
_err_error_exists=false;\
|
_err_error_exists=false;\
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
#define ERR_PRINTS(m_string) \
|
||||||
|
{ \
|
||||||
|
_err_print_error(FUNCTION_STR,__FILE__,__LINE__,String(m_string).utf8().get_data()); \
|
||||||
|
_err_error_exists=false;\
|
||||||
|
} \
|
||||||
|
|
||||||
/** Print a warning string.
|
/** Print a warning string.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -314,6 +314,7 @@ void Object::set(const StringName& p_name, const Variant& p_value, bool *r_valid
|
|||||||
|
|
||||||
_edited=true;
|
_edited=true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (script_instance) {
|
if (script_instance) {
|
||||||
|
|
||||||
if (script_instance->set(p_name,p_value)) {
|
if (script_instance->set(p_name,p_value)) {
|
||||||
@@ -326,9 +327,9 @@ void Object::set(const StringName& p_name, const Variant& p_value, bool *r_valid
|
|||||||
|
|
||||||
//try built-in setgetter
|
//try built-in setgetter
|
||||||
{
|
{
|
||||||
if (ObjectTypeDB::set_property(this,p_name,p_value)) {
|
if (ObjectTypeDB::set_property(this,p_name,p_value,r_valid)) {
|
||||||
if (r_valid)
|
//if (r_valid)
|
||||||
*r_valid=true;
|
// *r_valid=true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1694,6 +1695,26 @@ void Object::get_translatable_strings(List<String> *p_strings) const {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variant::Type Object::get_static_property_type(const StringName& p_property, bool *r_valid) const {
|
||||||
|
|
||||||
|
bool valid;
|
||||||
|
Variant::Type t = ObjectTypeDB::get_property_type(get_type_name(),p_property,&valid);
|
||||||
|
if (valid) {
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid=true;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_script_instance()) {
|
||||||
|
return get_script_instance()->get_property_type(p_property,r_valid);
|
||||||
|
}
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid=false;
|
||||||
|
|
||||||
|
return Variant::NIL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool Object::is_queued_for_deletion() const {
|
bool Object::is_queued_for_deletion() const {
|
||||||
return _is_queued_for_deletion;
|
return _is_queued_for_deletion;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -606,6 +606,8 @@ public:
|
|||||||
void set_block_signals(bool p_block);
|
void set_block_signals(bool p_block);
|
||||||
bool is_blocking_signals() const;
|
bool is_blocking_signals() const;
|
||||||
|
|
||||||
|
Variant::Type get_static_property_type(const StringName& p_property,bool *r_valid=NULL) const;
|
||||||
|
|
||||||
virtual void get_translatable_strings(List<String> *p_strings) const;
|
virtual void get_translatable_strings(List<String> *p_strings) const;
|
||||||
|
|
||||||
virtual void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
|
virtual void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
|
||||||
|
|||||||
@@ -612,6 +612,7 @@ void ObjectTypeDB::add_property(StringName p_type,const PropertyInfo& p_pinfo, c
|
|||||||
psg._setptr=mb_set;
|
psg._setptr=mb_set;
|
||||||
psg._getptr=mb_get;
|
psg._getptr=mb_get;
|
||||||
psg.index=p_index;
|
psg.index=p_index;
|
||||||
|
psg.type=p_pinfo.type;
|
||||||
|
|
||||||
type->property_setget[p_pinfo.name]=psg;
|
type->property_setget[p_pinfo.name]=psg;
|
||||||
|
|
||||||
@@ -634,7 +635,7 @@ void ObjectTypeDB::get_property_list(StringName p_type,List<PropertyInfo> *p_lis
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, const Variant& p_value) {
|
bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, const Variant& p_value,bool *r_valid) {
|
||||||
|
|
||||||
|
|
||||||
TypeInfo *type=types.getptr(p_object->get_type_name());
|
TypeInfo *type=types.getptr(p_object->get_type_name());
|
||||||
@@ -643,13 +644,17 @@ bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, c
|
|||||||
const PropertySetGet *psg = check->property_setget.getptr(p_property);
|
const PropertySetGet *psg = check->property_setget.getptr(p_property);
|
||||||
if (psg) {
|
if (psg) {
|
||||||
|
|
||||||
if (!psg->setter)
|
if (!psg->setter) {
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid=false;
|
||||||
return true; //return true but do nothing
|
return true; //return true but do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant::CallError ce;
|
||||||
|
|
||||||
if (psg->index>=0) {
|
if (psg->index>=0) {
|
||||||
Variant index=psg->index;
|
Variant index=psg->index;
|
||||||
const Variant* arg[2]={&index,&p_value};
|
const Variant* arg[2]={&index,&p_value};
|
||||||
Variant::CallError ce;
|
|
||||||
// p_object->call(psg->setter,arg,2,ce);
|
// p_object->call(psg->setter,arg,2,ce);
|
||||||
if (psg->_setptr) {
|
if (psg->_setptr) {
|
||||||
psg->_setptr->call(p_object,arg,2,ce);
|
psg->_setptr->call(p_object,arg,2,ce);
|
||||||
@@ -660,13 +665,16 @@ bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, c
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
const Variant* arg[1]={&p_value};
|
const Variant* arg[1]={&p_value};
|
||||||
Variant::CallError ce;
|
|
||||||
if (psg->_setptr) {
|
if (psg->_setptr) {
|
||||||
psg->_setptr->call(p_object,arg,1,ce);
|
psg->_setptr->call(p_object,arg,1,ce);
|
||||||
} else {
|
} else {
|
||||||
p_object->call(psg->setter,arg,1,ce);
|
p_object->call(psg->setter,arg,1,ce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid=ce.error==Variant::CallError::CALL_OK;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -718,6 +726,29 @@ bool ObjectTypeDB::get_property(Object* p_object,const StringName& p_property, V
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variant::Type ObjectTypeDB::get_property_type(const StringName& p_type, const StringName& p_property,bool *r_is_valid) {
|
||||||
|
|
||||||
|
TypeInfo *type=types.getptr(p_type);
|
||||||
|
TypeInfo *check=type;
|
||||||
|
while(check) {
|
||||||
|
const PropertySetGet *psg = check->property_setget.getptr(p_property);
|
||||||
|
if (psg) {
|
||||||
|
|
||||||
|
if (r_is_valid)
|
||||||
|
*r_is_valid=true;
|
||||||
|
|
||||||
|
return psg->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
check=check->inherits_ptr;
|
||||||
|
}
|
||||||
|
if (r_is_valid)
|
||||||
|
*r_is_valid=false;
|
||||||
|
|
||||||
|
return Variant::NIL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ObjectTypeDB::set_method_flags(StringName p_type,StringName p_method,int p_flags) {
|
void ObjectTypeDB::set_method_flags(StringName p_type,StringName p_method,int p_flags) {
|
||||||
|
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ class ObjectTypeDB {
|
|||||||
StringName getter;
|
StringName getter;
|
||||||
MethodBind *_setptr;
|
MethodBind *_setptr;
|
||||||
MethodBind *_getptr;
|
MethodBind *_getptr;
|
||||||
|
Variant::Type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TypeInfo {
|
struct TypeInfo {
|
||||||
@@ -456,8 +457,9 @@ public:
|
|||||||
|
|
||||||
static void add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index=-1);
|
static void add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index=-1);
|
||||||
static void get_property_list(StringName p_type,List<PropertyInfo> *p_list,bool p_no_inheritance=false);
|
static void get_property_list(StringName p_type,List<PropertyInfo> *p_list,bool p_no_inheritance=false);
|
||||||
static bool set_property(Object* p_object,const StringName& p_property, const Variant& p_value);
|
static bool set_property(Object* p_object, const StringName& p_property, const Variant& p_value, bool *r_valid=NULL);
|
||||||
static bool get_property(Object* p_object,const StringName& p_property, Variant& r_value);
|
static bool get_property(Object* p_object,const StringName& p_property, Variant& r_value);
|
||||||
|
static Variant::Type get_property_type(const StringName& p_type, const StringName& p_property,bool *r_is_valid=NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -267,6 +267,20 @@ void PlaceHolderScriptInstance::get_property_list(List<PropertyInfo> *p_properti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variant::Type PlaceHolderScriptInstance::get_property_type(const StringName& p_name,bool *r_is_valid) const {
|
||||||
|
|
||||||
|
if (values.has(p_name)) {
|
||||||
|
if (r_is_valid)
|
||||||
|
*r_is_valid=true;
|
||||||
|
return values[p_name].get_type();
|
||||||
|
}
|
||||||
|
if (r_is_valid)
|
||||||
|
*r_is_valid=false;
|
||||||
|
|
||||||
|
return Variant::NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties,const Map<StringName,Variant>& p_values) {
|
void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties,const Map<StringName,Variant>& p_values) {
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ public:
|
|||||||
virtual StringName get_instance_base_type() const=0; // this may not work in all scripts, will return empty if so
|
virtual StringName get_instance_base_type() const=0; // this may not work in all scripts, will return empty if so
|
||||||
virtual ScriptInstance* instance_create(Object *p_this)=0;
|
virtual ScriptInstance* instance_create(Object *p_this)=0;
|
||||||
virtual bool instance_has(const Object *p_this) const=0;
|
virtual bool instance_has(const Object *p_this) const=0;
|
||||||
|
|
||||||
|
|
||||||
virtual bool has_source_code() const=0;
|
virtual bool has_source_code() const=0;
|
||||||
virtual String get_source_code() const=0;
|
virtual String get_source_code() const=0;
|
||||||
@@ -109,6 +110,7 @@ public:
|
|||||||
virtual bool set(const StringName& p_name, const Variant& p_value)=0;
|
virtual bool set(const StringName& p_name, const Variant& p_value)=0;
|
||||||
virtual bool get(const StringName& p_name, Variant &r_ret) const=0;
|
virtual bool get(const StringName& p_name, Variant &r_ret) const=0;
|
||||||
virtual void get_property_list(List<PropertyInfo> *p_properties) const=0;
|
virtual void get_property_list(List<PropertyInfo> *p_properties) const=0;
|
||||||
|
virtual Variant::Type get_property_type(const StringName& p_name,bool *r_is_valid=NULL) const=0;
|
||||||
|
|
||||||
virtual void get_method_list(List<MethodInfo> *p_list) const=0;
|
virtual void get_method_list(List<MethodInfo> *p_list) const=0;
|
||||||
virtual bool has_method(const StringName& p_method) const=0;
|
virtual bool has_method(const StringName& p_method) const=0;
|
||||||
@@ -208,6 +210,7 @@ public:
|
|||||||
virtual bool set(const StringName& p_name, const Variant& p_value);
|
virtual bool set(const StringName& p_name, const Variant& p_value);
|
||||||
virtual bool get(const StringName& p_name, Variant &r_ret) const;
|
virtual bool get(const StringName& p_name, Variant &r_ret) const;
|
||||||
virtual void get_property_list(List<PropertyInfo> *p_properties) const;
|
virtual void get_property_list(List<PropertyInfo> *p_properties) const;
|
||||||
|
virtual Variant::Type get_property_type(const StringName& p_name,bool *r_is_valid=NULL) const;
|
||||||
|
|
||||||
virtual void get_method_list(List<MethodInfo> *p_list) const {}
|
virtual void get_method_list(List<MethodInfo> *p_list) const {}
|
||||||
virtual bool has_method(const StringName& p_method) const { return false; }
|
virtual bool has_method(const StringName& p_method) const { return false; }
|
||||||
|
|||||||
@@ -390,7 +390,7 @@ public:
|
|||||||
|
|
||||||
Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,CallError &r_error);
|
Variant call(const StringName& p_method,const Variant** p_args,int p_argcount,CallError &r_error);
|
||||||
Variant call(const StringName& p_method,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());
|
Variant call(const StringName& p_method,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());
|
||||||
static Variant construct(const Variant::Type,const Variant** p_args,int p_argcount,CallError &r_error);
|
static Variant construct(const Variant::Type,const Variant** p_args,int p_argcount,CallError &r_error,bool p_strict=true);
|
||||||
|
|
||||||
void get_method_list(List<MethodInfo> *p_list) const;
|
void get_method_list(List<MethodInfo> *p_list) const;
|
||||||
bool has_method(const StringName& p_method) const;
|
bool has_method(const StringName& p_method) const;
|
||||||
|
|||||||
@@ -959,7 +959,7 @@ Variant Variant::call(const StringName& p_method,const Variant** p_args,int p_ar
|
|||||||
#define VCALL(m_type,m_method) _VariantCall::_call_##m_type##_##m_method
|
#define VCALL(m_type,m_method) _VariantCall::_call_##m_type##_##m_method
|
||||||
|
|
||||||
|
|
||||||
Variant Variant::construct(const Variant::Type p_type,const Variant** p_args,int p_argcount,CallError &r_error) {
|
Variant Variant::construct(const Variant::Type p_type, const Variant** p_args, int p_argcount, CallError &r_error, bool p_strict) {
|
||||||
|
|
||||||
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
|
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
|
||||||
ERR_FAIL_INDEX_V(p_type,VARIANT_MAX,Variant());
|
ERR_FAIL_INDEX_V(p_type,VARIANT_MAX,Variant());
|
||||||
@@ -1035,7 +1035,7 @@ Variant Variant::construct(const Variant::Type p_type,const Variant** p_args,int
|
|||||||
|
|
||||||
} else if (p_argcount==1 && p_args[0]->type==p_type) {
|
} else if (p_argcount==1 && p_args[0]->type==p_type) {
|
||||||
return *p_args[0]; //copy construct
|
return *p_args[0]; //copy construct
|
||||||
} else if (p_argcount==1 && Variant::can_convert(p_args[0]->type,p_type)) {
|
} else if (p_argcount==1 && (!p_strict || Variant::can_convert(p_args[0]->type,p_type))) {
|
||||||
//near match construct
|
//near match construct
|
||||||
|
|
||||||
switch(p_type) {
|
switch(p_type) {
|
||||||
|
|||||||
@@ -2274,6 +2274,26 @@ bool GDInstance::get(const StringName& p_name, Variant &r_ret) const {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variant::Type GDInstance::get_property_type(const StringName& p_name,bool *r_is_valid) const {
|
||||||
|
|
||||||
|
|
||||||
|
const GDScript *sptr=script.ptr();
|
||||||
|
while(sptr) {
|
||||||
|
|
||||||
|
if (sptr->member_info.has(p_name)) {
|
||||||
|
if (r_is_valid)
|
||||||
|
*r_is_valid=true;
|
||||||
|
return sptr->member_info[p_name].type;
|
||||||
|
}
|
||||||
|
sptr = sptr->_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_is_valid)
|
||||||
|
*r_is_valid=false;
|
||||||
|
return Variant::NIL;
|
||||||
|
}
|
||||||
|
|
||||||
void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const {
|
void GDInstance::get_property_list(List<PropertyInfo> *p_properties) const {
|
||||||
// exported members, not doen yet!
|
// exported members, not doen yet!
|
||||||
|
|
||||||
|
|||||||
@@ -373,6 +373,8 @@ public:
|
|||||||
virtual bool set(const StringName& p_name, const Variant& p_value);
|
virtual bool set(const StringName& p_name, const Variant& p_value);
|
||||||
virtual bool get(const StringName& p_name, Variant &r_ret) const;
|
virtual bool get(const StringName& p_name, Variant &r_ret) const;
|
||||||
virtual void get_property_list(List<PropertyInfo> *p_properties) const;
|
virtual void get_property_list(List<PropertyInfo> *p_properties) const;
|
||||||
|
virtual Variant::Type get_property_type(const StringName& p_name,bool *r_is_valid=NULL) const;
|
||||||
|
|
||||||
|
|
||||||
virtual void get_method_list(List<MethodInfo> *p_list) const;
|
virtual void get_method_list(List<MethodInfo> *p_list) const;
|
||||||
virtual bool has_method(const StringName& p_method) const;
|
virtual bool has_method(const StringName& p_method) const;
|
||||||
|
|||||||
@@ -268,6 +268,7 @@ void AnimationPlayer::_generate_node_caches(AnimationData* p_anim) {
|
|||||||
TrackNodeCacheKey key;
|
TrackNodeCacheKey key;
|
||||||
key.id=id;
|
key.id=id;
|
||||||
key.bone_idx=bone_idx;
|
key.bone_idx=bone_idx;
|
||||||
|
|
||||||
|
|
||||||
if (node_cache_map.has(key)) {
|
if (node_cache_map.has(key)) {
|
||||||
|
|
||||||
@@ -278,6 +279,7 @@ void AnimationPlayer::_generate_node_caches(AnimationData* p_anim) {
|
|||||||
node_cache_map[key]=TrackNodeCache();
|
node_cache_map[key]=TrackNodeCache();
|
||||||
|
|
||||||
p_anim->node_cache[i]=&node_cache_map[key];
|
p_anim->node_cache[i]=&node_cache_map[key];
|
||||||
|
p_anim->node_cache[i]->path=a->track_get_path(i);
|
||||||
p_anim->node_cache[i]->node=child;
|
p_anim->node_cache[i]->node=child;
|
||||||
p_anim->node_cache[i]->resource=resource;
|
p_anim->node_cache[i]->resource=resource;
|
||||||
p_anim->node_cache[i]->node_2d=child->cast_to<Node2D>();
|
p_anim->node_cache[i]->node_2d=child->cast_to<Node2D>();
|
||||||
@@ -320,6 +322,7 @@ void AnimationPlayer::_generate_node_caches(AnimationData* p_anim) {
|
|||||||
pa.prop=property;
|
pa.prop=property;
|
||||||
pa.object=resource.is_valid()?(Object*)resource.ptr():(Object*)child;
|
pa.object=resource.is_valid()?(Object*)resource.ptr():(Object*)child;
|
||||||
pa.special=SP_NONE;
|
pa.special=SP_NONE;
|
||||||
|
pa.owner=p_anim->node_cache[i];
|
||||||
if (false && p_anim->node_cache[i]->node_2d) {
|
if (false && p_anim->node_cache[i]->node_2d) {
|
||||||
|
|
||||||
if (pa.prop==SceneStringNames::get_singleton()->transform_pos)
|
if (pa.prop==SceneStringNames::get_singleton()->transform_pos)
|
||||||
@@ -410,7 +413,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData* p_anim,float p
|
|||||||
TrackNodeCache::PropertyAnim *pa = &E->get();
|
TrackNodeCache::PropertyAnim *pa = &E->get();
|
||||||
|
|
||||||
|
|
||||||
if (a->value_track_is_continuous(i) || p_delta==0) {
|
if (a->value_track_is_continuous(i) || p_delta==0) { //delta == 0 means seek
|
||||||
|
|
||||||
|
|
||||||
Variant value=a->value_track_interpolate(i,p_time);
|
Variant value=a->value_track_interpolate(i,p_time);
|
||||||
@@ -436,10 +439,42 @@ void AnimationPlayer::_animation_process_animation(AnimationData* p_anim,float p
|
|||||||
Variant value=a->track_get_key_value(i,F->get());
|
Variant value=a->track_get_key_value(i,F->get());
|
||||||
switch(pa->special) {
|
switch(pa->special) {
|
||||||
|
|
||||||
case SP_NONE: pa->object->set(pa->prop,value); break; //you are not speshul
|
case SP_NONE: {
|
||||||
case SP_NODE2D_POS: static_cast<Node2D*>(pa->object)->set_pos(value); break;
|
bool valid;
|
||||||
case SP_NODE2D_ROT: static_cast<Node2D*>(pa->object)->set_rot(Math::deg2rad(value)); break;
|
pa->object->set(pa->prop,value,&valid); //you are not speshul
|
||||||
case SP_NODE2D_SCALE: static_cast<Node2D*>(pa->object)->set_scale(value); break;
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (!valid) {
|
||||||
|
ERR_PRINTS("Failed setting track value '"+String(pa->owner->path)+"'. Check if property exists or the type of key is valid");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case SP_NODE2D_POS: {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (value.get_type()!=Variant::VECTOR2) {
|
||||||
|
ERR_PRINTS("Position key at time "+rtos(p_time)+" in Animation Track '"+String(pa->owner->path)+"' not of type Vector2()");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
static_cast<Node2D*>(pa->object)->set_pos(value);
|
||||||
|
} break;
|
||||||
|
case SP_NODE2D_ROT: {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (value.is_num()) {
|
||||||
|
ERR_PRINTS("Rotation key at time "+rtos(p_time)+" in Animation Track '"+String(pa->owner->path)+"' not numerical");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static_cast<Node2D*>(pa->object)->set_rot(Math::deg2rad(value));
|
||||||
|
} break;
|
||||||
|
case SP_NODE2D_SCALE: {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (value.get_type()!=Variant::VECTOR2) {
|
||||||
|
ERR_PRINTS("Scale key at time "+rtos(p_time)+" in Animation Track '"+String(pa->owner->path)+"' not of type Vector2()");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static_cast<Node2D*>(pa->object)->set_scale(value);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -607,13 +642,53 @@ void AnimationPlayer::_animation_update_transforms() {
|
|||||||
ERR_CONTINUE( pa->accum_pass!=accum_pass );
|
ERR_CONTINUE( pa->accum_pass!=accum_pass );
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
switch(pa->special) {
|
/* switch(pa->special) {
|
||||||
|
|
||||||
|
|
||||||
case SP_NONE: pa->object->set(pa->prop,pa->value_accum); break; //you are not speshul
|
case SP_NONE: pa->object->set(pa->prop,pa->value_accum); break; //you are not speshul
|
||||||
case SP_NODE2D_POS: static_cast<Node2D*>(pa->object)->set_pos(pa->value_accum); break;
|
case SP_NODE2D_POS: static_cast<Node2D*>(pa->object)->set_pos(pa->value_accum); break;
|
||||||
case SP_NODE2D_ROT: static_cast<Node2D*>(pa->object)->set_rot(Math::deg2rad(pa->value_accum)); break;
|
case SP_NODE2D_ROT: static_cast<Node2D*>(pa->object)->set_rot(Math::deg2rad(pa->value_accum)); break;
|
||||||
case SP_NODE2D_SCALE: static_cast<Node2D*>(pa->object)->set_scale(pa->value_accum); break;
|
case SP_NODE2D_SCALE: static_cast<Node2D*>(pa->object)->set_scale(pa->value_accum); break;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
switch(pa->special) {
|
||||||
|
|
||||||
|
case SP_NONE: {
|
||||||
|
bool valid;
|
||||||
|
pa->object->set(pa->prop,pa->value_accum,&valid); //you are not speshul
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (!valid) {
|
||||||
|
ERR_PRINTS("Failed setting key at time "+rtos(playback.current.pos)+" in Animation '"+get_current_animation()+"', Track '"+String(pa->owner->path)+"'. Check if property exists or the type of key is right for the property");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case SP_NODE2D_POS: {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (pa->value_accum.get_type()!=Variant::VECTOR2) {
|
||||||
|
ERR_PRINTS("Position key at time "+rtos(playback.current.pos)+" in Animation '"+get_current_animation()+"', Track '"+String(pa->owner->path)+"' not of type Vector2()");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
static_cast<Node2D*>(pa->object)->set_pos(pa->value_accum);
|
||||||
|
} break;
|
||||||
|
case SP_NODE2D_ROT: {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (pa->value_accum.is_num()) {
|
||||||
|
ERR_PRINTS("Rotation key at time "+rtos(playback.current.pos)+" in Animation '"+get_current_animation()+"', Track '"+String(pa->owner->path)+"' not numerical");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static_cast<Node2D*>(pa->object)->set_rot(Math::deg2rad(pa->value_accum));
|
||||||
|
} break;
|
||||||
|
case SP_NODE2D_SCALE: {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (pa->value_accum.get_type()!=Variant::VECTOR2) {
|
||||||
|
ERR_PRINTS("Scale key at time "+rtos(playback.current.pos)+" in Animation '"+get_current_animation()+"', Track '"+String(pa->owner->path)+"' not of type Vector2()");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static_cast<Node2D*>(pa->object)->set_scale(pa->value_accum);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ private:
|
|||||||
|
|
||||||
struct TrackNodeCache {
|
struct TrackNodeCache {
|
||||||
|
|
||||||
|
NodePath path;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
RES resource;
|
RES resource;
|
||||||
Node *node;
|
Node *node;
|
||||||
@@ -84,6 +85,7 @@ private:
|
|||||||
|
|
||||||
struct PropertyAnim {
|
struct PropertyAnim {
|
||||||
|
|
||||||
|
TrackNodeCache *owner;
|
||||||
SpecialProperty special; //small optimization
|
SpecialProperty special; //small optimization
|
||||||
StringName prop;
|
StringName prop;
|
||||||
Object *object;
|
Object *object;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#include "pair.h"
|
#include "pair.h"
|
||||||
#include "scene/gui/separator.h"
|
#include "scene/gui/separator.h"
|
||||||
#include "editor_node.h"
|
#include "editor_node.h"
|
||||||
|
#include "tools/editor/plugins/animation_player_editor_plugin.h"
|
||||||
/* Missing to fix:
|
/* Missing to fix:
|
||||||
|
|
||||||
*Set
|
*Set
|
||||||
@@ -903,6 +904,23 @@ void AnimationKeyEditor::_menu_track(int p_type) {
|
|||||||
|
|
||||||
optimize_dialog->popup_centered(Size2(250,180));
|
optimize_dialog->popup_centered(Size2(250,180));
|
||||||
} break;
|
} break;
|
||||||
|
case TRACK_MENU_CLEAN_UP: {
|
||||||
|
|
||||||
|
cleanup_dialog->popup_centered_minsize(Size2(300,0));
|
||||||
|
} break;
|
||||||
|
case TRACK_MENU_CLEAN_UP_CONFIRM: {
|
||||||
|
|
||||||
|
if (cleanup_all->is_pressed()) {
|
||||||
|
List<StringName> names;
|
||||||
|
AnimationPlayerEditor::singleton->get_player()->get_animation_list(&names);
|
||||||
|
for (List<StringName>::Element *E=names.front();E;E=E->next()) {
|
||||||
|
_cleanup_animation(AnimationPlayerEditor::singleton->get_player()->get_animation(E->get()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_cleanup_animation(animation);
|
||||||
|
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case CURVE_SET_LINEAR: {
|
case CURVE_SET_LINEAR: {
|
||||||
curve_edit->force_transition(1.0);
|
curve_edit->force_transition(1.0);
|
||||||
|
|
||||||
@@ -933,6 +951,57 @@ void AnimationKeyEditor::_menu_track(int p_type) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnimationKeyEditor::_cleanup_animation(Ref<Animation> p_animation) {
|
||||||
|
|
||||||
|
|
||||||
|
for(int i=0;i<p_animation->get_track_count();i++) {
|
||||||
|
|
||||||
|
bool prop_exists=false;
|
||||||
|
Variant::Type valid_type=Variant::NIL;
|
||||||
|
Object *obj=NULL;
|
||||||
|
|
||||||
|
RES res;
|
||||||
|
Node *node = root->get_node_and_resource(animation->track_get_path(i),res);
|
||||||
|
|
||||||
|
if (res.is_valid()) {
|
||||||
|
obj=res.ptr();
|
||||||
|
} else if (node) {
|
||||||
|
obj=node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj && animation->track_get_type(i)==Animation::TYPE_VALUE) {
|
||||||
|
valid_type=obj->get_static_property_type(animation->track_get_path(i).get_property(),&prop_exists);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!obj && cleanup_tracks->is_pressed()) {
|
||||||
|
|
||||||
|
animation->remove_track(i);
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prop_exists || animation->track_get_type(i)!=Animation::TYPE_VALUE || cleanup_keys->is_pressed()==false)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for(int j=0;j<animation->track_get_key_count(i);j++) {
|
||||||
|
|
||||||
|
Variant v = animation->track_get_key_value(i,j);
|
||||||
|
|
||||||
|
if (!Variant::can_convert(v.get_type(),valid_type)) {
|
||||||
|
animation->track_remove_key(i,j);
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animation->track_get_key_count(i)==0 && cleanup_tracks->is_pressed()) {
|
||||||
|
animation->remove_track(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
undo_redo->clear_history();
|
||||||
|
_update_paths();
|
||||||
|
}
|
||||||
|
|
||||||
void AnimationKeyEditor::_animation_optimize() {
|
void AnimationKeyEditor::_animation_optimize() {
|
||||||
|
|
||||||
@@ -1042,6 +1111,7 @@ void AnimationKeyEditor::_track_editor_draw() {
|
|||||||
timecolor = Color::html("ff4a414f");
|
timecolor = Color::html("ff4a414f");
|
||||||
Color hover_color = Color(1,1,1,0.05);
|
Color hover_color = Color(1,1,1,0.05);
|
||||||
Color select_color = Color(1,1,1,0.1);
|
Color select_color = Color(1,1,1,0.1);
|
||||||
|
Color invalid_path_color = Color(1,0.6,0.4,0.5);
|
||||||
Color track_select_color =Color::html("ffbd8e8e");
|
Color track_select_color =Color::html("ffbd8e8e");
|
||||||
|
|
||||||
Ref<Texture> remove_icon = get_icon("Remove","EditorIcons");
|
Ref<Texture> remove_icon = get_icon("Remove","EditorIcons");
|
||||||
@@ -1068,6 +1138,9 @@ void AnimationKeyEditor::_track_editor_draw() {
|
|||||||
get_icon("KeyCall","EditorIcons")
|
get_icon("KeyCall","EditorIcons")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Ref<Texture> invalid_icon = get_icon("KeyInvalid","EditorIcons");
|
||||||
|
Ref<Texture> invalid_icon_hover = get_icon("KeyInvalidHover","EditorIcons");
|
||||||
|
|
||||||
Ref<Texture> hsize_icon = get_icon("Hsize","EditorIcons");
|
Ref<Texture> hsize_icon = get_icon("Hsize","EditorIcons");
|
||||||
|
|
||||||
Ref<Texture> type_hover=get_icon("KeyHover","EditorIcons");
|
Ref<Texture> type_hover=get_icon("KeyHover","EditorIcons");
|
||||||
@@ -1254,6 +1327,23 @@ void AnimationKeyEditor::_track_editor_draw() {
|
|||||||
break;
|
break;
|
||||||
int y = h+i*h+sep;
|
int y = h+i*h+sep;
|
||||||
|
|
||||||
|
bool prop_exists=false;
|
||||||
|
Variant::Type valid_type=Variant::NIL;
|
||||||
|
Object *obj=NULL;
|
||||||
|
|
||||||
|
RES res;
|
||||||
|
Node *node = root->get_node_and_resource(animation->track_get_path(idx),res);
|
||||||
|
|
||||||
|
if (res.is_valid()) {
|
||||||
|
obj=res.ptr();
|
||||||
|
} else if (node) {
|
||||||
|
obj=node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj && animation->track_get_type(idx)==Animation::TYPE_VALUE) {
|
||||||
|
valid_type=obj->get_static_property_type(animation->track_get_path(idx).get_property(),&prop_exists);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (/*mouse_over.over!=MouseOver::OVER_NONE &&*/ idx==mouse_over.track) {
|
if (/*mouse_over.over!=MouseOver::OVER_NONE &&*/ idx==mouse_over.track) {
|
||||||
Color sepc=hover_color;
|
Color sepc=hover_color;
|
||||||
@@ -1274,6 +1364,8 @@ void AnimationKeyEditor::_track_editor_draw() {
|
|||||||
ncol=track_select_color;
|
ncol=track_select_color;
|
||||||
te->draw_string(font,Point2(ofs+Point2(type_icon[0]->get_width()+sep,y+font->get_ascent()+(sep/2))).floor(),np,ncol,name_limit-(type_icon[0]->get_width()+sep)-5);
|
te->draw_string(font,Point2(ofs+Point2(type_icon[0]->get_width()+sep,y+font->get_ascent()+(sep/2))).floor(),np,ncol,name_limit-(type_icon[0]->get_width()+sep)-5);
|
||||||
|
|
||||||
|
if (!obj)
|
||||||
|
te->draw_line(ofs+Point2(0,y+h/2),ofs+Point2(name_limit,y+h/2),invalid_path_color);
|
||||||
|
|
||||||
te->draw_line(ofs+Point2(0,y+h),ofs+Point2(size.width,y+h),sepcolor);
|
te->draw_line(ofs+Point2(0,y+h),ofs+Point2(size.width,y+h),sepcolor);
|
||||||
|
|
||||||
@@ -1339,6 +1431,8 @@ void AnimationKeyEditor::_track_editor_draw() {
|
|||||||
int kc=animation->track_get_key_count(idx);
|
int kc=animation->track_get_key_count(idx);
|
||||||
bool first=true;
|
bool first=true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for(int i=0;i<kc;i++) {
|
for(int i=0;i<kc;i++) {
|
||||||
|
|
||||||
|
|
||||||
@@ -1386,7 +1480,21 @@ void AnimationKeyEditor::_track_editor_draw() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
te->draw_texture(tex,ofs+Point2(x,y+key_vofs).floor());
|
if (prop_exists && !Variant::can_convert(value.get_type(),valid_type)) {
|
||||||
|
te->draw_texture(invalid_icon,ofs+Point2(x,y+key_vofs).floor());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop_exists && !Variant::can_convert(value.get_type(),valid_type)) {
|
||||||
|
if (tex==type_hover)
|
||||||
|
te->draw_texture(invalid_icon_hover,ofs+Point2(x,y+key_vofs).floor());
|
||||||
|
else
|
||||||
|
te->draw_texture(invalid_icon,ofs+Point2(x,y+key_vofs).floor());
|
||||||
|
} else {
|
||||||
|
|
||||||
|
te->draw_texture(tex,ofs+Point2(x,y+key_vofs).floor());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
first=false;
|
first=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2555,6 +2663,8 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) {
|
|||||||
|
|
||||||
String text;
|
String text;
|
||||||
text="time: "+rtos(animation->track_get_key_time(idx,mouse_over.over_key))+"\n";
|
text="time: "+rtos(animation->track_get_key_time(idx,mouse_over.over_key))+"\n";
|
||||||
|
|
||||||
|
|
||||||
switch(animation->track_get_type(idx)) {
|
switch(animation->track_get_type(idx)) {
|
||||||
|
|
||||||
case Animation::TYPE_TRANSFORM: {
|
case Animation::TYPE_TRANSFORM: {
|
||||||
@@ -2569,8 +2679,33 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) {
|
|||||||
} break;
|
} break;
|
||||||
case Animation::TYPE_VALUE: {
|
case Animation::TYPE_VALUE: {
|
||||||
|
|
||||||
Variant v = animation->track_get_key_value(idx,mouse_over.over_key);
|
Variant v = animation->track_get_key_value(idx,mouse_over.over_key);;
|
||||||
text+="value: "+String(v)+"\n";
|
//text+="value: "+String(v)+"\n";
|
||||||
|
|
||||||
|
bool prop_exists=false;
|
||||||
|
Variant::Type valid_type=Variant::NIL;
|
||||||
|
Object *obj=NULL;
|
||||||
|
|
||||||
|
RES res;
|
||||||
|
Node *node = root->get_node_and_resource(animation->track_get_path(idx),res);
|
||||||
|
|
||||||
|
if (res.is_valid()) {
|
||||||
|
obj=res.ptr();
|
||||||
|
} else if (node) {
|
||||||
|
obj=node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj) {
|
||||||
|
valid_type=obj->get_static_property_type(animation->track_get_path(idx).get_property(),&prop_exists);
|
||||||
|
}
|
||||||
|
|
||||||
|
text+="type: "+Variant::get_type_name(v.get_type())+"\n";
|
||||||
|
if (prop_exists && !Variant::can_convert(v.get_type(),valid_type)) {
|
||||||
|
text+="value: "+String(v)+" (Invalid, expected type: "+Variant::get_type_name(valid_type)+")\n";
|
||||||
|
} else {
|
||||||
|
text+="value: "+String(v)+"\n";
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Animation::TYPE_METHOD: {
|
case Animation::TYPE_METHOD: {
|
||||||
|
|
||||||
@@ -2593,6 +2728,9 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) {
|
|||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
text+="easing: "+rtos(animation->track_get_key_transition(idx,mouse_over.over_key));
|
text+="easing: "+rtos(animation->track_get_key_transition(idx,mouse_over.over_key));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
track_editor->set_tooltip(text);
|
track_editor->set_tooltip(text);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -2703,6 +2841,7 @@ void AnimationKeyEditor::_notification(int p_what) {
|
|||||||
//menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions");
|
//menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions");
|
||||||
//menu_track->get_popup()->add_separator();
|
//menu_track->get_popup()->add_separator();
|
||||||
menu_track->get_popup()->add_item("Optimize Animation",TRACK_MENU_OPTIMIZE);
|
menu_track->get_popup()->add_item("Optimize Animation",TRACK_MENU_OPTIMIZE);
|
||||||
|
menu_track->get_popup()->add_item("Clean-Up Animation",TRACK_MENU_CLEAN_UP);
|
||||||
|
|
||||||
curve_linear->set_icon(get_icon("CurveLinear","EditorIcons"));
|
curve_linear->set_icon(get_icon("CurveLinear","EditorIcons"));
|
||||||
curve_in->set_icon(get_icon("CurveIn","EditorIcons"));
|
curve_in->set_icon(get_icon("CurveIn","EditorIcons"));
|
||||||
@@ -3862,6 +4001,32 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h
|
|||||||
add_child(call_select);
|
add_child(call_select);
|
||||||
call_select->set_title("Call Functions in Which Node?");
|
call_select->set_title("Call Functions in Which Node?");
|
||||||
|
|
||||||
|
cleanup_dialog = memnew( ConfirmationDialog );
|
||||||
|
add_child(cleanup_dialog);
|
||||||
|
VBoxContainer *cleanup_vb = memnew( VBoxContainer );
|
||||||
|
cleanup_dialog->add_child(cleanup_vb);
|
||||||
|
cleanup_dialog->set_child_rect(cleanup_vb);
|
||||||
|
cleanup_keys = memnew( CheckButton );
|
||||||
|
cleanup_keys->set_text("Remove invalid keys");
|
||||||
|
cleanup_keys->set_pressed(true);
|
||||||
|
cleanup_vb->add_child(cleanup_keys);
|
||||||
|
|
||||||
|
cleanup_tracks = memnew( CheckButton );
|
||||||
|
cleanup_tracks->set_text("Remove unresolved and empty tracks");
|
||||||
|
cleanup_tracks->set_pressed(true);
|
||||||
|
cleanup_vb->add_child(cleanup_tracks);
|
||||||
|
|
||||||
|
cleanup_all = memnew( CheckButton );
|
||||||
|
cleanup_all->set_text("Clean-Up all animations");
|
||||||
|
cleanup_vb->add_child(cleanup_all);
|
||||||
|
|
||||||
|
cleanup_dialog->set_title("Clean up Animation(s) (NO UNDO!)");
|
||||||
|
cleanup_dialog->get_ok()->set_text("Clean-Up");
|
||||||
|
|
||||||
|
cleanup_dialog->connect("confirmed",this,"_menu_track",varray(TRACK_MENU_CLEAN_UP_CONFIRM));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationKeyEditor::~AnimationKeyEditor() {
|
AnimationKeyEditor::~AnimationKeyEditor() {
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ class AnimationKeyEditor : public VBoxContainer {
|
|||||||
TRACK_MENU_NEXT_STEP,
|
TRACK_MENU_NEXT_STEP,
|
||||||
TRACK_MENU_PREV_STEP,
|
TRACK_MENU_PREV_STEP,
|
||||||
TRACK_MENU_OPTIMIZE,
|
TRACK_MENU_OPTIMIZE,
|
||||||
|
TRACK_MENU_CLEAN_UP,
|
||||||
|
TRACK_MENU_CLEAN_UP_CONFIRM,
|
||||||
CURVE_SET_LINEAR,
|
CURVE_SET_LINEAR,
|
||||||
CURVE_SET_IN,
|
CURVE_SET_IN,
|
||||||
CURVE_SET_OUT,
|
CURVE_SET_OUT,
|
||||||
@@ -190,6 +192,11 @@ class AnimationKeyEditor : public VBoxContainer {
|
|||||||
SpinBox *optimize_angular_error;
|
SpinBox *optimize_angular_error;
|
||||||
SpinBox *optimize_max_angle;
|
SpinBox *optimize_max_angle;
|
||||||
|
|
||||||
|
ConfirmationDialog *cleanup_dialog;
|
||||||
|
CheckButton *cleanup_keys;
|
||||||
|
CheckButton *cleanup_tracks;
|
||||||
|
CheckButton *cleanup_all;
|
||||||
|
|
||||||
SpinBox *step;
|
SpinBox *step;
|
||||||
|
|
||||||
MenuButton *menu_add_track;
|
MenuButton *menu_add_track;
|
||||||
@@ -284,6 +291,7 @@ class AnimationKeyEditor : public VBoxContainer {
|
|||||||
|
|
||||||
void _animation_changed();
|
void _animation_changed();
|
||||||
void _animation_optimize();
|
void _animation_optimize();
|
||||||
|
void _cleanup_animation(Ref<Animation> p_animation);
|
||||||
|
|
||||||
void _scroll_changed(double);
|
void _scroll_changed(double);
|
||||||
|
|
||||||
|
|||||||
BIN
tools/editor/icons/icon_key_invalid.png
Normal file
BIN
tools/editor/icons/icon_key_invalid.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 239 B |
BIN
tools/editor/icons/icon_key_invalid_hover.png
Normal file
BIN
tools/editor/icons/icon_key_invalid_hover.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 239 B |
@@ -1250,8 +1250,15 @@ void AnimationPlayerEditor::_bind_methods() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnimationPlayerEditor *AnimationPlayerEditor::singleton=NULL;
|
||||||
|
|
||||||
|
AnimationPlayer *AnimationPlayerEditor::get_player() const {
|
||||||
|
|
||||||
|
return player;
|
||||||
|
}
|
||||||
AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
|
AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
|
||||||
editor=p_editor;
|
editor=p_editor;
|
||||||
|
singleton=this;
|
||||||
|
|
||||||
updating=false;
|
updating=false;
|
||||||
|
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ class AnimationPlayerEditor : public VBoxContainer {
|
|||||||
void _animation_tool_menu(int p_option);
|
void _animation_tool_menu(int p_option);
|
||||||
void _animation_save_menu(int p_option);
|
void _animation_save_menu(int p_option);
|
||||||
|
|
||||||
|
|
||||||
AnimationPlayerEditor();
|
AnimationPlayerEditor();
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@@ -171,6 +172,9 @@ protected:
|
|||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
AnimationPlayer *get_player() const;
|
||||||
|
static AnimationPlayerEditor *singleton;
|
||||||
|
|
||||||
Dictionary get_state() const;
|
Dictionary get_state() const;
|
||||||
void set_state(const Dictionary& p_state);
|
void set_state(const Dictionary& p_state);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user