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 Oct 3, 2024
1 parent 5ccbf6e commit 9cfc0fa
Show file tree
Hide file tree
Showing 45 changed files with 1,965 additions and 259 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 freeze_time_scale ? 0 : _time_scale;
}

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

void Engine::set_freeze_time_scale(bool p_frozen) {
freeze_time_scale = p_frozen;
}

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 freeze_time_scale = false;

public:
static Engine *get_singleton();

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

void set_freeze_time_scale(bool p_frozen);

Engine();
virtual ~Engine();
};
Expand Down
80 changes: 80 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 (!active) {
active_mouse_mode = p_mode;
return;
}

set_mouse_mode_func(p_mode);
}

Expand Down Expand Up @@ -252,6 +258,10 @@ Input::VelocityTrack::VelocityTrack() {
bool Input::is_anything_pressed() const {
_THREAD_SAFE_METHOD_

if (!active) {
return false;
}

if (!keys_pressed.is_empty() || !joy_buttons_pressed.is_empty() || !mouse_button_mask.is_empty()) {
return true;
}
Expand All @@ -267,21 +277,41 @@ bool Input::is_anything_pressed() const {

bool Input::is_key_pressed(Key p_keycode) const {
_THREAD_SAFE_METHOD_

if (!active) {
return false;
}

return keys_pressed.has(p_keycode);
}

bool Input::is_physical_key_pressed(Key p_keycode) const {
_THREAD_SAFE_METHOD_

if (!active) {
return false;
}

return physical_keys_pressed.has(p_keycode);
}

bool Input::is_key_label_pressed(Key p_keycode) const {
_THREAD_SAFE_METHOD_

if (!active) {
return false;
}

return key_label_pressed.has(p_keycode);
}

bool Input::is_mouse_button_pressed(MouseButton p_button) const {
_THREAD_SAFE_METHOD_

if (!active) {
return false;
}

return mouse_button_mask.has_flag(mouse_button_to_mask(p_button));
}

Expand All @@ -295,11 +325,21 @@ static JoyButton _combine_device(JoyButton p_value, int p_device) {

bool Input::is_joy_button_pressed(int p_device, JoyButton p_button) const {
_THREAD_SAFE_METHOD_

if (!active) {
return false;
}

return joy_buttons_pressed.has(_combine_device(p_button, p_device));
}

bool Input::is_action_pressed(const StringName &p_action, bool p_exact) const {
ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action));

if (!active) {
return false;
}

HashMap<StringName, ActionState>::ConstIterator E = action_states.find(p_action);
if (!E) {
return false;
Expand All @@ -310,6 +350,11 @@ bool Input::is_action_pressed(const StringName &p_action, bool p_exact) const {

bool Input::is_action_just_pressed(const StringName &p_action, bool p_exact) const {
ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action));

if (!active) {
return false;
}

HashMap<StringName, ActionState>::ConstIterator E = action_states.find(p_action);
if (!E) {
return false;
Expand All @@ -331,6 +376,11 @@ bool Input::is_action_just_pressed(const StringName &p_action, bool p_exact) con

bool Input::is_action_just_released(const StringName &p_action, bool p_exact) const {
ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action));

if (!active) {
return false;
}

HashMap<StringName, ActionState>::ConstIterator E = action_states.find(p_action);
if (!E) {
return false;
Expand All @@ -352,6 +402,11 @@ bool Input::is_action_just_released(const StringName &p_action, bool p_exact) co

float Input::get_action_strength(const StringName &p_action, bool p_exact) const {
ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), 0.0, InputMap::get_singleton()->suggest_actions(p_action));

if (!active) {
return 0.0f;
}

HashMap<StringName, ActionState>::ConstIterator E = action_states.find(p_action);
if (!E) {
return 0.0f;
Expand All @@ -366,6 +421,11 @@ float Input::get_action_strength(const StringName &p_action, bool p_exact) const

float Input::get_action_raw_strength(const StringName &p_action, bool p_exact) const {
ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), 0.0, InputMap::get_singleton()->suggest_actions(p_action));

if (!active) {
return 0.0f;
}

HashMap<StringName, ActionState>::ConstIterator E = action_states.find(p_action);
if (!E) {
return 0.0f;
Expand Down Expand Up @@ -410,6 +470,11 @@ Vector2 Input::get_vector(const StringName &p_negative_x, const StringName &p_po

float Input::get_joy_axis(int p_device, JoyAxis p_axis) const {
_THREAD_SAFE_METHOD_

if (!active) {
return 0;
}

JoyAxis c = _combine_device(p_axis, p_device);
if (_joy_axis.has(c)) {
return _joy_axis[c];
Expand Down Expand Up @@ -1662,6 +1727,21 @@ int Input::get_unused_joy_id() {
return -1;
}

void Input::set_active(bool p_active) {
if (p_active == active) {
return;
}

active = p_active;

if (p_active) {
set_mouse_mode_func(active_mouse_mode);
} else {
active_mouse_mode = get_mouse_mode_func();
set_mouse_mode_func(MOUSE_MODE_VISIBLE);
}
}

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 active = true;
MouseMode active_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_active(bool p_active);

Input();
~Input();
};
Expand Down
5 changes: 4 additions & 1 deletion doc/classes/EditorFeatureProfile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,10 @@
<constant name="FEATURE_HISTORY_DOCK" value="7" 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_GAME" value="8" 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_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
8 changes: 3 additions & 5 deletions editor/debugger/editor_debugger_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,8 @@ class EditorDebuggerNode : public MarginContainer {
public:
enum CameraOverride {
OVERRIDE_NONE,
OVERRIDE_2D,
OVERRIDE_3D_1, // 3D Viewport 1
OVERRIDE_3D_2, // 3D Viewport 2
OVERRIDE_3D_3, // 3D Viewport 3
OVERRIDE_3D_4 // 3D Viewport 4
OVERRIDE_INGAME,
OVERRIDE_EDITORS
};

private:
Expand Down Expand Up @@ -132,6 +129,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
Loading

0 comments on commit 9cfc0fa

Please sign in to comment.