1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-26 15:46:23 +00:00

MacOS: Embedded window support.

This commit is contained in:
Stuart Carnie
2025-04-29 07:01:27 +10:00
parent 1cf573f44d
commit 00e1fdec2c
37 changed files with 3670 additions and 384 deletions

View File

@@ -35,25 +35,14 @@
#include "scene/resources/style_box_flat.h"
#include "scene/theme/theme_db.h"
void EmbeddedProcess::_notification(int p_what) {
void EmbeddedProcessBase::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
window = get_window();
} break;
case NOTIFICATION_PROCESS: {
if (updated_embedded_process_queued) {
updated_embedded_process_queued = false;
_update_embedded_process();
}
} break;
case NOTIFICATION_DRAW: {
_draw();
} break;
case NOTIFICATION_RESIZED:
case NOTIFICATION_VISIBILITY_CHANGED:
case NOTIFICATION_WM_POSITION_CHANGED: {
queue_update_embedded_process();
} break;
case NOTIFICATION_THEME_CHANGED: {
focus_style_box = get_theme_stylebox(SNAME("FocusViewport"), EditorStringName(EditorStyles));
Ref<StyleBoxFlat> focus_style_box_flat = focus_style_box;
@@ -68,60 +57,43 @@ void EmbeddedProcess::_notification(int p_what) {
margin_bottom_right = Point2i();
}
} break;
case NOTIFICATION_FOCUS_ENTER: {
queue_update_embedded_process();
} break;
case NOTIFICATION_APPLICATION_FOCUS_IN: {
application_has_focus = true;
last_application_focus_time = OS::get_singleton()->get_ticks_msec();
} break;
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
application_has_focus = false;
} break;
}
}
void EmbeddedProcess::set_window_size(const Size2i p_window_size) {
void EmbeddedProcessBase::_bind_methods() {
ADD_SIGNAL(MethodInfo("embedding_completed"));
ADD_SIGNAL(MethodInfo("embedding_failed"));
ADD_SIGNAL(MethodInfo("embedded_process_updated"));
ADD_SIGNAL(MethodInfo("embedded_process_focused"));
}
void EmbeddedProcessBase::_draw() {
if (is_process_focused() && focus_style_box.is_valid()) {
Size2 size = get_size();
Rect2 r = Rect2(Point2(), size);
focus_style_box->draw(get_canvas_item(), r);
}
}
void EmbeddedProcessBase::set_window_size(const Size2i &p_window_size) {
if (window_size != p_window_size) {
window_size = p_window_size;
queue_update_embedded_process();
}
}
void EmbeddedProcess::set_keep_aspect(bool p_keep_aspect) {
void EmbeddedProcessBase::set_keep_aspect(bool p_keep_aspect) {
if (keep_aspect != p_keep_aspect) {
keep_aspect = p_keep_aspect;
queue_update_embedded_process();
}
}
Rect2i EmbeddedProcess::get_adjusted_embedded_window_rect(Rect2i p_rect) {
Rect2i control_rect = Rect2i(p_rect.position + margin_top_left, (p_rect.size - get_margins_size()).maxi(1));
if (window) {
control_rect.position += window->get_position();
}
if (window_size != Size2i()) {
Rect2i desired_rect = Rect2i();
if (!keep_aspect && control_rect.size.x >= window_size.x && control_rect.size.y >= window_size.y) {
// Fixed at the desired size.
desired_rect.size = window_size;
} else {
float ratio = MIN((float)control_rect.size.x / window_size.x, (float)control_rect.size.y / window_size.y);
desired_rect.size = Size2i(window_size.x * ratio, window_size.y * ratio).maxi(1);
}
desired_rect.position = Size2i(control_rect.position.x + ((control_rect.size.x - desired_rect.size.x) / 2), control_rect.position.y + ((control_rect.size.y - desired_rect.size.y) / 2));
return desired_rect;
} else {
// Stretch, use all the control area.
return control_rect;
}
}
Rect2i EmbeddedProcess::get_screen_embedded_window_rect() {
Rect2i EmbeddedProcessBase::get_screen_embedded_window_rect() const {
return get_adjusted_embedded_window_rect(get_global_rect());
}
int EmbeddedProcess::get_margin_size(Side p_side) const {
int EmbeddedProcessBase::get_margin_size(Side p_side) const {
ERR_FAIL_INDEX_V((int)p_side, 4, 0);
switch (p_side) {
@@ -138,18 +110,51 @@ int EmbeddedProcess::get_margin_size(Side p_side) const {
return 0;
}
Size2 EmbeddedProcess::get_margins_size() {
Size2 EmbeddedProcessBase::get_margins_size() const {
return margin_top_left + margin_bottom_right;
}
bool EmbeddedProcess::is_embedding_in_progress() {
EmbeddedProcessBase::EmbeddedProcessBase() {
set_focus_mode(FOCUS_ALL);
}
EmbeddedProcessBase::~EmbeddedProcessBase() {
}
Rect2i EmbeddedProcess::get_adjusted_embedded_window_rect(const Rect2i &p_rect) const {
Rect2i control_rect = Rect2i(p_rect.position + margin_top_left, (p_rect.size - get_margins_size()).maxi(1));
if (window) {
control_rect.position += window->get_position();
}
if (window_size != Size2i()) {
Rect2i desired_rect;
if (!keep_aspect && control_rect.size.x >= window_size.x && control_rect.size.y >= window_size.y) {
// Fixed at the desired size.
desired_rect.size = window_size;
} else {
float ratio = MIN((float)control_rect.size.x / window_size.x, (float)control_rect.size.y / window_size.y);
desired_rect.size = Size2i(window_size.x * ratio, window_size.y * ratio).maxi(1);
}
desired_rect.position = Size2i(control_rect.position.x + ((control_rect.size.x - desired_rect.size.x) / 2), control_rect.position.y + ((control_rect.size.y - desired_rect.size.y) / 2));
return desired_rect;
} else {
// Stretch, use all the control area.
return control_rect;
}
}
bool EmbeddedProcess::is_embedding_in_progress() const {
return !timer_embedding->is_stopped();
}
bool EmbeddedProcess::is_embedding_completed() {
bool EmbeddedProcess::is_embedding_completed() const {
return embedding_completed;
}
bool EmbeddedProcess::is_process_focused() const {
return focused_process_id == current_process_id && has_focus();
}
int EmbeddedProcess::get_embedded_pid() const {
return current_process_id;
}
@@ -270,11 +275,29 @@ void EmbeddedProcess::_timer_embedding_timeout() {
_try_embed_process();
}
void EmbeddedProcess::_draw() {
if (focused_process_id == current_process_id && has_focus() && focus_style_box.is_valid()) {
Size2 size = get_size();
Rect2 r = Rect2(Point2(), size);
focus_style_box->draw(get_canvas_item(), r);
void EmbeddedProcess::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_PROCESS: {
if (updated_embedded_process_queued) {
updated_embedded_process_queued = false;
_update_embedded_process();
}
} break;
case NOTIFICATION_RESIZED:
case NOTIFICATION_VISIBILITY_CHANGED:
case NOTIFICATION_WM_POSITION_CHANGED: {
queue_update_embedded_process();
} break;
case NOTIFICATION_APPLICATION_FOCUS_IN: {
application_has_focus = true;
last_application_focus_time = OS::get_singleton()->get_ticks_msec();
} break;
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
application_has_focus = false;
} break;
case NOTIFICATION_FOCUS_ENTER: {
queue_update_embedded_process();
} break;
}
}
@@ -386,14 +409,8 @@ Window *EmbeddedProcess::_get_current_modal_window() {
return nullptr;
}
void EmbeddedProcess::_bind_methods() {
ADD_SIGNAL(MethodInfo("embedding_completed"));
ADD_SIGNAL(MethodInfo("embedding_failed"));
ADD_SIGNAL(MethodInfo("embedded_process_updated"));
ADD_SIGNAL(MethodInfo("embedded_process_focused"));
}
EmbeddedProcess::EmbeddedProcess() {
EmbeddedProcess::EmbeddedProcess() :
EmbeddedProcessBase() {
timer_embedding = memnew(Timer);
timer_embedding->set_wait_time(0.1);
timer_embedding->set_one_shot(true);
@@ -404,8 +421,6 @@ EmbeddedProcess::EmbeddedProcess() {
timer_update_embedded_process->set_wait_time(0.1);
add_child(timer_update_embedded_process);
timer_update_embedded_process->connect("timeout", callable_mp(this, &EmbeddedProcess::_timer_update_embedded_process_timeout));
set_focus_mode(FOCUS_ALL);
}
EmbeddedProcess::~EmbeddedProcess() {

View File

@@ -32,8 +32,49 @@
#include "scene/gui/control.h"
class EmbeddedProcess : public Control {
GDCLASS(EmbeddedProcess, Control);
class ScriptEditorDebugger;
class EmbeddedProcessBase : public Control {
GDCLASS(EmbeddedProcessBase, Control);
void _draw();
protected:
Ref<StyleBox> focus_style_box;
Size2i window_size;
bool keep_aspect = false;
Point2i margin_top_left;
Point2i margin_bottom_right;
Window *window = nullptr;
static void _bind_methods();
void _notification(int p_what);
public:
virtual void set_script_debugger(ScriptEditorDebugger *p_debugger) {}
virtual bool is_embedding_completed() const = 0;
virtual bool is_embedding_in_progress() const = 0;
virtual bool is_process_focused() const = 0;
virtual void embed_process(OS::ProcessID p_pid) = 0;
virtual int get_embedded_pid() const = 0;
virtual void reset() = 0;
virtual void request_close() = 0;
virtual void queue_update_embedded_process() = 0;
void set_window_size(const Size2i &p_window_size);
void set_keep_aspect(bool p_keep_aspect);
virtual Rect2i get_adjusted_embedded_window_rect(const Rect2i &p_rect) const = 0;
Rect2i get_screen_embedded_window_rect() const;
int get_margin_size(Side p_side) const;
Size2 get_margins_size() const;
EmbeddedProcessBase();
virtual ~EmbeddedProcessBase();
};
class EmbeddedProcess : public EmbeddedProcessBase {
GDCLASS(EmbeddedProcess, EmbeddedProcessBase);
bool application_has_focus = true;
uint64_t last_application_focus_time = 0;
@@ -45,51 +86,37 @@ class EmbeddedProcess : public Control {
bool updated_embedded_process_queued = false;
bool last_updated_embedded_process_focused = false;
Window *window = nullptr;
Timer *timer_embedding = nullptr;
Timer *timer_update_embedded_process = nullptr;
const int embedding_timeout = 45000;
bool keep_aspect = false;
Size2i window_size;
Ref<StyleBox> focus_style_box;
Point2i margin_top_left;
Point2i margin_bottom_right;
Rect2i last_global_rect;
void _try_embed_process();
void _update_embedded_process();
void _timer_embedding_timeout();
void _timer_update_embedded_process_timeout();
void _draw();
void _check_mouse_over();
void _check_focused_process_id();
bool _is_embedded_process_updatable();
Rect2i _get_global_embedded_window_rect();
Window *_get_current_modal_window();
protected:
static void _bind_methods();
void _notification(int p_what);
public:
void embed_process(OS::ProcessID p_pid);
void reset();
void request_close();
bool is_embedding_in_progress() const override;
bool is_embedding_completed() const override;
bool is_process_focused() const override;
void embed_process(OS::ProcessID p_pid) override;
int get_embedded_pid() const override;
void reset() override;
void request_close() override;
void queue_update_embedded_process() override;
void set_window_size(const Size2i p_window_size);
void set_keep_aspect(bool p_keep_aspect);
void queue_update_embedded_process();
Rect2i get_adjusted_embedded_window_rect(Rect2i p_rect);
Rect2i get_screen_embedded_window_rect();
int get_margin_size(Side p_side) const;
Size2 get_margins_size();
bool is_embedding_in_progress();
bool is_embedding_completed();
int get_embedded_pid() const;
Rect2i get_adjusted_embedded_window_rect(const Rect2i &p_rect) const override;
EmbeddedProcess();
~EmbeddedProcess();
~EmbeddedProcess() override;
};

View File

@@ -243,11 +243,17 @@ void GameView::_sessions_changed() {
_update_debugger_buttons();
#ifdef MACOS_ENABLED
if (!embedded_script_debugger || !embedded_script_debugger->is_session_active() || embedded_script_debugger->get_remote_pid() != embedded_process->get_embedded_pid()) {
_attach_script_debugger();
}
#else
if (embedded_process->is_embedding_completed()) {
if (!embedded_script_debugger || !embedded_script_debugger->is_session_active() || embedded_script_debugger->get_remote_pid() != embedded_process->get_embedded_pid()) {
_attach_script_debugger();
}
}
#endif
}
void GameView::_instance_starting_static(int p_idx, List<String> &r_arguments) {
@@ -370,7 +376,9 @@ void GameView::_stop_pressed() {
}
void GameView::_embedding_completed() {
#ifndef MACOS_ENABLED
_attach_script_debugger();
#endif
_update_ui();
if (make_floating_on_play) {
get_window()->set_flag(Window::FLAG_ALWAYS_ON_TOP, bool(GLOBAL_GET("display/window/size/always_on_top")));
@@ -507,9 +515,11 @@ GameView::EmbedAvailability GameView::_get_embed_available() {
if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_WINDOW_EMBEDDING)) {
return EMBED_NOT_AVAILABLE_FEATURE_NOT_SUPPORTED;
}
#ifndef MACOS_ENABLED
if (get_tree()->get_root()->is_embedding_subwindows()) {
return EMBED_NOT_AVAILABLE_SINGLE_WINDOW_MODE;
}
#endif
String display_driver = GLOBAL_GET("display/display_server/driver");
if (display_driver == "headless" || display_driver == "wayland") {
return EMBED_NOT_AVAILABLE_PROJECT_DISPLAY_DRIVER;
@@ -786,14 +796,19 @@ void GameView::_attach_script_debugger() {
}
embedded_script_debugger = nullptr;
for (int i = 0; EditorDebuggerNode::get_singleton()->get_debugger(i); i++) {
ScriptEditorDebugger *script_debugger = EditorDebuggerNode::get_singleton()->get_debugger(i);
int i = 0;
while (ScriptEditorDebugger *script_debugger = EditorDebuggerNode::get_singleton()->get_debugger(i)) {
if (script_debugger->is_session_active() && script_debugger->get_remote_pid() == embedded_process->get_embedded_pid()) {
embedded_script_debugger = script_debugger;
break;
}
i++;
}
#ifdef MACOS_ENABLED
embedded_process->set_script_debugger(embedded_script_debugger);
#endif
if (embedded_script_debugger) {
embedded_script_debugger->connect("remote_window_title_changed", callable_mp(this, &GameView::_remote_window_title_changed));
embedded_script_debugger->connect("embed_shortcut_requested", callable_mp(this, &GameView::_handle_shortcut_requested));
@@ -845,6 +860,12 @@ void GameView::_update_arguments_for_instance(int p_idx, List<String> &r_argumen
List<String>::Element *N = r_arguments.insert_before(user_args_element, "--wid");
N = r_arguments.insert_after(N, itos(DisplayServer::get_singleton()->window_get_native_handle(DisplayServer::WINDOW_HANDLE, get_window()->get_window_id())));
#if MACOS_ENABLED
r_arguments.push_back("--display-driver");
r_arguments.push_back("embedded");
r_arguments.push_back("--embedded");
#endif
// Be sure to have the correct window size in the embedded_process control.
_update_embed_window_size();
Rect2i rect = embedded_process->get_screen_embedded_window_rect();
@@ -931,11 +952,12 @@ void GameView::_feature_profile_changed() {
node_type_button[RuntimeNodeSelect::NODE_TYPE_3D]->set_visible(is_3d_enabled);
}
GameView::GameView(Ref<GameViewDebugger> p_debugger, WindowWrapper *p_wrapper) {
GameView::GameView(Ref<GameViewDebugger> p_debugger, EmbeddedProcessBase *p_embedded_process, WindowWrapper *p_wrapper) {
singleton = this;
debugger = p_debugger;
window_wrapper = p_wrapper;
embedded_process = p_embedded_process;
// Add some margin to the sides for better aesthetics.
// This prevents the first button's hover/pressed effect from "touching" the panel's border,
@@ -1051,7 +1073,6 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, WindowWrapper *p_wrapper) {
camera_override_menu->set_h_size_flags(SIZE_SHRINK_END);
camera_override_menu->set_tooltip_text(TTR("Camera Override Options"));
camera_override_menu->set_accessibility_name(TTRC("Camera Override Options"));
_camera_override_menu_id_pressed(EditorSettings::get_singleton()->get_project_metadata("game_view", "camera_override_mode", 0));
PopupMenu *menu = camera_override_menu->get_popup();
menu->connect(SceneStringName(id_pressed), callable_mp(this, &GameView::_camera_override_menu_id_pressed));
@@ -1061,6 +1082,7 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, WindowWrapper *p_wrapper) {
menu->add_radio_check_item(TTR("Manipulate In-Game"), CAMERA_MODE_INGAME);
menu->set_item_checked(menu->get_item_index(CAMERA_MODE_INGAME), true);
menu->add_radio_check_item(TTR("Manipulate From Editors"), CAMERA_MODE_EDITORS);
_camera_override_menu_id_pressed(EditorSettings::get_singleton()->get_project_metadata("game_view", "camera_override_mode", 0));
embedding_separator = memnew(VSeparator);
main_menu_hbox->add_child(embedding_separator);
@@ -1118,7 +1140,6 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, WindowWrapper *p_wrapper) {
panel->set_theme_type_variation("GamePanel");
panel->set_v_size_flags(SIZE_EXPAND_FILL);
embedded_process = memnew(EmbeddedProcess);
panel->add_child(embedded_process);
embedded_process->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
embedded_process->connect("embedding_failed", callable_mp(this, &GameView::_embedding_failed));
@@ -1131,6 +1152,9 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, WindowWrapper *p_wrapper) {
state_container->add_theme_constant_override("margin_left", 8 * EDSCALE);
state_container->add_theme_constant_override("margin_right", 8 * EDSCALE);
state_container->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
#ifdef MACOS_ENABLED
state_container->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
#endif
panel->add_child(state_container);
state_label = memnew(Label());
@@ -1156,7 +1180,7 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, WindowWrapper *p_wrapper) {
///////
void GameViewPlugin::selected_notify() {
void GameViewPluginBase::selected_notify() {
if (_is_window_wrapper_enabled()) {
#ifdef ANDROID_ENABLED
notify_main_screen_changed(get_plugin_name());
@@ -1168,7 +1192,7 @@ void GameViewPlugin::selected_notify() {
}
#ifndef ANDROID_ENABLED
void GameViewPlugin::make_visible(bool p_visible) {
void GameViewPluginBase::make_visible(bool p_visible) {
if (p_visible) {
window_wrapper->show();
} else {
@@ -1176,35 +1200,54 @@ void GameViewPlugin::make_visible(bool p_visible) {
}
}
void GameViewPlugin::set_window_layout(Ref<ConfigFile> p_layout) {
void GameViewPluginBase::set_window_layout(Ref<ConfigFile> p_layout) {
game_view->set_window_layout(p_layout);
}
void GameViewPlugin::get_window_layout(Ref<ConfigFile> p_layout) {
void GameViewPluginBase::get_window_layout(Ref<ConfigFile> p_layout) {
game_view->get_window_layout(p_layout);
}
void GameViewPluginBase::setup(Ref<GameViewDebugger> p_debugger, EmbeddedProcessBase *p_embedded_process) {
debugger = p_debugger;
window_wrapper = memnew(WindowWrapper);
window_wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), TTR("Game Workspace")));
window_wrapper->set_margins_enabled(true);
game_view = memnew(GameView(debugger, p_embedded_process, window_wrapper));
game_view->set_v_size_flags(Control::SIZE_EXPAND_FILL);
window_wrapper->set_wrapped_control(game_view, nullptr);
EditorNode::get_singleton()->get_editor_main_screen()->get_control()->add_child(window_wrapper);
window_wrapper->set_v_size_flags(Control::SIZE_EXPAND_FILL);
window_wrapper->hide();
window_wrapper->connect("window_visibility_changed", callable_mp(this, &GameViewPlugin::_focus_another_editor).unbind(1));
}
#endif // ANDROID_ENABLED
void GameViewPlugin::_notification(int p_what) {
void GameViewPluginBase::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
add_debugger_plugin(debugger);
connect("main_screen_changed", callable_mp(this, &GameViewPlugin::_save_last_editor));
connect("main_screen_changed", callable_mp(this, &GameViewPluginBase::_save_last_editor));
} break;
case NOTIFICATION_EXIT_TREE: {
remove_debugger_plugin(debugger);
disconnect("main_screen_changed", callable_mp(this, &GameViewPlugin::_save_last_editor));
disconnect("main_screen_changed", callable_mp(this, &GameViewPluginBase::_save_last_editor));
} break;
}
}
void GameViewPlugin::_save_last_editor(const String &p_editor) {
void GameViewPluginBase::_save_last_editor(const String &p_editor) {
if (p_editor != get_plugin_name()) {
last_editor = p_editor;
}
}
void GameViewPlugin::_focus_another_editor() {
void GameViewPluginBase::_focus_another_editor() {
if (_is_window_wrapper_enabled()) {
if (last_editor.is_empty()) {
EditorNode::get_singleton()->get_editor_main_screen()->select(EditorMainScreen::EDITOR_2D);
@@ -1214,7 +1257,7 @@ void GameViewPlugin::_focus_another_editor() {
}
}
bool GameViewPlugin::_is_window_wrapper_enabled() const {
bool GameViewPluginBase::_is_window_wrapper_enabled() const {
#ifdef ANDROID_ENABLED
return true;
#else
@@ -1222,22 +1265,15 @@ bool GameViewPlugin::_is_window_wrapper_enabled() const {
#endif // ANDROID_ENABLED
}
GameViewPlugin::GameViewPlugin() {
debugger.instantiate();
#ifndef ANDROID_ENABLED
window_wrapper = memnew(WindowWrapper);
window_wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), TTR("Game Workspace")));
window_wrapper->set_margins_enabled(true);
game_view = memnew(GameView(debugger, window_wrapper));
game_view->set_v_size_flags(Control::SIZE_EXPAND_FILL);
window_wrapper->set_wrapped_control(game_view, nullptr);
EditorNode::get_singleton()->get_editor_main_screen()->get_control()->add_child(window_wrapper);
window_wrapper->set_v_size_flags(Control::SIZE_EXPAND_FILL);
window_wrapper->hide();
window_wrapper->connect("window_visibility_changed", callable_mp(this, &GameViewPlugin::_focus_another_editor).unbind(1));
#endif // ANDROID_ENABLED
GameViewPluginBase::GameViewPluginBase() {
}
GameViewPlugin::GameViewPlugin() :
GameViewPluginBase() {
#ifndef ANDROID_ENABLED
Ref<GameViewDebugger> game_view_debugger;
game_view_debugger.instantiate();
EmbeddedProcess *embedded_process = memnew(EmbeddedProcess);
setup(game_view_debugger, embedded_process);
#endif
}

View File

@@ -37,7 +37,7 @@
#include "scene/debugger/scene_debugger.h"
#include "scene/gui/box_container.h"
class EmbeddedProcess;
class EmbeddedProcessBase;
class VSeparator;
class WindowWrapper;
class ScriptEditorDebugger;
@@ -154,7 +154,7 @@ class GameView : public VBoxContainer {
MenuButton *embed_options_menu = nullptr;
Label *game_size_label = nullptr;
Panel *panel = nullptr;
EmbeddedProcess *embedded_process = nullptr;
EmbeddedProcessBase *embedded_process = nullptr;
Label *state_label = nullptr;
void _sessions_changed();
@@ -214,11 +214,11 @@ public:
void set_window_layout(Ref<ConfigFile> p_layout);
void get_window_layout(Ref<ConfigFile> p_layout);
GameView(Ref<GameViewDebugger> p_debugger, WindowWrapper *p_wrapper);
GameView(Ref<GameViewDebugger> p_debugger, EmbeddedProcessBase *p_embedded_process, WindowWrapper *p_wrapper);
};
class GameViewPlugin : public EditorPlugin {
GDCLASS(GameViewPlugin, EditorPlugin);
class GameViewPluginBase : public EditorPlugin {
GDCLASS(GameViewPluginBase, EditorPlugin);
#ifndef ANDROID_ENABLED
GameView *game_view = nullptr;
@@ -238,6 +238,9 @@ class GameViewPlugin : public EditorPlugin {
protected:
void _notification(int p_what);
#ifndef ANDROID_ENABLED
void setup(Ref<GameViewDebugger> p_debugger, EmbeddedProcessBase *p_embedded_process);
#endif
public:
virtual String get_plugin_name() const override { return TTRC("Game"); }
@@ -254,6 +257,12 @@ public:
virtual void set_window_layout(Ref<ConfigFile> p_layout) override;
virtual void get_window_layout(Ref<ConfigFile> p_layout) override;
#endif // ANDROID_ENABLED
GameViewPluginBase();
};
class GameViewPlugin : public GameViewPluginBase {
GDCLASS(GameViewPlugin, GameViewPluginBase);
public:
GameViewPlugin();
};