Skip to content

Commit

Permalink
Embedding game process in editor
Browse files Browse the repository at this point in the history
  • Loading branch information
Hilderin committed Sep 27, 2024
1 parent 2ab283a commit e313ca3
Show file tree
Hide file tree
Showing 19 changed files with 612 additions and 24 deletions.
15 changes: 15 additions & 0 deletions editor/editor_run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,10 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) {
args.push_back("--skip-breakpoints");
}

if (start_embedded_enabled) {
args.push_back("--hidden");
}

if (!p_scene.is_empty()) {
args.push_back(p_scene);
}
Expand Down Expand Up @@ -286,6 +290,17 @@ void EditorRun::stop() {
running_scene = "";
}

OS::ProcessID EditorRun::get_current_process() const {
if (pids.is_empty()) {
return 0;
}
return pids.get(0);
}

void EditorRun::set_start_embedded_enabled(bool p_enabled) {
start_embedded_enabled = p_enabled;
}

EditorRun::EditorRun() {
status = STATUS_STOP;
running_scene = "";
Expand Down
3 changes: 3 additions & 0 deletions editor/editor_run.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class EditorRun {
private:
Status status;
String running_scene;
bool start_embedded_enabled = false;

public:
Status get_status() const;
Expand All @@ -58,6 +59,8 @@ class EditorRun {
void stop_child_process(OS::ProcessID p_pid);
bool has_child_process(OS::ProcessID p_pid) const;
int get_child_process_count() const { return pids.size(); }
OS::ProcessID get_current_process() const;
void set_start_embedded_enabled(bool p_enabled);

EditorRun();
};
Expand Down
8 changes: 8 additions & 0 deletions editor/gui/editor_run_bar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ void EditorRunBar::stop_child_process(OS::ProcessID p_pid) {
}
}

OS::ProcessID EditorRunBar::get_current_process() const {
return editor_run.get_current_process();
}

void EditorRunBar::set_movie_maker_enabled(bool p_enabled) {
write_movie_button->set_pressed(p_enabled);
}
Expand All @@ -353,6 +357,10 @@ bool EditorRunBar::is_movie_maker_enabled() const {
return write_movie_button->is_pressed();
}

void EditorRunBar::set_start_embedded_enabled(bool p_enabled) {
editor_run.set_start_embedded_enabled(p_enabled);
}

HBoxContainer *EditorRunBar::get_buttons_container() {
return main_hbox;
}
Expand Down
3 changes: 3 additions & 0 deletions editor/gui/editor_run_bar.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,13 @@ class EditorRunBar : public MarginContainer {

OS::ProcessID has_child_process(OS::ProcessID p_pid) const;
void stop_child_process(OS::ProcessID p_pid);
OS::ProcessID get_current_process() const;

void set_movie_maker_enabled(bool p_enabled);
bool is_movie_maker_enabled() const;

void set_start_embedded_enabled(bool p_enabled);

Button *get_pause_button() { return pause_button; }

HBoxContainer *get_buttons_container();
Expand Down
1 change: 1 addition & 0 deletions editor/icons/AutoFocus.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/EmbeddedProcess.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/KeepAspect.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
125 changes: 125 additions & 0 deletions editor/plugins/game_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "editor/editor_main_screen.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/gui/editor_run_bar.h"
#include "editor/themes/editor_scale.h"
#include "scene/gui/button.h"
#include "scene/gui/panel.h"
Expand Down Expand Up @@ -131,6 +132,35 @@ void GameEditor::_sessions_changed() {
_update_debugger_buttons();
}

void GameEditor::_play_pressed() {
OS::ProcessID current_process_id = EditorRunBar::get_singleton()->get_current_process();
if (current_process_id == 0) {
return;
}

if (embedded_button->is_pressed()) {
embedded_progress->embed_process(current_process_id);
_update_ui();

if (auto_focus_button->is_pressed()) {
EditorNode::get_singleton()->get_editor_main_screen()->select(EditorMainScreen::EDITOR_GAME);
}
}
}

void GameEditor::_stop_pressed() {
embedded_progress->reset();
_update_ui();
}

void GameEditor::_embedding_completed() {
_update_ui();
}

void GameEditor::_embedding_failed() {
state_label->set_text(TTR("Connection impossible to the game process."));
}

void GameEditor::_update_debugger_buttons() {
bool empty = active_sessions == 0;
suspend_button->set_disabled(empty);
Expand Down Expand Up @@ -167,6 +197,42 @@ void GameEditor::_select_mode_pressed(int p_option) {
debugger->set_select_mode(mode);
}

void GameEditor::_embedded_button_pressed() {
EditorSettings::get_singleton()->set_project_metadata("game_editor", "embedded", embedded_button->is_pressed());
EditorRunBar::get_singleton()->set_start_embedded_enabled(embedded_button->is_pressed());

if (embedded_button->is_pressed()) {
_play_pressed();
} else if (embedded_progress->get_embedding_completed()) {
embedded_progress->restore_embedded_process();
}

_update_ui();
}

void GameEditor::_auto_focus_button_pressed() {
EditorSettings::get_singleton()->set_project_metadata("game_editor", "auto_focus", auto_focus_button->is_pressed());
}

void GameEditor::_keep_aspect_button_pressed() {
EditorSettings::get_singleton()->set_project_metadata("game_editor", "keep_aspect", keep_aspect_button->is_pressed());
embedded_progress->set_keep_aspect(keep_aspect_button->is_pressed());
}

void GameEditor::_update_ui() {
if (embedded_progress->get_embedding_completed()) {
state_label->set_text("");
} else if (embedded_progress->get_embedding_in_progress()) {
state_label->set_text(TTR("Game starting..."));
} else if (EditorRunBar::get_singleton()->is_playing()) {
state_label->set_text(TTR("Game running not embedded."));
} else if (embedded_button->is_pressed()) {
state_label->set_text(TTR("Press play to start the game."));
} else {
state_label->set_text(TTR("Embedding is disabled."));
}
}

void GameEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE:
Expand All @@ -180,8 +246,31 @@ void GameEditor::_notification(int p_what) {
select_mode_button[RuntimeNodeSelect::SELECT_MODE_SINGLE]->set_icon(get_editor_theme_icon(SNAME("ToolSelect")));
select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_icon(get_editor_theme_icon(SNAME("ListSelect")));

embedded_button->set_icon(get_editor_theme_icon(SNAME("EmbeddedProcess")));
auto_focus_button->set_icon(get_editor_theme_icon(SNAME("AutoFocus")));
keep_aspect_button->set_icon(get_editor_theme_icon(SNAME("KeepAspect")));

panel->set_theme_type_variation("GamePanel");
} break;

case NOTIFICATION_READY: {
embedded_button->set_pressed(EditorSettings::get_singleton()->get_project_metadata("game_editor", "embedded", true));
auto_focus_button->set_pressed(EditorSettings::get_singleton()->get_project_metadata("game_editor", "auto_focus", true));
keep_aspect_button->set_pressed(EditorSettings::get_singleton()->get_project_metadata("game_editor", "keep_aspect", true));
embedded_progress->set_keep_aspect(keep_aspect_button->is_pressed());

EditorRunBar::get_singleton()->connect("play_pressed", callable_mp(this, &GameEditor::_play_pressed));
EditorRunBar::get_singleton()->connect("stop_pressed", callable_mp(this, &GameEditor::_stop_pressed));
EditorRunBar::get_singleton()->set_start_embedded_enabled(embedded_button->is_pressed());

_update_ui();
} break;

case NOTIFICATION_EXIT_TREE: {
if (EditorRunBar::get_singleton()) {
EditorRunBar::get_singleton()->set_start_embedded_enabled(false);
}
} break;
}
}

Expand Down Expand Up @@ -252,10 +341,46 @@ GameEditor::GameEditor(Ref<GameEditorDebugger> p_debugger) {
select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->connect(SceneStringName(pressed), callable_mp(this, &GameEditor::_select_mode_pressed).bind(RuntimeNodeSelect::SELECT_MODE_LIST));
select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_tooltip_text(TTR("Show list of selectable nodes at position clicked."));

main_menu_hbox->add_child(memnew(VSeparator));

embedded_button = memnew(Button);
main_menu_hbox->add_child(embedded_button);
embedded_button->set_toggle_mode(true);
embedded_button->set_theme_type_variation("FlatButton");
embedded_button->set_tooltip_text(TTR("Activate the game embedding mode."));
embedded_button->connect(SceneStringName(pressed), callable_mp(this, &GameEditor::_embedded_button_pressed));

auto_focus_button = memnew(Button);
main_menu_hbox->add_child(auto_focus_button);
auto_focus_button->set_toggle_mode(true);
auto_focus_button->set_theme_type_variation("FlatButton");
auto_focus_button->set_tooltip_text(TTR("Focus the game editor on project run."));
auto_focus_button->connect(SceneStringName(pressed), callable_mp(this, &GameEditor::_auto_focus_button_pressed));

keep_aspect_button = memnew(Button);
main_menu_hbox->add_child(keep_aspect_button);
keep_aspect_button->set_toggle_mode(true);
keep_aspect_button->set_theme_type_variation("FlatButton");
keep_aspect_button->set_tooltip_text(TTR("Keep aspect ratio of the embedded game."));
keep_aspect_button->connect(SceneStringName(pressed), callable_mp(this, &GameEditor::_keep_aspect_button_pressed));

panel = memnew(Panel);
add_child(panel);
panel->set_v_size_flags(SIZE_EXPAND_FILL);

embedded_progress = memnew(EmbeddedProcess);
panel->add_child(embedded_progress);
embedded_progress->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
embedded_progress->connect(SNAME("embedding_failed"), callable_mp(this, &GameEditor::_embedding_failed));
embedded_progress->connect(SNAME("embedding_completed"), callable_mp(this, &GameEditor::_embedding_completed));

state_label = memnew(Label());
panel->add_child(state_label);
state_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
state_label->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
state_label->set_autowrap_mode(TextServer::AUTOWRAP_WORD);
state_label->set_anchors_and_offsets_preset(PRESET_FULL_RECT);

p_debugger->connect("session_started", callable_mp(this, &GameEditor::_sessions_changed));
p_debugger->connect("session_stopped", callable_mp(this, &GameEditor::_sessions_changed));
}
Expand Down
16 changes: 16 additions & 0 deletions editor/plugins/game_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
#include "editor/plugins/editor_plugin.h"
#include "scene/debugger/scene_debugger.h"
#include "scene/gui/box_container.h"
#include "scene/gui/embedded_process.h"
#include "scene/gui/label.h"

class GameEditorDebugger : public EditorDebuggerPlugin {
GDCLASS(GameEditorDebugger, EditorDebuggerPlugin);
Expand Down Expand Up @@ -75,8 +77,13 @@ class GameEditor : public VBoxContainer {

Button *node_type_button[RuntimeNodeSelect::NODE_TYPE_MAX];
Button *select_mode_button[RuntimeNodeSelect::SELECT_MODE_MAX];
Button *embedded_button;
Button *auto_focus_button;
Button *keep_aspect_button;

Panel *panel = nullptr;
EmbeddedProcess *embedded_progress = nullptr;
Label *state_label = nullptr;

void _sessions_changed();

Expand All @@ -86,6 +93,15 @@ class GameEditor : public VBoxContainer {

void _node_type_pressed(int p_option);
void _select_mode_pressed(int p_option);
void _embedded_button_pressed();
void _auto_focus_button_pressed();
void _keep_aspect_button_pressed();

void _play_pressed();
void _stop_pressed();
void _embedding_completed();
void _embedding_failed();
void _update_ui();

protected:
void _notification(int p_what);
Expand Down
9 changes: 9 additions & 0 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ static bool init_always_on_top = false;
static bool init_use_custom_pos = false;
static bool init_use_custom_screen = false;
static Vector2 init_custom_pos;
static bool init_hidden = false;

// Debug

Expand Down Expand Up @@ -604,6 +605,7 @@ void Main::print_help(const char *p_binary) {
print_help_option("--screen <N>", "Request window screen.\n");
print_help_option("--single-window", "Use a single window (no separate subwindows).\n");
print_help_option("--xr-mode <mode>", "Select XR (Extended Reality) mode [\"default\", \"off\", \"on\"].\n");
print_help_option("--hidden", "Request window to be hidden.\n");

print_help_title("Debug options");
print_help_option("-d, --debug", "Debug (local stdout debugger).\n");
Expand Down Expand Up @@ -1202,6 +1204,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (arg == "-w" || arg == "--windowed") { // force windowed window

init_windowed = true;
} else if (arg == "--hidden") { // Force hidden window.

init_hidden = true;
} else if (arg == "--gpu-index") {
if (N) {
Engine::singleton->gpu_idx = N->get().to_int();
Expand Down Expand Up @@ -2910,6 +2915,10 @@ Error Main::setup2(bool p_show_boot_logo) {
context = DisplayServer::CONTEXT_ENGINE;
}

if (init_hidden) {
window_flags |= DisplayServer::WINDOW_FLAG_HIDDEN_BIT;
}

// rendering_driver now held in static global String in main and initialized in setup()
Error err;
display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_vsync_mode, window_flags, window_position, window_size, init_screen, context, err);
Expand Down
Loading

0 comments on commit e313ca3

Please sign in to comment.