Skip to content

Commit 3f90681

Browse files
committed
Add xr startup scene to setup wizard
1 parent 015038a commit 3f90681

File tree

7 files changed

+318
-33
lines changed

7 files changed

+318
-33
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ local.properties
2020
/toolkit/src/gen/
2121
compile_commands.json
2222

23+
# Generated files
24+
*.gen.h
25+
2326
# Binaries
2427
*.o
2528
*.os

SConstruct

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ meta_platform_sdk_bindings = env.MetaPlatformSDK(env.Dir('#toolkit/gen/'), sourc
1818
"generate_platform_sdk_bindings.py",
1919
])
2020

21+
from build_raw_headers import build_raw_headers_action
22+
env.Append(
23+
BUILDERS={
24+
"RawHeaders": Builder(action=build_raw_headers_action),
25+
})
26+
raw_headers = env.RawHeaders(
27+
target=[
28+
'#toolkit/src/main/cpp/include/raw_headers/xr_startup.tscn.gen.h',
29+
'#toolkit/src/main/cpp/include/raw_headers/start_xr.gd.gen.h'
30+
],
31+
source=[
32+
'#toolkit/src/main/cpp/include/raw_headers/xr_startup.tscn',
33+
'#toolkit/src/main/cpp/include/raw_headers/start_xr.gd'
34+
],
35+
)
36+
2137
# Add common includes.
2238
env.Append(CPPPATH=[
2339
"#thirdparty/ovr_platform_sdk/Include/",
@@ -68,6 +84,7 @@ else:
6884
source=sources,
6985
)
7086

87+
env.Depends(library, raw_headers)
7188
Default(library)
7289

7390
if env["platform"] == "android":

build_raw_headers.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import os
2+
3+
def build_raw_header(source_filename: str, constant_name: str) -> None:
4+
# Read the source file content.
5+
with open(source_filename, "r") as source_file:
6+
source_content = source_file.read()
7+
constant_name = constant_name.replace(".", "_")
8+
# Build header content using a C raw string literal.
9+
header_content = (
10+
"/* THIS FILE IS GENERATED. EDITS WILL BE LOST. */\n\n"
11+
"#pragma once\n\n"
12+
f"inline constexpr const char *{constant_name}"
13+
" = "
14+
f'R"<!>({source_content})<!>"'
15+
";\n"
16+
)
17+
# Write the header to the provided file name with a ".gen.h" suffix.
18+
header_filename = f"{source_filename}.gen.h"
19+
with open(header_filename, "w") as header_file:
20+
header_file.write(header_content)
21+
22+
def build_raw_headers_action(target, source, env):
23+
env.NoCache(target)
24+
for src in source:
25+
source_filename = str(src)
26+
constant_name = os.path.basename(source_filename)
27+
build_raw_header(source_filename, constant_name)

toolkit/src/main/cpp/editor/meta_project_setup_dialog.cpp

Lines changed: 95 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22

33
#include "editor/meta_project_setup_dialog.h"
44

5+
#include "raw_headers/start_xr.gd.gen.h"
6+
#include "raw_headers/xr_startup.tscn.gen.h"
7+
58
#include <godot_cpp/classes/button.hpp>
69
#include <godot_cpp/classes/center_container.hpp>
710
#include <godot_cpp/classes/config_file.hpp>
811
#include <godot_cpp/classes/control.hpp>
912
#include <godot_cpp/classes/dir_access.hpp>
13+
#include <godot_cpp/classes/editor_file_system.hpp>
1014
#include <godot_cpp/classes/editor_interface.hpp>
1115
#include <godot_cpp/classes/editor_settings.hpp>
1216
#include <godot_cpp/classes/file_access.hpp>
@@ -28,9 +32,11 @@
2832
#include <godot_cpp/classes/window.hpp>
2933
#include <godot_cpp/core/error_macros.hpp>
3034
#include <godot_cpp/core/memory.hpp>
31-
3235
#include <godot_cpp/variant/utility_functions.hpp>
3336

37+
static const char *XR_STARTUP_SCENE_PATH = "res://xr_startup.tscn";
38+
static const char *START_XR_SCRIPT_PATH = "res://start_xr.gd";
39+
3440
void MetaProjectSetupDialog::_bind_methods() {
3541
}
3642

@@ -40,14 +46,14 @@ void MetaProjectSetupDialog::_notification(uint32_t p_what) {
4046
recommendations.clear();
4147

4248
// Required XR settings
43-
recommendations.push_back({ "OpenXR", "xr/openxr/enabled", true, "OpenXR must be enabled", true, {} });
44-
recommendations.push_back({ "XR Shaders", "xr/shaders/enabled", true, "XR shaders must be compiled", true, {} });
49+
recommendations.push_back({ "OpenXR", "xr/openxr/enabled", true, "OpenXR must be enabled", ALERT_TYPE_ERROR, {} });
50+
recommendations.push_back({ "XR Shaders", "xr/shaders/enabled", true, "XR shaders must be compiled", ALERT_TYPE_ERROR, {} });
4551

4652
// Other XR setting recommendations
47-
recommendations.push_back({ "MSAA", "rendering/anti_aliasing/quality/msaa_3d", 1, "Recommended to set MSAA to 2x", false, {} });
48-
recommendations.push_back({ "VRS Mode", "rendering/vrs/mode", 2, "Recommended to set VRS mode to VR", false, {} });
49-
recommendations.push_back({ "Foveation Level", "xr/openxr/foveation_level", 3, "Recommended to set foveation level to high", false, {} });
50-
recommendations.push_back({ "Dynamic Foveation", "xr/openxr/foveation_dynamic", true, "Recommended to enable dynamic foveation", false, {} });
53+
recommendations.push_back({ "MSAA", "rendering/anti_aliasing/quality/msaa_3d", 1, "Recommended to set MSAA to 2x", ALERT_TYPE_WARNING, {} });
54+
recommendations.push_back({ "VRS Mode", "rendering/vrs/mode", 2, "Recommended to set VRS mode to VR", ALERT_TYPE_WARNING, {} });
55+
recommendations.push_back({ "Foveation Level", "xr/openxr/foveation_level", 3, "Recommended to set foveation level to high", ALERT_TYPE_WARNING, {} });
56+
recommendations.push_back({ "Dynamic Foveation", "xr/openxr/foveation_dynamic", true, "Recommended to enable dynamic foveation", ALERT_TYPE_WARNING, {} });
5157

5258
ScrollContainer *scroll_container = memnew(ScrollContainer);
5359
scroll_container->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
@@ -70,28 +76,33 @@ void MetaProjectSetupDialog::_notification(uint32_t p_what) {
7076
}
7177
}
7278

73-
vendors_plugin_entry = add_window_entry("Vendors Plugin", true);
79+
vendors_plugin_entry = add_window_entry("Vendors Plugin", ALERT_TYPE_ERROR);
7480
vendors_plugin_entry.description_label->set_text("Please install the Godot OpenXR Vendors Plugin");
7581
vendors_plugin_entry.button->set_text("Open");
7682
vendors_plugin_entry.button->connect("pressed", callable_mp(this, &MetaProjectSetupDialog::open_asset_lib));
7783

78-
export_preset_entry = add_window_entry("Export", true);
84+
export_preset_entry = add_window_entry("Export", ALERT_TYPE_ERROR);
7985
export_preset_entry.button->set_text("Open");
8086
export_preset_entry.button->connect("pressed", callable_mp(this, &MetaProjectSetupDialog::open_export_dialog));
8187

82-
java_sdk_entry = add_window_entry("Java SDK", true);
88+
java_sdk_entry = add_window_entry("Java SDK", ALERT_TYPE_ERROR);
8389
java_sdk_entry.description_label->set_text("Please set a valid Java SDK path in Editor Settings");
8490
java_sdk_entry.button->set_text("Info");
8591
java_sdk_entry.button->connect("pressed", callable_mp(this, &MetaProjectSetupDialog::open_android_export_doc));
8692

87-
android_sdk_entry = add_window_entry("Android SDK", true);
93+
android_sdk_entry = add_window_entry("Android SDK", ALERT_TYPE_ERROR);
8894
android_sdk_entry.description_label->set_text("Please set a valid Android SDK path in Editor Settings");
8995
android_sdk_entry.button->set_text("Info");
9096
android_sdk_entry.button->connect("pressed", callable_mp(this, &MetaProjectSetupDialog::open_android_export_doc));
9197

98+
main_scene_entry = add_window_entry("Main Scene", ALERT_TYPE_NONE);
99+
main_scene_entry.description_label->set_text("No main scene is set, add XR startup scene?");
100+
main_scene_entry.button->set_text("Add");
101+
main_scene_entry.button->connect("pressed", callable_mp(this, &MetaProjectSetupDialog::add_xr_startup_scene));
102+
92103
int rec_index = 0;
93104
for (ProjectSettingRecommendation &recommendation : recommendations) {
94-
recommendation.entry = add_window_entry(recommendation.setting_name, recommendation.is_high_priority);
105+
recommendation.entry = add_window_entry(recommendation.setting_name, recommendation.alert_type);
95106
recommendation.entry.button->set_text("Apply");
96107
recommendation.entry.button->connect("pressed", callable_mp(this, &MetaProjectSetupDialog::apply_recommendation).bind(rec_index));
97108
rec_index++;
@@ -108,7 +119,7 @@ void MetaProjectSetupDialog::_notification(uint32_t p_what) {
108119
}
109120
}
110121

111-
MetaProjectSetupDialog::WindowEntry MetaProjectSetupDialog::add_window_entry(const String &p_entry_name, bool p_is_high_priority) {
122+
MetaProjectSetupDialog::WindowEntry MetaProjectSetupDialog::add_window_entry(const String &p_entry_name, AlertType p_alert_type) {
112123
WindowEntry entry;
113124

114125
VBoxContainer *inner_vbox = memnew(VBoxContainer);
@@ -135,26 +146,33 @@ MetaProjectSetupDialog::WindowEntry MetaProjectSetupDialog::add_window_entry(con
135146
message_hbox->set_h_size_flags(Control::SIZE_EXPAND | Control::SIZE_SHRINK_BEGIN);
136147
hbox->add_child(message_hbox);
137148

138-
Ref<Texture2D> icon_texture = p_is_high_priority ? error_texture : warning_texture;
139-
if (icon_texture.is_valid()) {
140-
CenterContainer *icon_container = memnew(CenterContainer);
141-
message_hbox->add_child(icon_container);
142-
entry.icon_container = icon_container;
149+
CenterContainer *icon_container = memnew(CenterContainer);
150+
message_hbox->add_child(icon_container);
151+
entry.icon_container = icon_container;
143152

144-
TextureRect *icon = memnew(TextureRect);
145-
icon->set_texture(icon_texture);
146-
icon->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE);
147-
icon->set_custom_minimum_size(Vector2(15.0, 15.0));
148-
icon_container->add_child(icon);
149-
}
150-
151-
Color font_color = p_is_high_priority ? error_color : warning_color;
153+
TextureRect *icon = memnew(TextureRect);
154+
icon->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE);
155+
icon_container->add_child(icon);
152156

153157
Label *description_label = memnew(Label);
154-
description_label->add_theme_color_override("font_color", font_color);
155158
message_hbox->add_child(description_label);
156159
entry.description_label = description_label;
157160

161+
switch (p_alert_type) {
162+
case ALERT_TYPE_ERROR: {
163+
icon->set_texture(error_texture);
164+
icon->set_custom_minimum_size(Vector2(15.0, 15.0));
165+
description_label->add_theme_color_override("font_color", error_color);
166+
} break;
167+
case ALERT_TYPE_WARNING: {
168+
icon->set_texture(warning_texture);
169+
icon->set_custom_minimum_size(Vector2(15.0, 15.0));
170+
description_label->add_theme_color_override("font_color", warning_color);
171+
} break;
172+
case ALERT_TYPE_NONE: {
173+
} break;
174+
}
175+
158176
Button *button = memnew(Button);
159177
hbox->add_child(button);
160178
entry.button = button;
@@ -251,18 +269,34 @@ void MetaProjectSetupDialog::open() {
251269
}
252270
}
253271

272+
// Check for main scene.
273+
if (project_settings->get("application/run/main_scene") == String("")) {
274+
main_scene_entry.vbox->show();
275+
is_rec_list_empty = false;
276+
} else {
277+
main_scene_entry.vbox->hide();
278+
}
279+
254280
// Check project setting recommendations.
255281
for (const ProjectSettingRecommendation &recommendation : recommendations) {
256282
if (project_settings->get(recommendation.setting_path) == recommendation.recommended_value) {
257283
recommendation.entry.vbox->hide();
258284
} else {
259285
recommendation.entry.vbox->show();
260286
recommendation.entry.button->set_disabled(false);
261-
262-
Color font_color = recommendation.is_high_priority ? error_color : warning_color;
263-
recommendation.entry.description_label->add_theme_color_override("font_color", font_color);
264287
recommendation.entry.description_label->set_text(recommendation.description);
265288

289+
switch (recommendation.alert_type) {
290+
case ALERT_TYPE_ERROR: {
291+
recommendation.entry.description_label->add_theme_color_override("font_color", error_color);
292+
} break;
293+
case ALERT_TYPE_WARNING: {
294+
recommendation.entry.description_label->add_theme_color_override("font_color", warning_color);
295+
} break;
296+
case ALERT_TYPE_NONE: {
297+
} break;
298+
}
299+
266300
if (recommendation.entry.icon_container != nullptr) {
267301
recommendation.entry.icon_container->show();
268302
}
@@ -400,6 +434,36 @@ void MetaProjectSetupDialog::open_android_export_doc() {
400434
os->shell_open("https://docs.godotengine.org/en/stable/tutorials/export/exporting_for_android.html");
401435
}
402436

437+
void MetaProjectSetupDialog::add_xr_startup_scene() {
438+
ProjectSettings *project_settings = ProjectSettings::get_singleton();
439+
ERR_FAIL_NULL(project_settings);
440+
441+
EditorInterface *editor_interface = EditorInterface::get_singleton();
442+
ERR_FAIL_NULL(editor_interface);
443+
444+
if (FileAccess::file_exists(START_XR_SCRIPT_PATH)) {
445+
ERR_FAIL_EDMSG("XR startup script start_xr.gd already exists");
446+
}
447+
448+
if (FileAccess::file_exists(XR_STARTUP_SCENE_PATH)) {
449+
ERR_FAIL_EDMSG("XR startup scene xr_startup.tscn already exists");
450+
}
451+
452+
Ref<FileAccess> start_xr = FileAccess::open(START_XR_SCRIPT_PATH, FileAccess::WRITE);
453+
start_xr->store_string(String(start_xr_gd));
454+
start_xr->close();
455+
456+
Ref<FileAccess> startup_scene = FileAccess::open(XR_STARTUP_SCENE_PATH, FileAccess::WRITE);
457+
startup_scene->store_string(String(xr_startup_tscn));
458+
startup_scene->close();
459+
460+
project_settings->set_setting("application/run/main_scene", XR_STARTUP_SCENE_PATH);
461+
editor_interface->get_resource_filesystem()->scan();
462+
editor_interface->open_scene_from_path(XR_STARTUP_SCENE_PATH);
463+
464+
hide();
465+
}
466+
403467
void MetaProjectSetupDialog::apply_recommendation(int p_rec_index) {
404468
ProjectSettings *project_settings = ProjectSettings::get_singleton();
405469
ERR_FAIL_NULL(project_settings);
@@ -414,7 +478,7 @@ void MetaProjectSetupDialog::apply_recommendation(int p_rec_index) {
414478
recommendation.entry.icon_container->hide();
415479
}
416480

417-
if (recommendation.is_high_priority) {
481+
if (recommendation.alert_type == ALERT_TYPE_ERROR) {
418482
recommendation.entry.description_label->set_text("Restart editor to apply updated setting");
419483
recommendation.entry.description_label->add_theme_color_override("font_color", warning_color);
420484
} else {

toolkit/src/main/cpp/include/editor/meta_project_setup_dialog.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ using namespace godot;
1919
class MetaProjectSetupDialog : public AcceptDialog {
2020
GDCLASS(MetaProjectSetupDialog, AcceptDialog);
2121

22+
enum AlertType {
23+
ALERT_TYPE_ERROR,
24+
ALERT_TYPE_WARNING,
25+
ALERT_TYPE_NONE,
26+
};
27+
2228
struct WindowEntry {
2329
VBoxContainer *vbox = nullptr;
2430
CenterContainer *icon_container = nullptr;
@@ -31,14 +37,15 @@ class MetaProjectSetupDialog : public AcceptDialog {
3137
String setting_path;
3238
Variant recommended_value;
3339
String description;
34-
bool is_high_priority;
40+
AlertType alert_type;
3541
WindowEntry entry;
3642
};
3743

3844
WindowEntry vendors_plugin_entry;
3945
WindowEntry export_preset_entry;
4046
WindowEntry java_sdk_entry;
4147
WindowEntry android_sdk_entry;
48+
WindowEntry main_scene_entry;
4249

4350
LocalVector<ProjectSettingRecommendation> recommendations;
4451

@@ -51,7 +58,7 @@ class MetaProjectSetupDialog : public AcceptDialog {
5158
LineEdit *asset_lib_filter = nullptr;
5259
HTTPRequest *asset_lib_request = nullptr;
5360

54-
WindowEntry add_window_entry(const String &p_entry_name, bool p_is_high_priority);
61+
WindowEntry add_window_entry(const String &p_entry_name, AlertType p_alert_type);
5562

5663
void populate_asset_lib_nodes();
5764
void open_asset_lib();
@@ -61,6 +68,8 @@ class MetaProjectSetupDialog : public AcceptDialog {
6168

6269
void open_android_export_doc();
6370

71+
void add_xr_startup_scene();
72+
6473
void apply_recommendation(int p_rec_index);
6574

6675
Ref<Texture2D> error_texture;

0 commit comments

Comments
 (0)