浏览代码

Merge pull request #105518 from syntaxerror247/fixed-panel

Embed TouchActionsPanel directly into the Android editor UI
Thaddeus Crews 4 月之前
父节点
当前提交
8868c7a329

+ 4 - 4
doc/classes/EditorSettings.xml

@@ -1105,10 +1105,6 @@
 			If [code]true[/code], enable two finger pan and scale gestures on touchscreen devices.
 			If [code]true[/code], enable two finger pan and scale gestures on touchscreen devices.
 			[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.
 			[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.
 		</member>
 		</member>
-		<member name="interface/touchscreen/enable_touch_actions_panel" type="bool" setter="" getter="">
-			If [code]true[/code], enables the TouchActionsPanel to provide easy access to keyboard shortcuts on touchscreen devices.
-			[b]Note:[/b] Only available in the Android editor.
-		</member>
 		<member name="interface/touchscreen/increase_scrollbar_touch_area" type="bool" setter="" getter="">
 		<member name="interface/touchscreen/increase_scrollbar_touch_area" type="bool" setter="" getter="">
 			If [code]true[/code], increases the scrollbar touch area to improve usability on touchscreen devices.
 			If [code]true[/code], increases the scrollbar touch area to improve usability on touchscreen devices.
 			[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.
 			[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.
@@ -1117,6 +1113,10 @@
 			Specify the multiplier to apply to the scale for the editor gizmo handles to improve usability on touchscreen devices.
 			Specify the multiplier to apply to the scale for the editor gizmo handles to improve usability on touchscreen devices.
 			[b]Note:[/b] Defaults to [code]1[/code] on non-touchscreen devices.
 			[b]Note:[/b] Defaults to [code]1[/code] on non-touchscreen devices.
 		</member>
 		</member>
+		<member name="interface/touchscreen/touch_actions_panel" type="int" setter="" getter="">
+			A touch-friendly panel that provides easy access to common actions such as save, delete, undo, and redo without requiring a keyboard.
+			[b]Note:[/b] Only available in the Android and XR editor.
+		</member>
 		<member name="network/connection/check_for_updates" type="int" setter="" getter="">
 		<member name="network/connection/check_for_updates" type="int" setter="" getter="">
 			Specifies how the engine should check for updates.
 			Specifies how the engine should check for updates.
 			- [b]Disable Update Checks[/b] will block the engine from checking updates (see also [member network/connection/network_mode]).
 			- [b]Disable Update Checks[/b] will block the engine from checking updates (see also [member network/connection/network_mode]).

+ 46 - 8
editor/editor_node.cpp

@@ -940,6 +940,11 @@ void EditorNode::_notification(int p_what) {
 			if (EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme/highlighting")) {
 			if (EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme/highlighting")) {
 				EditorHelpHighlighter::get_singleton()->reset_cache();
 				EditorHelpHighlighter::get_singleton()->reset_cache();
 			}
 			}
+#endif
+#ifdef ANDROID_ENABLED
+			if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/touch_actions_panel")) {
+				_touch_actions_panel_mode_changed();
+			}
 #endif
 #endif
 		} break;
 		} break;
 	}
 	}
@@ -7063,6 +7068,34 @@ void EditorNode::set_unfocused_low_processor_usage_mode_enabled(bool p_enabled)
 	unfocused_low_processor_usage_mode_enabled = p_enabled;
 	unfocused_low_processor_usage_mode_enabled = p_enabled;
 }
 }
 
 
