diff options
-rw-r--r-- | scene/resources/animation.cpp | 28 | ||||
-rw-r--r-- | scene/resources/animation.h | 12 | ||||
-rw-r--r-- | tools/editor/animation_editor.cpp | 105 | ||||
-rw-r--r-- | tools/editor/animation_editor.h | 3 | ||||
-rw-r--r-- | tools/editor/icons/icon_interp_wrap_clamp.png | bin | 0 -> 175 bytes | |||
-rw-r--r-- | tools/editor/icons/icon_interp_wrap_loop.png | bin | 0 -> 176 bytes |
6 files changed, 122 insertions, 26 deletions
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 76c6f29bcb..c962e1a671 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -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); diff --git a/scene/resources/animation.h b/scene/resources/animation.h index c236b3ef37..b81ac4f1bf 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -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; diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index 4b918d75bc..e08091f7c0 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -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; } diff --git a/tools/editor/animation_editor.h b/tools/editor/animation_editor.h index 10cc1bf611..0c9b0b5ac6 100644 --- a/tools/editor/animation_editor.h +++ b/tools/editor/animation_editor.h @@ -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; diff --git a/tools/editor/icons/icon_interp_wrap_clamp.png b/tools/editor/icons/icon_interp_wrap_clamp.png Binary files differnew file mode 100644 index 0000000000..3026b19d97 --- /dev/null +++ b/tools/editor/icons/icon_interp_wrap_clamp.png diff --git a/tools/editor/icons/icon_interp_wrap_loop.png b/tools/editor/icons/icon_interp_wrap_loop.png Binary files differnew file mode 100644 index 0000000000..64beb6c670 --- /dev/null +++ b/tools/editor/icons/icon_interp_wrap_loop.png |