diff options
35 files changed, 305 insertions, 195 deletions
diff --git a/core/string/translation.cpp b/core/string/translation.cpp index ade5f7b4d8..153f0190fd 100644 --- a/core/string/translation.cpp +++ b/core/string/translation.cpp @@ -835,7 +835,7 @@ Vector<String> Translation::_get_message_list() const { void Translation::_set_messages(const Dictionary &p_messages) { List<Variant> keys; p_messages.get_key_list(&keys); - for (auto E = keys.front(); E; E = E->next()) { + for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { translation_map[E->get()] = p_messages[E->get()]; } } diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp index 2efadaa9b7..ad768f7140 100644 --- a/core/string/translation_po.cpp +++ b/core/string/translation_po.cpp @@ -47,14 +47,14 @@ void TranslationPO::print_translation_map() { List<StringName> context_l; translation_map.get_key_list(&context_l); - for (auto E = context_l.front(); E; E = E->next()) { + for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) { StringName ctx = E->get(); file->store_line(" ===== Context: " + String::utf8(String(ctx).utf8()) + " ===== "); const HashMap<StringName, Vector<StringName>> &inner_map = translation_map[ctx]; List<StringName> id_l; inner_map.get_key_list(&id_l); - for (auto E2 = id_l.front(); E2; E2 = E2->next()) { + for (List<StringName>::Element *E2 = id_l.front(); E2; E2 = E2->next()) { StringName id = E2->get(); file->store_line("msgid: " + String::utf8(String(id).utf8())); for (int i = 0; i < inner_map[id].size(); i++) { @@ -74,7 +74,7 @@ Dictionary TranslationPO::_get_messages() const { List<StringName> context_l; translation_map.get_key_list(&context_l); - for (auto E = context_l.front(); E; E = E->next()) { + for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) { StringName ctx = E->get(); const HashMap<StringName, Vector<StringName>> &id_str_map = translation_map[ctx]; @@ -82,7 +82,7 @@ Dictionary TranslationPO::_get_messages() const { List<StringName> id_l; id_str_map.get_key_list(&id_l); // Save list of id and strs associated with a context in a temporary dictionary. - for (auto E2 = id_l.front(); E2; E2 = E2->next()) { + for (List<StringName>::Element *E2 = id_l.front(); E2; E2 = E2->next()) { StringName id = E2->get(); d2[id] = id_str_map[id]; } @@ -98,14 +98,14 @@ void TranslationPO::_set_messages(const Dictionary &p_messages) { List<Variant> context_l; p_messages.get_key_list(&context_l); - for (auto E = context_l.front(); E; E = E->next()) { + for (List<Variant>::Element *E = context_l.front(); E; E = E->next()) { StringName ctx = E->get(); const Dictionary &id_str_map = p_messages[ctx]; HashMap<StringName, Vector<StringName>> temp_map; List<Variant> id_l; id_str_map.get_key_list(&id_l); - for (auto E2 = id_l.front(); E2; E2 = E2->next()) { + for (List<Variant>::Element *E2 = id_l.front(); E2; E2 = E2->next()) { StringName id = E2->get(); temp_map[id] = id_str_map[id]; } @@ -121,7 +121,7 @@ Vector<String> TranslationPO::_get_message_list() const { get_message_list(&msgs); Vector<String> v; - for (auto E = msgs.front(); E; E = E->next()) { + for (List<StringName>::Element *E = msgs.front(); E; E = E->next()) { v.push_back(E->get()); } @@ -281,7 +281,7 @@ void TranslationPO::get_message_list(List<StringName> *r_messages) const { List<StringName> context_l; translation_map.get_key_list(&context_l); - for (auto E = context_l.front(); E; E = E->next()) { + for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) { if (String(E->get()) != "") { continue; } @@ -289,7 +289,7 @@ void TranslationPO::get_message_list(List<StringName> *r_messages) const { List<StringName> msgid_l; translation_map[E->get()].get_key_list(&msgid_l); - for (auto E2 = msgid_l.front(); E2; E2 = E2->next()) { + for (List<StringName>::Element *E2 = msgid_l.front(); E2; E2 = E2->next()) { r_messages->push_back(E2->get()); } } @@ -300,7 +300,7 @@ int TranslationPO::get_message_count() const { translation_map.get_key_list(&context_l); int count = 0; - for (auto E = context_l.front(); E; E = E->next()) { + for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) { count += translation_map[E->get()].size(); } return count; diff --git a/doc/classes/MeshInstance3D.xml b/doc/classes/MeshInstance3D.xml index e1a6cf44a7..b015a21d67 100644 --- a/doc/classes/MeshInstance3D.xml +++ b/doc/classes/MeshInstance3D.xml @@ -20,6 +20,13 @@ This helper creates a [StaticBody3D] child node with a [ConvexPolygonShape3D] collision shape calculated from the mesh geometry. It's mainly used for testing. </description> </method> + <method name="create_multiple_convex_collisions"> + <return type="void"> + </return> + <description> + This helper creates a [StaticBody3D] child node with multiple [ConvexPolygonShape3D] collision shapes calculated from the mesh geometry via convex decomposition. It's mainly used for testing. + </description> + </method> <method name="create_debug_tangents"> <return type="void"> </return> diff --git a/editor/editor_translation_parser.cpp b/editor/editor_translation_parser.cpp index fd36372dde..49d5cf1fd3 100644 --- a/editor/editor_translation_parser.cpp +++ b/editor/editor_translation_parser.cpp @@ -105,7 +105,7 @@ void EditorTranslationParser::get_recognized_extensions(List<String> *r_extensio for (int i = 0; i < temp.size(); i++) { extensions.insert(temp[i]); } - for (auto E = extensions.front(); E; E = E->next()) { + for (Set<String>::Element *E = extensions.front(); E; E = E->next()) { r_extensions->push_back(E->get()); } } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index dea85e8799..acc77bd098 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -353,6 +353,11 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { bool is_expression = !expression_node.is_null(); String expression = ""; + VisualShaderNodeCustom *custom_node = Object::cast_to<VisualShaderNodeCustom>(vsnode.ptr()); + if (custom_node) { + custom_node->_set_initialized(true); + } + GraphNode *node = memnew(GraphNode); register_link(p_type, p_id, vsnode.ptr(), node); @@ -1782,8 +1787,15 @@ void VisualShaderEditor::_port_edited() { ERR_FAIL_COND(!vsn.is_valid()); undo_redo->create_action(TTR("Set Input Default Port")); - undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, value); - undo_redo->add_undo_method(vsn.ptr(), "set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port)); + + Ref<VisualShaderNodeCustom> custom = Object::cast_to<VisualShaderNodeCustom>(vsn.ptr()); + if (custom.is_valid()) { + undo_redo->add_do_method(custom.ptr(), "_set_input_port_default_value", editing_port, value); + undo_redo->add_undo_method(custom.ptr(), "_set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port)); + } else { + undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, value); + undo_redo->add_undo_method(vsn.ptr(), "set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port)); + } undo_redo->add_do_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, value); undo_redo->add_undo_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, vsn->get_input_port_default_value(editing_port)); undo_redo->commit_action(); diff --git a/editor/pot_generator.cpp b/editor/pot_generator.cpp index 497cc0cbdc..b58b7e4cac 100644 --- a/editor/pot_generator.cpp +++ b/editor/pot_generator.cpp @@ -39,7 +39,7 @@ POTGenerator *POTGenerator::singleton = nullptr; #ifdef DEBUG_POT void POTGenerator::_print_all_translation_strings() { - for (auto E = all_translation_strings.front(); E; E = E.next()) { + for (OrderedHashMap<String, Vector<POTGenerator::MsgidData>>::Element E = all_translation_strings.front(); E; E = E.next()) { Vector<MsgidData> v_md = all_translation_strings[E.key()]; for (int i = 0; i < v_md.size(); i++) { print_line("++++++"); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index ec37fa53b3..b4f7eda391 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -277,7 +277,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll } Ref<Texture2D> icon_temp; - auto signal_temp = BUTTON_SIGNALS; + SceneTreeEditorButton signal_temp = BUTTON_SIGNALS; if (num_connections >= 1 && num_groups >= 1) { icon_temp = get_theme_icon("SignalsAndGroups", "EditorIcons"); } else if (num_connections >= 1) { diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index fd5157f04f..b4c27b7c1f 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -43,7 +43,7 @@ class SceneTreeEditor : public Control { EditorSelection *editor_selection; - enum { + enum SceneTreeEditorButton { BUTTON_SUBSCENE = 0, BUTTON_VISIBILITY = 1, BUTTON_SCRIPT = 2, diff --git a/misc/dist/html/full-size.html b/misc/dist/html/full-size.html index abc0479739..7afb6fdb6b 100644 --- a/misc/dist/html/full-size.html +++ b/misc/dist/html/full-size.html @@ -3,7 +3,6 @@ <head> <meta charset='utf-8' /> <meta name='viewport' content='width=device-width, user-scalable=no' /> - <link id='-gd-engine-icon' rel='icon' type='image/png' href='favicon.png' /> <title>$GODOT_PROJECT_NAME</title> <style type='text/css'> diff --git a/modules/fbx/editor_scene_importer_fbx.cpp b/modules/fbx/editor_scene_importer_fbx.cpp index b23a58a414..edea1963a7 100644 --- a/modules/fbx/editor_scene_importer_fbx.cpp +++ b/modules/fbx/editor_scene_importer_fbx.cpp @@ -1014,7 +1014,6 @@ Node3D *EditorSceneImporterFBX::_generate_scene( int track_idx = animation->add_track(Animation::TYPE_TRANSFORM); // animation->track_set_path(track_idx, node_path); - // animation->track_set_path(track_idx, node_path); Ref<FBXBone> bone; // note we must not run the below code if the entry doesn't exist, it will create dummy entries which is very bad. diff --git a/modules/fbx/fbx_parser/FBXMaterial.cpp b/modules/fbx/fbx_parser/FBXMaterial.cpp index 08fff5714a..bf8922267e 100644 --- a/modules/fbx/fbx_parser/FBXMaterial.cpp +++ b/modules/fbx/fbx_parser/FBXMaterial.cpp @@ -325,7 +325,7 @@ Video::Video(uint64_t id, const ElementPtr element, const Document &doc, const s DOMError("embedded content is not surrounded by quotation marks", element); } else { size_t targetLength = 0; - auto numTokens = Content->Tokens().size(); + const size_t numTokens = Content->Tokens().size(); // First time compute size (it could be large like 64Gb and it is good to allocate it once) for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx) { const Token *dataToken = GetRequiredToken(Content, tokenIdx); diff --git a/modules/fbx/fbx_parser/FBXParser.h b/modules/fbx/fbx_parser/FBXParser.h index bfbcb22ffa..8b248e8791 100644 --- a/modules/fbx/fbx_parser/FBXParser.h +++ b/modules/fbx/fbx_parser/FBXParser.h @@ -160,7 +160,7 @@ public: } ElementPtr FindElementCaseInsensitive(const std::string &elementName) const { - for (auto element = elements.begin(); element != elements.end(); ++element) { + for (FBXDocParser::ElementMap::const_iterator element = elements.begin(); element != elements.end(); ++element) { if (element->first.compare(elementName)) { return element->second; } diff --git a/modules/fbx/fbx_parser/FBXUtil.cpp b/modules/fbx/fbx_parser/FBXUtil.cpp index 4295cb6f5e..1f14a69099 100644 --- a/modules/fbx/fbx_parser/FBXUtil.cpp +++ b/modules/fbx/fbx_parser/FBXUtil.cpp @@ -121,7 +121,7 @@ static const uint8_t base64DecodeTable[128] = { }; uint8_t DecodeBase64(char ch) { - const auto idx = static_cast<uint8_t>(ch); + const uint8_t idx = static_cast<uint8_t>(ch); if (idx > 127) { return 255; } diff --git a/modules/gdnavigation/gd_navigation_server.cpp b/modules/gdnavigation/gd_navigation_server.cpp index 39f208c7a4..88ef434e0f 100644 --- a/modules/gdnavigation/gd_navigation_server.cpp +++ b/modules/gdnavigation/gd_navigation_server.cpp @@ -122,7 +122,7 @@ GdNavigationServer::~GdNavigationServer() { } void GdNavigationServer::add_command(SetCommand *command) const { - auto mut_this = const_cast<GdNavigationServer *>(this); + GdNavigationServer *mut_this = const_cast<GdNavigationServer *>(this); { MutexLock lock(commands_mutex); mut_this->commands.push_back(command); @@ -130,7 +130,7 @@ void GdNavigationServer::add_command(SetCommand *command) const { } RID GdNavigationServer::map_create() const { - auto mut_this = const_cast<GdNavigationServer *>(this); + GdNavigationServer *mut_this = const_cast<GdNavigationServer *>(this); MutexLock lock(mut_this->operations_mutex); NavMap *space = memnew(NavMap); RID rid = map_owner.make_rid(space); @@ -240,7 +240,7 @@ RID GdNavigationServer::map_get_closest_point_owner(RID p_map, const Vector3 &p_ } RID GdNavigationServer::region_create() const { - auto mut_this = const_cast<GdNavigationServer *>(this); + GdNavigationServer *mut_this = const_cast<GdNavigationServer *>(this); MutexLock lock(mut_this->operations_mutex); NavRegion *reg = memnew(NavRegion); RID rid = region_owner.make_rid(reg); @@ -330,7 +330,7 @@ Vector3 GdNavigationServer::region_get_connection_pathway_end(RID p_region, int } RID GdNavigationServer::agent_create() const { - auto mut_this = const_cast<GdNavigationServer *>(this); + GdNavigationServer *mut_this = const_cast<GdNavigationServer *>(this); MutexLock lock(mut_this->operations_mutex); RvoAgent *agent = memnew(RvoAgent()); RID rid = agent_owner.make_rid(agent); @@ -504,7 +504,7 @@ COMMAND_1(free, RID, p_object) { } void GdNavigationServer::set_active(bool p_active) const { - auto mut_this = const_cast<GdNavigationServer *>(this); + GdNavigationServer *mut_this = const_cast<GdNavigationServer *>(this); MutexLock lock(mut_this->operations_mutex); mut_this->active = p_active; } diff --git a/modules/gdnavigation/nav_map.cpp b/modules/gdnavigation/nav_map.cpp index 464082221f..2513c62b6a 100644 --- a/modules/gdnavigation/nav_map.cpp +++ b/modules/gdnavigation/nav_map.cpp @@ -168,7 +168,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly->entry, pathway); const float new_distance = least_cost_poly->entry.distance_to(new_entry) + least_cost_poly->traveled_distance; - auto it = std::find( + const std::vector<gd::NavigationPoly>::iterator it = std::find( navigation_polys.begin(), navigation_polys.end(), gd::NavigationPoly(connection.polygon)); @@ -504,7 +504,7 @@ void NavMap::add_region(NavRegion *p_region) { } void NavMap::remove_region(NavRegion *p_region) { - std::vector<NavRegion *>::iterator it = std::find(regions.begin(), regions.end(), p_region); + const std::vector<NavRegion *>::iterator it = std::find(regions.begin(), regions.end(), p_region); if (it != regions.end()) { regions.erase(it); regenerate_links = true; @@ -524,7 +524,7 @@ void NavMap::add_agent(RvoAgent *agent) { void NavMap::remove_agent(RvoAgent *agent) { remove_agent_as_controlled(agent); - auto it = std::find(agents.begin(), agents.end(), agent); + const std::vector<RvoAgent *>::iterator it = std::find(agents.begin(), agents.end(), agent); if (it != agents.end()) { agents.erase(it); agents_dirty = true; @@ -540,7 +540,7 @@ void NavMap::set_agent_as_controlled(RvoAgent *agent) { } void NavMap::remove_agent_as_controlled(RvoAgent *agent) { - auto it = std::find(controlled_agents.begin(), controlled_agents.end(), agent); + const std::vector<RvoAgent *>::iterator it = std::find(controlled_agents.begin(), controlled_agents.end(), agent); if (it != controlled_agents.end()) { controlled_agents.erase(it); } diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index f53c3046e6..76ae43e792 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -441,7 +441,7 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) { result.output = get_text_for_status(result.status) + "\n"; const List<GDScriptParser::ParserError> &errors = parser.get_errors(); - for (auto *E = errors.front(); E; E = E->next()) { + for (const List<GDScriptParser::ParserError>::Element *E = errors.front(); E; E = E->next()) { result.output += E->get().message + "\n"; // TODO: line, column? break; // Only the first error since the following might be cascading. } @@ -460,7 +460,7 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) { result.output = get_text_for_status(result.status) + "\n"; const List<GDScriptParser::ParserError> &errors = parser.get_errors(); - for (auto *E = errors.front(); E; E = E->next()) { + for (const List<GDScriptParser::ParserError>::Element *E = errors.front(); E; E = E->next()) { result.output += E->get().message + "\n"; // TODO: line, column? break; // Only the first error since the following might be cascading. } diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 43f57a7caa..09f3ea1f50 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -2016,7 +2016,7 @@ void CSharpInstance::connect_event_signals() { StringName signal_name = event_signal.field->get_name(); // TODO: Use pooling for ManagedCallable instances. - auto event_signal_callable = memnew(EventSignalCallable(owner, &event_signal)); + EventSignalCallable *event_signal_callable = memnew(EventSignalCallable(owner, &event_signal)); Callable callable(event_signal_callable); connected_event_signals.push_back(callable); @@ -2027,7 +2027,7 @@ void CSharpInstance::connect_event_signals() { void CSharpInstance::disconnect_event_signals() { for (const List<Callable>::Element *E = connected_event_signals.front(); E; E = E->next()) { const Callable &callable = E->get(); - auto event_signal_callable = static_cast<const EventSignalCallable *>(callable.get_custom()); + const EventSignalCallable *event_signal_callable = static_cast<const EventSignalCallable *>(callable.get_custom()); owner->disconnect(event_signal_callable->get_signal(), callable); } diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 560788fb3a..c523d381f6 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -119,11 +119,11 @@ void gd_mono_profiler_init() { const String env_var_name = "MONO_ENV_OPTIONS"; if (OS::get_singleton()->has_environment(env_var_name)) { - const auto mono_env_ops = OS::get_singleton()->get_environment(env_var_name); + const String mono_env_ops = OS::get_singleton()->get_environment(env_var_name); // Usually MONO_ENV_OPTIONS looks like: --profile=jb:prof=timeline,ctl=remote,host=127.0.0.1:55467 const String prefix = "--profile="; if (mono_env_ops.begins_with(prefix)) { - const auto ops = mono_env_ops.substr(prefix.length(), mono_env_ops.length()); + const String ops = mono_env_ops.substr(prefix.length(), mono_env_ops.length()); mono_profiler_load(ops.utf8()); } } diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index f3502b2220..ba92b81b49 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -855,7 +855,6 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { bool screen_support_xlarge = p_preset->get("screen/support_xlarge"); int xr_mode_index = p_preset->get("xr_features/xr_mode"); - bool focus_awareness = p_preset->get("xr_features/focus_awareness"); Vector<String> perms; // Write permissions into the perms variable. @@ -921,7 +920,6 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String tname = string_table[name]; uint32_t attrcount = decode_uint32(&p_manifest[iofs + 20]); iofs += 28; - bool is_focus_aware_metadata = false; for (uint32_t i = 0; i < attrcount; i++) { uint32_t attr_nspace = decode_uint32(&p_manifest[iofs]); @@ -973,28 +971,6 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } } - // FIXME: `attr_value != 0xFFFFFFFF` below added as a stopgap measure for GH-32553, - // but the issue should be debugged further and properly addressed. - if (tname == "meta-data" && attrname == "name" && value == "xr_mode_metadata_name") { - // Update the meta-data 'android:name' attribute based on the selected XR mode. - if (xr_mode_index == 1 /* XRMode.OVR */) { - string_table.write[attr_value] = "com.samsung.android.vr.application.mode"; - } - } - - if (tname == "meta-data" && attrname == "value" && value == "xr_mode_metadata_value") { - // Update the meta-data 'android:value' attribute based on the selected XR mode. - if (xr_mode_index == 1 /* XRMode.OVR */) { - string_table.write[attr_value] = "vr_only"; - } - } - - if (tname == "meta-data" && attrname == "value" && is_focus_aware_metadata) { - // Update the focus awareness meta-data value - encode_uint32(xr_mode_index == /* XRMode.OVR */ 1 && focus_awareness ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); - } - - is_focus_aware_metadata = tname == "meta-data" && attrname == "name" && value == "com.oculus.vr.focusaware"; iofs += 20; } @@ -1010,15 +986,6 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { Vector<int> feature_versions; if (xr_mode_index == 1 /* XRMode.OVR */) { - // Check for degrees of freedom - int dof_index = p_preset->get("xr_features/degrees_of_freedom"); // 0: none, 1: 3dof and 6dof, 2: 6dof - - if (dof_index > 0) { - feature_names.push_back("android.hardware.vr.headtracking"); - feature_required_list.push_back(dof_index == 2); - feature_versions.push_back(1); - } - // Check for hand tracking int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required if (hand_tracking_index > 0) { @@ -1708,9 +1675,7 @@ public: r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "graphics/opengl_debug"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,Oculus Mobile VR"), 0)); - r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/degrees_of_freedom", PROPERTY_HINT_ENUM, "None,3DOF and 6DOF,6DOF"), 0)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/hand_tracking", PROPERTY_HINT_ENUM, "None,Optional,Required"), 0)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "xr_features/focus_awareness"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/immersive_mode"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_small"), true)); @@ -2159,27 +2124,13 @@ public: // Validate the Xr features are properly populated int xr_mode_index = p_preset->get("xr_features/xr_mode"); - int degrees_of_freedom = p_preset->get("xr_features/degrees_of_freedom"); int hand_tracking = p_preset->get("xr_features/hand_tracking"); - bool focus_awareness = p_preset->get("xr_features/focus_awareness"); if (xr_mode_index != /* XRMode.OVR*/ 1) { - if (degrees_of_freedom > 0) { - valid = false; - err += TTR("\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"."); - err += "\n"; - } - if (hand_tracking > 0) { valid = false; err += TTR("\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"."); err += "\n"; } - - if (focus_awareness) { - valid = false; - err += TTR("\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"."); - err += "\n"; - } } if (int(p_preset->get("custom_template/export_format")) == EXPORT_FORMAT_AAB && diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index 40b8e90c6f..bbbb526af9 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -241,12 +241,6 @@ String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset) { String manifest_xr_features; bool uses_xr = (int)(p_preset->get("xr_features/xr_mode")) == 1; if (uses_xr) { - int dof_index = p_preset->get("xr_features/degrees_of_freedom"); // 0: none, 1: 3dof and 6dof, 2: 6dof - if (dof_index == 1) { - manifest_xr_features += " <uses-feature tools:node=\"replace\" android:name=\"android.hardware.vr.headtracking\" android:required=\"false\" android:version=\"1\" />\n"; - } else if (dof_index == 2) { - manifest_xr_features += " <uses-feature tools:node=\"replace\" android:name=\"android.hardware.vr.headtracking\" android:required=\"true\" android:version=\"1\" />\n"; - } int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required if (hand_tracking_index == 1) { manifest_xr_features += " <uses-feature tools:node=\"replace\" android:name=\"oculus.software.handtracking\" android:required=\"false\" />\n"; @@ -278,10 +272,7 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) { "tools:replace=\"android:screenOrientation\" " "android:screenOrientation=\"%s\">\n", orientation); - if (uses_xr) { - String focus_awareness = bool_to_string(p_preset->get("xr_features/focus_awareness")); - manifest_activity_text += vformat(" <meta-data tools:node=\"replace\" android:name=\"com.oculus.vr.focusaware\" android:value=\"%s\" />\n", focus_awareness); - } else { + if (!uses_xr) { manifest_activity_text += " <meta-data tools:node=\"remove\" android:name=\"com.oculus.vr.focusaware\" />\n"; } manifest_activity_text += " </activity>\n"; @@ -289,16 +280,11 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) { } String _get_application_tag(const Ref<EditorExportPreset> &p_preset) { - bool uses_xr = (int)(p_preset->get("xr_features/xr_mode")) == 1; String manifest_application_text = " <application android:label=\"@string/godot_project_name_string\"\n" " android:allowBackup=\"false\" tools:ignore=\"GoogleAppIndexingWarning\"\n" - " android:icon=\"@mipmap/icon\">\n\n" - " <meta-data tools:node=\"remove\" android:name=\"xr_mode_metadata_name\" />\n"; + " android:icon=\"@mipmap/icon\">\n\n"; - if (uses_xr) { - manifest_application_text += " <meta-data tools:node=\"replace\" android:name=\"com.samsung.android.vr.application.mode\" android:value=\"vr_only\" />\n"; - } manifest_application_text += _get_activity_tag(p_preset); manifest_application_text += " </application>\n"; return manifest_application_text; diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml index 948fa8c00b..15feea15a4 100644 --- a/platform/android/java/app/AndroidManifest.xml +++ b/platform/android/java/app/AndroidManifest.xml @@ -30,11 +30,6 @@ <!-- The following metadata values are replaced when Godot exports, modifying them here has no effect. --> <!-- Do these changes in the export preset. Adding new ones is fine. --> - <!-- XR mode metadata. This is modified by the exporter based on the selected xr mode. DO NOT CHANGE the values here. --> - <meta-data - android:name="xr_mode_metadata_name" - android:value="xr_mode_metadata_value" /> - <activity android:name=".GodotApp" android:label="@string/godot_project_name_string" @@ -45,8 +40,8 @@ android:resizeableActivity="false" tools:ignore="UnusedAttribute" > - <!-- Focus awareness metadata is updated at export time if the user enables it in the 'Xr Features' section. --> - <meta-data android:name="com.oculus.vr.focusaware" android:value="false" /> + <!-- Focus awareness metadata is removed at export time if the xr mode is not VR. --> + <meta-data android:name="com.oculus.vr.focusaware" android:value="true" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 3f04bedea2..b69c245540 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -28,7 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "core/io/image_loader.h" #include "core/io/json.h" +#include "core/io/stream_peer_ssl.h" #include "core/io/tcp_server.h" #include "core/io/zip_io.h" #include "editor/editor_export.h" @@ -40,20 +42,55 @@ class EditorHTTPServer : public Reference { private: Ref<TCP_Server> server; - Ref<StreamPeerTCP> connection; + Map<String, String> mimes; + Ref<StreamPeerTCP> tcp; + Ref<StreamPeerSSL> ssl; + Ref<StreamPeer> peer; + Ref<CryptoKey> key; + Ref<X509Certificate> cert; + bool use_ssl = false; uint64_t time = 0; uint8_t req_buf[4096]; int req_pos = 0; void _clear_client() { - connection = Ref<StreamPeerTCP>(); + peer = Ref<StreamPeer>(); + ssl = Ref<StreamPeerSSL>(); + tcp = Ref<StreamPeerTCP>(); memset(req_buf, 0, sizeof(req_buf)); time = 0; req_pos = 0; } + void _set_internal_certs(Ref<Crypto> p_crypto) { + const String cache_path = EditorSettings::get_singleton()->get_cache_dir(); + const String key_path = cache_path.plus_file("html5_server.key"); + const String crt_path = cache_path.plus_file("html5_server.crt"); + bool regen = !FileAccess::exists(key_path) || !FileAccess::exists(crt_path); + if (!regen) { + key = Ref<CryptoKey>(CryptoKey::create()); + cert = Ref<X509Certificate>(X509Certificate::create()); + if (key->load(key_path) != OK || cert->load(crt_path) != OK) { + regen = true; + } + } + if (regen) { + key = p_crypto->generate_rsa(2048); + key->save(key_path); + cert = p_crypto->generate_self_signed_certificate(key, "CN=godot-debug.local,O=A Game Dev,C=XXA", "20140101000000", "20340101000000"); + cert->save(crt_path); + } + } + public: EditorHTTPServer() { + mimes["html"] = "text/html"; + mimes["js"] = "application/javascript"; + mimes["json"] = "application/json"; + mimes["pck"] = "application/octet-stream"; + mimes["png"] = "image/png"; + mimes["svg"] = "image/svg"; + mimes["wasm"] = "application/wasm"; server.instance(); stop(); } @@ -63,7 +100,24 @@ public: _clear_client(); } - Error listen(int p_port, IP_Address p_address) { + Error listen(int p_port, IP_Address p_address, bool p_use_ssl, String p_ssl_key, String p_ssl_cert) { + use_ssl = p_use_ssl; + if (use_ssl) { + Ref<Crypto> crypto = Crypto::create(); + if (crypto.is_null()) { + return ERR_UNAVAILABLE; + } + if (!p_ssl_key.is_empty() && !p_ssl_cert.is_empty()) { + key = Ref<CryptoKey>(CryptoKey::create()); + Error err = key->load(p_ssl_key); + ERR_FAIL_COND_V(err != OK, err); + cert = Ref<X509Certificate>(X509Certificate::create()); + err = cert->load(p_ssl_cert); + ERR_FAIL_COND_V(err != OK, err); + } else { + _set_internal_certs(crypto); + } + } return server->listen(p_port, p_address); } @@ -82,51 +136,21 @@ public: // Wrong protocol ERR_FAIL_COND_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", "Invalid method or HTTP version."); - const String cache_path = EditorSettings::get_singleton()->get_cache_dir(); - const String basereq = "/tmp_js_export"; - String filepath; - String ctype; - if (req[1] == basereq + ".html") { - filepath = cache_path.plus_file(req[1].get_file()); - ctype = "text/html"; - } else if (req[1] == basereq + ".js") { - filepath = cache_path.plus_file(req[1].get_file()); - ctype = "application/javascript"; - } else if (req[1] == basereq + ".audio.worklet.js") { - filepath = cache_path.plus_file(req[1].get_file()); - ctype = "application/javascript"; - } else if (req[1] == basereq + ".worker.js") { - filepath = cache_path.plus_file(req[1].get_file()); - ctype = "application/javascript"; - } else if (req[1] == basereq + ".pck") { - filepath = cache_path.plus_file(req[1].get_file()); - ctype = "application/octet-stream"; - } else if (req[1] == basereq + ".png" || req[1] == "/favicon.png") { - // Also allow serving the generated favicon for a smoother loading experience. - if (req[1] == "/favicon.png") { - filepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("favicon.png"); - } else { - filepath = basereq + ".png"; - } - ctype = "image/png"; - } else if (req[1] == basereq + ".side.wasm") { - filepath = cache_path.plus_file(req[1].get_file()); - ctype = "application/wasm"; - } else if (req[1] == basereq + ".wasm") { - filepath = cache_path.plus_file(req[1].get_file()); - ctype = "application/wasm"; - } else if (req[1].ends_with(".wasm")) { - filepath = cache_path.plus_file(req[1].get_file()); // TODO dangerous? - ctype = "application/wasm"; - } - if (filepath.is_empty() || !FileAccess::exists(filepath)) { + const String req_file = req[1].get_file(); + const String req_ext = req[1].get_extension(); + const String cache_path = EditorSettings::get_singleton()->get_cache_dir().plus_file("web"); + const String filepath = cache_path.plus_file(req_file); + + if (!mimes.has(req_ext) || !FileAccess::exists(filepath)) { String s = "HTTP/1.1 404 Not Found\r\n"; s += "Connection: Close\r\n"; s += "\r\n"; CharString cs = s.utf8(); - connection->put_data((const uint8_t *)cs.get_data(), cs.size() - 1); + peer->put_data((const uint8_t *)cs.get_data(), cs.size() - 1); return; } + const String ctype = mimes[req_ext]; + FileAccess *f = FileAccess::open(filepath, FileAccess::READ); ERR_FAIL_COND(!f); String s = "HTTP/1.1 200 OK\r\n"; @@ -138,7 +162,7 @@ public: s += "Cache-Control: no-store, max-age=0\r\n"; s += "\r\n"; CharString cs = s.utf8(); - Error err = connection->put_data((const uint8_t *)cs.get_data(), cs.size() - 1); + Error err = peer->put_data((const uint8_t *)cs.get_data(), cs.size() - 1); if (err != OK) { memdelete(f); ERR_FAIL(); @@ -150,7 +174,7 @@ public: if (read < 1) { break; } - err = connection->put_data(bytes, read); + err = peer->put_data(bytes, read); if (err != OK) { memdelete(f); ERR_FAIL(); @@ -163,21 +187,43 @@ public: if (!server->is_listening()) { return; } - if (connection.is_null()) { + if (tcp.is_null()) { if (!server->is_connection_available()) { return; } - connection = server->take_connection(); + tcp = server->take_connection(); + peer = tcp; time = OS::get_singleton()->get_ticks_usec(); } if (OS::get_singleton()->get_ticks_usec() - time > 1000000) { _clear_client(); return; } - if (connection->get_status() != StreamPeerTCP::STATUS_CONNECTED) { + if (tcp->get_status() != StreamPeerTCP::STATUS_CONNECTED) { return; } + if (use_ssl) { + if (ssl.is_null()) { + ssl = Ref<StreamPeerSSL>(StreamPeerSSL::create()); + peer = ssl; + ssl->set_blocking_handshake_enabled(false); + if (ssl->accept_stream(tcp, key, cert) != OK) { + _clear_client(); + return; + } + } + ssl->poll(); + if (ssl->get_status() == StreamPeerSSL::STATUS_HANDSHAKING) { + // Still handshaking, keep waiting. + return; + } + if (ssl->get_status() != StreamPeerSSL::STATUS_CONNECTED) { + _clear_client(); + return; + } + } + while (true) { char *r = (char *)req_buf; int l = req_pos - 1; @@ -189,7 +235,7 @@ public: int read = 0; ERR_FAIL_COND(req_pos >= 4096); - Error err = connection->get_partial_data(&req_buf[req_pos], 1, read); + Error err = peer->get_partial_data(&req_buf[req_pos], 1, read); if (err != OK) { // Got an error _clear_client(); @@ -304,11 +350,16 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re config["fileSizes"] = p_file_sizes; const String str_config = JSON::print(config); + String head_include; + if (p_preset->get("html/export_icon")) { + head_include += "<link id='-gd-engine-icon' rel='icon' type='image/png' href='" + p_name + ".icon.png' />\n"; + } + head_include += static_cast<String>(p_preset->get("html/head_include")); for (int i = 0; i < lines.size(); i++) { String current_line = lines[i]; current_line = current_line.replace("$GODOT_URL", p_name + ".js"); current_line = current_line.replace("$GODOT_PROJECT_NAME", ProjectSettings::get_singleton()->get_setting("application/config/name")); - current_line = current_line.replace("$GODOT_HEAD_INCLUDE", p_preset->get("html/head_include")); + current_line = current_line.replace("$GODOT_HEAD_INCLUDE", head_include); current_line = current_line.replace("$GODOT_CONFIG", str_config); str_export += current_line + "\n"; } @@ -350,6 +401,7 @@ void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_op r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_desktop"), true)); // S3TC r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_mobile"), false)); // ETC or ETC2, depending on renderer + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/export_icon"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/custom_html_shell", PROPERTY_HINT_FILE, "*.html"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "html/head_include", PROPERTY_HINT_MULTILINE_TEXT), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "html/canvas_resize_policy", PROPERTY_HINT_ENUM, "None,Project,Adaptive"), 2)); @@ -422,6 +474,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese String custom_debug = p_preset->get("custom_template/debug"); String custom_release = p_preset->get("custom_template/release"); String custom_html = p_preset->get("html/custom_html_shell"); + bool export_icon = p_preset->get("html/export_icon"); String template_path = p_debug ? custom_debug : custom_release; @@ -567,7 +620,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese const String splash_path = String(GLOBAL_GET("application/boot_splash/image")).strip_edges(); if (!splash_path.is_empty()) { splash.instance(); - const Error err = splash->load(splash_path); + const Error err = ImageLoader::load_image(splash_path, splash); if (err) { EditorNode::get_singleton()->show_warning(TTR("Could not read boot splash image file:") + "\n" + splash_path + "\n" + TTR("Using default boot splash image.")); splash.unref(); @@ -584,18 +637,21 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese // Save a favicon that can be accessed without waiting for the project to finish loading. // This way, the favicon can be displayed immediately when loading the page. - Ref<Image> favicon; - const String favicon_path = String(GLOBAL_GET("application/config/icon")).strip_edges(); - if (!favicon_path.is_empty()) { - favicon.instance(); - const Error err = favicon->load(favicon_path); - if (err) { - favicon.unref(); + if (export_icon) { + Ref<Image> favicon; + const String favicon_path = String(GLOBAL_GET("application/config/icon")).strip_edges(); + if (!favicon_path.is_empty()) { + favicon.instance(); + const Error err = ImageLoader::load_image(favicon_path, favicon); + if (err) { + favicon.unref(); + } } - } - if (favicon.is_valid()) { - const String favicon_png_path = p_path.get_base_dir().plus_file("favicon.png"); + if (favicon.is_null()) { + favicon = EditorNode::get_singleton()->get_editor_theme()->get_icon("DefaultProjectIcon", "EditorIcons")->get_image(); + } + const String favicon_png_path = p_path.get_base_dir().plus_file(p_path.get_file().get_basename() + ".icon.png"); if (favicon->save_png(favicon_png_path) != OK) { EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + favicon_png_path); return ERR_FILE_CANT_WRITE; @@ -644,7 +700,16 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese return OK; } - const String basepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_js_export"); + const String dest = EditorSettings::get_singleton()->get_cache_dir().plus_file("web"); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + if (!da->dir_exists(dest)) { + Error err = da->make_dir_recursive(dest); + if (err != OK) { + EditorNode::get_singleton()->show_warning(TTR("Could not create HTTP server directory:") + "\n" + dest); + return err; + } + } + const String basepath = dest.plus_file("tmp_js_export"); Error err = export_project(p_preset, true, basepath + ".html", p_debug_flags); if (err != OK) { // Export generates several files, clean them up on failure. @@ -656,7 +721,7 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese DirAccess::remove_file_or_error(basepath + ".png"); DirAccess::remove_file_or_error(basepath + ".side.wasm"); DirAccess::remove_file_or_error(basepath + ".wasm"); - DirAccess::remove_file_or_error(EditorSettings::get_singleton()->get_cache_dir().plus_file("favicon.png")); + DirAccess::remove_file_or_error(basepath + ".icon.png"); return err; } @@ -671,16 +736,23 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese } ERR_FAIL_COND_V_MSG(!bind_ip.is_valid(), ERR_INVALID_PARAMETER, "Invalid editor setting 'export/web/http_host': '" + bind_host + "'. Try using '127.0.0.1'."); + const bool use_ssl = EDITOR_GET("export/web/use_ssl"); + const String ssl_key = EDITOR_GET("export/web/ssl_key"); + const String ssl_cert = EDITOR_GET("export/web/ssl_certificate"); + // Restart server. { MutexLock lock(server_lock); server->stop(); - err = server->listen(bind_port, bind_ip); + err = server->listen(bind_port, bind_ip, use_ssl, ssl_key, ssl_cert); + } + if (err != OK) { + EditorNode::get_singleton()->show_warning(TTR("Error starting HTTP server:") + "\n" + itos(err)); + return err; } - ERR_FAIL_COND_V_MSG(err != OK, err, "Unable to start HTTP server."); - OS::get_singleton()->shell_open(String("http://" + bind_host + ":" + itos(bind_port) + "/tmp_js_export.html")); + OS::get_singleton()->shell_open(String((use_ssl ? "https://" : "http://") + bind_host + ":" + itos(bind_port) + "/tmp_js_export.html")); // FIXME: Find out how to clean up export files after running the successfully // exported game. Might not be trivial. return OK; @@ -730,7 +802,12 @@ EditorExportPlatformJavaScript::~EditorExportPlatformJavaScript() { void register_javascript_exporter() { EDITOR_DEF("export/web/http_host", "localhost"); EDITOR_DEF("export/web/http_port", 8060); + EDITOR_DEF("export/web/use_ssl", false); + EDITOR_DEF("export/web/ssl_key", ""); + EDITOR_DEF("export/web/ssl_certificate", ""); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "export/web/http_port", PROPERTY_HINT_RANGE, "1,65535,1")); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/web/ssl_key", PROPERTY_HINT_GLOBAL_FILE, "*.key")); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/web/ssl_certificate", PROPERTY_HINT_GLOBAL_FILE, "*.crt,*.pem")); Ref<EditorExportPlatformJavaScript> platform; platform.instance(); diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index 3f8201b559..f9cbdbf377 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -104,12 +104,7 @@ void NavigationAgent2D::_notification(int p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { if (agent_parent) { NavigationServer2D::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().get_origin()); - if (!target_reached) { - if (distance_to_target() < target_desired_distance) { - emit_signal("target_reached"); - target_reached = true; - } - } + _check_distance_to_target(); } } break; } @@ -305,6 +300,7 @@ void NavigationAgent2D::update_navigation() { while (o.distance_to(navigation_path[nav_path_index]) < target_desired_distance) { nav_path_index += 1; if (nav_path_index == navigation_path.size()) { + _check_distance_to_target(); nav_path_index -= 1; navigation_finished = true; emit_signal("navigation_finished"); @@ -313,3 +309,12 @@ void NavigationAgent2D::update_navigation() { } } } + +void NavigationAgent2D::_check_distance_to_target() { + if (!target_reached) { + if (distance_to_target() < target_desired_distance) { + emit_signal("target_reached"); + target_reached = true; + } + } +} diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h index 138ba3bc64..234cad333f 100644 --- a/scene/2d/navigation_agent_2d.h +++ b/scene/2d/navigation_agent_2d.h @@ -140,6 +140,7 @@ public: private: void update_navigation(); + void _check_distance_to_target(); }; #endif diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp index 7623ede0fc..99fa8f1f3e 100644 --- a/scene/3d/mesh_instance_3d.cpp +++ b/scene/3d/mesh_instance_3d.cpp @@ -271,6 +271,41 @@ void MeshInstance3D::create_convex_collision() { } } +Node *MeshInstance3D::create_multiple_convex_collisions_node() { + if (mesh.is_null()) { + return nullptr; + } + + Vector<Ref<Shape3D>> shapes = mesh->convex_decompose(); + if (!shapes.size()) { + return nullptr; + } + + StaticBody3D *static_body = memnew(StaticBody3D); + for (int i = 0; i < shapes.size(); i++) { + CollisionShape3D *cshape = memnew(CollisionShape3D); + cshape->set_shape(shapes[i]); + static_body->add_child(cshape); + } + return static_body; +} + +void MeshInstance3D::create_multiple_convex_collisions() { + StaticBody3D *static_body = Object::cast_to<StaticBody3D>(create_multiple_convex_collisions_node()); + ERR_FAIL_COND(!static_body); + static_body->set_name(String(get_name()) + "_col"); + + add_child(static_body); + if (get_owner()) { + static_body->set_owner(get_owner()); + int count = static_body->get_child_count(); + for (int i = 0; i < count; i++) { + CollisionShape3D *cshape = Object::cast_to<CollisionShape3D>(static_body->get_child(i)); + cshape->set_owner(get_owner()); + } + } +} + void MeshInstance3D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { _resolve_skeleton_path(); @@ -417,6 +452,8 @@ void MeshInstance3D::_bind_methods() { ClassDB::set_method_flags("MeshInstance3D", "create_trimesh_collision", METHOD_FLAGS_DEFAULT); ClassDB::bind_method(D_METHOD("create_convex_collision"), &MeshInstance3D::create_convex_collision); ClassDB::set_method_flags("MeshInstance3D", "create_convex_collision", METHOD_FLAGS_DEFAULT); + ClassDB::bind_method(D_METHOD("create_multiple_convex_collisions"), &MeshInstance3D::create_multiple_convex_collisions); + ClassDB::set_method_flags("MeshInstance3D", "create_multiple_convex_collisions", METHOD_FLAGS_DEFAULT); ClassDB::bind_method(D_METHOD("create_debug_tangents"), &MeshInstance3D::create_debug_tangents); ClassDB::set_method_flags("MeshInstance3D", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h index 8aec227337..9dea5804e0 100644 --- a/scene/3d/mesh_instance_3d.h +++ b/scene/3d/mesh_instance_3d.h @@ -86,6 +86,9 @@ public: Node *create_convex_collision_node(); void create_convex_collision(); + Node *create_multiple_convex_collisions_node(); + void create_multiple_convex_collisions(); + void create_debug_tangents(); virtual AABB get_aabb() const override; diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 4f5e56e227..64cfe4dca7 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -111,12 +111,7 @@ void NavigationAgent3D::_notification(int p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { if (agent_parent) { NavigationServer3D::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().origin); - if (!target_reached) { - if (distance_to_target() < target_desired_distance) { - emit_signal("target_reached"); - target_reached = true; - } - } + _check_distance_to_target(); } } break; } @@ -314,6 +309,7 @@ void NavigationAgent3D::update_navigation() { while (o.distance_to(navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0)) < target_desired_distance) { nav_path_index += 1; if (nav_path_index == navigation_path.size()) { + _check_distance_to_target(); nav_path_index -= 1; navigation_finished = true; emit_signal("navigation_finished"); @@ -322,3 +318,12 @@ void NavigationAgent3D::update_navigation() { } } } + +void NavigationAgent3D::_check_distance_to_target() { + if (!target_reached) { + if (distance_to_target() < target_desired_distance) { + emit_signal("target_reached"); + target_reached = true; + } + } +} diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h index 814c0714e8..56da2d1acf 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -147,6 +147,7 @@ public: private: void update_navigation(); + void _check_distance_to_target(); }; #endif diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index d09cf4b971..b810f9562e 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -300,6 +300,30 @@ String VisualShaderNodeCustom::generate_global_per_node(Shader::Mode p_mode, Vis return ""; } +void VisualShaderNodeCustom::set_input_port_default_value(int p_port, const Variant &p_value) { + if (!is_initialized) { + VisualShaderNode::set_input_port_default_value(p_port, p_value); + } +} + +void VisualShaderNodeCustom::set_default_input_values(const Array &p_values) { + if (!is_initialized) { + VisualShaderNode::set_default_input_values(p_values); + } +} + +void VisualShaderNodeCustom::_set_input_port_default_value(int p_port, const Variant &p_value) { + VisualShaderNode::set_input_port_default_value(p_port, p_value); +} + +bool VisualShaderNodeCustom::_is_initialized() { + return is_initialized; +} + +void VisualShaderNodeCustom::_set_initialized(bool p_enabled) { + is_initialized = p_enabled; +} + void VisualShaderNodeCustom::_bind_methods() { BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_name")); BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_description")); @@ -314,6 +338,12 @@ void VisualShaderNodeCustom::_bind_methods() { BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_code", PropertyInfo(Variant::ARRAY, "input_vars"), PropertyInfo(Variant::ARRAY, "output_vars"), PropertyInfo(Variant::INT, "mode"), PropertyInfo(Variant::INT, "type"))); BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_global_code", PropertyInfo(Variant::INT, "mode"))); BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_highend")); + + ClassDB::bind_method(D_METHOD("_set_initialized", "enabled"), &VisualShaderNodeCustom::_set_initialized); + ClassDB::bind_method(D_METHOD("_is_initialized"), &VisualShaderNodeCustom::_is_initialized); + ClassDB::bind_method(D_METHOD("_set_input_port_default_value", "port", "value"), &VisualShaderNodeCustom::_set_input_port_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "initialized", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_initialized", "_is_initialized"); } VisualShaderNodeCustom::VisualShaderNodeCustom() { diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index e2e1b473ed..8af0fc9e44 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -223,10 +223,10 @@ public: virtual PortType get_input_port_type(int p_port) const = 0; virtual String get_input_port_name(int p_port) const = 0; - void set_input_port_default_value(int p_port, const Variant &p_value); + virtual void set_input_port_default_value(int p_port, const Variant &p_value); Variant get_input_port_default_value(int p_port) const; // if NIL (default if node does not set anything) is returned, it means no default value is wanted if disconnected, thus no input var must be supplied (empty string will be supplied) Array get_default_input_values() const; - void set_default_input_values(const Array &p_values); + virtual void set_default_input_values(const Array &p_values); virtual int get_output_port_count() const = 0; virtual PortType get_output_port_type(int p_port) const = 0; @@ -272,6 +272,7 @@ class VisualShaderNodeCustom : public VisualShaderNode { int type = 0; }; + bool is_initialized = false; List<Port> input_ports; List<Port> output_ports; @@ -288,7 +289,12 @@ protected: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; + virtual void set_input_port_default_value(int p_port, const Variant &p_value) override; + virtual void set_default_input_values(const Array &p_values) override; + protected: + void _set_input_port_default_value(int p_port, const Variant &p_value); + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; @@ -297,6 +303,9 @@ protected: public: VisualShaderNodeCustom(); void update_ports(); + + bool _is_initialized(); + void _set_initialized(bool p_enabled); }; ///// diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 189c5782f4..540b32481b 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -7923,7 +7923,6 @@ void RendererStorageRD::global_variable_set_override(const StringName &p_name, c _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements); } else { //texture - //texture for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { Material *material = material_owner.getornull(E->get()); ERR_CONTINUE(!material); diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index f5228f9747..32c38e9138 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -3956,8 +3956,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons ERR_FAIL_COND_V(!expr, nullptr); /* OK now see what's NEXT to the operator.. */ - /* OK now see what's NEXT to the operator.. */ - /* OK now see what's NEXT to the operator.. */ while (true) { TkPos pos2 = _get_tkpos(); @@ -4735,7 +4733,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons ERR_FAIL_COND_V(next_op == -1, nullptr); // OK! create operator.. - // OK! create operator.. if (is_unary) { int expr_pos = next_op; while (expression[expr_pos].is_op) { diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp index 6873a95d90..c79623bd57 100644 --- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp +++ b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp @@ -80,7 +80,6 @@ struct ClipVertex btVector3 v; int id; //b2ContactID id; - //b2ContactID id; }; #define b2Dot(a, b) (a).dot(b) diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp index fec9b03213..4372489fa1 100644 --- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp +++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp @@ -43,7 +43,6 @@ void btMultiBodyJointMotor::finalizeMultiDof() unsigned int offset = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF); // row 0: the lower bound - // row 0: the lower bound jacobianA(0)[offset] = 1; m_numDofsFinalized = m_jacSizeBoth; diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp index 25ddd539bf..5c20d2a0d4 100644 --- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp +++ b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp @@ -45,7 +45,6 @@ void btMultiBodySphericalJointMotor::finalizeMultiDof() unsigned int offset = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF); // row 0: the lower bound - // row 0: the lower bound jacobianA(0)[offset] = 1; m_numDofsFinalized = m_jacSizeBoth; |