+#ifdef ANDROID_ENABLED
+void EditorNode::_touch_actions_panel_mode_changed() {
+	int panel_mode = EDITOR_GET("interface/touchscreen/touch_actions_panel");
+	switch (panel_mode) {
+		case 1:
+			if (touch_actions_panel != nullptr) {
+				touch_actions_panel->queue_free();
+			}
+			touch_actions_panel = memnew(TouchActionsPanel);
+			main_hbox->call_deferred("add_child", touch_actions_panel);
+			break;
+		case 2:
+			if (touch_actions_panel != nullptr) {
+				touch_actions_panel->queue_free();
+			}
+			touch_actions_panel = memnew(TouchActionsPanel);
+			call_deferred("add_child", touch_actions_panel);
+			break;
+		case 0:
+			if (touch_actions_panel != nullptr) {
+				touch_actions_panel->queue_free();
+				touch_actions_panel = nullptr;
+			}
+			break;
+	}
+}
+#endif
+
 EditorNode::EditorNode() {
 EditorNode::EditorNode() {
 	DEV_ASSERT(!singleton);
 	DEV_ASSERT(!singleton);
 	singleton = this;
 	singleton = this;
@@ -7368,7 +7401,20 @@ EditorNode::EditorNode() {
 	gui_base->set_end(Point2(0, 0));
 	gui_base->set_end(Point2(0, 0));
 
 
 	main_vbox = memnew(VBoxContainer);
 	main_vbox = memnew(VBoxContainer);
+
+#ifdef ANDROID_ENABLED
+	main_hbox = memnew(HBoxContainer);
+	main_hbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
+
+	main_hbox->add_child(main_vbox);
+	main_vbox->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+	_touch_actions_panel_mode_changed();
+
+	gui_base->add_child(main_hbox);
+#else
 	gui_base->add_child(main_vbox);
 	gui_base->add_child(main_vbox);
+#endif
 
 
 	title_bar = memnew(EditorTitleBar);
 	title_bar = memnew(EditorTitleBar);
 	main_vbox->add_child(title_bar);
 	main_vbox->add_child(title_bar);
@@ -7952,14 +7998,6 @@ EditorNode::EditorNode() {
 
 
 	_update_layouts_menu();
 	_update_layouts_menu();
 
 
-#ifdef ANDROID_ENABLED
-	// Add TouchActionsPanel node.
-	bool is_enabled = EDITOR_GET("interface/touchscreen/enable_touch_actions_panel");
-	if (is_enabled) {
-		add_child(memnew(TouchActionsPanel));
-	}
-#endif
-
 	// Bottom panels.
 	// Bottom panels.
 
 
 	bottom_panel = memnew(EditorBottomPanel);
 	bottom_panel = memnew(EditorBottomPanel);

+ 11 - 0
editor/editor_node.h

@@ -99,6 +99,11 @@ class ProjectSettingsEditor;
 class SceneImportSettingsDialog;
 class SceneImportSettingsDialog;
 class ProjectUpgradeTool;
 class ProjectUpgradeTool;
 
 
+#ifdef ANDROID_ENABLED
+class HBoxContainer;
+class TouchActionsPanel;
+#endif
+
 struct EditorProgress {
 struct EditorProgress {
 	String task;
 	String task;
 	bool force_background = false;
 	bool force_background = false;
@@ -276,6 +281,12 @@ private:
 	VBoxContainer *main_vbox = nullptr;
 	VBoxContainer *main_vbox = nullptr;
 	OptionButton *renderer = nullptr;
 	OptionButton *renderer = nullptr;
 
 
+#ifdef ANDROID_ENABLED
+	HBoxContainer *main_hbox = nullptr; // Only created on Android for TouchActionsPanel.
+	TouchActionsPanel *touch_actions_panel = nullptr;
+	void _touch_actions_panel_mode_changed();
+#endif
+
 	ConfirmationDialog *video_restart_dialog = nullptr;
 	ConfirmationDialog *video_restart_dialog = nullptr;
 
 
 	int renderer_current = 0;
 	int renderer_current = 0;

+ 4 - 4
editor/editor_settings.cpp

@@ -584,10 +584,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 	EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/touchscreen/scale_gizmo_handles", has_touchscreen_ui ? 3 : 1, "1,5,1")
 	EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/touchscreen/scale_gizmo_handles", has_touchscreen_ui ? 3 : 1, "1,5,1")
 	set_restart_if_changed("interface/touchscreen/scale_gizmo_handles", true);
 	set_restart_if_changed("interface/touchscreen/scale_gizmo_handles", true);
 
 
-	// Only available in the Android editor.
-	EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/touchscreen/enable_touch_actions_panel", true, "")
-	set_restart_if_changed("interface/touchscreen/enable_touch_actions_panel", true);
-
 	// Disable some touchscreen settings by default for the XR Editor.
 	// Disable some touchscreen settings by default for the XR Editor.
 	bool is_native_touchscreen = has_touchscreen_ui && !OS::get_singleton()->has_feature("xr_editor");
 	bool is_native_touchscreen = has_touchscreen_ui && !OS::get_singleton()->has_feature("xr_editor");
 	EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/touchscreen/enable_long_press_as_right_click", is_native_touchscreen, "")
 	EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/touchscreen/enable_long_press_as_right_click", is_native_touchscreen, "")
@@ -595,6 +591,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 	EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/touchscreen/increase_scrollbar_touch_area", is_native_touchscreen, "")
 	EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/touchscreen/increase_scrollbar_touch_area", is_native_touchscreen, "")
 	set_restart_if_changed("interface/touchscreen/increase_scrollbar_touch_area", true);
 	set_restart_if_changed("interface/touchscreen/increase_scrollbar_touch_area", true);
 
 
+	// Only available in the Android editor.
+	String touch_actions_panel_hints = "Disabled:0,Embedded Panel:1,Floating Panel:2";
+	EDITOR_SETTING_BASIC(Variant::INT, PROPERTY_HINT_ENUM, "interface/touchscreen/touch_actions_panel", 1, touch_actions_panel_hints)
+
 	// Scene tabs
 	// Scene tabs
 	EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/scene_tabs/display_close_button", 1, "Never,If Tab Active,Always"); // TabBar::CloseButtonDisplayPolicy
 	EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/scene_tabs/display_close_button", 1, "Never,If Tab Active,Always"); // TabBar::CloseButtonDisplayPolicy
 	_initial_set("interface/scene_tabs/show_thumbnail_on_hover", true);
 	_initial_set("interface/scene_tabs/show_thumbnail_on_hover", true);

+ 84 - 36
editor/gui/touch_actions_panel.cpp

@@ -44,14 +44,25 @@ void TouchActionsPanel::_notification(int p_what) {
 		case NOTIFICATION_ENTER_TREE: {
 		case NOTIFICATION_ENTER_TREE: {
 			DisplayServer::get_singleton()->set_hardware_keyboard_connection_change_callback(callable_mp(this, &TouchActionsPanel::_hardware_keyboard_connected));
 			DisplayServer::get_singleton()->set_hardware_keyboard_connection_change_callback(callable_mp(this, &TouchActionsPanel::_hardware_keyboard_connected));
 			_hardware_keyboard_connected(DisplayServer::get_singleton()->has_hardware_keyboard());
 			_hardware_keyboard_connected(DisplayServer::get_singleton()->has_hardware_keyboard());
+			if (!is_floating) {
+				get_parent()->move_child(this, embedded_panel_index);
+			}
 		} break;
 		} break;
 		case NOTIFICATION_VISIBILITY_CHANGED: {
 		case NOTIFICATION_VISIBILITY_CHANGED: {
 			set_process_input(is_visible_in_tree());
 			set_process_input(is_visible_in_tree());
 		} break;
 		} break;
 		case NOTIFICATION_THEME_CHANGED: {
 		case NOTIFICATION_THEME_CHANGED: {
-			drag_handle->set_texture(get_editor_theme_icon(SNAME("DragHandle")));
-			layout_toggle_button->set_button_icon(get_editor_theme_icon(SNAME("Orientation")));
-			lock_panel_button->set_button_icon(get_editor_theme_icon(SNAME("Lock")));
+			if (is_floating) {
+				drag_handle->set_texture(get_editor_theme_icon(SNAME("DragHandle")));
+				layout_toggle_button->set_button_icon(get_editor_theme_icon(SNAME("Orientation")));
+				lock_panel_button->set_button_icon(get_editor_theme_icon(SNAME("Lock")));
+			} else {
+				if (embedded_panel_index == 1) {
+					panel_pos_button->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignLeftWide")));
+				} else {
+					panel_pos_button->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignRightWide")));
+				}
+			}
 			save_button->set_button_icon(get_editor_theme_icon(SNAME("Save")));
 			save_button->set_button_icon(get_editor_theme_icon(SNAME("Save")));
 			delete_button->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
 			delete_button->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
 			undo_button->set_button_icon(get_editor_theme_icon(SNAME("UndoRedo")));
 			undo_button->set_button_icon(get_editor_theme_icon(SNAME("UndoRedo")));
@@ -154,7 +165,7 @@ void TouchActionsPanel::_add_new_modifier_button(Modifier p_modifier) {
 }
 }
 
 
 void TouchActionsPanel::_on_drag_handle_gui_input(const Ref<InputEvent> &p_event) {
 void TouchActionsPanel::_on_drag_handle_gui_input(const Ref<InputEvent> &p_event) {
-	if (lock_panel_position) {
+	if (locked_panel) {
 		return;
 		return;
 	}
 	}
 	Ref<InputEventMouseButton> mouse_button_event = p_event;
 	Ref<InputEventMouseButton> mouse_button_event = p_event;
@@ -191,50 +202,87 @@ void TouchActionsPanel::_switch_layout() {
 }
 }
 
 
 void TouchActionsPanel::_lock_panel_toggled(bool p_pressed) {
 void TouchActionsPanel::_lock_panel_toggled(bool p_pressed) {
-	lock_panel_position = p_pressed;
-	layout_toggle_button->set_disabled(p_pressed);
+	locked_panel = p_pressed;
+	layout_toggle_button->set_visible(!p_pressed);
+	drag_handle->set_visible(!p_pressed);
+	reset_size();
+	queue_redraw();
+}
+
+void TouchActionsPanel::_switch_embedded_panel_side() {
+	if (embedded_panel_index == 0) {
+		embedded_panel_index = 1;
+		panel_pos_button->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignLeftWide")));
+	} else {
+		embedded_panel_index = 0;
+		panel_pos_button->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignRightWide")));
+	}
+	get_parent()->move_child(this, embedded_panel_index); // Parent is a hbox with only two children -- TouchActionsPanel and main Editor UI.
+	EditorSettings::get_singleton()->set("_touch_actions_panel_embed_index", embedded_panel_index);
+	EditorSettings::get_singleton()->save();
 }
 }
 
 
 TouchActionsPanel::TouchActionsPanel() {
 TouchActionsPanel::TouchActionsPanel() {
-	Ref<StyleBoxFlat> panel_style;
-	panel_style.instantiate();
-	panel_style->set_bg_color(Color(0.1, 0.1, 0.1, 1));
-	panel_style->set_border_color(Color(0.3, 0.3, 0.3, 1));
-	panel_style->set_border_width_all(3);
-	panel_style->set_corner_radius_all(10);
-	panel_style->set_content_margin_all(12);
-	add_theme_style_override(SceneStringName(panel), panel_style);
+	int panel_mode = EDITOR_GET("interface/touchscreen/touch_actions_panel");
+	is_floating = panel_mode == 2;
+
+	if (is_floating) {
+		Ref<StyleBoxFlat> panel_style;
+		panel_style.instantiate();
+		panel_style->set_bg_color(Color(0.1, 0.1, 0.1, 1));
+		panel_style->set_border_color(Color(0.3, 0.3, 0.3, 1));
+		panel_style->set_border_width_all(3);
+		panel_style->set_corner_radius_all(10);
+		panel_style->set_content_margin_all(12);
+		add_theme_style_override(SceneStringName(panel), panel_style);
 
 
-	set_position(EDITOR_DEF("_touch_actions_panel_position", Point2(480, 480))); // Dropped it here for no good reason — users can move it anyway.
+		set_position(EDITOR_DEF("_touch_actions_panel_position", Point2(480, 480))); // Dropped it here for no good reason — users can move it anyway.
+	}
 
 
 	box = memnew(BoxContainer);
 	box = memnew(BoxContainer);
 	box->set_alignment(BoxContainer::ALIGNMENT_CENTER);
 	box->set_alignment(BoxContainer::ALIGNMENT_CENTER);
 	box->add_theme_constant_override("separation", 20);
 	box->add_theme_constant_override("separation", 20);
-	box->set_vertical(EDITOR_DEF("_touch_actions_panel_vertical_layout", false));
+	if (is_floating) {
+		box->set_vertical(EDITOR_DEF("_touch_actions_panel_vertical_layout", false));
+	} else {
+		box->set_vertical(true);
+	}
 	add_child(box);
 	add_child(box);
 
 
-	drag_handle = memnew(TextureRect);
-	drag_handle->set_custom_minimum_size(Size2(40, 40));
-	drag_handle->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
-	drag_handle->connect(SceneStringName(gui_input), callable_mp(this, &TouchActionsPanel::_on_drag_handle_gui_input));
-	box->add_child(drag_handle);
+	if (is_floating) {
+		drag_handle = memnew(TextureRect);
+		drag_handle->set_custom_minimum_size(Size2(40, 40));
+		drag_handle->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
+		drag_handle->connect(SceneStringName(gui_input), callable_mp(this, &TouchActionsPanel::_on_drag_handle_gui_input));
+		box->add_child(drag_handle);
+
+		layout_toggle_button = memnew(Button);
+		layout_toggle_button->set_theme_type_variation("FlatMenuButton");
+		layout_toggle_button->set_accessibility_name(TTRC("Switch Layout"));
+		layout_toggle_button->set_focus_mode(FOCUS_NONE);
+		layout_toggle_button->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER);
+		layout_toggle_button->connect(SceneStringName(pressed), callable_mp(this, &TouchActionsPanel::_switch_layout));
+		box->add_child(layout_toggle_button);
 
 
-	layout_toggle_button = memnew(Button);
-	layout_toggle_button->set_theme_type_variation("FlatMenuButton");
-	layout_toggle_button->set_accessibility_name(TTRC("Switch Layout"));
-	layout_toggle_button->set_focus_mode(FOCUS_NONE);
-	layout_toggle_button->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER);
-	layout_toggle_button->connect(SceneStringName(pressed), callable_mp(this, &TouchActionsPanel::_switch_layout));
-	box->add_child(layout_toggle_button);
+		lock_panel_button = memnew(Button);
+		lock_panel_button->set_toggle_mode(true);
+		lock_panel_button->set_theme_type_variation("FlatMenuButton");
+		lock_panel_button->set_accessibility_name(TTRC("Lock Panel"));
+		lock_panel_button->set_focus_mode(FOCUS_NONE);
+		lock_panel_button->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER);
+		lock_panel_button->connect(SceneStringName(toggled), callable_mp(this, &TouchActionsPanel::_lock_panel_toggled));
+		box->add_child(lock_panel_button);
+	} else {
+		panel_pos_button = memnew(Button);
+		panel_pos_button->set_theme_type_variation("FlatMenuButton");
+		panel_pos_button->set_accessibility_name(TTRC("Switch Embedded Panel Position"));
+		panel_pos_button->set_focus_mode(FOCUS_NONE);
+		panel_pos_button->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER);
+		panel_pos_button->connect(SceneStringName(pressed), callable_mp(this, &TouchActionsPanel::_switch_embedded_panel_side));
+		box->add_child(panel_pos_button);
 
 
-	lock_panel_button = memnew(Button);
-	lock_panel_button->set_toggle_mode(true);
-	lock_panel_button->set_theme_type_variation("FlatMenuButton");
-	lock_panel_button->set_accessibility_name(TTRC("Lock Panel"));
-	lock_panel_button->set_focus_mode(FOCUS_NONE);
-	lock_panel_button->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER);
-	lock_panel_button->connect(SceneStringName(toggled), callable_mp(this, &TouchActionsPanel::_lock_panel_toggled));
-	box->add_child(lock_panel_button);
+		embedded_panel_index = EDITOR_DEF("_touch_actions_panel_embed_index", 0);
+	}
 
 
 	ColorRect *separator = memnew(ColorRect);
 	ColorRect *separator = memnew(ColorRect);
 	separator->set_color(Color(0.5, 0.5, 0.5));
 	separator->set_color(Color(0.5, 0.5, 0.5));

+ 7 - 2
editor/gui/touch_actions_panel.h

@@ -52,8 +52,9 @@ private:
 	TextureRect *drag_handle = nullptr;
 	TextureRect *drag_handle = nullptr;
 	Button *layout_toggle_button = nullptr;
 	Button *layout_toggle_button = nullptr;
 	Button *lock_panel_button = nullptr;
 	Button *lock_panel_button = nullptr;
+	Button *panel_pos_button = nullptr;
 
 
-	bool lock_panel_position = false;
+	bool locked_panel = false;
 	bool dragging = false;
 	bool dragging = false;
 	Vector2 drag_offset;
 	Vector2 drag_offset;
 
 
@@ -67,6 +68,9 @@ private:
 	bool shift_btn_pressed = false;
 	bool shift_btn_pressed = false;
 	bool alt_btn_pressed = false;
 	bool alt_btn_pressed = false;
 
 
+	bool is_floating = false; // Embedded panel mode is default.
+	int embedded_panel_index = 0;
+
 	void _notification(int p_what);
 	void _notification(int p_what);
 	virtual void input(const Ref<InputEvent> &event) override;
 	virtual void input(const Ref<InputEvent> &event) override;
 
 
@@ -75,8 +79,9 @@ private:
 	void _on_drag_handle_gui_input(const Ref<InputEvent> &p_event);
 	void _on_drag_handle_gui_input(const Ref<InputEvent> &p_event);
 	void _switch_layout();
 	void _switch_layout();
 	void _lock_panel_toggled(bool p_pressed);
 	void _lock_panel_toggled(bool p_pressed);
-	Button *_add_new_action_button(const String &p_shortcut, const String &p_name, Key p_keycode = Key::NONE);
+	void _switch_embedded_panel_side();
 
 
+	Button *_add_new_action_button(const String &p_shortcut, const String &p_name, Key p_keycode = Key::NONE);
 	void _add_new_modifier_button(Modifier p_modifier);
 	void _add_new_modifier_button(Modifier p_modifier);
 	void _on_modifier_button_toggled(bool p_pressed, int p_modifier);
 	void _on_modifier_button_toggled(bool p_pressed, int p_modifier);