From 06252449d265584d3bb24c00e273bb884cfd83ac Mon Sep 17 00:00:00 2001 From: Yuri Roubinski Date: Sun, 4 Aug 2019 10:30:24 +0300 Subject: [PATCH] Add a Pause button to the 2D and 3D editor This can be used to decrease CPU/GPU usage if particles or shaders are being displayed in the editor. This closes https://github.com/godotengine/godot-proposals/issues/942. Co-authored-by: Chaosus --- editor/editor_node.cpp | 3 ++ editor/icons/ToolFreeze.svg | 1 + editor/plugins/canvas_item_editor_plugin.cpp | 41 +++++++++++++++++- editor/plugins/canvas_item_editor_plugin.h | 10 +++++ editor/plugins/node_3d_editor_plugin.cpp | 44 +++++++++++++++++++- editor/plugins/node_3d_editor_plugin.h | 9 ++++ 6 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 editor/icons/ToolFreeze.svg diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4cc7c91d38a8..0f4983fdfcb7 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -6704,6 +6704,9 @@ EditorNode::EditorNode() { preview_gen = memnew(AudioStreamPreviewGenerator); add_child(preview_gen); + + ED_SHORTCUT("editor/editor_timeline_pause", TTR("Pause Timeline"), KEY_PAUSE); + //plugin stuff add_editor_plugin(memnew(DebuggerEditorPlugin(this, debug_menu))); diff --git a/editor/icons/ToolFreeze.svg b/editor/icons/ToolFreeze.svg new file mode 100644 index 000000000000..77a0e4210409 --- /dev/null +++ b/editor/icons/ToolFreeze.svg @@ -0,0 +1 @@ + diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index d4e06aa9caf9..4f54620a2cda 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -4213,6 +4213,10 @@ void CanvasItemEditor::_notification(int p_what) { zoom_minus->set_icon(get_theme_icon("ZoomLess", "EditorIcons")); zoom_plus->set_icon(get_theme_icon("ZoomMore", "EditorIcons")); + // Use a different icon to avoid confusion with the project "pause" icon. + pause_button->set_icon(get_theme_icon("ToolFreeze", "EditorIcons")); + pause_button->set_tooltip(TTR("Pause the scene processing such as particles and shaders. This can be used to decrease CPU and GPU usage while in the editor.")); + presets_menu->set_icon(get_theme_icon("ControlLayout", "EditorIcons")); PopupMenu *p = presets_menu->get_popup(); @@ -5401,6 +5405,14 @@ void CanvasItemEditor::_focus_selection(int p_op) { } } +void CanvasItemEditor::_timeline_pause_button_toggled(bool pressed) { + if (pressed) { + Engine::get_singleton()->set_time_scale(0.0); + } else { + Engine::get_singleton()->set_time_scale(1.0); + } +} + void CanvasItemEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_override_camera_button", "game_running"), &CanvasItemEditor::_update_override_camera_button); ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data); @@ -5410,6 +5422,8 @@ void CanvasItemEditor::_bind_methods() { ClassDB::bind_method("_reset_create_position", &CanvasItemEditor::_reset_create_position); ClassDB::bind_method(D_METHOD("set_state"), &CanvasItemEditor::set_state); ClassDB::bind_method(D_METHOD("update_viewport"), &CanvasItemEditor::update_viewport); + ClassDB::bind_method("_timeline_pause_button_toggled", &CanvasItemEditor::_timeline_pause_button_toggled); + ClassDB::bind_method(D_METHOD("set_pause_button_pressed", "pressed"), &CanvasItemEditor::set_pause_button_pressed); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); ADD_SIGNAL(MethodInfo("item_group_status_changed")); @@ -5658,6 +5672,10 @@ VSplitContainer *CanvasItemEditor::get_bottom_split() { return bottom_split; } +void CanvasItemEditor::set_pause_button_pressed(bool p_pressed) { + pause_button->set_pressed(p_pressed); +} + void CanvasItemEditor::focus_selection() { _focus_selection(VIEW_CENTER_TO_SELECTION); } @@ -5735,8 +5753,11 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { editor->call_deferred("connect", "play_pressed", Callable(this, "_update_override_camera_button"), make_binds(true)); editor->call_deferred("connect", "stop_pressed", Callable(this, "_update_override_camera_button"), make_binds(false)); + main_hb = memnew(HBoxContainer); + add_child(main_hb); + hb = memnew(HBoxContainer); - add_child(hb); + main_hb->add_child(hb); hb->set_anchors_and_offsets_preset(Control::PRESET_WIDE); bottom_split = memnew(VSplitContainer); @@ -6081,6 +6102,19 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { animation_hb->add_child(memnew(VSeparator)); animation_hb->hide(); + main_hb->add_spacer(); + + extra_hb = memnew(HBoxContainer); + main_hb->add_child(extra_hb); + + pause_button = memnew(Button); + extra_hb->add_child(pause_button); + pause_button->set_flat(true); + pause_button->set_toggle_mode(true); + pause_button->set_focus_mode(FOCUS_NONE); + pause_button->set_shortcut(ED_GET_SHORTCUT("editor/editor_timeline_pause")); + pause_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_timeline_pause_button_toggled)); + key_loc_button = memnew(Button); key_loc_button->set_toggle_mode(true); key_loc_button->set_flat(true); @@ -6204,6 +6238,11 @@ void CanvasItemEditorPlugin::set_state(const Dictionary &p_state) { canvas_item_editor->set_state(p_state); } +void CanvasItemEditorPlugin::selected_notify() { + // Toggle pause. + canvas_item_editor->set_pause_button_pressed(Engine::get_singleton()->get_time_scale() <= CMP_EPSILON); +} + CanvasItemEditorPlugin::CanvasItemEditorPlugin(EditorNode *p_node) { editor = p_node; canvas_item_editor = memnew(CanvasItemEditor(editor)); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 62a9b1e1629c..e54183a358e2 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -231,12 +231,17 @@ class CanvasItemEditor : public VBoxContainer { HScrollBar *h_scroll; VScrollBar *v_scroll; + + HBoxContainer *main_hb; HBoxContainer *hb; + HBoxContainer *extra_hb; Button *zoom_minus; Button *zoom_reset; Button *zoom_plus; + Button *pause_button; + Map popup_temporarily_timers; Label *warning_child_of_container; @@ -447,6 +452,8 @@ class CanvasItemEditor : public VBoxContainer { void _node_created(Node *p_node); void _reset_create_position(); + void _timeline_pause_button_toggled(bool pressed); + UndoRedo *undo_redo; bool _build_bones_list(Node *p_node); bool _get_bone_shape(Vector *shape, Vector *outline_shape, Map::Element *bone); @@ -644,6 +651,8 @@ class CanvasItemEditor : public VBoxContainer { void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; } void edit(CanvasItem *p_canvas_item); + void set_pause_button_pressed(bool p_pressed); + void focus_selection(); bool is_anchors_mode_enabled() { return anchors_mode; }; @@ -665,6 +674,7 @@ class CanvasItemEditorPlugin : public EditorPlugin { virtual void make_visible(bool p_visible) override; virtual Dictionary get_state() const override; virtual void set_state(const Dictionary &p_state) override; + virtual void selected_notify() override; CanvasItemEditor *get_canvas_item_editor() { return canvas_item_editor; } diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index fccc042a0253..feb645034dca 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -4986,6 +4986,14 @@ void Node3DEditor::_menu_item_toggled(bool pressed, int p_option) { } } +void Node3DEditor::_timeline_pause_button_toggled(bool pressed) { + if (pressed) { + Engine::get_singleton()->set_time_scale(0.0); + } else { + Engine::get_singleton()->set_time_scale(1.0); + } +} + void Node3DEditor::_menu_gizmo_toggled(int p_option) { const int idx = gizmos_menu->get_item_index(p_option); gizmos_menu->toggle_item_multistate(idx); @@ -6218,6 +6226,10 @@ void Node3DEditor::_notification(int p_what) { tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon("Group", "EditorIcons")); tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon("Ungroup", "EditorIcons")); + // Use a different icon to avoid confusion with the project "pause" icon. + pause_button->set_icon(get_theme_icon("ToolFreeze", "EditorIcons")); + pause_button->set_tooltip(TTR("Pause the scene processing such as particles and shaders. This can be used to decrease CPU and GPU usage while in the editor.")); + tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon("Object", "EditorIcons")); tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon("Snap", "EditorIcons")); tool_option_button[Node3DEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon("Camera3D", "EditorIcons")); @@ -6272,6 +6284,9 @@ void Node3DEditor::_notification(int p_what) { tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon("Group", "EditorIcons")); tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon("Ungroup", "EditorIcons")); + // Use a different icon to avoid confusion with the project "pause" icon. + pause_button->set_icon(get_theme_icon("ToolFreeze", "EditorIcons")); + tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon("Object", "EditorIcons")); tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon("Snap", "EditorIcons")); @@ -6465,6 +6480,8 @@ void Node3DEditor::_bind_methods() { ClassDB::bind_method("_get_editor_data", &Node3DEditor::_get_editor_data); ClassDB::bind_method("_request_gizmo", &Node3DEditor::_request_gizmo); ClassDB::bind_method("_refresh_menu_icons", &Node3DEditor::_refresh_menu_icons); + ClassDB::bind_method("_timeline_pause_button_toggled", &Node3DEditor::_timeline_pause_button_toggled); + ClassDB::bind_method("set_pause_button_pressed", &Node3DEditor::set_pause_button_pressed); ADD_SIGNAL(MethodInfo("transform_key_request")); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); @@ -6618,6 +6635,10 @@ void Node3DEditor::_sun_direction_input(const Ref &p_event) { } } +void Node3DEditor::set_pause_button_pressed(bool p_pressed) { + pause_button->set_pressed(p_pressed); +} + Node3DEditor::Node3DEditor(EditorNode *p_editor) { gizmo.visible = true; gizmo.scale = 1.0; @@ -6638,8 +6659,11 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { camera_override_viewport_id = 0; + main_hbc_menu = memnew(HBoxContainer); + vbc->add_child(main_hbc_menu); + hbc_menu = memnew(HBoxContainer); - vbc->add_child(hbc_menu); + main_hbc_menu->add_child(hbc_menu); Vector button_binds; button_binds.resize(1); @@ -6823,6 +6847,19 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { view_menu->set_shortcut_context(this); hbc_menu->add_child(view_menu); + main_hbc_menu->add_spacer(); + + extra_hbc_menu = memnew(HBoxContainer); + main_hbc_menu->add_child(extra_hbc_menu); + + pause_button = memnew(Button); + extra_hbc_menu->add_child(pause_button); + pause_button->set_flat(true); + pause_button->set_toggle_mode(true); + pause_button->set_focus_mode(FOCUS_NONE); + pause_button->set_shortcut(ED_GET_SHORTCUT("editor/editor_timeline_pause")); + pause_button->connect("toggled", callable_mp(this, &Node3DEditor::_timeline_pause_button_toggled)); + p = view_menu->get_popup(); accept = memnew(AcceptDialog); @@ -7235,6 +7272,11 @@ float Node3DEditor::get_scale_snap() const { return snap_value; } +void Node3DEditorPlugin::selected_notify() { + // Toggle pause. + spatial_editor->set_pause_button_pressed(Engine::get_singleton()->get_time_scale() <= CMP_EPSILON); +} + void Node3DEditorPlugin::_bind_methods() { ClassDB::bind_method("snap_cursor_to_plane", &Node3DEditorPlugin::snap_cursor_to_plane); } diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index ff4a941b06cc..1691b20b56c1 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -676,6 +676,10 @@ class Node3DEditor : public VBoxContainer { PopupMenu *gizmos_menu; MenuButton *view_menu; + Button *lock_button; + Button *unlock_button; + Button *pause_button; + AcceptDialog *accept; ConfirmationDialog *snap_dialog; @@ -707,8 +711,11 @@ class Node3DEditor : public VBoxContainer { void _menu_gizmo_toggled(int p_option); void _update_camera_override_button(bool p_game_running); void _update_camera_override_viewport(Object *p_viewport); + void _timeline_pause_button_toggled(bool pressed); + HBoxContainer *main_hbc_menu; HBoxContainer *hbc_menu; + HBoxContainer *extra_hbc_menu; void _generate_selection_boxes(); UndoRedo *undo_redo; @@ -875,6 +882,7 @@ class Node3DEditor : public VBoxContainer { void edit(Node3D *p_spatial); void clear(); + void set_pause_button_pressed(bool p_pressed); Node3DEditor(EditorNode *p_editor); ~Node3DEditor(); @@ -898,6 +906,7 @@ class Node3DEditorPlugin : public EditorPlugin { virtual void make_visible(bool p_visible) override; virtual void edit(Object *p_object) override; virtual bool handles(Object *p_object) const override; + virtual void selected_notify() override; virtual Dictionary get_state() const override; virtual void set_state(const Dictionary &p_state) override;