Skip to content

Commit

Permalink
Add "Game" editor for better runtime debugging
Browse files Browse the repository at this point in the history
  • Loading branch information
YeldhamDev committed Sep 22, 2024
1 parent e4e024a commit 39a0360
Show file tree
Hide file tree
Showing 38 changed files with 1,343 additions and 81 deletions.
6 changes: 5 additions & 1 deletion core/config/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ void Engine::set_time_scale(double p_scale) {
}

double Engine::get_time_scale() const {
return _time_scale;
return suspended ? 0 : _time_scale;
}

Dictionary Engine::get_version_info() const {
Expand Down Expand Up @@ -384,6 +384,10 @@ bool Engine::notify_frame_server_synced() {
return server_syncs > SERVER_SYNC_FRAME_COUNT_WARNING;
}

void Engine::set_suspend(bool p_enabled) {
suspended = p_enabled;
}

Engine::Engine() {
singleton = this;
}
Expand Down
4 changes: 4 additions & 0 deletions core/config/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ class Engine {
int server_syncs = 0;
bool frame_server_synced = false;

bool suspended = false;

public:
static Engine *get_singleton();

Expand Down Expand Up @@ -188,6 +190,8 @@ class Engine {
void increment_frames_drawn();
bool notify_frame_server_synced();

void set_suspend(bool p_enabled);

Engine();
virtual ~Engine();
};
Expand Down
21 changes: 21 additions & 0 deletions core/input/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ Input *Input::get_singleton() {

void Input::set_mouse_mode(MouseMode p_mode) {
ERR_FAIL_INDEX((int)p_mode, 5);

if (suspended) {
suspended_mouse_mode = p_mode;
return;
}

set_mouse_mode_func(p_mode);
}

Expand Down Expand Up @@ -1662,6 +1668,21 @@ int Input::get_unused_joy_id() {
return -1;
}

void Input::set_suspend(bool p_enabled) {
if (p_enabled == suspended) {
return;
}

suspended = p_enabled;

if (p_enabled) {
suspended_mouse_mode = get_mouse_mode_func();
set_mouse_mode_func(MOUSE_MODE_VISIBLE);
} else {
set_mouse_mode_func(suspended_mouse_mode);
}
}

Input::Input() {
singleton = this;

Expand Down
5 changes: 5 additions & 0 deletions core/input/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ class Input : public Object {
int64_t mouse_window = 0;
bool legacy_just_pressed_behavior = false;

bool suspended = false;
MouseMode suspended_mouse_mode = MOUSE_MODE_VISIBLE;

struct ActionState {
uint64_t pressed_physics_frame = UINT64_MAX;
uint64_t pressed_process_frame = UINT64_MAX;
Expand Down Expand Up @@ -380,6 +383,8 @@ class Input : public Object {

void set_event_dispatch_function(EventDispatchFunc p_function);

void set_suspend(bool p_enabled);

Input();
~Input();
};
Expand Down
17 changes: 10 additions & 7 deletions doc/classes/EditorFeatureProfile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,25 +103,28 @@
<constant name="FEATURE_SCRIPT" value="1" enum="Feature">
The Script tab, which contains the script editor and class reference browser. If this feature is disabled, the Script tab won't display.
</constant>
<constant name="FEATURE_ASSET_LIB" value="2" enum="Feature">
<constant name="FEATURE_GAME" value="2" enum="Feature">
The Game tab, which allows embedding the game window and selecting nodes by clicking inside of it. If this feature is disabled, the Game tab won't display.
</constant>
<constant name="FEATURE_ASSET_LIB" value="3" enum="Feature">
The AssetLib tab. If this feature is disabled, the AssetLib tab won't display.
</constant>
<constant name="FEATURE_SCENE_TREE" value="3" enum="Feature">
<constant name="FEATURE_SCENE_TREE" value="4" enum="Feature">
Scene tree editing. If this feature is disabled, the Scene tree dock will still be visible but will be read-only.
</constant>
<constant name="FEATURE_NODE_DOCK" value="4" enum="Feature">
<constant name="FEATURE_NODE_DOCK" value="5" enum="Feature">
The Node dock. If this feature is disabled, signals and groups won't be visible and modifiable from the editor.
</constant>
<constant name="FEATURE_FILESYSTEM_DOCK" value="5" enum="Feature">
<constant name="FEATURE_FILESYSTEM_DOCK" value="6" enum="Feature">
The FileSystem dock. If this feature is disabled, the FileSystem dock won't be visible.
</constant>
<constant name="FEATURE_IMPORT_DOCK" value="6" enum="Feature">
<constant name="FEATURE_IMPORT_DOCK" value="7" enum="Feature">
The Import dock. If this feature is disabled, the Import dock won't be visible.
</constant>
<constant name="FEATURE_HISTORY_DOCK" value="7" enum="Feature">
<constant name="FEATURE_HISTORY_DOCK" value="8" enum="Feature">
The History dock. If this feature is disabled, the History dock won't be visible.
</constant>
<constant name="FEATURE_MAX" value="8" enum="Feature">
<constant name="FEATURE_MAX" value="9" enum="Feature">
Represents the size of the [enum Feature] enum.
</constant>
</constants>
Expand Down
8 changes: 8 additions & 0 deletions editor/debugger/editor_debugger_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ ScriptEditorDebugger *EditorDebuggerNode::_add_debugger() {
node->connect("breakpoint_selected", callable_mp(this, &EditorDebuggerNode::_error_selected).bind(id));
node->connect("clear_execution", callable_mp(this, &EditorDebuggerNode::_clear_execution));
node->connect("breaked", callable_mp(this, &EditorDebuggerNode::_breaked).bind(id));
node->connect("remote_tree_select_requested", callable_mp(this, &EditorDebuggerNode::_remote_tree_select_requested).bind(id));
node->connect("remote_tree_updated", callable_mp(this, &EditorDebuggerNode::_remote_tree_updated).bind(id));
node->connect("remote_object_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_updated).bind(id));
node->connect("remote_object_property_updated", callable_mp(this, &EditorDebuggerNode::_remote_object_property_updated).bind(id));
Expand Down Expand Up @@ -637,6 +638,13 @@ void EditorDebuggerNode::request_remote_tree() {
get_current_debugger()->request_remote_tree();
}

void EditorDebuggerNode::_remote_tree_select_requested(ObjectID p_id, int p_debugger) {
if (p_debugger != tabs->get_current_tab()) {
return;
}
remote_scene_tree->select_node(p_id);
}

void EditorDebuggerNode::_remote_tree_updated(int p_debugger) {
if (p_debugger != tabs->get_current_tab()) {
return;
Expand Down
1 change: 1 addition & 0 deletions editor/debugger/editor_debugger_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class EditorDebuggerNode : public MarginContainer {
void _debugger_stopped(int p_id);
void _debugger_wants_stop(int p_id);
void _debugger_changed(int p_tab);
void _remote_tree_select_requested(ObjectID p_id, int p_debugger);
void _remote_tree_updated(int p_debugger);
void _remote_tree_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button);
void _remote_object_updated(ObjectID p_id, int p_debugger);
Expand Down
23 changes: 22 additions & 1 deletion editor/debugger/editor_debugger_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "editor/editor_string_names.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/scene_tree_dock.h"
#include "editor_debugger_node.h"
#include "scene/debugger/scene_debugger.h"
#include "scene/gui/texture_rect.h"
#include "scene/resources/packed_scene.h"
Expand Down Expand Up @@ -185,7 +186,17 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int
// Select previously selected node.
if (debugger_id == p_debugger) { // Can use remote id.
if (node.id == inspected_object_id) {
if (selection_uncollapse_all) {
selection_uncollapse_all = false;

// Temporarily set to `false`, to allow caching the unfolds.
updating_scene_tree = false;
item->uncollapse_tree();
updating_scene_tree = true;
}

item->select(0);

if (filter_changed) {
scroll_item = item;
}
Expand Down Expand Up @@ -258,14 +269,24 @@ void EditorDebuggerTree::update_scene_tree(const SceneDebuggerTree *p_tree, int
}
}
}
debugger_id = p_debugger; // Needed by hook, could be avoided if every debugger had its own tree
debugger_id = p_debugger; // Needed by hook, could be avoided if every debugger had its own tree.
if (scroll_item) {
callable_mp((Tree *)this, &Tree::scroll_to_item).call_deferred(scroll_item, false);
}
last_filter = filter;
updating_scene_tree = false;
}

void EditorDebuggerTree::select_node(ObjectID p_id) {
// Manually select, as the tree control may be out-of-date for some reason (e.g. not shown yet).
selection_uncollapse_all = true;
inspected_object_id = uint64_t(p_id);
emit_signal(SNAME("object_selected"), inspected_object_id, debugger_id);

// Request a tree refresh.
EditorDebuggerNode::get_singleton()->request_remote_tree();
}

Variant EditorDebuggerTree::get_drag_data(const Point2 &p_point) {
if (get_button_id_at_position(p_point) != -1) {
return Variant();
Expand Down
2 changes: 2 additions & 0 deletions editor/debugger/editor_debugger_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class EditorDebuggerTree : public Tree {
ObjectID inspected_object_id;
int debugger_id = 0;
bool updating_scene_tree = false;
bool selection_uncollapse_all = false;
HashSet<ObjectID> unfold_cache;
PopupMenu *item_menu = nullptr;
EditorFileDialog *file_dialog = nullptr;
Expand Down Expand Up @@ -78,6 +79,7 @@ class EditorDebuggerTree : public Tree {
ObjectID get_selected_object();
int get_current_debugger(); // Would love to have one tree for every debugger.
void update_scene_tree(const SceneDebuggerTree *p_tree, int p_debugger);
void select_node(ObjectID p_id);
EditorDebuggerTree();
};

Expand Down
5 changes: 5 additions & 0 deletions editor/debugger/script_editor_debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,10 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, uint64_t p_thread
} else if (p_msg == "request_quit") {
emit_signal(SNAME("stop_requested"));
_stop_and_notify();
} else if (p_msg == "remote_node_clicked") {
if (!p_data.is_empty()) {
emit_signal(SNAME("remote_tree_select_requested"), p_data[0]);
}
} else if (p_msg == "performance:profile_names") {
Vector<StringName> monitors;
monitors.resize(p_data.size());
Expand Down Expand Up @@ -1765,6 +1769,7 @@ void ScriptEditorDebugger::_bind_methods() {
ADD_SIGNAL(MethodInfo("remote_object_updated", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("remote_object_property_updated", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "property")));
ADD_SIGNAL(MethodInfo("remote_tree_updated"));
ADD_SIGNAL(MethodInfo("remote_tree_select_requested", PropertyInfo(Variant::NODE_PATH, "path")));
ADD_SIGNAL(MethodInfo("output", PropertyInfo(Variant::STRING, "msg"), PropertyInfo(Variant::INT, "level")));
ADD_SIGNAL(MethodInfo("stack_dump", PropertyInfo(Variant::ARRAY, "stack_dump")));
ADD_SIGNAL(MethodInfo("stack_frame_vars", PropertyInfo(Variant::INT, "num_vars")));
Expand Down
4 changes: 4 additions & 0 deletions editor/editor_feature_profile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
const char *EditorFeatureProfile::feature_names[FEATURE_MAX] = {
TTRC("3D Editor"),
TTRC("Script Editor"),
TTRC("Game Editor"),
TTRC("Asset Library"),
TTRC("Scene Tree Editing"),
TTRC("Node Dock"),
Expand All @@ -54,6 +55,7 @@ const char *EditorFeatureProfile::feature_names[FEATURE_MAX] = {
const char *EditorFeatureProfile::feature_descriptions[FEATURE_MAX] = {
TTRC("Allows to view and edit 3D scenes."),
TTRC("Allows to edit scripts using the integrated script editor."),
TTRC("Provides tools for selecting and debugging nodes at runtime."),
TTRC("Provides built-in access to the Asset Library."),
TTRC("Allows editing the node hierarchy in the Scene dock."),
TTRC("Allows to work with signals and groups of the node selected in the Scene dock."),
Expand All @@ -65,6 +67,7 @@ const char *EditorFeatureProfile::feature_descriptions[FEATURE_MAX] = {
const char *EditorFeatureProfile::feature_identifiers[FEATURE_MAX] = {
"3d",
"script",
"game",
"asset_lib",
"scene_tree",
"node_dock",
Expand Down Expand Up @@ -301,6 +304,7 @@ void EditorFeatureProfile::_bind_methods() {

BIND_ENUM_CONSTANT(FEATURE_3D);
BIND_ENUM_CONSTANT(FEATURE_SCRIPT);
BIND_ENUM_CONSTANT(FEATURE_GAME);
BIND_ENUM_CONSTANT(FEATURE_ASSET_LIB);
BIND_ENUM_CONSTANT(FEATURE_SCENE_TREE);
BIND_ENUM_CONSTANT(FEATURE_NODE_DOCK);
Expand Down
1 change: 1 addition & 0 deletions editor/editor_feature_profile.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class EditorFeatureProfile : public RefCounted {
enum Feature {
FEATURE_3D,
FEATURE_SCRIPT,
FEATURE_GAME,
FEATURE_ASSET_LIB,
FEATURE_SCENE_TREE,
FEATURE_NODE_DOCK,
Expand Down
1 change: 1 addition & 0 deletions editor/editor_main_screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class EditorMainScreen : public PanelContainer {
EDITOR_2D = 0,
EDITOR_3D,
EDITOR_SCRIPT,
EDITOR_GAME,
EDITOR_ASSETLIB,
};

Expand Down
12 changes: 10 additions & 2 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
#include "editor/plugins/editor_plugin.h"
#include "editor/plugins/editor_preview_plugins.h"
#include "editor/plugins/editor_resource_conversion_plugin.h"
#include "editor/plugins/game_editor_plugin.h"
#include "editor/plugins/gdextension_export_plugin.h"
#include "editor/plugins/material_editor_plugin.h"
#include "editor/plugins/mesh_library_editor_plugin.h"
Expand Down Expand Up @@ -355,6 +356,8 @@ void EditorNode::shortcut_input(const Ref<InputEvent> &p_event) {
editor_main_screen->select(EditorMainScreen::EDITOR_3D);
} else if (ED_IS_SHORTCUT("editor/editor_script", p_event)) {
editor_main_screen->select(EditorMainScreen::EDITOR_SCRIPT);
} else if (ED_IS_SHORTCUT("editor/editor_game", p_event)) {
editor_main_screen->select(EditorMainScreen::EDITOR_GAME);
} else if (ED_IS_SHORTCUT("editor/editor_help", p_event)) {
emit_signal(SNAME("request_help_search"), "");
} else if (ED_IS_SHORTCUT("editor/editor_assetlib", p_event) && AssetLibraryEditorPlugin::is_available()) {
Expand Down Expand Up @@ -6573,6 +6576,7 @@ void EditorNode::_feature_profile_changed() {

editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_3D, !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_3D));
editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_SCRIPT, !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_SCRIPT));
editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_GAME, !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_GAME));
if (AssetLibraryEditorPlugin::is_available()) {
editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_ASSETLIB, !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_ASSET_LIB));
}
Expand All @@ -6583,6 +6587,7 @@ void EditorNode::_feature_profile_changed() {
editor_dock_manager->set_dock_enabled(history_dock, true);
editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_3D, true);
editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_SCRIPT, true);
editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_GAME, true);
if (AssetLibraryEditorPlugin::is_available()) {
editor_main_screen->set_button_enabled(EditorMainScreen::EDITOR_ASSETLIB, true);
}
Expand Down Expand Up @@ -7713,6 +7718,7 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(CanvasItemEditorPlugin));
add_editor_plugin(memnew(Node3DEditorPlugin));
add_editor_plugin(memnew(ScriptEditorPlugin));
add_editor_plugin(memnew(GameEditorPlugin));

EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor();

Expand Down Expand Up @@ -7895,12 +7901,14 @@ EditorNode::EditorNode() {
ED_SHORTCUT_AND_COMMAND("editor/editor_2d", TTR("Open 2D Editor"), KeyModifierMask::CTRL | Key::F1);
ED_SHORTCUT_AND_COMMAND("editor/editor_3d", TTR("Open 3D Editor"), KeyModifierMask::CTRL | Key::F2);
ED_SHORTCUT_AND_COMMAND("editor/editor_script", TTR("Open Script Editor"), KeyModifierMask::CTRL | Key::F3);
ED_SHORTCUT_AND_COMMAND("editor/editor_assetlib", TTR("Open Asset Library"), KeyModifierMask::CTRL | Key::F4);
ED_SHORTCUT_AND_COMMAND("editor/editor_game", TTR("Open Game Editor"), KeyModifierMask::CTRL | Key::F4);
ED_SHORTCUT_AND_COMMAND("editor/editor_assetlib", TTR("Open Asset Library"), KeyModifierMask::CTRL | Key::F5);

ED_SHORTCUT_OVERRIDE("editor/editor_2d", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_1);
ED_SHORTCUT_OVERRIDE("editor/editor_3d", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_2);
ED_SHORTCUT_OVERRIDE("editor/editor_script", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_3);
ED_SHORTCUT_OVERRIDE("editor/editor_assetlib", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_4);
ED_SHORTCUT_OVERRIDE("editor/editor_game", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_4);
ED_SHORTCUT_OVERRIDE("editor/editor_assetlib", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::KEY_5);

ED_SHORTCUT_AND_COMMAND("editor/editor_next", TTR("Open the next Editor"));
ED_SHORTCUT_AND_COMMAND("editor/editor_prev", TTR("Open the previous Editor"));
Expand Down
1 change: 1 addition & 0 deletions editor/icons/2DNodes.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions editor/icons/Game.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions editor/icons/NextFrame.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 39a0360

Please sign in to comment.