|
@@ -3354,7 +3354,7 @@ bool AnimationTrackEdit::_try_select_at_ui_pos(const Point2 &p_pos, bool p_aggre
|
|
|
}
|
|
|
|
|
|
Variant AnimationTrackEdit::get_drag_data(const Point2 &p_point) {
|
|
|
- if (!clicking_on_name) {
|
|
|
+ if (!clicking_on_name || (get_editor()->is_sorting_alphabetically() && !get_editor()->is_grouping_tracks())) {
|
|
|
return Variant();
|
|
|
}
|
|
|
|
|
@@ -3774,6 +3774,10 @@ Size2 AnimationTrackEditGroup::get_minimum_size() const {
|
|
|
return Vector2(0, MAX(font->get_height(font_size), icon_size.y) + separation + content_margin);
|
|
|
}
|
|
|
|
|
|
+String AnimationTrackEditGroup::get_node_name() const {
|
|
|
+ return node_name;
|
|
|
+}
|
|
|
+
|
|
|
void AnimationTrackEditGroup::set_timeline(AnimationTimelineEdit *p_timeline) {
|
|
|
timeline = p_timeline;
|
|
|
timeline->connect("zoom_changed", callable_mp(this, &AnimationTrackEditGroup::_zoom_changed));
|
|
@@ -4901,9 +4905,13 @@ void AnimationTrackEditor::_update_tracks() {
|
|
|
}
|
|
|
|
|
|
RBMap<String, VBoxContainer *> group_sort;
|
|
|
+ LocalVector<VBoxContainer *> group_containers;
|
|
|
|
|
|
bool use_grouping = !view_group->is_pressed();
|
|
|
bool use_filter = selected_filter->is_pressed();
|
|
|
+ bool use_alphabetic_sorting = alphabetic_sorting->is_pressed();
|
|
|
+
|
|
|
+ AnimationTrackEdit *selected_track_edit = nullptr;
|
|
|
|
|
|
for (int i = 0; i < animation->get_track_count(); i++) {
|
|
|
AnimationTrackEdit *track_edit = nullptr;
|
|
@@ -5014,8 +5022,8 @@ void AnimationTrackEditor::_update_tracks() {
|
|
|
VBoxContainer *vb = memnew(VBoxContainer);
|
|
|
vb->add_theme_constant_override("separation", 0);
|
|
|
vb->add_child(g);
|
|
|
- track_vbox->add_child(vb);
|
|
|
group_sort[base_path] = vb;
|
|
|
+ group_containers.push_back(vb);
|
|
|
}
|
|
|
|
|
|
track_edit->set_in_group(true);
|
|
@@ -5023,7 +5031,6 @@ void AnimationTrackEditor::_update_tracks() {
|
|
|
|
|
|
} else {
|
|
|
track_edit->set_in_group(false);
|
|
|
- track_vbox->add_child(track_edit);
|
|
|
}
|
|
|
|
|
|
track_edit->set_timeline(timeline);
|
|
@@ -5033,7 +5040,7 @@ void AnimationTrackEditor::_update_tracks() {
|
|
|
track_edit->set_editor(this);
|
|
|
|
|
|
if (selected == i) {
|
|
|
- track_edit->grab_focus();
|
|
|
+ selected_track_edit = track_edit;
|
|
|
}
|
|
|
|
|
|
track_edit->connect("timeline_changed", callable_mp(this, &AnimationTrackEditor::_timeline_changed));
|
|
@@ -5054,6 +5061,45 @@ void AnimationTrackEditor::_update_tracks() {
|
|
|
track_edit->connect("create_reset_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_ADD_RESET_KEY), CONNECT_DEFERRED);
|
|
|
track_edit->connect("delete_request", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_DELETE_SELECTION), CONNECT_DEFERRED);
|
|
|
}
|
|
|
+
|
|
|
+ if (use_grouping) {
|
|
|
+ if (use_alphabetic_sorting) {
|
|
|
+ struct GroupAlphaCompare {
|
|
|
+ bool operator()(const VBoxContainer *p_lhs, const VBoxContainer *p_rhs) const {
|
|
|
+ String lhs_node_name = Object::cast_to<AnimationTrackEditGroup>(p_lhs->get_child(0))->get_node_name();
|
|
|
+ String rhs_node_name = Object::cast_to<AnimationTrackEditGroup>(p_rhs->get_child(0))->get_node_name();
|
|
|
+ return lhs_node_name < rhs_node_name;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ group_containers.sort_custom<GroupAlphaCompare>();
|
|
|
+ }
|
|
|
+
|
|
|
+ for (VBoxContainer *vb : group_containers) {
|
|
|
+ track_vbox->add_child(vb);
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ if (use_alphabetic_sorting) {
|
|
|
+ struct TrackAlphaCompare {
|
|
|
+ bool operator()(const AnimationTrackEdit *p_lhs, const AnimationTrackEdit *p_rhs) const {
|
|
|
+ String lhs_leaf = (String)p_lhs->get_path().slice(-p_lhs->get_path().get_subname_count() - 1);
|
|
|
+ String rhs_leaf = (String)p_rhs->get_path().slice(-p_rhs->get_path().get_subname_count() - 1);
|
|
|
+ return lhs_leaf < rhs_leaf;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ track_edits.sort_custom<TrackAlphaCompare>();
|
|
|
+ }
|
|
|
+
|
|
|
+ for (AnimationTrackEdit *track_edit : track_edits) {
|
|
|
+ track_vbox->add_child(track_edit);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (selected_track_edit != nullptr) {
|
|
|
+ selected_track_edit->grab_focus();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void AnimationTrackEditor::_redraw_tracks() {
|
|
@@ -5210,6 +5256,7 @@ void AnimationTrackEditor::_notification(int p_what) {
|
|
|
view_group->set_button_icon(get_editor_theme_icon(view_group->is_pressed() ? SNAME("AnimationTrackList") : SNAME("AnimationTrackGroup")));
|
|
|
function_name_toggler->set_button_icon(get_editor_theme_icon(SNAME("MemberMethod")));
|
|
|
selected_filter->set_button_icon(get_editor_theme_icon(SNAME("AnimationFilter")));
|
|
|
+ alphabetic_sorting->set_button_icon(get_editor_theme_icon(SNAME("Sort")));
|
|
|
imported_anim_warning->set_button_icon(get_editor_theme_icon(SNAME("NodeWarning")));
|
|
|
dummy_player_warning->set_button_icon(get_editor_theme_icon(SNAME("NodeWarning")));
|
|
|
inactive_player_warning->set_button_icon(get_editor_theme_icon(SNAME("NodeWarning")));
|
|
@@ -7412,6 +7459,10 @@ bool AnimationTrackEditor::is_grouping_tracks() {
|
|
|
return !view_group->is_pressed();
|
|
|
}
|
|
|
|
|
|
+bool AnimationTrackEditor::is_sorting_alphabetically() {
|
|
|
+ return alphabetic_sorting->is_pressed();
|
|
|
+}
|
|
|
+
|
|
|
bool AnimationTrackEditor::is_function_name_pressed() {
|
|
|
return function_name_toggler->is_pressed();
|
|
|
}
|
|
@@ -7730,6 +7781,14 @@ AnimationTrackEditor::AnimationTrackEditor() {
|
|
|
|
|
|
bottom_hf->add_child(selected_filter);
|
|
|
|
|
|
+ alphabetic_sorting = memnew(Button);
|
|
|
+ alphabetic_sorting->set_flat(true);
|
|
|
+ alphabetic_sorting->connect(SceneStringName(pressed), callable_mp(this, &AnimationTrackEditor::_update_tracks));
|
|
|
+ alphabetic_sorting->set_toggle_mode(true);
|
|
|
+ alphabetic_sorting->set_tooltip_text(TTR("Sort tracks/groups alphabetically.\nIf disabled, tracks are shown in the order they are added and can be reordered using drag-and-drop."));
|
|
|
+
|
|
|
+ bottom_hf->add_child(alphabetic_sorting);
|
|
|
+
|
|
|
view_group = memnew(Button);
|
|
|
view_group->set_flat(true);
|
|
|
view_group->connect(SceneStringName(pressed), callable_mp(this, &AnimationTrackEditor::_view_group_toggle));
|