Add clamp and wrap loop modes for animation tracks.
This commit is contained in:
parent
62273e51a2
commit
a168cd7a23
@ -72,6 +72,8 @@ bool Animation::_set(const StringName& p_name, const Variant& p_value) {
|
||||
track_set_path(track,p_value);
|
||||
else if (what=="interp")
|
||||
track_set_interpolation_type(track,InterpolationType(p_value.operator int()));
|
||||
else if (what=="loop_wrap")
|
||||
track_set_interpolation_loop_wrap(track,p_value);
|
||||
else if (what=="imported")
|
||||
track_set_imported(track,p_value);
|
||||
else if (what == "keys" || what=="key_values") {
|
||||
@ -291,6 +293,8 @@ bool Animation::_get(const StringName& p_name,Variant &r_ret) const {
|
||||
r_ret=track_get_path(track);
|
||||
else if (what=="interp")
|
||||
r_ret = track_get_interpolation_type(track);
|
||||
else if (what=="loop_wrap")
|
||||
r_ret = track_get_interpolation_loop_wrap(track);
|
||||
else if (what=="imported")
|
||||
r_ret = track_is_imported(track);
|
||||
else if (what=="keys") {
|
||||
@ -440,6 +444,7 @@ void Animation::_get_property_list( List<PropertyInfo> *p_list) const {
|
||||
p_list->push_back( PropertyInfo( Variant::STRING, "tracks/"+itos(i)+"/type", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
|
||||
p_list->push_back( PropertyInfo( Variant::NODE_PATH, "tracks/"+itos(i)+"/path", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
|
||||
p_list->push_back( PropertyInfo( Variant::INT, "tracks/"+itos(i)+"/interp", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "tracks/"+itos(i)+"/loop_wrap", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
|
||||
p_list->push_back( PropertyInfo( Variant::BOOL, "tracks/"+itos(i)+"/imported", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
|
||||
p_list->push_back( PropertyInfo( Variant::ARRAY, "tracks/"+itos(i)+"/keys", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
|
||||
}
|
||||
@ -559,6 +564,19 @@ Animation::InterpolationType Animation::track_get_interpolation_type(int p_track
|
||||
return tracks[p_track]->interpolation;
|
||||
}
|
||||
|
||||
void Animation::track_set_interpolation_loop_wrap(int p_track,bool p_enable) {
|
||||
ERR_FAIL_INDEX(p_track, tracks.size());
|
||||
tracks[p_track]->loop_wrap=p_enable;
|
||||
emit_changed();
|
||||
|
||||
}
|
||||
|
||||
bool Animation::track_get_interpolation_loop_wrap(int p_track) const{
|
||||
|
||||
ERR_FAIL_INDEX_V(p_track, tracks.size(),INTERPOLATION_NEAREST);
|
||||
return tracks[p_track]->loop_wrap;
|
||||
|
||||
}
|
||||
|
||||
// transform
|
||||
/*
|
||||
@ -1211,7 +1229,7 @@ float Animation::_cubic_interpolate( const float& p_pre_a,const float& p_a, cons
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T Animation::_interpolate( const Vector< TKey<T> >& p_keys, float p_time, InterpolationType p_interp, bool *p_ok) const {
|
||||
T Animation::_interpolate( const Vector< TKey<T> >& p_keys, float p_time, InterpolationType p_interp, bool p_loop_wrap,bool *p_ok) const {
|
||||
|
||||
int len=_find( p_keys, length )+1; // try to find last key (there may be more past the end)
|
||||
|
||||
@ -1239,7 +1257,7 @@ T Animation::_interpolate( const Vector< TKey<T> >& p_keys, float p_time, Inter
|
||||
float c=0;
|
||||
// prepare for all cases of interpolation
|
||||
|
||||
if (loop) {
|
||||
if (loop && p_loop_wrap) {
|
||||
// loop
|
||||
if (idx>=0) {
|
||||
|
||||
@ -1363,7 +1381,7 @@ Error Animation::transform_track_interpolate(int p_track, float p_time, Vector3
|
||||
|
||||
bool ok;
|
||||
|
||||
TransformKey tk = _interpolate( tt->transforms, p_time, tt->interpolation, &ok );
|
||||
TransformKey tk = _interpolate( tt->transforms, p_time, tt->interpolation, tt->loop_wrap, &ok );
|
||||
|
||||
if (!ok) // ??
|
||||
return ERR_UNAVAILABLE;
|
||||
@ -1391,7 +1409,7 @@ Variant Animation::value_track_interpolate(int p_track, float p_time) const {
|
||||
bool ok;
|
||||
|
||||
|
||||
Variant res = _interpolate( vt->values, p_time, vt->update_mode==UPDATE_CONTINUOUS?vt->interpolation:INTERPOLATION_NEAREST, &ok );
|
||||
Variant res = _interpolate( vt->values, p_time, vt->update_mode==UPDATE_CONTINUOUS?vt->interpolation:INTERPOLATION_NEAREST,vt->loop_wrap, &ok );
|
||||
|
||||
|
||||
if (ok) {
|
||||
@ -1711,6 +1729,8 @@ void Animation::_bind_methods() {
|
||||
ClassDB::bind_method(_MD("track_set_interpolation_type","idx","interpolation"),&Animation::track_set_interpolation_type);
|
||||
ClassDB::bind_method(_MD("track_get_interpolation_type","idx"),&Animation::track_get_interpolation_type);
|
||||
|
||||
ClassDB::bind_method(_MD("track_set_interpolation_loop_wrap","idx","interpolation"),&Animation::track_set_interpolation_loop_wrap);
|
||||
ClassDB::bind_method(_MD("track_get_interpolation_loop_wrap","idx"),&Animation::track_get_interpolation_loop_wrap);
|
||||
|
||||
|
||||
ClassDB::bind_method(_MD("transform_track_interpolate","idx","time_sec"),&Animation::_transform_track_interpolate);
|
||||
|
@ -39,12 +39,7 @@ class Animation : public Resource {
|
||||
RES_BASE_EXTENSION("anm");
|
||||
public:
|
||||
|
||||
enum LoopMode {
|
||||
|
||||
LOOP_NONE,
|
||||
LOOP_ENABLED,
|
||||
LOOP_WRAP
|
||||
};
|
||||
|
||||
enum TrackType {
|
||||
TYPE_VALUE, ///< Set a value in a property, can be interpolated.
|
||||
@ -71,9 +66,10 @@ private:
|
||||
|
||||
TrackType type;
|
||||
InterpolationType interpolation;
|
||||
bool loop_wrap;
|
||||
NodePath path; // path to something
|
||||
bool imported;
|
||||
Track() { interpolation=INTERPOLATION_LINEAR; imported=false;}
|
||||
Track() { interpolation=INTERPOLATION_LINEAR; imported=false; loop_wrap=true;}
|
||||
virtual ~Track() {}
|
||||
};
|
||||
|
||||
@ -164,7 +160,7 @@ private:
|
||||
_FORCE_INLINE_ float _cubic_interpolate( const float& p_pre_a,const float& p_a, const float& p_b, const float& p_post_b, float p_c) const;
|
||||
|
||||
template<class T>
|
||||
_FORCE_INLINE_ T _interpolate( const Vector< TKey<T> >& p_keys, float p_time, InterpolationType p_interp,bool *p_ok) const;
|
||||
_FORCE_INLINE_ T _interpolate( const Vector< TKey<T> >& p_keys, float p_time, InterpolationType p_interp,bool p_loop_wrap,bool *p_ok) const;
|
||||
|
||||
_FORCE_INLINE_ void _value_track_get_key_indices_in_range(const ValueTrack * vt, float from_time, float to_time,List<int> *p_indices) const;
|
||||
_FORCE_INLINE_ void _method_track_get_key_indices_in_range(const MethodTrack * mt, float from_time, float to_time,List<int> *p_indices) const;
|
||||
@ -260,6 +256,8 @@ public:
|
||||
void track_set_interpolation_type(int p_track,InterpolationType p_interp);
|
||||
InterpolationType track_get_interpolation_type(int p_track) const;
|
||||
|
||||
void track_set_interpolation_loop_wrap(int p_track,bool p_enable);
|
||||
bool track_get_interpolation_loop_wrap(int p_track) const;
|
||||
|
||||
Error transform_track_interpolate(int p_track, float p_time, Vector3 * r_loc, Quat *r_rot, Vector3 *r_scale) const;
|
||||
|
||||
|
@ -1157,6 +1157,12 @@ void AnimationKeyEditor::_track_editor_draw() {
|
||||
Ref<Texture> add_key_icon = get_icon("TrackAddKey","EditorIcons");
|
||||
Ref<Texture> add_key_icon_hl = get_icon("TrackAddKeyHl","EditorIcons");
|
||||
Ref<Texture> down_icon = get_icon("select_arrow","Tree");
|
||||
|
||||
Ref<Texture> wrap_icon[2]={
|
||||
get_icon("InterpWrapClamp","EditorIcons"),
|
||||
get_icon("InterpWrapLoop","EditorIcons"),
|
||||
};
|
||||
|
||||
Ref<Texture> interp_icon[3]={
|
||||
get_icon("InterpRaw","EditorIcons"),
|
||||
get_icon("InterpLinear","EditorIcons"),
|
||||
@ -1181,7 +1187,7 @@ void AnimationKeyEditor::_track_editor_draw() {
|
||||
Ref<Texture> type_hover=get_icon("KeyHover","EditorIcons");
|
||||
Ref<Texture> type_selected=get_icon("KeySelected","EditorIcons");
|
||||
|
||||
int right_separator_ofs = down_icon->get_width() *2 + add_key_icon->get_width() + interp_icon[0]->get_width() + cont_icon[0]->get_width() + hsep*7;
|
||||
int right_separator_ofs = down_icon->get_width() *3 + add_key_icon->get_width() + interp_icon[0]->get_width() + wrap_icon[0]->get_width() + cont_icon[0]->get_width() + hsep*9;
|
||||
|
||||
int h = font->get_height()+sep;
|
||||
|
||||
@ -1421,6 +1427,20 @@ void AnimationKeyEditor::_track_editor_draw() {
|
||||
|
||||
icon_ofs.x-=hsep;
|
||||
*/
|
||||
track_ofs[0]=size.width-icon_ofs.x;
|
||||
icon_ofs.x-=down_icon->get_width();
|
||||
te->draw_texture(down_icon,icon_ofs);
|
||||
|
||||
int wrap_type = animation->track_get_interpolation_loop_wrap(idx)?1:0;
|
||||
icon_ofs.x-=hsep;
|
||||
icon_ofs.x-=wrap_icon[wrap_type]->get_width();
|
||||
te->draw_texture(wrap_icon[wrap_type],icon_ofs);
|
||||
|
||||
icon_ofs.x-=hsep;
|
||||
te->draw_line(Point2(icon_ofs.x,ofs.y+y),Point2(icon_ofs.x,ofs.y+y+h),sepcolor);
|
||||
|
||||
track_ofs[1]=size.width-icon_ofs.x;
|
||||
|
||||
icon_ofs.x-=down_icon->get_width();
|
||||
te->draw_texture(down_icon,icon_ofs);
|
||||
|
||||
@ -1433,6 +1453,8 @@ void AnimationKeyEditor::_track_editor_draw() {
|
||||
icon_ofs.x-=hsep;
|
||||
te->draw_line(Point2(icon_ofs.x,ofs.y+y),Point2(icon_ofs.x,ofs.y+y+h),sepcolor);
|
||||
|
||||
track_ofs[2]=size.width-icon_ofs.x;
|
||||
|
||||
if (animation->track_get_type(idx)==Animation::TYPE_VALUE) {
|
||||
|
||||
|
||||
@ -1453,10 +1475,14 @@ void AnimationKeyEditor::_track_editor_draw() {
|
||||
icon_ofs.x-=hsep;
|
||||
te->draw_line(Point2(icon_ofs.x,ofs.y+y),Point2(icon_ofs.x,ofs.y+y+h),sepcolor);
|
||||
|
||||
track_ofs[3]=size.width-icon_ofs.x;
|
||||
|
||||
icon_ofs.x-=hsep;
|
||||
icon_ofs.x-=add_key_icon->get_width();
|
||||
te->draw_texture((mouse_over.over==MouseOver::OVER_ADD_KEY && mouse_over.track==idx)?add_key_icon_hl:add_key_icon,icon_ofs);
|
||||
|
||||
track_ofs[4]=size.width-icon_ofs.x;
|
||||
|
||||
//draw the keys;
|
||||
int tt = animation->track_get_type(idx);
|
||||
float key_vofs = Math::floor((h - type_icon[tt]->get_height())/2);
|
||||
@ -1621,6 +1647,14 @@ void AnimationKeyEditor::_track_menu_selected(int p_idx) {
|
||||
undo_redo->add_do_method(animation.ptr(),"value_track_set_update_mode",cont_editing,p_idx);
|
||||
undo_redo->add_undo_method(animation.ptr(),"value_track_set_update_mode",cont_editing,animation->value_track_get_update_mode(cont_editing));
|
||||
undo_redo->commit_action();
|
||||
} else if (wrap_editing!=-1) {
|
||||
|
||||
ERR_FAIL_INDEX(wrap_editing,animation->get_track_count());
|
||||
|
||||
undo_redo->create_action(TTR("Anim Track Change Wrap Mode"));
|
||||
undo_redo->add_do_method(animation.ptr(),"track_set_interpolation_loop_wrap",wrap_editing,p_idx?true:false);
|
||||
undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_loop_wrap",wrap_editing,animation->track_get_interpolation_loop_wrap(wrap_editing));
|
||||
undo_redo->commit_action();
|
||||
} else {
|
||||
switch (p_idx) {
|
||||
|
||||
@ -1833,6 +1867,10 @@ void AnimationKeyEditor::_track_editor_gui_input(const InputEvent& p_input) {
|
||||
Ref<Texture> hsize_icon = get_icon("Hsize","EditorIcons");
|
||||
Ref<Texture> add_key_icon = get_icon("TrackAddKey","EditorIcons");
|
||||
|
||||
Ref<Texture> wrap_icon[2]={
|
||||
get_icon("InterpWrapClamp","EditorIcons"),
|
||||
get_icon("InterpWrapLoop","EditorIcons"),
|
||||
};
|
||||
Ref<Texture> interp_icon[3]={
|
||||
get_icon("InterpRaw","EditorIcons"),
|
||||
get_icon("InterpLinear","EditorIcons"),
|
||||
@ -1848,7 +1886,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const InputEvent& p_input) {
|
||||
get_icon("KeyXform","EditorIcons"),
|
||||
get_icon("KeyCall","EditorIcons")
|
||||
};
|
||||
int right_separator_ofs = down_icon->get_width() *2 + add_key_icon->get_width() + interp_icon[0]->get_width() + cont_icon[0]->get_width() + hsep*7;
|
||||
int right_separator_ofs = down_icon->get_width() *3 + add_key_icon->get_width() + interp_icon[0]->get_width() + wrap_icon[0]->get_width() + cont_icon[0]->get_width() + hsep*9;
|
||||
|
||||
int h = font->get_height()+sep;
|
||||
|
||||
@ -2054,6 +2092,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const InputEvent& p_input) {
|
||||
|
||||
interp_editing=-1;
|
||||
cont_editing=-1;
|
||||
wrap_editing=-1;
|
||||
|
||||
track_menu->popup();
|
||||
}
|
||||
@ -2277,7 +2316,33 @@ void AnimationKeyEditor::_track_editor_gui_input(const InputEvent& p_input) {
|
||||
ofsx-=hsep*3+move_up_icon->get_width();
|
||||
*/
|
||||
|
||||
if (ofsx < down_icon->get_width() + interp_icon[0]->get_width() + hsep*2) {
|
||||
|
||||
if (ofsx < track_ofs[1]) {
|
||||
|
||||
track_menu->clear();
|
||||
track_menu->set_size(Point2(1,1));
|
||||
static const char *interp_name[2]={"Clamp Loop Interp","Wrap Loop Interp"};
|
||||
for(int i=0;i<2;i++) {
|
||||
track_menu->add_icon_item(wrap_icon[i],interp_name[i]);
|
||||
}
|
||||
|
||||
int popup_y = ofs.y+((int(mpos.y)/h)+2)*h;
|
||||
int popup_x = size.width-track_ofs[1];
|
||||
|
||||
track_menu->set_pos(te->get_global_pos()+Point2(popup_x,popup_y));
|
||||
|
||||
|
||||
wrap_editing=idx;
|
||||
interp_editing=-1;
|
||||
cont_editing=-1;
|
||||
|
||||
track_menu->popup();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (ofsx < track_ofs[2]) {
|
||||
|
||||
track_menu->clear();
|
||||
track_menu->set_size(Point2(1,1));
|
||||
@ -2286,24 +2351,22 @@ void AnimationKeyEditor::_track_editor_gui_input(const InputEvent& p_input) {
|
||||
track_menu->add_icon_item(interp_icon[i],interp_name[i]);
|
||||
}
|
||||
|
||||
int lofs = remove_icon->get_width() + move_up_icon->get_width() + move_down_icon->get_width() + down_icon->get_width() *2 + hsep*7;//interp_icon[0]->get_width() + cont_icon[0]->get_width() ;
|
||||
int popup_y = ofs.y+((int(mpos.y)/h)+2)*h;
|
||||
int popup_x = ofs.x+size.width-lofs;
|
||||
int popup_x = size.width-track_ofs[2];
|
||||
|
||||
track_menu->set_pos(te->get_global_pos()+Point2(popup_x,popup_y));
|
||||
|
||||
|
||||
interp_editing=idx;
|
||||
cont_editing=-1;
|
||||
wrap_editing=-1;
|
||||
|
||||
track_menu->popup();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ofsx-=hsep*2+interp_icon[0]->get_width()+down_icon->get_width();
|
||||
|
||||
if (ofsx < down_icon->get_width() + cont_icon[0]->get_width()) {
|
||||
if (ofsx < track_ofs[3]) {
|
||||
|
||||
track_menu->clear();
|
||||
track_menu->set_size(Point2(1,1));
|
||||
@ -2312,13 +2375,14 @@ void AnimationKeyEditor::_track_editor_gui_input(const InputEvent& p_input) {
|
||||
track_menu->add_icon_item(cont_icon[i],cont_name[i]);
|
||||
}
|
||||
|
||||
int lofs = settings_limit;
|
||||
|
||||
int popup_y = ofs.y+((int(mpos.y)/h)+2)*h;
|
||||
int popup_x = ofs.x+lofs;
|
||||
int popup_x = size.width-track_ofs[3];
|
||||
|
||||
track_menu->set_pos(te->get_global_pos()+Point2(popup_x,popup_y));
|
||||
|
||||
interp_editing=-1;
|
||||
wrap_editing=-1;
|
||||
cont_editing=idx;
|
||||
|
||||
track_menu->popup();
|
||||
@ -2326,9 +2390,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const InputEvent& p_input) {
|
||||
return;
|
||||
}
|
||||
|
||||
ofsx-=hsep*3+cont_icon[0]->get_width()+down_icon->get_width();
|
||||
|
||||
if (ofsx < add_key_icon->get_width()) {
|
||||
if (ofsx < track_ofs[4]) {
|
||||
|
||||
Animation::TrackType tt = animation->track_get_type(idx);
|
||||
|
||||
@ -2940,7 +3002,15 @@ void AnimationKeyEditor::_track_editor_gui_input(const InputEvent& p_input) {
|
||||
|
||||
*/
|
||||
|
||||
if (ofsx < down_icon->get_width() + interp_icon[0]->get_width() + hsep*2) {
|
||||
if (ofsx < down_icon->get_width() + wrap_icon[0]->get_width() + hsep*3) {
|
||||
|
||||
mouse_over.over=MouseOver::OVER_WRAP;
|
||||
return;
|
||||
}
|
||||
|
||||
ofsx-=hsep*3+wrap_icon[0]->get_width() + down_icon->get_width();
|
||||
|
||||
if (ofsx < down_icon->get_width() + interp_icon[0]->get_width() + hsep*3) {
|
||||
|
||||
mouse_over.over=MouseOver::OVER_INTERP;
|
||||
return;
|
||||
@ -3068,8 +3138,13 @@ void AnimationKeyEditor::_notification(int p_what) {
|
||||
get_icon("TrackTrigger","EditorIcons")
|
||||
};
|
||||
|
||||
Ref<Texture> wrap_icon[2]={
|
||||
get_icon("InterpWrapClamp","EditorIcons"),
|
||||
get_icon("InterpWrapLoop","EditorIcons"),
|
||||
};
|
||||
|
||||
//right_data_size_cache = remove_icon->get_width() + move_up_icon->get_width() + move_down_icon->get_width() + down_icon->get_width() *2 + interp_icon[0]->get_width() + cont_icon[0]->get_width() + add_key_icon->get_width() + hsep*11;
|
||||
right_data_size_cache = down_icon->get_width() *2 + add_key_icon->get_width() + interp_icon[0]->get_width() + cont_icon[0]->get_width() + hsep*7;
|
||||
right_data_size_cache = down_icon->get_width() *3 + add_key_icon->get_width() + interp_icon[0]->get_width() + cont_icon[0]->get_width() + wrap_icon[0]->get_width() + hsep*8;
|
||||
|
||||
|
||||
}
|
||||
|
@ -113,6 +113,7 @@ class AnimationKeyEditor : public VBoxContainer {
|
||||
OVER_KEY,
|
||||
OVER_VALUE,
|
||||
OVER_INTERP,
|
||||
OVER_WRAP,
|
||||
OVER_UP,
|
||||
OVER_DOWN,
|
||||
OVER_REMOVE,
|
||||
@ -166,7 +167,9 @@ class AnimationKeyEditor : public VBoxContainer {
|
||||
int track_name_editing;
|
||||
int interp_editing;
|
||||
int cont_editing;
|
||||
int wrap_editing;
|
||||
int selected_track;
|
||||
int track_ofs[5];
|
||||
|
||||
int last_menu_track_opt;
|
||||
LineEdit *track_name;
|
||||
|
BIN
tools/editor/icons/icon_interp_wrap_clamp.png
Normal file
BIN
tools/editor/icons/icon_interp_wrap_clamp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 175 B |
BIN
tools/editor/icons/icon_interp_wrap_loop.png
Normal file
BIN
tools/editor/icons/icon_interp_wrap_loop.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 176 B |
Loading…
Reference in New Issue
Block a user