diff options
-rw-r--r-- | editor/plugins/node_3d_editor_plugin.cpp | 206 | ||||
-rw-r--r-- | editor/plugins/node_3d_editor_plugin.h | 27 | ||||
-rw-r--r-- | main/main.cpp | 20 | ||||
-rw-r--r-- | modules/gdscript/gdscript_vm.cpp | 1 | ||||
-rw-r--r-- | modules/openxr/openxr_api.cpp | 15 | ||||
-rw-r--r-- | scene/resources/mesh.cpp | 66 | ||||
-rw-r--r-- | scene/resources/mesh.h | 3 | ||||
-rw-r--r-- | servers/rendering/renderer_compositor.cpp | 7 | ||||
-rw-r--r-- | servers/xr_server.cpp | 10 | ||||
-rw-r--r-- | servers/xr_server.h | 11 |
10 files changed, 340 insertions, 26 deletions
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 44ab4e0a41..837fc120bf 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -515,7 +515,7 @@ void Node3DEditorViewport::_select_clicked(bool p_allow_locked) { } } -ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) { +ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) const { Vector3 ray = _get_ray(p_pos); Vector3 pos = _get_ray_pos(p_pos); Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink(); @@ -1260,7 +1260,9 @@ void Node3DEditorViewport::_surface_mouse_enter() { } void Node3DEditorViewport::_surface_mouse_exit() { - _remove_preview(); + _remove_preview_node(); + _reset_preview_material(); + _remove_preview_material(); } void Node3DEditorViewport::_surface_focus_enter() { @@ -2703,6 +2705,13 @@ void Node3DEditorViewport::_notification(int p_what) { cinema_label->add_theme_style_override("normal", gui_base->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles"))); locked_label->add_theme_style_override("normal", gui_base->get_theme_stylebox(SNAME("Information3dViewport"), SNAME("EditorStyles"))); } break; + + case NOTIFICATION_DRAG_END: { + // Clear preview material when dropped outside applicable object. + if (spatial_editor->get_preview_material().is_valid() && !is_drag_successful()) { + _remove_preview_material(); + } + } break; } } @@ -3794,7 +3803,7 @@ Node *Node3DEditorViewport::_sanitize_preview_node(Node *p_node) const { return p_node; } -void Node3DEditorViewport::_create_preview(const Vector<String> &files) const { +void Node3DEditorViewport::_create_preview_node(const Vector<String> &files) const { for (int i = 0; i < files.size(); i++) { String path = files[i]; Ref<Resource> res = ResourceLoader::load(path); @@ -3821,7 +3830,7 @@ void Node3DEditorViewport::_create_preview(const Vector<String> &files) const { *preview_bounds = _calculate_spatial_bounds(preview_node); } -void Node3DEditorViewport::_remove_preview() { +void Node3DEditorViewport::_remove_preview_node() { if (preview_node->get_parent()) { for (int i = preview_node->get_child_count() - 1; i >= 0; i--) { Node *node = preview_node->get_child(i); @@ -3832,6 +3841,106 @@ void Node3DEditorViewport::_remove_preview() { } } +bool Node3DEditorViewport::_apply_preview_material(ObjectID p_target, const Point2 &p_point) const { + _reset_preview_material(); + + if (p_target.is_null()) { + return false; + } + + spatial_editor->set_preview_material_target(p_target); + + Object *target_inst = ObjectDB::get_instance(p_target); + + bool is_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); + + MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(target_inst); + if (is_ctrl && mesh_instance) { + Ref<Mesh> mesh = mesh_instance->get_mesh(); + int surface_count = mesh->get_surface_count(); + + Vector3 world_ray = _get_ray(p_point); + Vector3 world_pos = _get_ray_pos(p_point); + + int closest_surface = -1; + float closest_dist = 1e20; + + Transform3D gt = mesh_instance->get_global_transform(); + + Transform3D ai = gt.affine_inverse(); + Vector3 xform_ray = ai.basis.xform(world_ray).normalized(); + Vector3 xform_pos = ai.xform(world_pos); + + for (int surface = 0; surface < surface_count; surface++) { + Ref<TriangleMesh> surface_mesh = mesh->generate_surface_triangle_mesh(surface); + + Vector3 rpos, rnorm; + if (surface_mesh->intersect_ray(xform_pos, xform_ray, rpos, rnorm)) { + Vector3 hitpos = gt.xform(rpos); + + const real_t dist = world_pos.distance_to(hitpos); + + if (dist < 0) { + continue; + } + + if (dist < closest_dist) { + closest_surface = surface; + closest_dist = dist; + } + } + } + + if (closest_surface == -1) { + return false; + } + + if (spatial_editor->get_preview_material() != mesh_instance->get_surface_override_material(closest_surface)) { + spatial_editor->set_preview_material_surface(closest_surface); + spatial_editor->set_preview_reset_material(mesh_instance->get_surface_override_material(closest_surface)); + mesh_instance->set_surface_override_material(closest_surface, spatial_editor->get_preview_material()); + } + + return true; + } + + GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(target_inst); + if (geometry_instance && spatial_editor->get_preview_material() != geometry_instance->get_material_override()) { + spatial_editor->set_preview_reset_material(geometry_instance->get_material_override()); + geometry_instance->set_material_override(spatial_editor->get_preview_material()); + return true; + } + + return false; +} + +void Node3DEditorViewport::_reset_preview_material() const { + ObjectID last_target = spatial_editor->get_preview_material_target(); + if (last_target.is_null()) { + return; + } + Object *last_target_inst = ObjectDB::get_instance(last_target); + + MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(last_target_inst); + GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(last_target_inst); + if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) { + mesh_instance->set_surface_override_material(spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material()); + spatial_editor->set_preview_material_surface(-1); + } else if (geometry_instance) { + geometry_instance->set_material_override(spatial_editor->get_preview_reset_material()); + } +} + +void Node3DEditorViewport::_remove_preview_material() { + preview_material_label->hide(); + preview_material_label_desc->hide(); + + spatial_editor->set_preview_material(Ref<Material>()); + spatial_editor->set_preview_reset_material(Ref<Material>()); + spatial_editor->set_preview_material_target(ObjectID()); + spatial_editor->set_preview_material_surface(-1); +} + bool Node3DEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) { if (p_desired_node->get_scene_file_path() == p_target_scene_path) { return true; @@ -3930,7 +4039,26 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po } void Node3DEditorViewport::_perform_drop_data() { - _remove_preview(); + if (spatial_editor->get_preview_material_target().is_valid()) { + GeometryInstance3D *geometry_instance = Object::cast_to<GeometryInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target())); + MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(ObjectDB::get_instance(spatial_editor->get_preview_material_target())); + if (mesh_instance && spatial_editor->get_preview_material_surface() != -1) { + editor_data->get_undo_redo().create_action(vformat(TTR("Set Surface %d Override Material"), spatial_editor->get_preview_material_surface())); + editor_data->get_undo_redo().add_do_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_material()); + editor_data->get_undo_redo().add_undo_method(geometry_instance, "set_surface_override_material", spatial_editor->get_preview_material_surface(), spatial_editor->get_preview_reset_material()); + editor_data->get_undo_redo().commit_action(); + } else if (geometry_instance) { + editor_data->get_undo_redo().create_action(TTR("Set Material Override")); + editor_data->get_undo_redo().add_do_method(geometry_instance, "set_material_override", spatial_editor->get_preview_material()); + editor_data->get_undo_redo().add_undo_method(geometry_instance, "set_material_override", spatial_editor->get_preview_reset_material()); + editor_data->get_undo_redo().commit_action(); + } + + _remove_preview_material(); + return; + } + + _remove_preview_node(); Vector<String> error_files; @@ -3968,7 +4096,7 @@ void Node3DEditorViewport::_perform_drop_data() { bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { bool can_instantiate = false; - if (!preview_node->is_inside_tree()) { + if (!preview_node->is_inside_tree() && spatial_editor->get_preview_material().is_null()) { Dictionary d = p_data; if (d.has("type") && (String(d["type"]) == "files")) { Vector<String> files = d["files"]; @@ -3977,40 +4105,78 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions); List<String> mesh_extensions; ResourceLoader::get_recognized_extensions_for_type("Mesh", &mesh_extensions); + List<String> material_extensions; + ResourceLoader::get_recognized_extensions_for_type("Material", &material_extensions); + List<String> texture_extensions; + ResourceLoader::get_recognized_extensions_for_type("Texture", &texture_extensions); for (int i = 0; i < files.size(); i++) { // Check if dragged files with mesh or scene extension can be created at least once. - if (mesh_extensions.find(files[i].get_extension()) || scene_extensions.find(files[i].get_extension())) { + if (mesh_extensions.find(files[i].get_extension()) || + scene_extensions.find(files[i].get_extension()) || + material_extensions.find(files[i].get_extension()) || + texture_extensions.find(files[i].get_extension())) { Ref<Resource> res = ResourceLoader::load(files[i]); if (res.is_null()) { continue; } Ref<PackedScene> scn = res; + Ref<Material> mat = res; + Ref<Texture2D> tex = res; if (scn.is_valid()) { Node *instantiated_scene = scn->instantiate(PackedScene::GEN_EDIT_STATE_INSTANCE); if (!instantiated_scene) { continue; } memdelete(instantiated_scene); + } else if (mat.is_valid()) { + Ref<BaseMaterial3D> base_mat = res; + Ref<ShaderMaterial> shader_mat = res; + + if (base_mat.is_null() && !shader_mat.is_null()) { + break; + } + + spatial_editor->set_preview_material(mat); + break; + } else if (tex.is_valid()) { + Ref<StandardMaterial3D> new_mat = memnew(StandardMaterial3D); + new_mat->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, tex); + + spatial_editor->set_preview_material(new_mat); + break; + } else { + continue; } can_instantiate = true; break; } } if (can_instantiate) { - _create_preview(files); + _create_preview_node(files); } } } else { - can_instantiate = true; + if (preview_node->is_inside_tree()) { + can_instantiate = true; + } } if (can_instantiate) { Transform3D global_transform = Transform3D(Basis(), _get_instance_position(p_point)); preview_node->set_global_transform(global_transform); + return true; + } + + if (spatial_editor->get_preview_material().is_valid()) { + preview_material_label->show(); + preview_material_label_desc->show(); + + ObjectID new_preview_material_target = _select_ray(p_point); + return _apply_preview_material(new_preview_material_target, p_point); } - return can_instantiate; + return false; } void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { @@ -4048,7 +4214,7 @@ void Node3DEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p_ } else { accept->set_text(TTR("Cannot drag and drop into multiple selected nodes.")); accept->popup_centered(); - _remove_preview(); + _remove_preview_node(); return; } @@ -4699,6 +4865,23 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p zoom_limit_label->hide(); surface->add_child(zoom_limit_label); + preview_material_label = memnew(Label); + preview_material_label->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT); + preview_material_label->set_offset(Side::SIDE_TOP, -70 * EDSCALE); + preview_material_label->set_text(TTR("Overriding material...")); + preview_material_label->add_theme_color_override("font_color", Color(1, 1, 1, 1)); + preview_material_label->hide(); + surface->add_child(preview_material_label); + + preview_material_label_desc = memnew(Label); + preview_material_label_desc->set_anchors_and_offsets_preset(LayoutPreset::PRESET_BOTTOM_LEFT); + preview_material_label_desc->set_offset(Side::SIDE_TOP, -50 * EDSCALE); + preview_material_label_desc->set_text(TTR("Drag and drop to override the material of any geometry node.\nHold Ctrl when dropping to override a specific surface.")); + preview_material_label_desc->add_theme_color_override("font_color", Color(0.8, 0.8, 0.8, 1)); + preview_material_label_desc->add_theme_constant_override("line_spacing", 0); + preview_material_label_desc->hide(); + surface->add_child(preview_material_label_desc); + frame_time_gradient = memnew(Gradient); // The color is set when the theme changes. frame_time_gradient->add_point(0.5, Color()); @@ -8140,7 +8323,6 @@ void fragment() { _preview_settings_changed(); } } - Node3DEditor::~Node3DEditor() { memdelete(preview_node); } diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 244b461e16..4469271a38 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -227,6 +227,9 @@ private: Label *locked_label = nullptr; Label *zoom_limit_label = nullptr; + Label *preview_material_label = nullptr; + Label *preview_material_label_desc = nullptr; + VBoxContainer *top_right_vbox = nullptr; ViewportRotationControl *rotation_control = nullptr; Gradient *frame_time_gradient = nullptr; @@ -244,7 +247,7 @@ private: void _compute_edit(const Point2 &p_point); void _clear_selected(); void _select_clicked(bool p_allow_locked); - ObjectID _select_ray(const Point2 &p_pos); + ObjectID _select_ray(const Point2 &p_pos) const; void _find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked); Vector3 _get_ray_pos(const Vector2 &p_pos) const; Vector3 _get_ray(const Vector2 &p_pos) const; @@ -272,6 +275,7 @@ private: float get_fov() const; ObjectID clicked; + ObjectID material_target; Vector<_RayResult> selection_results; bool clicked_wants_append = false; bool selection_in_progress = false; @@ -399,8 +403,11 @@ private: Node *_sanitize_preview_node(Node *p_node) const; - void _create_preview(const Vector<String> &files) const; - void _remove_preview(); + void _create_preview_node(const Vector<String> &files) const; + void _remove_preview_node(); + bool _apply_preview_material(ObjectID p_target, const Point2 &p_point) const; + void _reset_preview_material() const; + void _remove_preview_material(); bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node); bool _create_instance(Node *parent, String &path, const Point2 &p_point); void _perform_drop_data(); @@ -593,6 +600,11 @@ private: Node3D *preview_node = nullptr; AABB preview_bounds; + Ref<Material> preview_material; + Ref<Material> preview_reset_material; + ObjectID preview_material_target; + int preview_material_surface = -1; + struct Gizmo { bool visible = false; real_t scale = 0; @@ -850,6 +862,15 @@ public: void set_can_preview(Camera3D *p_preview); + void set_preview_material(Ref<Material> p_material) { preview_material = p_material; } + Ref<Material> get_preview_material() { return preview_material; } + void set_preview_reset_material(Ref<Material> p_material) { preview_reset_material = p_material; } + Ref<Material> get_preview_reset_material() const { return preview_reset_material; } + void set_preview_material_target(ObjectID p_object_id) { preview_material_target = p_object_id; } + ObjectID get_preview_material_target() const { return preview_material_target; } + void set_preview_material_surface(int p_surface) { preview_material_surface = p_surface; } + int get_preview_material_surface() const { return preview_material_surface; } + Node3DEditorViewport *get_editor_viewport(int p_idx) { ERR_FAIL_INDEX_V(p_idx, static_cast<int>(VIEWPORTS_COUNT), nullptr); return viewports[p_idx]; diff --git a/main/main.cpp b/main/main.cpp index 3f9fe34545..3e29323337 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -343,6 +343,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n"); OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n"); OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n"); + OS::get_singleton()->print(" --xr-mode <mode> Select XR mode (default/off/on).\n"); OS::get_singleton()->print("\n"); OS::get_singleton()->print("Debug options:\n"); @@ -1181,6 +1182,25 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->disable_crash_handler(); } else if (I->get() == "--skip-breakpoints") { skip_breakpoints = true; + } else if (I->get() == "--xr-mode") { + if (I->next()) { + String xr_mode = I->next()->get().to_lower(); + N = I->next()->next(); + if (xr_mode == "default") { + XRServer::set_xr_mode(XRServer::XRMODE_DEFAULT); + } else if (xr_mode == "off") { + XRServer::set_xr_mode(XRServer::XRMODE_OFF); + } else if (xr_mode == "on") { + XRServer::set_xr_mode(XRServer::XRMODE_ON); + } else { + OS::get_singleton()->print("Unknown --xr-mode argument \"%s\", aborting.\n", xr_mode.ascii().get_data()); + goto error; + } + } else { + OS::get_singleton()->print("Missing --xr-mode argument, aborting.\n"); + goto error; + } + } else { main_args.push_back(I->get()); } diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 10365f8481..36ccb3d696 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -3295,6 +3295,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a int globalname_idx = _code_ptr[ip + 2]; GD_ERR_BREAK(globalname_idx < 0 || globalname_idx >= _global_names_count); const StringName *globalname = &_global_names_ptr[globalname_idx]; + GD_ERR_BREAK(!GDScriptLanguage::get_singleton()->get_named_globals_map().has(*globalname)); GET_INSTRUCTION_ARG(dst, 0); *dst = GDScriptLanguage::get_singleton()->get_named_globals_map()[*globalname]; diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index 938b017e3a..92d074cb75 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -58,19 +58,14 @@ bool OpenXRAPI::openxr_is_enabled(bool p_check_run_in_editor) { // @TODO we need an overrule switch so we can force enable openxr, i.e run "godot --openxr_enabled" if (Engine::get_singleton()->is_editor_hint() && p_check_run_in_editor) { -#ifdef TOOLS_ENABLED // Disabled for now, using XR inside of the editor we'll be working on during the coming months. return false; - - // bool enabled = GLOBAL_GET("xr/openxr/in_editor"); // EDITOR_GET("xr/openxr/in_editor"); - // return enabled; -#else - // we should never get here, editor hint won't be true if the editor isn't compiled in. - return false; -#endif } else { - bool enabled = GLOBAL_GET("xr/openxr/enabled"); - return enabled; + if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) { + return GLOBAL_GET("xr/openxr/enabled"); + } else { + return XRServer::get_xr_mode() == XRServer::XRMODE_ON; + } } } diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 3e7b0a2808..ec9db89794 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -260,6 +260,64 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { return triangle_mesh; } +Ref<TriangleMesh> Mesh::generate_surface_triangle_mesh(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, get_surface_count(), Ref<TriangleMesh>()); + + if (surface_triangle_meshes.size() != get_surface_count()) { + surface_triangle_meshes.resize(get_surface_count()); + } + + if (surface_triangle_meshes[p_surface].is_valid()) { + return surface_triangle_meshes[p_surface]; + } + + int facecount = 0; + + if (surface_get_primitive_type(p_surface) != PRIMITIVE_TRIANGLES) { + return Ref<TriangleMesh>(); + } + + if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) { + facecount += surface_get_array_index_len(p_surface); + } else { + facecount += surface_get_array_len(p_surface); + } + + Vector<Vector3> faces; + faces.resize(facecount); + Vector3 *facesw = faces.ptrw(); + + Array a = surface_get_arrays(p_surface); + ERR_FAIL_COND_V(a.is_empty(), Ref<TriangleMesh>()); + + int vc = surface_get_array_len(p_surface); + Vector<Vector3> vertices = a[ARRAY_VERTEX]; + const Vector3 *vr = vertices.ptr(); + int widx = 0; + + if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) { + int ic = surface_get_array_index_len(p_surface); + Vector<int> indices = a[ARRAY_INDEX]; + const int *ir = indices.ptr(); + + for (int j = 0; j < ic; j++) { + int index = ir[j]; + facesw[widx++] = vr[index]; + } + + } else { + for (int j = 0; j < vc; j++) { + facesw[widx++] = vr[j]; + } + } + + Ref<TriangleMesh> triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); + triangle_mesh->create(faces); + surface_triangle_meshes.set(p_surface, triangle_mesh); + + return triangle_mesh; +} + void Mesh::generate_debug_mesh_lines(Vector<Vector3> &r_lines) { if (debug_lines.size() > 0) { r_lines = debug_lines; @@ -320,6 +378,14 @@ Vector<Face3> Mesh::get_faces() const { return Vector<Face3>(); } +Vector<Face3> Mesh::get_surface_faces(int p_surface) const { + Ref<TriangleMesh> tm = generate_surface_triangle_mesh(p_surface); + if (tm.is_valid()) { + return tm->get_faces(); + } + return Vector<Face3>(); +} + Ref<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const { if (p_simplify) { ConvexDecompositionSettings settings; diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 0f3fae4179..142373ce7f 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -42,6 +42,7 @@ class Mesh : public Resource { GDCLASS(Mesh, Resource); mutable Ref<TriangleMesh> triangle_mesh; //cached + mutable Vector<Ref<TriangleMesh>> surface_triangle_meshes; //cached mutable Vector<Vector3> debug_lines; Size2i lightmap_size_hint; @@ -161,7 +162,9 @@ public: virtual AABB get_aabb() const; Vector<Face3> get_faces() const; + Vector<Face3> get_surface_faces(int p_surface) const; Ref<TriangleMesh> generate_triangle_mesh() const; + Ref<TriangleMesh> generate_surface_triangle_mesh(int p_surface) const; void generate_debug_mesh_lines(Vector<Vector3> &r_lines); void generate_debug_mesh_indices(Vector<Vector3> &r_points); diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp index b331ec2c1d..80e71a0df3 100644 --- a/servers/rendering/renderer_compositor.cpp +++ b/servers/rendering/renderer_compositor.cpp @@ -33,6 +33,7 @@ #include "core/config/project_settings.h" #include "core/os/os.h" #include "core/string/print_string.h" +#include "servers/xr_server.h" RendererCompositor *(*RendererCompositor::_create_func)() = nullptr; bool RendererCompositor::low_end = false; @@ -46,7 +47,11 @@ bool RendererCompositor::is_xr_enabled() const { } RendererCompositor::RendererCompositor() { - xr_enabled = GLOBAL_GET("xr/shaders/enabled"); + if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) { + xr_enabled = GLOBAL_GET("xr/shaders/enabled"); + } else { + xr_enabled = XRServer::get_xr_mode() == XRServer::XRMODE_ON; + } } RendererCanvasRender *RendererCanvasRender::singleton = nullptr; diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp index ad61aa94bc..990281d96d 100644 --- a/servers/xr_server.cpp +++ b/servers/xr_server.cpp @@ -33,6 +33,16 @@ #include "xr/xr_interface.h" #include "xr/xr_positional_tracker.h" +XRServer::XRMode XRServer::xr_mode = XRMODE_DEFAULT; + +XRServer::XRMode XRServer::get_xr_mode() { + return xr_mode; +} + +void XRServer::set_xr_mode(XRServer::XRMode p_mode) { + xr_mode = p_mode; +} + XRServer *XRServer::singleton = nullptr; XRServer *XRServer::get_singleton() { diff --git a/servers/xr_server.h b/servers/xr_server.h index d9188d2de1..74128bfb54 100644 --- a/servers/xr_server.h +++ b/servers/xr_server.h @@ -57,6 +57,12 @@ class XRServer : public Object { _THREAD_SAFE_CLASS_ public: + enum XRMode { + XRMODE_DEFAULT, /* Default behaviour, means we check project settings */ + XRMODE_OFF, /* Ignore project settings, disable OpenXR, disable shaders */ + XRMODE_ON, /* Ignore project settings, enable OpenXR, enable shaders, run editor in VR (if applicable) */ + }; + enum TrackerType { TRACKER_HEAD = 0x01, /* tracks the position of the players head (or in case of handheld AR, location of the phone) */ TRACKER_CONTROLLER = 0x02, /* tracks a controller */ @@ -75,6 +81,8 @@ public: }; private: + static XRMode xr_mode; + Vector<Ref<XRInterface>> interfaces; Dictionary trackers; @@ -90,6 +98,9 @@ protected: static void _bind_methods(); public: + static XRMode get_xr_mode(); + static void set_xr_mode(XRMode p_mode); + static XRServer *get_singleton(); /* |