diff options
441 files changed, 6235 insertions, 2685 deletions
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 8a966dcb05..a3e06c545f 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -288,7 +288,7 @@ License: Apache-2.0 Files: ./thirdparty/meshoptimizer/ Comment: meshoptimizer -Copyright: 2016-2021, Arseny Kapoulkine +Copyright: 2016-2022, Arseny Kapoulkine License: Expat Files: ./thirdparty/minimp3/ diff --git a/SConstruct b/SConstruct index 1acbd83e63..845b9be4a6 100644 --- a/SConstruct +++ b/SConstruct @@ -172,7 +172,7 @@ opts.Add( "optimize", "Optimization level", "speed_trace", ("none", "custom", "debug", "speed", "speed_trace", "size") ) ) -opts.Add(BoolVariable("debug_symbols", "Build with debugging symbols", True)) +opts.Add(BoolVariable("debug_symbols", "Build with debugging symbols", False)) opts.Add(BoolVariable("separate_debug_symbols", "Extract debugging symbols to a separate file", False)) opts.Add(EnumVariable("lto", "Link-time optimization (production builds)", "none", ("none", "auto", "thin", "full"))) opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False)) diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 00e74a7cce..6a1d802453 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -221,7 +221,9 @@ String ProjectSettings::localize_path(const String &p_path) const { void ProjectSettings::set_initial_value(const String &p_name, const Variant &p_value) { ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); - props[p_name].initial = p_value; + + // Duplicate so that if value is array or dictionary, changing the setting will not change the stored initial value. + props[p_name].initial = p_value.duplicate(); } void ProjectSettings::set_restart_if_changed(const String &p_name, bool p_restart) { @@ -1116,7 +1118,9 @@ bool ProjectSettings::_property_get_revert(const StringName &p_name, Variant &r_ return false; } - r_property = props[p_name].initial; + // Duplicate so that if value is array or dictionary, changing the setting will not change the stored initial value. + r_property = props[p_name].initial.duplicate(); + return true; } @@ -1137,8 +1141,8 @@ Array ProjectSettings::get_global_class_list() { Ref<ConfigFile> cf; cf.instantiate(); - if (cf->load(get_project_data_path().path_join("global_script_class_cache.cfg")) == OK) { - script_classes = cf->get_value("", "list"); + if (cf->load(get_global_class_list_path()) == OK) { + script_classes = cf->get_value("", "list", Array()); } else { #ifndef TOOLS_ENABLED // Script classes can't be recreated in exported project, so print an error. @@ -1148,11 +1152,15 @@ Array ProjectSettings::get_global_class_list() { return script_classes; } +String ProjectSettings::get_global_class_list_path() const { + return get_project_data_path().path_join("global_script_class_cache.cfg"); +} + void ProjectSettings::store_global_class_list(const Array &p_classes) { Ref<ConfigFile> cf; cf.instantiate(); cf->set_value("", "list", p_classes); - cf->save(get_project_data_path().path_join("global_script_class_cache.cfg")); + cf->save(get_global_class_list_path()); } bool ProjectSettings::has_custom_feature(const String &p_feature) const { diff --git a/core/config/project_settings.h b/core/config/project_settings.h index d1704a7c31..70f697741f 100644 --- a/core/config/project_settings.h +++ b/core/config/project_settings.h @@ -143,6 +143,7 @@ public: Variant get_setting(const String &p_setting, const Variant &p_default_value = Variant()) const; Array get_global_class_list(); void store_global_class_list(const Array &p_classes); + String get_global_class_list_path() const; bool has_setting(String p_var) const; String localize_path(const String &p_path) const; diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 9de901754a..c752bdd057 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -717,7 +717,7 @@ TypedArray<PackedVector2Array> Geometry2D::decompose_polygon_in_convex(const Vec TypedArray<PackedVector2Array> Geometry2D::merge_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { Vector<Vector<Point2>> polys = ::Geometry2D::merge_polygons(p_polygon_a, p_polygon_b); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -739,7 +739,7 @@ TypedArray<PackedVector2Array> Geometry2D::clip_polygons(const Vector<Vector2> & TypedArray<PackedVector2Array> Geometry2D::intersect_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { Vector<Vector<Point2>> polys = ::Geometry2D::intersect_polygons(p_polygon_a, p_polygon_b); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -750,7 +750,7 @@ TypedArray<PackedVector2Array> Geometry2D::intersect_polygons(const Vector<Vecto TypedArray<PackedVector2Array> Geometry2D::exclude_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { Vector<Vector<Point2>> polys = ::Geometry2D::exclude_polygons(p_polygon_a, p_polygon_b); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -761,7 +761,7 @@ TypedArray<PackedVector2Array> Geometry2D::exclude_polygons(const Vector<Vector2 TypedArray<PackedVector2Array> Geometry2D::clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { Vector<Vector<Point2>> polys = ::Geometry2D::clip_polyline_with_polygon(p_polyline, p_polygon); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -772,7 +772,7 @@ TypedArray<PackedVector2Array> Geometry2D::clip_polyline_with_polygon(const Vect TypedArray<PackedVector2Array> Geometry2D::intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { Vector<Vector<Point2>> polys = ::Geometry2D::intersect_polyline_with_polygon(p_polyline, p_polygon); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -783,7 +783,7 @@ TypedArray<PackedVector2Array> Geometry2D::intersect_polyline_with_polygon(const TypedArray<PackedVector2Array> Geometry2D::offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) { Vector<Vector<Point2>> polys = ::Geometry2D::offset_polygon(p_polygon, p_delta, ::Geometry2D::PolyJoinType(p_join_type)); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); @@ -794,7 +794,7 @@ TypedArray<PackedVector2Array> Geometry2D::offset_polygon(const Vector<Vector2> TypedArray<PackedVector2Array> Geometry2D::offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { Vector<Vector<Point2>> polys = ::Geometry2D::offset_polyline(p_polygon, p_delta, ::Geometry2D::PolyJoinType(p_join_type), ::Geometry2D::PolyEndType(p_end_type)); - Array ret; + TypedArray<PackedVector2Array> ret; for (int i = 0; i < polys.size(); ++i) { ret.push_back(polys[i]); diff --git a/core/doc_data.cpp b/core/doc_data.cpp index f90dbe1423..5e09e560d5 100644 --- a/core/doc_data.cpp +++ b/core/doc_data.cpp @@ -30,6 +30,14 @@ #include "doc_data.h" +String DocData::get_default_value_string(const Variant &p_value) { + if (p_value.get_type() == Variant::ARRAY) { + return Variant(Array(p_value, 0, StringName(), Variant())).get_construct_string().replace("\n", " "); + } else { + return p_value.get_construct_string().replace("\n", " "); + } +} + void DocData::return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo) { if (p_retinfo.type == Variant::INT && p_retinfo.hint == PROPERTY_HINT_INT_IS_POINTER) { p_method.return_type = p_retinfo.hint_string; @@ -105,7 +113,7 @@ void DocData::property_doc_from_scriptmemberinfo(DocData::PropertyDoc &p_propert p_property.getter = p_memberinfo.getter; if (p_memberinfo.has_default_value && p_memberinfo.default_value.get_type() != Variant::OBJECT) { - p_property.default_value = p_memberinfo.default_value.get_construct_string().replace("\n", ""); + p_property.default_value = get_default_value_string(p_memberinfo.default_value); } p_property.overridden = false; @@ -148,7 +156,7 @@ void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const Met int default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size()); if (default_arg_index >= 0) { Variant default_arg = p_methodinfo.default_arguments[default_arg_index]; - argument.default_value = default_arg.get_construct_string().replace("\n", ""); + argument.default_value = get_default_value_string(default_arg); } p_method.arguments.push_back(argument); } diff --git a/core/doc_data.h b/core/doc_data.h index 1cf4e4f206..c503a4e0d6 100644 --- a/core/doc_data.h +++ b/core/doc_data.h @@ -516,6 +516,8 @@ public: } }; + static String get_default_value_string(const Variant &p_value); + static void return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo); static void argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo); static void property_doc_from_scriptmemberinfo(DocData::PropertyDoc &p_property, const ScriptMemberInfo &p_memberinfo); diff --git a/core/extension/gdextension_interface.cpp b/core/extension/gdextension_interface.cpp index 63ed60a710..3bea013fab 100644 --- a/core/extension/gdextension_interface.cpp +++ b/core/extension/gdextension_interface.cpp @@ -856,6 +856,12 @@ static GDExtensionVariantPtr gdextension_array_operator_index_const(GDExtensionC return (GDExtensionVariantPtr)&self->operator[](p_index); } +void gdextension_array_ref(GDExtensionTypePtr p_self, GDExtensionConstTypePtr p_from) { + Array *self = (Array *)p_self; + const Array *from = (const Array *)p_from; + self->_ref(*from); +} + void gdextension_array_set_typed(GDExtensionTypePtr p_self, uint32_t p_type, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstVariantPtr p_script) { Array *self = reinterpret_cast<Array *>(p_self); const StringName *class_name = reinterpret_cast<const StringName *>(p_class_name); @@ -1136,6 +1142,7 @@ void gdextension_setup_interface(GDExtensionInterface *p_interface) { gde_interface.array_operator_index = gdextension_array_operator_index; gde_interface.array_operator_index_const = gdextension_array_operator_index_const; + gde_interface.array_ref = gdextension_array_ref; gde_interface.array_set_typed = gdextension_array_set_typed; /* Dictionary functions */ diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h index 7f8f7374e9..876a09beff 100644 --- a/core/extension/gdextension_interface.h +++ b/core/extension/gdextension_interface.h @@ -551,6 +551,7 @@ typedef struct { GDExtensionVariantPtr (*array_operator_index)(GDExtensionTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr GDExtensionVariantPtr (*array_operator_index_const)(GDExtensionConstTypePtr p_self, GDExtensionInt p_index); // p_self should be an Array ptr + void (*array_ref)(GDExtensionTypePtr p_self, GDExtensionConstTypePtr p_from); // p_self should be an Array ptr void (*array_set_typed)(GDExtensionTypePtr p_self, uint32_t p_type, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstVariantPtr p_script); // p_self should be an Array ptr /* Dictionary functions */ diff --git a/core/input/input.cpp b/core/input/input.cpp index 3cf83fd64b..2e886f9093 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -891,6 +891,31 @@ void Input::parse_input_event(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); +#ifdef DEBUG_ENABLED + uint64_t curr_frame = Engine::get_singleton()->get_process_frames(); + if (curr_frame != last_parsed_frame) { + frame_parsed_events.clear(); + last_parsed_frame = curr_frame; + frame_parsed_events.insert(p_event); + } else if (frame_parsed_events.has(p_event)) { + // It would be technically safe to send the same event in cases such as: + // - After an explicit flush. + // - In platforms using buffering when agile flushing is enabled, after one of the mid-frame flushes. + // - If platform doesn't use buffering and event accumulation is disabled. + // - If platform doesn't use buffering and the event type is not accumulable. + // However, it wouldn't be reasonable to ask users to remember the full ruleset and be aware at all times + // of the possibilities of the target platform, project settings and engine internals, which may change + // without prior notice. + // Therefore, the guideline is, "don't send the same event object more than once per frame". + WARN_PRINT_ONCE( + "An input event object is being parsed more than once in the same frame, which is unsafe.\n" + "If you are generating events in a script, you have to instantiate a new event instead of sending the same one more than once, unless the original one was sent on an earlier frame.\n" + "You can call duplicate() on the event to get a new instance with identical values."); + } else { + frame_parsed_events.insert(p_event); + } +#endif + if (use_accumulated_input) { if (buffered_events.is_empty() || !buffered_events.back()->get()->accumulate(p_event)) { buffered_events.push_back(p_event); diff --git a/core/input/input.h b/core/input/input.h index f2de56b6b9..c254650ef8 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -223,6 +223,10 @@ private: void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated); List<Ref<InputEvent>> buffered_events; +#ifdef DEBUG_ENABLED + HashSet<Ref<InputEvent>> frame_parsed_events; + uint64_t last_parsed_frame = UINT64_MAX; +#endif friend class DisplayServer; diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index c0463de427..38f41d645c 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -832,6 +832,18 @@ Error ResourceLoaderBinary::load() { } } + if (value.get_type() == Variant::ARRAY) { + Array set_array = value; + bool is_get_valid = false; + Variant get_value = res->get(name, &is_get_valid); + if (is_get_valid && get_value.get_type() == Variant::ARRAY) { + Array get_array = get_value; + if (!set_array.is_same_typed(get_array)) { + value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script()); + } + } + } + if (set_valid) { res->set(name, value); } diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 7447119ab7..fc3547261b 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -176,9 +176,9 @@ Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Hash deps_dict[E.key] = E.value; } - int64_t err = OK; + Error err = OK; GDVIRTUAL_CALL(_rename_dependencies, p_path, deps_dict, err); - return (Error)err; + return err; } void ResourceFormatLoader::_bind_methods() { diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index eb8155e046..c47b6c950a 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -58,7 +58,7 @@ protected: GDVIRTUAL1RC(ResourceUID::ID, _get_resource_uid, String) GDVIRTUAL2RC(Vector<String>, _get_dependencies, String, bool) GDVIRTUAL1RC(Vector<String>, _get_classes_used, String) - GDVIRTUAL2RC(int64_t, _rename_dependencies, String, Dictionary) + GDVIRTUAL2RC(Error, _rename_dependencies, String, Dictionary) GDVIRTUAL1RC(bool, _exists, String) GDVIRTUAL4RC(Variant, _load, String, String, bool, int) diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index b8201cc6b9..6e377847a8 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -42,9 +42,9 @@ ResourceSavedCallback ResourceSaver::save_callback = nullptr; ResourceSaverGetResourceIDForPath ResourceSaver::save_get_id_for_path = nullptr; Error ResourceFormatSaver::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { - int64_t res = ERR_METHOD_NOT_FOUND; - GDVIRTUAL_CALL(_save, p_resource, p_path, p_flags, res); - return (Error)res; + Error err = ERR_METHOD_NOT_FOUND; + GDVIRTUAL_CALL(_save, p_resource, p_path, p_flags, err); + return err; } Error ResourceFormatSaver::set_uid(const String &p_path, ResourceUID::ID p_uid) { diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h index 9e88b2086b..572742d129 100644 --- a/core/io/resource_saver.h +++ b/core/io/resource_saver.h @@ -41,7 +41,7 @@ class ResourceFormatSaver : public RefCounted { protected: static void _bind_methods(); - GDVIRTUAL3R(int64_t, _save, Ref<Resource>, String, uint32_t) + GDVIRTUAL3R(Error, _save, Ref<Resource>, String, uint32_t) GDVIRTUAL2R(Error, _set_uid, String, ResourceUID::ID) GDVIRTUAL1RC(bool, _recognize, Ref<Resource>) GDVIRTUAL1RC(Vector<String>, _get_recognized_extensions, Ref<Resource>) diff --git a/core/math/dynamic_bvh.cpp b/core/math/dynamic_bvh.cpp index 4452445241..e1315d1c64 100644 --- a/core/math/dynamic_bvh.cpp +++ b/core/math/dynamic_bvh.cpp @@ -36,8 +36,8 @@ void DynamicBVH::_delete_node(Node *p_node) { void DynamicBVH::_recurse_delete_node(Node *p_node) { if (!p_node->is_leaf()) { - _recurse_delete_node(p_node->childs[0]); - _recurse_delete_node(p_node->childs[1]); + _recurse_delete_node(p_node->children[0]); + _recurse_delete_node(p_node->children[1]); } if (p_node == bvh_root) { bvh_root = nullptr; @@ -65,31 +65,31 @@ void DynamicBVH::_insert_leaf(Node *p_root, Node *p_leaf) { } else { if (!p_root->is_leaf()) { do { - p_root = p_root->childs[p_leaf->volume.select_by_proximity( - p_root->childs[0]->volume, - p_root->childs[1]->volume)]; + p_root = p_root->children[p_leaf->volume.select_by_proximity( + p_root->children[0]->volume, + p_root->children[1]->volume)]; } while (!p_root->is_leaf()); } Node *prev = p_root->parent; Node *node = _create_node_with_volume(prev, p_leaf->volume.merge(p_root->volume), nullptr); if (prev) { - prev->childs[p_root->get_index_in_parent()] = node; - node->childs[0] = p_root; + prev->children[p_root->get_index_in_parent()] = node; + node->children[0] = p_root; p_root->parent = node; - node->childs[1] = p_leaf; + node->children[1] = p_leaf; p_leaf->parent = node; do { if (!prev->volume.contains(node->volume)) { - prev->volume = prev->childs[0]->volume.merge(prev->childs[1]->volume); + prev->volume = prev->children[0]->volume.merge(prev->children[1]->volume); } else { break; } node = prev; } while (nullptr != (prev = node->parent)); } else { - node->childs[0] = p_root; + node->children[0] = p_root; p_root->parent = node; - node->childs[1] = p_leaf; + node->children[1] = p_leaf; p_leaf->parent = node; bvh_root = node; } @@ -103,14 +103,14 @@ DynamicBVH::Node *DynamicBVH::_remove_leaf(Node *leaf) { } else { Node *parent = leaf->parent; Node *prev = parent->parent; - Node *sibling = parent->childs[1 - leaf->get_index_in_parent()]; + Node *sibling = parent->children[1 - leaf->get_index_in_parent()]; if (prev) { - prev->childs[parent->get_index_in_parent()] = sibling; + prev->children[parent->get_index_in_parent()] = sibling; sibling->parent = prev; _delete_node(parent); while (prev) { const Volume pb = prev->volume; - prev->volume = prev->childs[0]->volume.merge(prev->childs[1]->volume); + prev->volume = prev->children[0]->volume.merge(prev->children[1]->volume); if (pb.is_not_equal_to(prev->volume)) { prev = prev->parent; } else { @@ -129,8 +129,8 @@ DynamicBVH::Node *DynamicBVH::_remove_leaf(Node *leaf) { void DynamicBVH::_fetch_leaves(Node *p_root, LocalVector<Node *> &r_leaves, int p_depth) { if (p_root->is_internal() && p_depth) { - _fetch_leaves(p_root->childs[0], r_leaves, p_depth - 1); - _fetch_leaves(p_root->childs[1], r_leaves, p_depth - 1); + _fetch_leaves(p_root->children[0], r_leaves, p_depth - 1); + _fetch_leaves(p_root->children[1], r_leaves, p_depth - 1); _delete_node(p_root); } else { r_leaves.push_back(p_root); @@ -195,8 +195,8 @@ void DynamicBVH::_bottom_up(Node **leaves, int p_count) { } Node *n[] = { leaves[minidx[0]], leaves[minidx[1]] }; Node *p = _create_node_with_volume(nullptr, n[0]->volume.merge(n[1]->volume), nullptr); - p->childs[0] = n[0]; - p->childs[1] = n[1]; + p->children[0] = n[0]; + p->children[1] = n[1]; n[0]->parent = p; n[1]->parent = p; leaves[minidx[0]] = p; @@ -241,10 +241,10 @@ DynamicBVH::Node *DynamicBVH::_top_down(Node **leaves, int p_count, int p_bu_thr } Node *node = _create_node_with_volume(nullptr, vol, nullptr); - node->childs[0] = _top_down(&leaves[0], partition, p_bu_threshold); - node->childs[1] = _top_down(&leaves[partition], p_count - partition, p_bu_threshold); - node->childs[0]->parent = node; - node->childs[1]->parent = node; + node->children[0] = _top_down(&leaves[0], partition, p_bu_threshold); + node->children[1] = _top_down(&leaves[partition], p_count - partition, p_bu_threshold); + node->children[0]->parent = node; + node->children[1]->parent = node; return (node); } else { _bottom_up(leaves, p_count); @@ -260,23 +260,23 @@ DynamicBVH::Node *DynamicBVH::_node_sort(Node *n, Node *&r) { if (p > n) { const int i = n->get_index_in_parent(); const int j = 1 - i; - Node *s = p->childs[j]; + Node *s = p->children[j]; Node *q = p->parent; - ERR_FAIL_COND_V(n != p->childs[i], nullptr); + ERR_FAIL_COND_V(n != p->children[i], nullptr); if (q) { - q->childs[p->get_index_in_parent()] = n; + q->children[p->get_index_in_parent()] = n; } else { r = n; } s->parent = n; p->parent = n; n->parent = q; - p->childs[0] = n->childs[0]; - p->childs[1] = n->childs[1]; - n->childs[0]->parent = p; - n->childs[1]->parent = p; - n->childs[i] = p; - n->childs[j] = s; + p->children[0] = n->children[0]; + p->children[1] = n->children[1]; + n->children[0]->parent = p; + n->children[1]->parent = p; + n->children[i] = p; + n->children[j] = s; SWAP(p->volume, n->volume); return (p); } @@ -320,7 +320,7 @@ void DynamicBVH::optimize_incremental(int passes) { Node *node = bvh_root; unsigned bit = 0; while (node->is_internal()) { - node = _node_sort(node, bvh_root)->childs[(opath >> bit) & 1]; + node = _node_sort(node, bvh_root)->children[(opath >> bit) & 1]; bit = (bit + 1) & (sizeof(unsigned) * 8 - 1); } _update(node); @@ -396,8 +396,8 @@ void DynamicBVH::remove(const ID &p_id) { void DynamicBVH::_extract_leaves(Node *p_node, List<ID> *r_elements) { if (p_node->is_internal()) { - _extract_leaves(p_node->childs[0], r_elements); - _extract_leaves(p_node->childs[1], r_elements); + _extract_leaves(p_node->children[0], r_elements); + _extract_leaves(p_node->children[1], r_elements); } else { ID id; id.node = p_node; diff --git a/core/math/dynamic_bvh.h b/core/math/dynamic_bvh.h index 46bf56ae58..21b5340aaa 100644 --- a/core/math/dynamic_bvh.h +++ b/core/math/dynamic_bvh.h @@ -182,21 +182,21 @@ private: Volume volume; Node *parent = nullptr; union { - Node *childs[2]; + Node *children[2]; void *data; }; - _FORCE_INLINE_ bool is_leaf() const { return childs[1] == nullptr; } + _FORCE_INLINE_ bool is_leaf() const { return children[1] == nullptr; } _FORCE_INLINE_ bool is_internal() const { return (!is_leaf()); } _FORCE_INLINE_ int get_index_in_parent() const { ERR_FAIL_COND_V(!parent, 0); - return (parent->childs[1] == this) ? 1 : 0; + return (parent->children[1] == this) ? 1 : 0; } void get_max_depth(int depth, int &maxdepth) { if (is_internal()) { - childs[0]->get_max_depth(depth + 1, maxdepth); - childs[1]->get_max_depth(depth + 1, maxdepth); + children[0]->get_max_depth(depth + 1, maxdepth); + children[1]->get_max_depth(depth + 1, maxdepth); } else { maxdepth = MAX(maxdepth, depth); } @@ -205,7 +205,7 @@ private: // int count_leaves() const { if (is_internal()) { - return childs[0]->count_leaves() + childs[1]->count_leaves(); + return children[0]->count_leaves() + children[1]->count_leaves(); } else { return (1); } @@ -216,8 +216,8 @@ private: } Node() { - childs[0] = nullptr; - childs[1] = nullptr; + children[0] = nullptr; + children[1] = nullptr; } }; @@ -350,8 +350,8 @@ void DynamicBVH::aabb_query(const AABB &p_box, QueryResult &r_result) { stack = aux_stack.ptr(); threshold = aux_stack.size() - 2; } - stack[depth++] = n->childs[0]; - stack[depth++] = n->childs[1]; + stack[depth++] = n->children[0]; + stack[depth++] = n->children[1]; } else { if (r_result(n->data)) { return; @@ -406,8 +406,8 @@ void DynamicBVH::convex_query(const Plane *p_planes, int p_plane_count, const Ve stack = aux_stack.ptr(); threshold = aux_stack.size() - 2; } - stack[depth++] = n->childs[0]; - stack[depth++] = n->childs[1]; + stack[depth++] = n->children[0]; + stack[depth++] = n->children[1]; } else { if (r_result(n->data)) { return; @@ -463,8 +463,8 @@ void DynamicBVH::ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResu stack = aux_stack.ptr(); threshold = aux_stack.size() - 2; } - stack[depth++] = node->childs[0]; - stack[depth++] = node->childs[1]; + stack[depth++] = node->children[0]; + stack[depth++] = node->children[1]; } else { if (r_result(node->data)) { return; diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index df5486512d..61f5cfc22a 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -369,6 +369,14 @@ void ScriptServer::save_global_classes() { ProjectSettings::get_singleton()->store_global_class_list(gcarr); } +bool ScriptServer::has_global_classes() { + return !global_classes.is_empty(); +} + +String ScriptServer::get_global_class_cache_file_path() { + return ProjectSettings::get_singleton()->get_global_class_list_path(); +} + //////////////////// Variant ScriptInstance::call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { diff --git a/core/object/script_language.h b/core/object/script_language.h index f82b58439f..b1393c7196 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -91,6 +91,8 @@ public: static void get_global_class_list(List<StringName> *r_global_classes); static void get_inheriters_list(const StringName &p_base_type, List<StringName> *r_classes); static void save_global_classes(); + static bool has_global_classes(); + static String get_global_class_cache_file_path(); static void init_languages(); static void finish_languages(); diff --git a/core/variant/array.cpp b/core/variant/array.cpp index 94d1596514..2d7dff0b27 100644 --- a/core/variant/array.cpp +++ b/core/variant/array.cpp @@ -64,7 +64,7 @@ void Array::_ref(const Array &p_from) const { _unref(); - _p = p_from._p; + _p = _fp; } void Array::_unref() const { @@ -191,62 +191,73 @@ uint32_t Array::recursive_hash(int recursion_count) const { return hash_fmix32(h); } -bool Array::_assign(const Array &p_array) { - bool can_convert = p_array._p->typed.type == Variant::NIL; - can_convert |= _p->typed.type == Variant::STRING && p_array._p->typed.type == Variant::STRING_NAME; - can_convert |= _p->typed.type == Variant::STRING_NAME && p_array._p->typed.type == Variant::STRING; +void Array::operator=(const Array &p_array) { + if (this == &p_array) { + return; + } + _ref(p_array); +} + +void Array::assign(const Array &p_array) { + const ContainerTypeValidate &typed = _p->typed; + const ContainerTypeValidate &source_typed = p_array._p->typed; - if (_p->typed.type != Variant::OBJECT && _p->typed.type == p_array._p->typed.type) { - //same type or untyped, just reference, should be fine - _ref(p_array); - } else if (_p->typed.type == Variant::NIL) { //from typed to untyped, must copy, but this is cheap anyway + if (typed == source_typed || typed.type == Variant::NIL || (source_typed.type == Variant::OBJECT && typed.can_reference(source_typed))) { + // from same to same or + // from anything to variants or + // from subclasses to base classes _p->array = p_array._p->array; - } else if (can_convert) { //from untyped to typed, must try to check if they are all valid - if (_p->typed.type == Variant::OBJECT) { - //for objects, it needs full validation, either can be converted or fail - for (int i = 0; i < p_array._p->array.size(); i++) { - const Variant &element = p_array._p->array[i]; - if (element.get_type() != Variant::OBJECT || !_p->typed.validate_object(element, "assign")) { - return false; - } - } - _p->array = p_array._p->array; //then just copy, which is cheap anyway + return; + } - } else { - //for non objects, we need to check if there is a valid conversion, which needs to happen one by one, so this is the worst case. - Vector<Variant> new_array; - new_array.resize(p_array._p->array.size()); - for (int i = 0; i < p_array._p->array.size(); i++) { - Variant src_val = p_array._p->array[i]; - if (src_val.get_type() == _p->typed.type) { - new_array.write[i] = src_val; - } else if (Variant::can_convert_strict(src_val.get_type(), _p->typed.type)) { - Variant *ptr = &src_val; - Callable::CallError ce; - Variant::construct(_p->typed.type, new_array.write[i], (const Variant **)&ptr, 1, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_FAIL_V_MSG(false, "Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'."); - } - } else { - ERR_FAIL_V_MSG(false, "Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'."); - } + const Variant *source = p_array._p->array.ptr(); + int size = p_array._p->array.size(); + + if ((source_typed.type == Variant::NIL && typed.type == Variant::OBJECT) || (source_typed.type == Variant::OBJECT && source_typed.can_reference(typed))) { + // from variants to objects or + // from base classes to subclasses + for (int i = 0; i < size; i++) { + const Variant &element = source[i]; + if (element.get_type() != Variant::NIL && (element.get_type() != Variant::OBJECT || !typed.validate_object(element, "assign"))) { + ERR_FAIL_MSG(vformat(R"(Unable to convert array index %i from "%s" to "%s".)", i, Variant::get_type_name(element.get_type()), Variant::get_type_name(typed.type))); } + } + _p->array = p_array._p->array; + return; + } - _p->array = new_array; + Vector<Variant> array; + array.resize(size); + Variant *data = array.ptrw(); + + if (source_typed.type == Variant::NIL && typed.type != Variant::OBJECT) { + // from variants to primitives + for (int i = 0; i < size; i++) { + const Variant *value = source + i; + if (value->get_type() == typed.type) { + data[i] = *value; + continue; + } + if (!Variant::can_convert_strict(value->get_type(), typed.type)) { + ERR_FAIL_MSG("Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(value->get_type()) + "' to '" + Variant::get_type_name(typed.type) + "'."); + } + Callable::CallError ce; + Variant::construct(typed.type, data[i], &value, 1, ce); + ERR_FAIL_COND_MSG(ce.error, vformat(R"(Unable to convert array index %i from "%s" to "%s".)", i, Variant::get_type_name(value->get_type()), Variant::get_type_name(typed.type))); + } + } else if (Variant::can_convert_strict(source_typed.type, typed.type)) { + // from primitives to different convertible primitives + for (int i = 0; i < size; i++) { + const Variant *value = source + i; + Callable::CallError ce; + Variant::construct(typed.type, data[i], &value, 1, ce); + ERR_FAIL_COND_MSG(ce.error, vformat(R"(Unable to convert array index %i from "%s" to "%s".)", i, Variant::get_type_name(value->get_type()), Variant::get_type_name(typed.type))); } - } else if (_p->typed.can_reference(p_array._p->typed)) { //same type or compatible - _ref(p_array); } else { - ERR_FAIL_V_MSG(false, "Assignment of arrays of incompatible types."); + ERR_FAIL_MSG(vformat(R"(Cannot assign contents of "Array[%s]" to "Array[%s]".)", Variant::get_type_name(source_typed.type), Variant::get_type_name(typed.type))); } - return true; -} -void Array::operator=(const Array &p_array) { - if (this == &p_array) { - return; - } - _ref(p_array); + _p->array = array; } void Array::push_back(const Variant &p_value) { @@ -269,7 +280,15 @@ void Array::append_array(const Array &p_array) { Error Array::resize(int p_new_size) { ERR_FAIL_COND_V_MSG(_p->read_only, ERR_LOCKED, "Array is in read-only state."); - return _p->array.resize(p_new_size); + Variant::Type &variant_type = _p->typed.type; + int old_size = _p->array.size(); + Error err = _p->array.resize_zeroed(p_new_size); + if (!err && variant_type != Variant::NIL && variant_type != Variant::OBJECT) { + for (int i = old_size; i < p_new_size; i++) { + VariantInternal::initialize(&_p->array.write[i], variant_type); + } + } + return err; } Error Array::insert(int p_pos, const Variant &p_value) { @@ -403,24 +422,22 @@ Array Array::duplicate(bool p_deep) const { Array Array::recursive_duplicate(bool p_deep, int recursion_count) const { Array new_arr; + new_arr._p->typed = _p->typed; if (recursion_count > MAX_RECURSION) { ERR_PRINT("Max recursion reached"); return new_arr; } - int element_count = size(); - new_arr.resize(element_count); - new_arr._p->typed = _p->typed; if (p_deep) { recursion_count++; + int element_count = size(); + new_arr.resize(element_count); for (int i = 0; i < element_count; i++) { new_arr[i] = get(i).recursive_duplicate(true, recursion_count); } } else { - for (int i = 0; i < element_count; i++) { - new_arr[i] = get(i); - } + new_arr._p->array = _p->array; } return new_arr; @@ -737,11 +754,7 @@ Array::Array(const Array &p_from, uint32_t p_type, const StringName &p_class_nam _p = memnew(ArrayPrivate); _p->refcount.init(); set_typed(p_type, p_class_name, p_script); - _assign(p_from); -} - -bool Array::typed_assign(const Array &p_other) { - return _assign(p_other); + assign(p_from); } void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script) { @@ -763,6 +776,10 @@ bool Array::is_typed() const { return _p->typed.type != Variant::NIL; } +bool Array::is_same_typed(const Array &p_other) const { + return _p->typed == p_other._p->typed; +} + uint32_t Array::get_typed_builtin() const { return _p->typed.type; } diff --git a/core/variant/array.h b/core/variant/array.h index d9ca3278fb..4ef8ba8ce7 100644 --- a/core/variant/array.h +++ b/core/variant/array.h @@ -43,13 +43,11 @@ class Callable; class Array { mutable ArrayPrivate *_p; - void _ref(const Array &p_from) const; void _unref() const; -protected: - bool _assign(const Array &p_array); - public: + void _ref(const Array &p_from) const; + Variant &operator[](int p_idx); const Variant &operator[](int p_idx) const; @@ -68,6 +66,7 @@ public: uint32_t recursive_hash(int recursion_count) const; void operator=(const Array &p_array); + void assign(const Array &p_array); void push_back(const Variant &p_value); _FORCE_INLINE_ void append(const Variant &p_value) { push_back(p_value); } //for python compatibility void append_array(const Array &p_array); @@ -120,9 +119,9 @@ public: const void *id() const; - bool typed_assign(const Array &p_other); void set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script); bool is_typed() const; + bool is_same_typed(const Array &p_other) const; uint32_t get_typed_builtin() const; StringName get_typed_class_name() const; Variant get_typed_script() const; diff --git a/core/variant/container_type_validate.h b/core/variant/container_type_validate.h index 377be03bdf..796b66dc77 100644 --- a/core/variant/container_type_validate.h +++ b/core/variant/container_type_validate.h @@ -74,8 +74,15 @@ struct ContainerTypeValidate { return true; } + _FORCE_INLINE_ bool operator==(const ContainerTypeValidate &p_type) const { + return type == p_type.type && class_name == p_type.class_name && script == p_type.script; + } + _FORCE_INLINE_ bool operator!=(const ContainerTypeValidate &p_type) const { + return type != p_type.type || class_name != p_type.class_name || script != p_type.script; + } + // Coerces String and StringName into each other when needed. - _FORCE_INLINE_ bool validate(Variant &inout_variant, const char *p_operation = "use") { + _FORCE_INLINE_ bool validate(Variant &inout_variant, const char *p_operation = "use") const { if (type == Variant::NIL) { return true; } @@ -102,7 +109,7 @@ struct ContainerTypeValidate { return validate_object(inout_variant, p_operation); } - _FORCE_INLINE_ bool validate_object(const Variant &p_variant, const char *p_operation = "use") { + _FORCE_INLINE_ bool validate_object(const Variant &p_variant, const char *p_operation = "use") const { ERR_FAIL_COND_V(p_variant.get_type() != Variant::OBJECT, false); #ifdef DEBUG_ENABLED diff --git a/core/variant/typed_array.h b/core/variant/typed_array.h index 5aeabbacf8..03e557819b 100644 --- a/core/variant/typed_array.h +++ b/core/variant/typed_array.h @@ -40,14 +40,9 @@ template <class T> class TypedArray : public Array { public: - template <class U> - _FORCE_INLINE_ void operator=(const TypedArray<U> &p_array) { - static_assert(__is_base_of(T, U)); - _assign(p_array); - } - _FORCE_INLINE_ void operator=(const Array &p_array) { - _assign(p_array); + ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign an array with a different element type."); + _ref(p_array); } _FORCE_INLINE_ TypedArray(const Variant &p_variant) : Array(Array(p_variant), Variant::OBJECT, T::get_class_static(), Variant()) { @@ -62,22 +57,23 @@ public: //specialization for the rest of variant types -#define MAKE_TYPED_ARRAY(m_type, m_variant_type) \ - template <> \ - class TypedArray<m_type> : public Array { \ - public: \ - _FORCE_INLINE_ void operator=(const Array &p_array) { \ - _assign(p_array); \ - } \ - _FORCE_INLINE_ TypedArray(const Variant &p_variant) : \ - Array(Array(p_variant), m_variant_type, StringName(), Variant()) { \ - } \ - _FORCE_INLINE_ TypedArray(const Array &p_array) : \ - Array(p_array, m_variant_type, StringName(), Variant()) { \ - } \ - _FORCE_INLINE_ TypedArray() { \ - set_typed(m_variant_type, StringName(), Variant()); \ - } \ +#define MAKE_TYPED_ARRAY(m_type, m_variant_type) \ + template <> \ + class TypedArray<m_type> : public Array { \ + public: \ + _FORCE_INLINE_ void operator=(const Array &p_array) { \ + ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign an array with a different element type."); \ + _ref(p_array); \ + } \ + _FORCE_INLINE_ TypedArray(const Variant &p_variant) : \ + Array(Array(p_variant), m_variant_type, StringName(), Variant()) { \ + } \ + _FORCE_INLINE_ TypedArray(const Array &p_array) : \ + Array(p_array, m_variant_type, StringName(), Variant()) { \ + } \ + _FORCE_INLINE_ TypedArray() { \ + set_typed(m_variant_type, StringName(), Variant()); \ + } \ }; MAKE_TYPED_ARRAY(bool, Variant::BOOL) diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index e7d1a2478f..0c0c8f657a 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -2189,6 +2189,7 @@ static void _register_variant_builtin_methods() { bind_method(Array, is_empty, sarray(), varray()); bind_method(Array, clear, sarray(), varray()); bind_method(Array, hash, sarray(), varray()); + bind_method(Array, assign, sarray("array"), varray()); bind_method(Array, push_back, sarray("value"), varray()); bind_method(Array, push_front, sarray("value"), varray()); bind_method(Array, append, sarray("value"), varray()); @@ -2223,8 +2224,8 @@ static void _register_variant_builtin_methods() { bind_method(Array, all, sarray("method"), varray()); bind_method(Array, max, sarray(), varray()); bind_method(Array, min, sarray(), varray()); - bind_method(Array, typed_assign, sarray("array"), varray()); bind_method(Array, is_typed, sarray(), varray()); + bind_method(Array, is_same_typed, sarray("array"), varray()); bind_method(Array, get_typed_builtin, sarray(), varray()); bind_method(Array, get_typed_class_name, sarray(), varray()); bind_method(Array, get_typed_script, sarray(), varray()); @@ -2402,7 +2403,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedStringArray, remove_at, sarray("index"), varray()); bind_method(PackedStringArray, insert, sarray("at_index", "value"), varray()); bind_method(PackedStringArray, fill, sarray("value"), varray()); - bind_method(PackedStringArray, resize, sarray("new_size"), varray()); + bind_methodv(PackedStringArray, resize, &PackedStringArray::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedStringArray, clear, sarray(), varray()); bind_method(PackedStringArray, has, sarray("value"), varray()); bind_method(PackedStringArray, reverse, sarray(), varray()); @@ -2426,7 +2427,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedVector2Array, remove_at, sarray("index"), varray()); bind_method(PackedVector2Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedVector2Array, fill, sarray("value"), varray()); - bind_method(PackedVector2Array, resize, sarray("new_size"), varray()); + bind_methodv(PackedVector2Array, resize, &PackedVector2Array::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedVector2Array, clear, sarray(), varray()); bind_method(PackedVector2Array, has, sarray("value"), varray()); bind_method(PackedVector2Array, reverse, sarray(), varray()); @@ -2450,7 +2451,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedVector3Array, remove_at, sarray("index"), varray()); bind_method(PackedVector3Array, insert, sarray("at_index", "value"), varray()); bind_method(PackedVector3Array, fill, sarray("value"), varray()); - bind_method(PackedVector3Array, resize, sarray("new_size"), varray()); + bind_methodv(PackedVector3Array, resize, &PackedVector3Array::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedVector3Array, clear, sarray(), varray()); bind_method(PackedVector3Array, has, sarray("value"), varray()); bind_method(PackedVector3Array, reverse, sarray(), varray()); @@ -2474,7 +2475,7 @@ static void _register_variant_builtin_methods() { bind_method(PackedColorArray, remove_at, sarray("index"), varray()); bind_method(PackedColorArray, insert, sarray("at_index", "value"), varray()); bind_method(PackedColorArray, fill, sarray("value"), varray()); - bind_method(PackedColorArray, resize, sarray("new_size"), varray()); + bind_methodv(PackedColorArray, resize, &PackedColorArray::resize_zeroed, sarray("new_size"), varray()); bind_method(PackedColorArray, clear, sarray(), varray()); bind_method(PackedColorArray, has, sarray("value"), varray()); bind_method(PackedColorArray, reverse, sarray(), varray()); diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h index 21e1d21342..0d55ee4ae2 100644 --- a/core/variant/variant_internal.h +++ b/core/variant/variant_internal.h @@ -58,7 +58,13 @@ public: init_basis(v); break; case Variant::TRANSFORM3D: - init_transform(v); + init_transform3d(v); + break; + case Variant::PROJECTION: + init_projection(v); + break; + case Variant::COLOR: + init_color(v); break; case Variant::STRING_NAME: init_string_name(v); @@ -209,13 +215,12 @@ public: // Should be in the same order as Variant::Type for consistency. // Those primitive and vector types don't need an `init_` method: - // Nil, bool, float, Vector2/i, Rect2/i, Vector3/i, Plane, Quat, Color, RID. + // Nil, bool, float, Vector2/i, Rect2/i, Vector3/i, Plane, Quat, RID. // Object is a special case, handled via `object_assign_null`. _FORCE_INLINE_ static void init_string(Variant *v) { memnew_placement(v->_data._mem, String); v->type = Variant::STRING; } - _FORCE_INLINE_ static void init_transform2d(Variant *v) { v->_data._transform2d = (Transform2D *)Variant::Pools::_bucket_small.alloc(); memnew_placement(v->_data._transform2d, Transform2D); @@ -231,7 +236,7 @@ public: memnew_placement(v->_data._basis, Basis); v->type = Variant::BASIS; } - _FORCE_INLINE_ static void init_transform(Variant *v) { + _FORCE_INLINE_ static void init_transform3d(Variant *v) { v->_data._transform3d = (Transform3D *)Variant::Pools::_bucket_medium.alloc(); memnew_placement(v->_data._transform3d, Transform3D); v->type = Variant::TRANSFORM3D; @@ -241,6 +246,10 @@ public: memnew_placement(v->_data._projection, Projection); v->type = Variant::PROJECTION; } + _FORCE_INLINE_ static void init_color(Variant *v) { + memnew_placement(v->_data._mem, Color); + v->type = Variant::COLOR; + } _FORCE_INLINE_ static void init_string_name(Variant *v) { memnew_placement(v->_data._mem, StringName); v->type = Variant::STRING_NAME; @@ -1191,7 +1200,7 @@ struct VariantInitializer<Basis> { template <> struct VariantInitializer<Transform3D> { - static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform(v); } + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform3d(v); } }; template <> struct VariantInitializer<Projection> { diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index 87874deb8d..a40fcfbd47 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -910,7 +910,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, bool at_key = true; String key; - Token token2; bool need_comma = false; while (true) { @@ -920,18 +919,18 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } if (at_key) { - Error err = get_token(p_stream, token2, line, r_err_str); + Error err = get_token(p_stream, token, line, r_err_str); if (err != OK) { return err; } - if (token2.type == TK_PARENTHESIS_CLOSE) { + if (token.type == TK_PARENTHESIS_CLOSE) { value = ref.is_valid() ? Variant(ref) : Variant(obj); return OK; } if (need_comma) { - if (token2.type != TK_COMMA) { + if (token.type != TK_COMMA) { r_err_str = "Expected '}' or ','"; return ERR_PARSE_ERROR; } else { @@ -940,31 +939,31 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } } - if (token2.type != TK_STRING) { + if (token.type != TK_STRING) { r_err_str = "Expected property name as string"; return ERR_PARSE_ERROR; } - key = token2.value; + key = token.value; - err = get_token(p_stream, token2, line, r_err_str); + err = get_token(p_stream, token, line, r_err_str); if (err != OK) { return err; } - if (token2.type != TK_COLON) { + if (token.type != TK_COLON) { r_err_str = "Expected ':'"; return ERR_PARSE_ERROR; } at_key = false; } else { - Error err = get_token(p_stream, token2, line, r_err_str); + Error err = get_token(p_stream, token, line, r_err_str); if (err != OK) { return err; } Variant v; - err = parse_value(token2, v, p_stream, line, r_err_str, p_res_parser); + err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser); if (err) { return err; } @@ -1026,6 +1025,89 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } } + } else if (id == "Array") { + Error err = OK; + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_BRACKET_OPEN) { + r_err_str = "Expected '['"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_IDENTIFIER) { + r_err_str = "Expected type identifier"; + return ERR_PARSE_ERROR; + } + + static HashMap<StringName, Variant::Type> builtin_types; + if (builtin_types.is_empty()) { + for (int i = 1; i < Variant::VARIANT_MAX; i++) { + builtin_types[Variant::get_type_name((Variant::Type)i)] = (Variant::Type)i; + } + } + + Array array = Array(); + bool got_bracket_token = false; + if (builtin_types.has(token.value)) { + array.set_typed(builtin_types.get(token.value), StringName(), Variant()); + } else if (token.value == "Resource" || token.value == "SubResource" || token.value == "ExtResource") { + Variant resource; + err = parse_value(token, resource, p_stream, line, r_err_str, p_res_parser); + if (err) { + if (token.value == "Resource" && err == ERR_PARSE_ERROR && r_err_str == "Expected '('" && token.type == TK_BRACKET_CLOSE) { + err = OK; + r_err_str = String(); + array.set_typed(Variant::OBJECT, token.value, Variant()); + got_bracket_token = true; + } else { + return err; + } + } else { + Ref<Script> script = resource; + if (script.is_valid() && script->is_valid()) { + array.set_typed(Variant::OBJECT, script->get_instance_base_type(), script); + } + } + } else if (ClassDB::class_exists(token.value)) { + array.set_typed(Variant::OBJECT, token.value, Variant()); + } + + if (!got_bracket_token) { + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_BRACKET_CLOSE) { + r_err_str = "Expected ']'"; + return ERR_PARSE_ERROR; + } + } + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_PARENTHESIS_OPEN) { + r_err_str = "Expected '('"; + return ERR_PARSE_ERROR; + } + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_BRACKET_OPEN) { + r_err_str = "Expected '['"; + return ERR_PARSE_ERROR; + } + + Array values; + err = _parse_array(values, p_stream, line, r_err_str, p_res_parser); + if (err) { + return err; + } + + get_token(p_stream, token, line, r_err_str); + if (token.type != TK_PARENTHESIS_CLOSE) { + r_err_str = "Expected ')'"; + return ERR_PARSE_ERROR; + } + + array.assign(values); + + value = array; } else if (id == "PackedByteArray" || id == "PoolByteArray" || id == "ByteArray") { Vector<uint8_t> args; Error err = _parse_construct<uint8_t>(p_stream, args, line, r_err_str); @@ -1843,6 +1925,38 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::ARRAY: { + Array array = p_variant; + if (array.get_typed_builtin() != Variant::NIL) { + p_store_string_func(p_store_string_ud, "Array["); + + Variant::Type builtin_type = (Variant::Type)array.get_typed_builtin(); + StringName class_name = array.get_typed_class_name(); + Ref<Script> script = array.get_typed_script(); + + if (script.is_valid()) { + String resource_text = String(); + if (p_encode_res_func) { + resource_text = p_encode_res_func(p_encode_res_ud, script); + } + if (resource_text.is_empty() && script->get_path().is_resource_file()) { + resource_text = "Resource(\"" + script->get_path() + "\")"; + } + + if (!resource_text.is_empty()) { + p_store_string_func(p_store_string_ud, resource_text); + } else { + ERR_PRINT("Failed to encode a path to a custom script for an array type."); + p_store_string_func(p_store_string_ud, class_name); + } + } else if (class_name != StringName()) { + p_store_string_func(p_store_string_ud, class_name); + } else { + p_store_string_func(p_store_string_ud, Variant::get_type_name(builtin_type)); + } + + p_store_string_func(p_store_string_ud, "]("); + } + if (recursion_count > MAX_RECURSION) { ERR_PRINT("Max recursion reached"); p_store_string_func(p_store_string_ud, "[]"); @@ -1850,7 +1964,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str recursion_count++; p_store_string_func(p_store_string_ud, "["); - Array array = p_variant; int len = array.size(); for (int i = 0; i < len; i++) { if (i > 0) { @@ -1862,11 +1975,14 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, "]"); } + if (array.get_typed_builtin() != Variant::NIL) { + p_store_string_func(p_store_string_ud, ")"); + } + } break; case Variant::PACKED_BYTE_ARRAY: { p_store_string_func(p_store_string_ud, "PackedByteArray("); - String s; Vector<uint8_t> data = p_variant; int len = data.size(); const uint8_t *ptr = data.ptr(); @@ -1954,15 +2070,11 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str int len = data.size(); const String *ptr = data.ptr(); - String s; - //write_string("\n"); - for (int i = 0; i < len; i++) { if (i > 0) { p_store_string_func(p_store_string_ud, ", "); } - String str = ptr[i]; - p_store_string_func(p_store_string_ud, "\"" + str.c_escape() + "\""); + p_store_string_func(p_store_string_ud, "\"" + ptr[i].c_escape() + "\""); } p_store_string_func(p_store_string_ud, ")"); @@ -2010,9 +2122,9 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str if (i > 0) { p_store_string_func(p_store_string_ud, ", "); } - p_store_string_func(p_store_string_ud, rtos_fix(ptr[i].r) + ", " + rtos_fix(ptr[i].g) + ", " + rtos_fix(ptr[i].b) + ", " + rtos_fix(ptr[i].a)); } + p_store_string_func(p_store_string_ud, ")"); } break; diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 0d6524ccbe..3b2e260dcb 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -1271,7 +1271,13 @@ <method name="str" qualifiers="vararg"> <return type="String" /> <description> - Converts one or more arguments of any [Variant] type to [String] in the best way possible. + Converts one or more arguments of any [Variant] type to a [String] in the best way possible. + [codeblock] + var a = [10, 20, 30] + var b = str(a) + print(len(a)) # Prints 3 (the number of elements in the array). + print(len(b)) # Prints 12 (the length of the string "[10, 20, 30]"). + [/codeblock] </description> </method> <method name="str_to_var"> diff --git a/doc/classes/AESContext.xml b/doc/classes/AESContext.xml index 7f582e4be7..747968ea91 100644 --- a/doc/classes/AESContext.xml +++ b/doc/classes/AESContext.xml @@ -39,39 +39,38 @@ [/gdscript] [csharp] using Godot; - using System; using System.Diagnostics; - public class Example : Node + public partial class MyNode : Node { - public AESContext Aes = new AESContext(); + private AesContext _aes = new AesContext(); public override void _Ready() { string key = "My secret key!!!"; // Key must be either 16 or 32 bytes. string data = "My secret text!!"; // Data size must be multiple of 16 bytes, apply padding if needed. // Encrypt ECB - Aes.Start(AESContext.Mode.EcbEncrypt, key.ToUTF8()); - byte[] encrypted = Aes.Update(data.ToUTF8()); - Aes.Finish(); + _aes.Start(AesContext.Mode.EcbEncrypt, key.ToUtf8()); + byte[] encrypted = _aes.Update(data.ToUtf8()); + _aes.Finish(); // Decrypt ECB - Aes.Start(AESContext.Mode.EcbDecrypt, key.ToUTF8()); - byte[] decrypted = Aes.Update(encrypted); - Aes.Finish(); + _aes.Start(AesContext.Mode.EcbDecrypt, key.ToUtf8()); + byte[] decrypted = _aes.Update(encrypted); + _aes.Finish(); // Check ECB - Debug.Assert(decrypted == data.ToUTF8()); + Debug.Assert(decrypted == data.ToUtf8()); string iv = "My secret iv!!!!"; // IV must be of exactly 16 bytes. // Encrypt CBC - Aes.Start(AESContext.Mode.EcbEncrypt, key.ToUTF8(), iv.ToUTF8()); - encrypted = Aes.Update(data.ToUTF8()); - Aes.Finish(); + _aes.Start(AesContext.Mode.EcbEncrypt, key.ToUtf8(), iv.ToUtf8()); + encrypted = _aes.Update(data.ToUtf8()); + _aes.Finish(); // Decrypt CBC - Aes.Start(AESContext.Mode.EcbDecrypt, key.ToUTF8(), iv.ToUTF8()); - decrypted = Aes.Update(encrypted); - Aes.Finish(); + _aes.Start(AesContext.Mode.EcbDecrypt, key.ToUtf8(), iv.ToUtf8()); + decrypted = _aes.Update(encrypted); + _aes.Finish(); // Check CBC - Debug.Assert(decrypted == data.ToUTF8()); + Debug.Assert(decrypted == data.ToUtf8()); } } [/csharp] diff --git a/doc/classes/AStar3D.xml b/doc/classes/AStar3D.xml index 4e8394195d..f0481c1745 100644 --- a/doc/classes/AStar3D.xml +++ b/doc/classes/AStar3D.xml @@ -19,15 +19,16 @@ return min(0, abs(u - v) - 1) [/gdscript] [csharp] - public class MyAStar : AStar3D + public partial class MyAStar : AStar3D { - public override float _ComputeCost(int u, int v) + public override float _ComputeCost(long fromId, long toId) { - return Mathf.Abs(u - v); + return Mathf.Abs((int)(fromId - toId)); } - public override float _EstimateCost(int u, int v) + + public override float _EstimateCost(long fromId, long toId) { - return Mathf.Min(0, Mathf.Abs(u - v) - 1); + return Mathf.Min(0, Mathf.Abs((int)(fromId - toId)) - 1); } } [/csharp] diff --git a/doc/classes/AnimationNodeBlendSpace1D.xml b/doc/classes/AnimationNodeBlendSpace1D.xml index 0f1ce127cd..9a7872f50e 100644 --- a/doc/classes/AnimationNodeBlendSpace1D.xml +++ b/doc/classes/AnimationNodeBlendSpace1D.xml @@ -67,6 +67,9 @@ </method> </methods> <members> + <member name="blend_mode" type="int" setter="set_blend_mode" getter="get_blend_mode" enum="AnimationNodeBlendSpace1D.BlendMode" default="0"> + Controls the interpolation between animations. See [enum BlendMode] constants. + </member> <member name="max_space" type="float" setter="set_max_space" getter="get_max_space" default="1.0"> The blend space's axis's upper limit for the points' position. See [method add_blend_point]. </member> @@ -84,4 +87,15 @@ Label of the virtual axis of the blend space. </member> </members> + <constants> + <constant name="BLEND_MODE_INTERPOLATED" value="0" enum="BlendMode"> + The interpolation between animations is linear. + </constant> + <constant name="BLEND_MODE_DISCRETE" value="1" enum="BlendMode"> + The blend space plays the animation of the node the blending position is closest to. Useful for frame-by-frame 2D animations. + </constant> + <constant name="BLEND_MODE_DISCRETE_CARRY" value="2" enum="BlendMode"> + Similar to [constant BLEND_MODE_DISCRETE], but starts the new animation at the last animation's playback position. + </constant> + </constants> </class> diff --git a/doc/classes/AnimationNodeStateMachine.xml b/doc/classes/AnimationNodeStateMachine.xml index 0fb789875f..95891a9061 100644 --- a/doc/classes/AnimationNodeStateMachine.xml +++ b/doc/classes/AnimationNodeStateMachine.xml @@ -161,4 +161,9 @@ </description> </method> </methods> + <members> + <member name="allow_transition_to_self" type="bool" setter="set_allow_transition_to_self" getter="is_allow_transition_to_self" default="false"> + If [code]true[/code], allows teleport to the self state with [method AnimationNodeStateMachinePlayback.travel]. When the reset option is enabled in [method AnimationNodeStateMachinePlayback.travel], the animation is restarted. If [code]false[/code], nothing happens on the teleportation to the self state. + </member> + </members> </class> diff --git a/doc/classes/AnimationNodeTransition.xml b/doc/classes/AnimationNodeTransition.xml index a067b0a9ba..bc3e5716dd 100644 --- a/doc/classes/AnimationNodeTransition.xml +++ b/doc/classes/AnimationNodeTransition.xml @@ -44,6 +44,9 @@ </method> </methods> <members> + <member name="allow_transition_to_self" type="bool" setter="set_allow_transition_to_self" getter="is_allow_transition_to_self" default="false"> + If [code]true[/code], allows transition to the self state. When the reset option is enabled in input, the animation is restarted. If [code]false[/code], nothing happens on the transition to the self state. + </member> <member name="input_count" type="int" setter="set_input_count" getter="get_input_count" default="0"> The number of enabled input ports for this node. </member> diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml index 3f76cc16ec..8a98921a60 100644 --- a/doc/classes/Area2D.xml +++ b/doc/classes/Area2D.xml @@ -87,8 +87,9 @@ <member name="gravity_point_center" type="Vector2" setter="set_gravity_point_center" getter="get_gravity_point_center" default="Vector2(0, 1)"> If gravity is a point (see [member gravity_point]), this will be the point of attraction. </member> - <member name="gravity_point_distance_scale" type="float" setter="set_gravity_point_distance_scale" getter="get_gravity_point_distance_scale" default="0.0"> - The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance. + <member name="gravity_point_unit_distance" type="float" setter="set_gravity_point_unit_distance" getter="get_gravity_point_unit_distance" default="0.0"> + The distance at which the gravity strength is equal to [member gravity]. For example, on a planet 100 pixels in radius with a surface gravity of 4.0 px/s², set the [member gravity] to 4.0 and the unit distance to 100.0. The gravity will have falloff according to the inverse square law, so in the example, at 200 pixels from the center the gravity will be 1.0 px/s² (twice the distance, 1/4th the gravity), at 50 pixels it will be 16.0 px/s² (half the distance, 4x the gravity), and so on. + The above is true only when the unit distance is a positive number. When this is set to 0.0, the gravity will be constant regardless of distance. </member> <member name="gravity_space_override" type="int" setter="set_gravity_space_override_mode" getter="get_gravity_space_override_mode" enum="Area2D.SpaceOverride" default="0"> Override mode for gravity calculations within this area. See [enum SpaceOverride] for possible values. diff --git a/doc/classes/Area3D.xml b/doc/classes/Area3D.xml index d40bca99d8..bd046b7cb8 100644 --- a/doc/classes/Area3D.xml +++ b/doc/classes/Area3D.xml @@ -86,8 +86,9 @@ <member name="gravity_point_center" type="Vector3" setter="set_gravity_point_center" getter="get_gravity_point_center" default="Vector3(0, -1, 0)"> If gravity is a point (see [member gravity_point]), this will be the point of attraction. </member> - <member name="gravity_point_distance_scale" type="float" setter="set_gravity_point_distance_scale" getter="get_gravity_point_distance_scale" default="0.0"> - The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance. + <member name="gravity_point_unit_distance" type="float" setter="set_gravity_point_unit_distance" getter="get_gravity_point_unit_distance" default="0.0"> + The distance at which the gravity strength is equal to [member gravity]. For example, on a planet 100 meters in radius with a surface gravity of 4.0 m/s², set the [member gravity] to 4.0 and the unit distance to 100.0. The gravity will have falloff according to the inverse square law, so in the example, at 200 meters from the center the gravity will be 1.0 m/s² (twice the distance, 1/4th the gravity), at 50 meters it will be 16.0 m/s² (half the distance, 4x the gravity), and so on. + The above is true only when the unit distance is a positive number. When this is set to 0.0, the gravity will be constant regardless of distance. </member> <member name="gravity_space_override" type="int" setter="set_gravity_space_override_mode" getter="get_gravity_space_override_mode" enum="Area3D.SpaceOverride" default="0"> Override mode for gravity calculations within this area. See [enum SpaceOverride] for possible values. diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 9be5e60f4a..213a2254af 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -59,14 +59,14 @@ <param index="2" name="class_name" type="StringName" /> <param index="3" name="script" type="Variant" /> <description> - Creates a typed array from the [param base] array. The base array can't be already typed. + Creates a typed array from the [param base] array. </description> </constructor> <constructor name="Array"> <return type="Array" /> <param index="0" name="from" type="Array" /> <description> - Constructs an [Array] as a copy of the given [Array]. + Returns the same array as [param from]. If you need a copy of the array, use [method duplicate]. </description> </constructor> <constructor name="Array"> @@ -200,6 +200,13 @@ [/codeblock] </description> </method> + <method name="assign"> + <return type="void" /> + <param index="0" name="array" type="Array" /> + <description> + Assigns elements of another [param array] into the array. Resizes the array to match [param array]. Performs type conversions if the array is typed. + </description> + </method> <method name="back" qualifiers="const"> <return type="Variant" /> <description> @@ -395,6 +402,13 @@ Returns [code]true[/code] if the array is read-only. See [method make_read_only]. Arrays are automatically read-only if declared with [code]const[/code] keyword. </description> </method> + <method name="is_same_typed" qualifiers="const"> + <return type="bool" /> + <param index="0" name="array" type="Array" /> + <description> + Returns [code]true[/code] if the array is typed the same as [param array]. + </description> + </method> <method name="is_typed" qualifiers="const"> <return type="bool" /> <description> @@ -609,13 +623,6 @@ [/codeblocks] </description> </method> - <method name="typed_assign"> - <return type="bool" /> - <param index="0" name="array" type="Array" /> - <description> - Assigns a different [Array] to this array reference. It the array is typed, the new array's type must be compatible and its elements will be automatically converted. - </description> - </method> </methods> <operators> <operator name="operator !="> diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml index 36f12dd5c4..ae331f8491 100644 --- a/doc/classes/AudioServer.xml +++ b/doc/classes/AudioServer.xml @@ -29,13 +29,6 @@ Adds an [AudioEffect] effect to the bus [param bus_idx] at [param at_position]. </description> </method> - <method name="capture_get_device_list"> - <return type="PackedStringArray" /> - <description> - Returns the names of all audio input devices detected on the system. - [b]Note:[/b] [member ProjectSettings.audio/driver/enable_input] must be [code]true[/code] for audio input to work. See also that setting's description for caveats related to permissions and operating system privacy settings. - </description> - </method> <method name="generate_bus_layout" qualifiers="const"> <return type="AudioBusLayout" /> <description> @@ -117,10 +110,11 @@ Returns the volume of the bus at index [param bus_idx] in dB. </description> </method> - <method name="get_device_list"> + <method name="get_input_device_list"> <return type="PackedStringArray" /> <description> - Returns the names of all audio devices detected on the system. + Returns the names of all audio input devices detected on the system. + [b]Note:[/b] [member ProjectSettings.audio/driver/enable_input] must be [code]true[/code] for audio input to work. See also that setting's description for caveats related to permissions and operating system privacy settings. </description> </method> <method name="get_mix_rate" qualifiers="const"> @@ -129,6 +123,12 @@ Returns the sample rate at the output of the [AudioServer]. </description> </method> + <method name="get_output_device_list"> + <return type="PackedStringArray" /> + <description> + Returns the names of all audio output devices detected on the system. + </description> + </method> <method name="get_output_latency" qualifiers="const"> <return type="float" /> <description> @@ -302,12 +302,12 @@ <member name="bus_count" type="int" setter="set_bus_count" getter="get_bus_count" default="1"> Number of available audio buses. </member> - <member name="capture_device" type="String" setter="capture_set_device" getter="capture_get_device" default=""Default""> - Name of the current device for audio input (see [method capture_get_device_list]). On systems with multiple audio inputs (such as analog, USB and HDMI audio), this can be used to select the audio input device. The value [code]"Default"[/code] will record audio on the system-wide default audio input. If an invalid device name is set, the value will be reverted back to [code]"Default"[/code]. + <member name="input_device" type="String" setter="set_input_device" getter="get_input_device" default=""Default""> + Name of the current device for audio input (see [method get_input_device_list]). On systems with multiple audio inputs (such as analog, USB and HDMI audio), this can be used to select the audio input device. The value [code]"Default"[/code] will record audio on the system-wide default audio input. If an invalid device name is set, the value will be reverted back to [code]"Default"[/code]. [b]Note:[/b] [member ProjectSettings.audio/driver/enable_input] must be [code]true[/code] for audio input to work. See also that setting's description for caveats related to permissions and operating system privacy settings. </member> - <member name="device" type="String" setter="set_device" getter="get_device" default=""Default""> - Name of the current device for audio output (see [method get_device_list]). On systems with multiple audio outputs (such as analog, USB and HDMI audio), this can be used to select the audio output device. The value [code]"Default"[/code] will play audio on the system-wide default audio output. If an invalid device name is set, the value will be reverted back to [code]"Default"[/code]. + <member name="output_device" type="String" setter="set_output_device" getter="get_output_device" default=""Default""> + Name of the current device for audio output (see [method get_output_device_list]). On systems with multiple audio outputs (such as analog, USB and HDMI audio), this can be used to select the audio output device. The value [code]"Default"[/code] will play audio on the system-wide default audio output. If an invalid device name is set, the value will be reverted back to [code]"Default"[/code]. </member> <member name="playback_speed_scale" type="float" setter="set_playback_speed_scale" getter="get_playback_speed_scale" default="1.0"> Scales the rate at which audio is played (i.e. setting it to [code]0.5[/code] will make the audio be played at half its speed). diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml index 9315a85e1f..4156c9451a 100644 --- a/doc/classes/Camera2D.xml +++ b/doc/classes/Camera2D.xml @@ -55,6 +55,18 @@ [b]Note:[/b] The returned value is not the same as [member Node2D.global_position], as it is affected by the drag properties. It is also not the same as the current position if [member position_smoothing_enabled] is [code]true[/code] (see [method get_screen_center_position]). </description> </method> + <method name="is_current" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if this [Camera2D] is the active camera (see [method Viewport.get_camera_2d]). + </description> + </method> + <method name="make_current"> + <return type="void" /> + <description> + Forces this [Camera2D] to become the current active one. [member enabled] must be [code]true[/code]. + </description> + </method> <method name="reset_smoothing"> <return type="void" /> <description> @@ -83,9 +95,6 @@ <member name="anchor_mode" type="int" setter="set_anchor_mode" getter="get_anchor_mode" enum="Camera2D.AnchorMode" default="1"> The Camera2D's anchor point. See [enum AnchorMode] constants. </member> - <member name="current" type="bool" setter="set_current" getter="is_current" default="false"> - If [code]true[/code], the camera acts as the active camera for its [Viewport] ancestor. Only one camera can be current in a given viewport, so setting a different camera in the same viewport [code]current[/code] will disable whatever camera was already active in that viewport. - </member> <member name="custom_viewport" type="Node" setter="set_custom_viewport" getter="get_custom_viewport"> The custom [Viewport] node attached to the [Camera2D]. If [code]null[/code] or not a [Viewport], uses the default viewport instead. </member> @@ -124,6 +133,10 @@ <member name="editor_draw_screen" type="bool" setter="set_screen_drawing_enabled" getter="is_screen_drawing_enabled" default="true"> If [code]true[/code], draws the camera's screen rectangle in the editor. </member> + <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true"> + Controls whether the camera can be active or not. If [code]true[/code], the [Camera2D] will become the main camera when it enters the scene tree and there is no active camera currently (see [method Viewport.get_camera_2d]). + When the camera is currently active and [member enabled] is set to [code]false[/code], the next enabled [Camera2D] in the scene tree will become active. + </member> <member name="ignore_rotation" type="bool" setter="set_ignore_rotation" getter="is_ignoring_rotation" default="true"> If [code]true[/code], the camera's rendered view is not affected by its [member Node2D.rotation] and [member Node2D.global_rotation]. </member> diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml index 57278d9241..cee0e3ef7d 100644 --- a/doc/classes/Color.xml +++ b/doc/classes/Color.xml @@ -233,7 +233,6 @@ <description> Returns a new color from [param rgba], an HTML hexadecimal color string. [param rgba] is not case-sensitive, and may be prefixed by a hash sign ([code]#[/code]). [param rgba] must be a valid three-digit or six-digit hexadecimal color string, and may contain an alpha channel value. If [param rgba] does not contain an alpha channel value, an alpha channel value of 1.0 is applied. If [param rgba] is invalid, returns an empty color. - [b]Note:[/b] In C#, this method is not implemented. The same functionality is provided by the Color constructor. [codeblocks] [gdscript] var blue = Color.html("#0000ff") # blue is Color(0.0, 0.0, 1.0, 1.0) @@ -264,13 +263,13 @@ Color.html_is_valid("#55aaFF5") # Returns false [/gdscript] [csharp] - Color.IsHtmlValid("#55AAFF"); // Returns true - Color.IsHtmlValid("#55AAFF20"); // Returns true - Color.IsHtmlValid("55AAFF"); // Returns true - Color.IsHtmlValid("#F2C"); // Returns true + Color.HtmlIsValid("#55AAFF"); // Returns true + Color.HtmlIsValid("#55AAFF20"); // Returns true + Color.HtmlIsValid("55AAFF"); // Returns true + Color.HtmlIsValid("#F2C"); // Returns true - Color.IsHtmlValid("#AABBC"); // Returns false - Color.IsHtmlValid("#55aaFF5"); // Returns false + Color.HtmlIsValid("#AABBC"); // Returns false + Color.HtmlIsValid("#55aaFF5"); // Returns false [/csharp] [/codeblocks] </description> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 0d675112b8..d74ddba369 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -37,11 +37,11 @@ return typeof(data) == TYPE_DICTIONARY and data.has("expected") [/gdscript] [csharp] - public override bool CanDropData(Vector2 position, object data) + public override bool _CanDropData(Vector2 atPosition, Variant data) { // Check position if it is relevant to you // Otherwise, just check data - return data is Godot.Collections.Dictionary && (data as Godot.Collections.Dictionary).Contains("expected"); + return data.VariantType == Variant.Type.Dictionary && data.AsGodotDictionary().Contains("expected"); } [/csharp] [/codeblocks] @@ -57,17 +57,19 @@ [gdscript] func _can_drop_data(position, data): return typeof(data) == TYPE_DICTIONARY and data.has("color") + func _drop_data(position, data): var color = data["color"] [/gdscript] [csharp] - public override bool CanDropData(Vector2 position, object data) + public override bool _CanDropData(Vector2 atPosition, Variant data) { - return data is Godot.Collections.Dictionary && (data as Godot.Collections.Dictionary).Contains("color"); + return data.VariantType == Variant.Type.Dictionary && dict.AsGodotDictionary().Contains("color"); } - public override void DropData(Vector2 position, object data) + + public override void _DropData(Vector2 atPosition, Variant data) { - Color color = (Color)(data as Godot.Collections.Dictionary)["color"]; + Color color = data.AsGodotDictionary()["color"].AsColor(); } [/csharp] [/codeblocks] @@ -87,11 +89,11 @@ return mydata [/gdscript] [csharp] - public override object GetDragData(Vector2 position) + public override Variant _GetDragData(Vector2 atPosition) { - object mydata = MakeData(); // This is your custom method generating the drag data. - SetDragPreview(MakePreview(mydata)); // This is your custom method generating the preview of the drag data. - return mydata; + var myData = MakeData(); // This is your custom method generating the drag data. + SetDragPreview(MakePreview(myData)); // This is your custom method generating the preview of the drag data. + return myData; } [/csharp] [/codeblocks] @@ -121,10 +123,9 @@ [csharp] public override void _GuiInput(InputEvent @event) { - if (@event is InputEventMouseButton) + if (@event is InputEventMouseButton mb) { - var mb = @event as InputEventMouseButton; - if (mb.ButtonIndex == (int)ButtonList.Left && mb.Pressed) + if (mb.ButtonIndex == MouseButton.Left && mb.Pressed) { GD.Print("I've been clicked D:"); } @@ -168,7 +169,7 @@ return label [/gdscript] [csharp] - public override Godot.Control _MakeCustomTooltip(String forText) + public override Control _MakeCustomTooltip(string forText) { var label = new Label(); label.Text = forText; @@ -185,7 +186,7 @@ return tooltip [/gdscript] [csharp] - public override Godot.Control _MakeCustomTooltip(String forText) + public override Control _MakeCustomTooltip(string forText) { Node tooltip = ResourceLoader.Load<PackedScene>("res://some_tooltip_scene.tscn").Instantiate(); tooltip.GetNode<Label>("Label").Text = forText; @@ -229,11 +230,11 @@ [/gdscript] [csharp] // Given the child Label node "MyLabel", override its font color with a custom value. - GetNode<Label>("MyLabel").AddThemeColorOverride("font_color", new Color(1, 0.5f, 0)) + GetNode<Label>("MyLabel").AddThemeColorOverride("font_color", new Color(1, 0.5f, 0)); // Reset the font color of the child label. - GetNode<Label>("MyLabel").RemoveThemeColorOverride("font_color") + GetNode<Label>("MyLabel").RemoveThemeColorOverride("font_color"); // Alternatively it can be overridden with the default value from the Label type. - GetNode<Label>("MyLabel").AddThemeColorOverride("font_color", GetThemeColor("font_color", "Label")) + GetNode<Label>("MyLabel").AddThemeColorOverride("font_color", GetThemeColor("font_color", "Label")); [/csharp] [/codeblocks] </description> @@ -542,12 +543,12 @@ [codeblocks] [gdscript] func _process(delta): - grab_click_focus() #when clicking another Control node, this node will be clicked instead + grab_click_focus() # When clicking another Control node, this node will be clicked instead. [/gdscript] [csharp] - public override void _Process(float delta) + public override void _Process(double delta) { - GrabClickFocus(); //when clicking another Control node, this node will be clicked instead + GrabClickFocus(); // When clicking another Control node, this node will be clicked instead. } [/csharp] [/codeblocks] @@ -812,16 +813,16 @@ [/gdscript] [csharp] [Export] - public Color Color = new Color(1, 0, 0, 1); + private Color _color = new Color(1, 0, 0, 1); - public override object GetDragData(Vector2 position) + public override Variant _GetDragData(Vector2 atPosition) { // Use a control that is not in the tree var cpb = new ColorPickerButton(); - cpb.Color = Color; - cpb.RectSize = new Vector2(50, 50); + cpb.Color = _color; + cpb.Size = new Vector2(50, 50); SetDragPreview(cpb); - return Color; + return _color; } [/csharp] [/codeblocks] diff --git a/doc/classes/Crypto.xml b/doc/classes/Crypto.xml index ade63225dc..a7e7e756c6 100644 --- a/doc/classes/Crypto.xml +++ b/doc/classes/Crypto.xml @@ -9,9 +9,11 @@ [codeblocks] [gdscript] extends Node + var crypto = Crypto.new() var key = CryptoKey.new() var cert = X509Certificate.new() + func _ready(): # Generate new RSA key. key = crypto.generate_rsa(4096) @@ -35,35 +37,35 @@ [/gdscript] [csharp] using Godot; - using System; using System.Diagnostics; - public class CryptoNode : Node + public partial class MyNode : Node { - public Crypto Crypto = new Crypto(); - public CryptoKey Key = new CryptoKey(); - public X509Certificate Cert = new X509Certificate(); + private Crypto _crypto = new Crypto(); + private CryptoKey _key = new CryptoKey(); + private X509Certificate _cert = new X509Certificate(); + public override void _Ready() { // Generate new RSA key. - Key = Crypto.GenerateRsa(4096); + _key = _crypto.GenerateRsa(4096); // Generate new self-signed certificate with the given key. - Cert = Crypto.GenerateSelfSignedCertificate(Key, "CN=mydomain.com,O=My Game Company,C=IT"); + _cert = _crypto.GenerateSelfSignedCertificate(_key, "CN=mydomain.com,O=My Game Company,C=IT"); // Save key and certificate in the user folder. - Key.Save("user://generated.key"); - Cert.Save("user://generated.crt"); + _key.Save("user://generated.key"); + _cert.Save("user://generated.crt"); // Encryption string data = "Some data"; - byte[] encrypted = Crypto.Encrypt(Key, data.ToUTF8()); + byte[] encrypted = _crypto.Encrypt(_key, data.ToUtf8()); // Decryption - byte[] decrypted = Crypto.Decrypt(Key, encrypted); + byte[] decrypted = _crypto.Decrypt(_key, encrypted); // Signing - byte[] signature = Crypto.Sign(HashingContext.HashType.Sha256, Data.SHA256Buffer(), Key); + byte[] signature = _crypto.Sign(HashingContext.HashType.Sha256, Data.Sha256Buffer(), _key); // Verifying - bool verified = Crypto.Verify(HashingContext.HashType.Sha256, Data.SHA256Buffer(), signature, Key); + bool verified = _crypto.Verify(HashingContext.HashType.Sha256, Data.Sha256Buffer(), signature, _key); // Checks Debug.Assert(verified); - Debug.Assert(data.ToUTF8() == decrypted); + Debug.Assert(data.ToUtf8() == decrypted); } } [/csharp] diff --git a/doc/classes/DTLSServer.xml b/doc/classes/DTLSServer.xml index a3a0b0456c..ae1ba10ec7 100644 --- a/doc/classes/DTLSServer.xml +++ b/doc/classes/DTLSServer.xml @@ -38,45 +38,46 @@ p.put_packet("Hello DTLS client".to_utf8()) [/gdscript] [csharp] - using Godot; - using System; // ServerNode.cs - public class ServerNode : Node + using Godot; + + public partial class ServerNode : Node { - public DTLSServer Dtls = new DTLSServer(); - public UDPServer Server = new UDPServer(); - public Godot.Collections.Array<PacketPeerDTLS> Peers = new Godot.Collections.Array<PacketPeerDTLS>(); + private DtlsServer _dtls = new DtlsServer(); + private UdpServer _server = new UdpServer(); + private Godot.Collections.Array<PacketPeerDTLS> _peers = new Godot.Collections.Array<PacketPeerDTLS>(); + public override void _Ready() { - Server.Listen(4242); + _server.Listen(4242); var key = GD.Load<CryptoKey>("key.key"); // Your private key. var cert = GD.Load<X509Certificate>("cert.crt"); // Your X509 certificate. - Dtls.Setup(key, cert); + _dtls.Setup(key, cert); } - public override void _Process(float delta) + public override void _Process(double delta) { while (Server.IsConnectionAvailable()) { - PacketPeerUDP peer = Server.TakeConnection(); - PacketPeerDTLS dtlsPeer = Dtls.TakeConnection(peer); - if (dtlsPeer.GetStatus() != PacketPeerDTLS.Status.Handshaking) + PacketPeerUDP peer = _server.TakeConnection(); + PacketPeerDTLS dtlsPeer = _dtls.TakeConnection(peer); + if (dtlsPeer.GetStatus() != PacketPeerDtls.Status.Handshaking) { continue; // It is normal that 50% of the connections fails due to cookie exchange. } GD.Print("Peer connected!"); - Peers.Add(dtlsPeer); + _peers.Add(dtlsPeer); } - foreach (var p in Peers) + foreach (var p in _peers) { p.Poll(); // Must poll to update the state. - if (p.GetStatus() == PacketPeerDTLS.Status.Connected) + if (p.GetStatus() == PacketPeerDtls.Status.Connected) { while (p.GetAvailablePacketCount() > 0) { - GD.Print("Received Message From Client: " + p.GetPacket().GetStringFromUTF8()); - p.PutPacket("Hello Dtls Client".ToUTF8()); + GD.Print($"Received Message From Client: {p.GetPacket().GetStringFromUtf8()}"); + p.PutPacket("Hello DTLS Client".ToUtf8()); } } } @@ -108,34 +109,36 @@ connected = true [/gdscript] [csharp] + // ClientNode.cs using Godot; using System.Text; - // ClientNode.cs - public class ClientNode : Node + + public partial class ClientNode : Node { - public PacketPeerDTLS Dtls = new PacketPeerDTLS(); - public PacketPeerUDP Udp = new PacketPeerUDP(); - public bool Connected = false; + private PacketPeerDtls _dtls = new PacketPeerDtls(); + private PacketPeerUdp _udp = new PacketPeerUdp(); + private bool _connected = false; + public override void _Ready() { - Udp.ConnectToHost("127.0.0.1", 4242); - Dtls.ConnectToPeer(Udp, false); // Use true in production for certificate validation! + _udp.ConnectToHost("127.0.0.1", 4242); + _dtls.ConnectToPeer(_udp, validateCerts: false); // Use true in production for certificate validation! } - public override void _Process(float delta) + public override void _Process(double delta) { - Dtls.Poll(); - if (Dtls.GetStatus() == PacketPeerDTLS.Status.Connected) + _dtls.Poll(); + if (_dtls.GetStatus() == PacketPeerDtls.Status.Connected) { - if (!Connected) + if (!_connected) { // Try to contact server - Dtls.PutPacket("The Answer Is..42!".ToUTF8()); + _dtls.PutPacket("The Answer Is..42!".ToUtf8()); } - while (Dtls.GetAvailablePacketCount() > 0) + while (_dtls.GetAvailablePacketCount() > 0) { - GD.Print("Connected: " + Dtls.GetPacket().GetStringFromUTF8()); - Connected = true; + GD.Print($"Connected: {_dtls.GetPacket().GetStringFromUtf8()}"); + _connected = true; } } } diff --git a/doc/classes/Decal.xml b/doc/classes/Decal.xml index b9d3f1d81e..fb8bc18c1a 100644 --- a/doc/classes/Decal.xml +++ b/doc/classes/Decal.xml @@ -75,9 +75,6 @@ <member name="emission_energy" type="float" setter="set_emission_energy" getter="get_emission_energy" default="1.0"> Energy multiplier for the emission texture. This will make the decal emit light at a higher or lower intensity, independently of the albedo color. See also [member modulate]. </member> - <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> - Sets the size of the [AABB] used by the decal. The AABB goes from [code]-extents[/code] to [code]extents[/code]. - </member> <member name="lower_fade" type="float" setter="set_lower_fade" getter="get_lower_fade" default="0.3"> Sets the curve over which the decal will fade as the surface gets further from the center of the [AABB]. Only positive values are valid (negative values will be clamped to [code]0.0[/code]). See also [member upper_fade]. </member> @@ -88,6 +85,9 @@ Fades the Decal if the angle between the Decal's [AABB] and the target surface becomes too large. A value of [code]0[/code] projects the Decal regardless of angle, a value of [code]1[/code] limits the Decal to surfaces that are nearly perpendicular. [b]Note:[/b] Setting [member normal_fade] to a value greater than [code]0.0[/code] has a small performance cost due to the added normal angle computations. </member> + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(2, 2, 2)"> + Sets the size of the [AABB] used by the decal. The AABB goes from [code]-size/2[/code] to [code]size/2[/code]. + </member> <member name="texture_albedo" type="Texture2D" setter="set_texture" getter="get_texture"> [Texture2D] with the base [Color] of the Decal. Either this or the [member texture_emission] must be set for the Decal to be visible. Use the alpha channel like a mask to smoothly blend the edges of the decal with the underlying object. [b]Note:[/b] Unlike [BaseMaterial3D] whose filter mode can be adjusted on a per-material basis, the filter mode for [Decal] textures is set globally with [member ProjectSettings.rendering/textures/decals/filter]. diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml index 776a9f6fc1..a5a50b4c6a 100644 --- a/doc/classes/Dictionary.xml +++ b/doc/classes/Dictionary.xml @@ -51,7 +51,7 @@ [csharp] [Export(PropertyHint.Enum, "White,Yellow,Orange")] public string MyColor { get; set; } - public Godot.Collections.Dictionary pointsDict = new Godot.Collections.Dictionary + private Godot.Collections.Dictionary _pointsDict = new Godot.Collections.Dictionary { {"White", 50}, {"Yellow", 75}, @@ -60,7 +60,7 @@ public override void _Ready() { - int points = (int)pointsDict[MyColor]; + int points = (int)_pointsDict[MyColor]; } [/csharp] [/codeblocks] @@ -153,7 +153,7 @@ <return type="Dictionary" /> <param index="0" name="from" type="Dictionary" /> <description> - Returns the same array as [param from]. If you need a copy of the array, use [method duplicate]. + Returns the same dictionary as [param from]. If you need a copy of the dictionary, use [method duplicate]. </description> </constructor> </constructors> diff --git a/doc/classes/DirAccess.xml b/doc/classes/DirAccess.xml index 181d2eb485..27f2eb7f2f 100644 --- a/doc/classes/DirAccess.xml +++ b/doc/classes/DirAccess.xml @@ -44,11 +44,11 @@ { if (dir.CurrentIsDir()) { - GD.Print("Found directory: " + fileName); + GD.Print($"Found directory: {fileName}"); } else { - GD.Print("Found file: " + fileName); + GD.Print($"Found file: {fileName}"); } fileName = dir.GetNext(); } diff --git a/doc/classes/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml index ec9efcc9c4..6a976d218f 100644 --- a/doc/classes/EditorImportPlugin.xml +++ b/doc/classes/EditorImportPlugin.xml @@ -48,61 +48,67 @@ [/gdscript] [csharp] using Godot; - using System; - public class MySpecialPlugin : EditorImportPlugin + public partial class MySpecialPlugin : EditorImportPlugin { - public override String GetImporterName() + public override string _GetImporterName() { return "my.special.plugin"; } - public override String GetVisibleName() + public override string _GetVisibleName() { return "Special Mesh"; } - public override Godot.Collections.Array GetRecognizedExtensions() + public override string[] _GetRecognizedExtensions() { - return new Godot.Collections.Array{"special", "spec"}; + return new string[] { "special", "spec" }; } - public override String GetSaveExtension() + public override string _GetSaveExtension() { return "mesh"; } - public override String GetResourceType() + public override string _GetResourceType() { return "Mesh"; } - public override int GetPresetCount() + public override int _GetPresetCount() { return 1; } - public override String GetPresetName(int i) + public override string _GetPresetName(int presetIndex) { return "Default"; } - public override Godot.Collections.Array GetImportOptions(int i) + public override Godot.Collections.Array<Godot.Collections.Dictionary> _GetImportOptions(string path, int presetIndex) { - return new Godot.Collections.Array{new Godot.Collections.Dictionary{{"name", "myOption"}, {"defaultValue", false}}}; + return new Godot.Collections.Array<Godot.Collections.Dictionary> + { + new Godot.Collections.Dictionary + { + { "name", "myOption" }, + { "defaultValue", false }, + } + }; } - public override int Import(String sourceFile, String savePath, Godot.Collections.Dictionary options, Godot.Collections.Array platformVariants, Godot.Collections.Array genFiles) + public override int _Import(string sourceFile, string savePath, Godot.Collections.Dictionary options, Godot.Collections.Array<string> platformVariants, Godot.Collections.Array<string> genFiles) { - var file = new File(); - if (file.Open(sourceFile, File.ModeFlags.Read) != Error.Ok) + using var file = FileAccess.Open(sourceFile, FileAccess.ModeFlags.Read); + if (file.GetError() != Error.Ok) { return (int)Error.Failed; } var mesh = new ArrayMesh(); // Fill the Mesh with data read in "file", left as an exercise to the reader. - String filename = savePath + "." + GetSaveExtension(); + string filename = $"{savePath}.{_GetSaveExtension()}"; return (int)ResourceSaver.Save(mesh, filename); } } @@ -210,7 +216,7 @@ </description> </method> <method name="_import" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="source_file" type="String" /> <param index="1" name="save_path" type="String" /> <param index="2" name="options" type="Dictionary" /> diff --git a/doc/classes/EditorInspectorPlugin.xml b/doc/classes/EditorInspectorPlugin.xml index ba2f7b24bf..7ffd7f9426 100644 --- a/doc/classes/EditorInspectorPlugin.xml +++ b/doc/classes/EditorInspectorPlugin.xml @@ -56,11 +56,11 @@ <method name="_parse_property" qualifiers="virtual"> <return type="bool" /> <param index="0" name="object" type="Object" /> - <param index="1" name="type" type="int" /> + <param index="1" name="type" type="int" enum="Variant.Type" /> <param index="2" name="name" type="String" /> - <param index="3" name="hint_type" type="int" /> + <param index="3" name="hint_type" type="int" enum="PropertyHint" /> <param index="4" name="hint_string" type="String" /> - <param index="5" name="usage_flags" type="int" /> + <param index="5" name="usage_flags" type="int" enum="PropertyUsageFlags" /> <param index="6" name="wide" type="bool" /> <description> Called to allow adding property-specific editors to the property list for [param object]. The added editor control must extend [EditorProperty]. Returning [code]true[/code] removes the built-in editor for this property, otherwise allows to insert a custom editor before the built-in one. diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 326c4f6456..f4b912de9e 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -69,21 +69,22 @@ return EditorPlugin.AFTER_GUI_INPUT_PASS [/gdscript] [csharp] - public override void _Forward3dDrawOverViewport(Godot.Control overlay) + public override void _Forward3DDrawOverViewport(Control viewportControl) { // Draw a circle at cursor position. - overlay.DrawCircle(overlay.GetLocalMousePosition(), 64, Colors.White); + viewportControl.DrawCircle(viewportControl.GetLocalMousePosition(), 64, Colors.White); } - public override EditorPlugin.AfterGUIInput _Forward3dGuiInput(Godot.Camera3D camera, InputEvent @event) + public override EditorPlugin.AfterGuiInput _Forward3DGuiInput(Camera3D viewportCamera, InputEvent @event) { if (@event is InputEventMouseMotion) { // Redraw viewport when cursor is moved. UpdateOverlays(); - return EditorPlugin.AFTER_GUI_INPUT_STOP; + return EditorPlugin.AfterGuiInput.Stop; } - return EditorPlugin.AFTER_GUI_INPUT_PASS; + return EditorPlugin.AfterGuiInput.Pass; + } [/csharp] [/codeblocks] </description> @@ -111,9 +112,9 @@ [/gdscript] [csharp] // Prevents the InputEvent from reaching other Editor classes. - public override EditorPlugin.AfterGUIInput _Forward3dGuiInput(Camera3D camera, InputEvent @event) + public override EditorPlugin.AfterGuiInput _Forward3DGuiInput(Camera3D camera, InputEvent @event) { - return EditorPlugin.AFTER_GUI_INPUT_STOP; + return EditorPlugin.AfterGuiInput.Stop; } [/csharp] [/codeblocks] @@ -127,9 +128,9 @@ [/gdscript] [csharp] // Consumes InputEventMouseMotion and forwards other InputEvent types. - public override EditorPlugin.AfterGUIInput _Forward3dGuiInput(Camera3D camera, InputEvent @event) + public override EditorPlugin.AfterGuiInput _Forward3DGuiInput(Camera3D camera, InputEvent @event) { - return @event is InputEventMouseMotion ? EditorPlugin.AFTER_GUI_INPUT_STOP : EditorPlugin.AFTER_GUI_INPUT_PASS; + return @event is InputEventMouseMotion ? EditorPlugin.AfterGuiInput.Stop : EditorPlugin.AfterGuiInput.Pass; } [/csharp] [/codeblocks] @@ -154,13 +155,13 @@ return false [/gdscript] [csharp] - public override void ForwardCanvasDrawOverViewport(Godot.Control overlay) + public override void _ForwardCanvasDrawOverViewport(Control viewportControl) { // Draw a circle at cursor position. - overlay.DrawCircle(overlay.GetLocalMousePosition(), 64, Colors.White); + viewportControl.DrawCircle(viewportControl.GetLocalMousePosition(), 64, Colors.White); } - public override bool ForwardCanvasGuiInput(InputEvent @event) + public override bool _ForwardCanvasGuiInput(InputEvent @event) { if (@event is InputEventMouseMotion) { @@ -169,6 +170,7 @@ return true; } return false; + } [/csharp] [/codeblocks] </description> @@ -213,12 +215,13 @@ [/gdscript] [csharp] // Consumes InputEventMouseMotion and forwards other InputEvent types. - public override bool ForwardCanvasGuiInput(InputEvent @event) + public override bool _ForwardCanvasGuiInput(InputEvent @event) { - if (@event is InputEventMouseMotion) { + if (@event is InputEventMouseMotion) + { return true; } - return false + return false; } [/csharp] [/codeblocks] @@ -245,7 +248,7 @@ return get_editor_interface().get_base_control().get_theme_icon("Node", "EditorIcons") [/gdscript] [csharp] - public override Texture2D GetPluginIcon() + public override Texture2D _GetPluginIcon() { // You can use a custom icon: return ResourceLoader.Load<Texture2D>("res://addons/my_plugin/my_plugin_icon.svg"); @@ -409,6 +412,7 @@ <description> Adds a custom type, which will appear in the list of nodes or resources. An icon can be optionally passed. When a given node or resource is selected, the base type will be instantiated (e.g. "Node3D", "Control", "Resource"), then the script will be loaded and set to this object. + [b]Note:[/b] The base type is the base engine class which this type's class hierarchy inherits, not any custom type parent classes. You can use the virtual method [method _handles] to check if your custom object is being edited by checking the script or using the [code]is[/code] keyword. During run-time, this will be a simple object with a script so this function does not need to be called then. [b]Note:[/b] Custom types added this way are not true classes. They are just a helper to create a node with specific script. diff --git a/doc/classes/EditorScenePostImport.xml b/doc/classes/EditorScenePostImport.xml index d2ad8d1bed..44bc72ea49 100644 --- a/doc/classes/EditorScenePostImport.xml +++ b/doc/classes/EditorScenePostImport.xml @@ -10,12 +10,14 @@ [gdscript] @tool # Needed so it runs in editor. extends EditorScenePostImport + # This sample changes all node names. # Called right after the scene is imported and gets the root node. func _post_import(scene): # Change all node names to "modified_[oldnodename]" iterate(scene) return scene # Remember to return the imported scene + func iterate(node): if node != null: node.name = "modified_" + node.name @@ -30,17 +32,18 @@ [Tool] public partial class NodeRenamer : EditorScenePostImport { - public override Object _PostImport(Node scene) + public override GodotObject _PostImport(Node scene) { // Change all node names to "modified_[oldnodename]" Iterate(scene); return scene; // Remember to return the imported scene } + public void Iterate(Node node) { if (node != null) { - node.Name = "modified_" + node.Name; + node.Name = $"modified_{node.Name}"; foreach (Node child in node.GetChildren()) { Iterate(child); diff --git a/doc/classes/EditorScript.xml b/doc/classes/EditorScript.xml index a02fd215d8..33d2f40d0b 100644 --- a/doc/classes/EditorScript.xml +++ b/doc/classes/EditorScript.xml @@ -17,10 +17,9 @@ [/gdscript] [csharp] using Godot; - using System; [Tool] - public class HelloEditor : EditorScript + public partial class HelloEditor : EditorScript { public override void _Run() { diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 72843eb157..1bf8cbf175 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -22,7 +22,7 @@ settings.SetSetting("some/property", Value); // `settings.get("some/property", value)` also works as this class overrides `_get()` internally. settings.GetSetting("some/property"); - Godot.Collections.Array listOfSettings = settings.GetPropertyList(); + Godot.Collections.Array<Godot.Collections.Dictionary> listOfSettings = settings.GetPropertyList(); [/csharp] [/codeblocks] [b]Note:[/b] This class shouldn't be instantiated directly. Instead, access the singleton using [method EditorInterface.get_editor_settings]. diff --git a/doc/classes/EditorTranslationParserPlugin.xml b/doc/classes/EditorTranslationParserPlugin.xml index 89746363d8..40b469de0a 100644 --- a/doc/classes/EditorTranslationParserPlugin.xml +++ b/doc/classes/EditorTranslationParserPlugin.xml @@ -27,27 +27,25 @@ [/gdscript] [csharp] using Godot; - using System; [Tool] - public class CustomParser : EditorTranslationParserPlugin + public partial class CustomParser : EditorTranslationParserPlugin { - public override void ParseFile(string path, Godot.Collections.Array msgids, Godot.Collections.Array msgidsContextPlural) + public override void _ParseFile(string path, Godot.Collections.Array<string> msgids, Godot.Collections.Array<Godot.Collections.Array> msgidsContextPlural) { - var file = new File(); - file.Open(path, File.ModeFlags.Read); + using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read); string text = file.GetAsText(); - string[] splitStrs = text.Split(",", false); - foreach (var s in splitStrs) + string[] splitStrs = text.Split(",", allowEmpty: false); + foreach (string s in splitStrs) { msgids.Add(s); - //GD.Print("Extracted string: " + s) + //GD.Print($"Extracted string: {s}"); } } - public override Godot.Collections.Array GetRecognizedExtensions() + public override string[] _GetRecognizedExtensions() { - return new Godot.Collections.Array{"csv"}; + return new string[] { "csv" }; } } [/csharp] @@ -84,16 +82,16 @@ return ["gd"] [/gdscript] [csharp] - public override void ParseFile(string path, Godot.Collections.Array msgids, Godot.Collections.Array msgidsContextPlural) + public override void _ParseFile(string path, Godot.Collections.Array<string> msgids, Godot.Collections.Array<Godot.Collections.Array> msgidsContextPlural) { var res = ResourceLoader.Load<Script>(path, "Script"); string text = res.SourceCode; // Parsing logic. } - public override Godot.Collections.Array GetRecognizedExtensions() + public override string[] _GetRecognizedExtensions() { - return new Godot.Collections.Array{"gd"}; + return new string[] { "gd" }; } [/csharp] [/codeblocks] diff --git a/doc/classes/Expression.xml b/doc/classes/Expression.xml index 2c7d83a811..fd5a921836 100644 --- a/doc/classes/Expression.xml +++ b/doc/classes/Expression.xml @@ -24,7 +24,7 @@ $LineEdit.text = str(result) [/gdscript] [csharp] - public Expression expression = new Expression(); + private Expression _expression = new Expression(); public override void _Ready() { @@ -33,14 +33,14 @@ private void OnTextEntered(string command) { - Error error = expression.Parse(command); + Error error = _expression.Parse(command); if (error != Error.Ok) { - GD.Print(expression.GetErrorText()); + GD.Print(_expression.GetErrorText()); return; } - object result = expression.Execute(); - if (!expression.HasExecuteFailed()) + Variant result = _expression.Execute(); + if (!_expression.HasExecuteFailed()) { GetNode<LineEdit>("LineEdit").Text = result.ToString(); } diff --git a/doc/classes/FileAccess.xml b/doc/classes/FileAccess.xml index be0c8fd6ca..687a64b8ff 100644 --- a/doc/classes/FileAccess.xml +++ b/doc/classes/FileAccess.xml @@ -348,8 +348,8 @@ f.Seek(0); // Go back to start to read the stored value. ushort read1 = f.Get16(); // 65494 ushort read2 = f.Get16(); // 121 - short converted1 = BitConverter.ToInt16(BitConverter.GetBytes(read1), 0); // -42 - short converted2 = BitConverter.ToInt16(BitConverter.GetBytes(read2), 0); // 121 + short converted1 = (short)read1; // -42 + short converted2 = (short)read2; // 121 } [/csharp] [/codeblocks] diff --git a/doc/classes/FogVolume.xml b/doc/classes/FogVolume.xml index d9fa2e6ebb..e2f9038be5 100644 --- a/doc/classes/FogVolume.xml +++ b/doc/classes/FogVolume.xml @@ -11,16 +11,16 @@ <tutorials> </tutorials> <members> - <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> - The size of the [FogVolume] when [member shape] is [constant RenderingServer.FOG_VOLUME_SHAPE_ELLIPSOID], [constant RenderingServer.FOG_VOLUME_SHAPE_CONE], [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER] or [constant RenderingServer.FOG_VOLUME_SHAPE_BOX]. - [b]Note:[/b] Thin fog volumes may appear to flicker when the camera moves or rotates. This can be alleviated by increasing [member ProjectSettings.rendering/environment/volumetric_fog/volume_depth] (at a performance cost) or by decreasing [member Environment.volumetric_fog_length] (at no performance cost, but at the cost of lower fog range). Alternatively, the [FogVolume] can be made thicker and use a lower density in the [member material]. - [b]Note:[/b] If [member shape] is [constant RenderingServer.FOG_VOLUME_SHAPE_CONE] or [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER], the cone/cylinder will be adjusted to fit within the extents. Non-uniform scaling of cone/cylinder shapes via the [member extents] property is not supported, but you can scale the [FogVolume] node instead. - </member> <member name="material" type="Material" setter="set_material" getter="get_material"> The [Material] used by the [FogVolume]. Can be either a built-in [FogMaterial] or a custom [ShaderMaterial]. </member> <member name="shape" type="int" setter="set_shape" getter="get_shape" enum="RenderingServer.FogVolumeShape" default="3"> The shape of the [FogVolume]. This can be set to either [constant RenderingServer.FOG_VOLUME_SHAPE_ELLIPSOID], [constant RenderingServer.FOG_VOLUME_SHAPE_CONE], [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER], [constant RenderingServer.FOG_VOLUME_SHAPE_BOX] or [constant RenderingServer.FOG_VOLUME_SHAPE_WORLD]. </member> + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(2, 2, 2)"> + The size of the [FogVolume] when [member shape] is [constant RenderingServer.FOG_VOLUME_SHAPE_ELLIPSOID], [constant RenderingServer.FOG_VOLUME_SHAPE_CONE], [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER] or [constant RenderingServer.FOG_VOLUME_SHAPE_BOX]. + [b]Note:[/b] Thin fog volumes may appear to flicker when the camera moves or rotates. This can be alleviated by increasing [member ProjectSettings.rendering/environment/volumetric_fog/volume_depth] (at a performance cost) or by decreasing [member Environment.volumetric_fog_length] (at no performance cost, but at the cost of lower fog range). Alternatively, the [FogVolume] can be made thicker and use a lower density in the [member material]. + [b]Note:[/b] If [member shape] is [constant RenderingServer.FOG_VOLUME_SHAPE_CONE] or [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER], the cone/cylinder will be adjusted to fit within the size. Non-uniform scaling of cone/cylinder shapes via the [member size] property is not supported, but you can scale the [FogVolume] node instead. + </member> </members> </class> diff --git a/doc/classes/GPUParticlesAttractorBox3D.xml b/doc/classes/GPUParticlesAttractorBox3D.xml index 6595428cc2..65a4c6d4a5 100644 --- a/doc/classes/GPUParticlesAttractorBox3D.xml +++ b/doc/classes/GPUParticlesAttractorBox3D.xml @@ -10,8 +10,8 @@ <tutorials> </tutorials> <members> - <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> - The attractor box's extents in 3D units. + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(2, 2, 2)"> + The attractor box's size in 3D units. </member> </members> </class> diff --git a/doc/classes/GPUParticlesAttractorVectorField3D.xml b/doc/classes/GPUParticlesAttractorVectorField3D.xml index aeadfaf4ab..12e6774471 100644 --- a/doc/classes/GPUParticlesAttractorVectorField3D.xml +++ b/doc/classes/GPUParticlesAttractorVectorField3D.xml @@ -11,12 +11,12 @@ <tutorials> </tutorials> <members> - <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> - The extents of the vector field box in 3D units. + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(2, 2, 2)"> + The size of the vector field box in 3D units. </member> <member name="texture" type="Texture3D" setter="set_texture" getter="get_texture"> The 3D texture to be used. Values are linearly interpolated between the texture's pixels. - [b]Note:[/b] To get better performance, the 3D texture's resolution should reflect the [member extents] of the attractor. Since particle attraction is usually low-frequency data, the texture can be kept at a low resolution such as 64×64×64. + [b]Note:[/b] To get better performance, the 3D texture's resolution should reflect the [member size] of the attractor. Since particle attraction is usually low-frequency data, the texture can be kept at a low resolution such as 64×64×64. </member> </members> </class> diff --git a/doc/classes/GPUParticlesCollisionBox3D.xml b/doc/classes/GPUParticlesCollisionBox3D.xml index 103be18bfd..737db0ba8a 100644 --- a/doc/classes/GPUParticlesCollisionBox3D.xml +++ b/doc/classes/GPUParticlesCollisionBox3D.xml @@ -11,8 +11,8 @@ <tutorials> </tutorials> <members> - <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> - The collision box's extents in 3D units. + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(2, 2, 2)"> + The collision box's size in 3D units. </member> </members> </class> diff --git a/doc/classes/GPUParticlesCollisionHeightField3D.xml b/doc/classes/GPUParticlesCollisionHeightField3D.xml index 6e996d5fbd..c8ed78b85e 100644 --- a/doc/classes/GPUParticlesCollisionHeightField3D.xml +++ b/doc/classes/GPUParticlesCollisionHeightField3D.xml @@ -13,9 +13,6 @@ <tutorials> </tutorials> <members> - <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> - The collision heightmap's extents in 3D units. To improve heightmap quality, [member extents] should be set as small as possible while covering the parts of the scene you need. - </member> <member name="follow_camera_enabled" type="bool" setter="set_follow_camera_enabled" getter="is_follow_camera_enabled" default="false"> If [code]true[/code], the [GPUParticlesCollisionHeightField3D] will follow the current camera in global space. The [GPUParticlesCollisionHeightField3D] does not need to be a child of the [Camera3D] node for this to work. Following the camera has a performance cost, as it will force the heightmap to update whenever the camera moves. Consider lowering [member resolution] to improve performance if [member follow_camera_enabled] is [code]true[/code]. @@ -23,6 +20,9 @@ <member name="resolution" type="int" setter="set_resolution" getter="get_resolution" enum="GPUParticlesCollisionHeightField3D.Resolution" default="2"> Higher resolutions can represent small details more accurately in large scenes, at the cost of lower performance. If [member update_mode] is [constant UPDATE_MODE_ALWAYS], consider using the lowest resolution possible. </member> + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(2, 2, 2)"> + The collision heightmap's size in 3D units. To improve heightmap quality, [member size] should be set as small as possible while covering the parts of the scene you need. + </member> <member name="update_mode" type="int" setter="set_update_mode" getter="get_update_mode" enum="GPUParticlesCollisionHeightField3D.UpdateMode" default="0"> The update policy to use for the generated heightmap. </member> diff --git a/doc/classes/GPUParticlesCollisionSDF3D.xml b/doc/classes/GPUParticlesCollisionSDF3D.xml index 8467cfdda1..dc4a4a2027 100644 --- a/doc/classes/GPUParticlesCollisionSDF3D.xml +++ b/doc/classes/GPUParticlesCollisionSDF3D.xml @@ -6,7 +6,7 @@ <description> Baked signed distance field 3D particle attractor affecting [GPUParticles3D] nodes. Signed distance fields (SDF) allow for efficiently representing approximate collision shapes for convex and concave objects of any shape. This is more flexible than [GPUParticlesCollisionHeightField3D], but it requires a baking step. - [b]Baking:[/b] The signed distance field texture can be baked by selecting the [GPUParticlesCollisionSDF3D] node in the editor, then clicking [b]Bake SDF[/b] at the top of the 3D viewport. Any [i]visible[/i] [MeshInstance3D]s touching the [member extents] will be taken into account for baking, regardless of their [member GeometryInstance3D.gi_mode]. + [b]Baking:[/b] The signed distance field texture can be baked by selecting the [GPUParticlesCollisionSDF3D] node in the editor, then clicking [b]Bake SDF[/b] at the top of the 3D viewport. Any [i]visible[/i] [MeshInstance3D]s within the [member size] will be taken into account for baking, regardless of their [member GeometryInstance3D.gi_mode]. [b]Note:[/b] Baking a [GPUParticlesCollisionSDF3D]'s [member texture] is only possible within the editor, as there is no bake method exposed for use in exported projects. However, it's still possible to load pre-baked [Texture3D]s into its [member texture] property in an exported project. [b]Note:[/b] [member ParticleProcessMaterial.collision_mode] must be [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. @@ -34,12 +34,12 @@ <member name="bake_mask" type="int" setter="set_bake_mask" getter="get_bake_mask" default="4294967295"> The visual layers to account for when baking the particle collision SDF. Only [MeshInstance3D]s whose [member VisualInstance3D.layers] match with this [member bake_mask] will be included in the generated particle collision SDF. By default, all objects are taken into account for the particle collision SDF baking. </member> - <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(1, 1, 1)"> - The collision SDF's extents in 3D units. To improve SDF quality, the [member extents] should be set as small as possible while covering the parts of the scene you need. - </member> <member name="resolution" type="int" setter="set_resolution" getter="get_resolution" enum="GPUParticlesCollisionSDF3D.Resolution" default="2"> The bake resolution to use for the signed distance field [member texture]. The texture must be baked again for changes to the [member resolution] property to be effective. Higher resolutions have a greater performance cost and take more time to bake. Higher resolutions also result in larger baked textures, leading to increased VRAM and storage space requirements. To improve performance and reduce bake times, use the lowest resolution possible for the object you're representing the collision of. </member> + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(2, 2, 2)"> + The collision SDF's size in 3D units. To improve SDF quality, the [member size] should be set as small as possible while covering the parts of the scene you need. + </member> <member name="texture" type="Texture3D" setter="set_texture" getter="get_texture"> The 3D texture representing the signed distance field. </member> diff --git a/doc/classes/Geometry2D.xml b/doc/classes/Geometry2D.xml index 0142018f1a..f015026bc1 100644 --- a/doc/classes/Geometry2D.xml +++ b/doc/classes/Geometry2D.xml @@ -160,14 +160,13 @@ var polygon = PackedVector2Array([Vector2(0, 0), Vector2(100, 0), Vector2(100, 100), Vector2(0, 100)]) var offset = Vector2(50, 50) polygon = Transform2D(0, offset) * polygon - print(polygon) # prints [Vector2(50, 50), Vector2(150, 50), Vector2(150, 150), Vector2(50, 150)] + print(polygon) # prints [(50, 50), (150, 50), (150, 150), (50, 150)] [/gdscript] [csharp] var polygon = new Vector2[] { new Vector2(0, 0), new Vector2(100, 0), new Vector2(100, 100), new Vector2(0, 100) }; var offset = new Vector2(50, 50); - // TODO: This code is not valid right now. Ping @aaronfranke about it before Godot 4.0 is out. - //polygon = (Vector2[]) new Transform2D(0, offset).Xform(polygon); - //GD.Print(polygon); // prints [Vector2(50, 50), Vector2(150, 50), Vector2(150, 150), Vector2(50, 150)] + polygon = new Transform2D(0, offset) * polygon; + GD.Print((Variant)polygon); // prints [(50, 50), (150, 50), (150, 150), (50, 150)] [/csharp] [/codeblocks] </description> diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index ea4e4b53ba..490637374d 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -72,8 +72,9 @@ return from != to [/gdscript] [csharp] - public override bool _IsNodeHoverValid(String from, int fromSlot, String to, int toSlot) { - return from != to; + public override bool _IsNodeHoverValid(StringName fromNode, int fromPort, StringName toNode, int toPort) + { + return fromNode != toNode; } [/csharp] [/codeblocks] diff --git a/doc/classes/HMACContext.xml b/doc/classes/HMACContext.xml index 706ee30963..fbdc6b5e64 100644 --- a/doc/classes/HMACContext.xml +++ b/doc/classes/HMACContext.xml @@ -26,25 +26,24 @@ [/gdscript] [csharp] using Godot; - using System; using System.Diagnostics; - public class CryptoNode : Node + public partial class MyNode : Node { - private HMACContext ctx = new HMACContext(); + private HmacContext _ctx = new HmacContext(); public override void _Ready() { - byte[] key = "supersecret".ToUTF8(); - Error err = ctx.Start(HashingContext.HashType.Sha256, key); + byte[] key = "supersecret".ToUtf8(); + Error err = _ctx.Start(HashingContext.HashType.Sha256, key); Debug.Assert(err == Error.Ok); - byte[] msg1 = "this is ".ToUTF8(); - byte[] msg2 = "super duper secret".ToUTF8(); - err = ctx.Update(msg1); + byte[] msg1 = "this is ".ToUtf8(); + byte[] msg2 = "super duper secret".ToUtf8(); + err = _ctx.Update(msg1); Debug.Assert(err == Error.Ok); - err = ctx.Update(msg2); + err = _ctx.Update(msg2); Debug.Assert(err == Error.Ok); - byte[] hmac = ctx.Finish(); + byte[] hmac = _ctx.Finish(); GD.Print(hmac.HexEncode()); } } diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml index b7a5cff694..4973f3fddf 100644 --- a/doc/classes/HTTPClient.xml +++ b/doc/classes/HTTPClient.xml @@ -105,7 +105,7 @@ [/gdscript] [csharp] var fields = new Godot.Collections.Dictionary { { "username", "user" }, { "password", "pass" } }; - string queryString = new HTTPClient().QueryStringFromDict(fields); + string queryString = httpClient.QueryStringFromDict(fields); // Returns "username=user&password=pass" [/csharp] [/codeblocks] @@ -117,8 +117,13 @@ # Returns "single=123&not_valued&multiple=22&multiple=33&multiple=44" [/gdscript] [csharp] - var fields = new Godot.Collections.Dictionary{{"single", 123}, {"notValued", null}, {"multiple", new Godot.Collections.Array{22, 33, 44}}}; - string queryString = new HTTPClient().QueryStringFromDict(fields); + var fields = new Godot.Collections.Dictionary + { + { "single", 123 }, + { "notValued", default }, + { "multiple", new Godot.Collections.Array { 22, 33, 44 } }, + }; + string queryString = httpClient.QueryStringFromDict(fields); // Returns "single=123&not_valued&multiple=22&multiple=33&multiple=44" [/csharp] [/codeblocks] @@ -151,7 +156,7 @@ [csharp] var fields = new Godot.Collections.Dictionary { { "username", "user" }, { "password", "pass" } }; string queryString = new HTTPClient().QueryStringFromDict(fields); - string[] headers = {"Content-Type: application/x-www-form-urlencoded", "Content-Length: " + queryString.Length}; + string[] headers = { "Content-Type: application/x-www-form-urlencoded", $"Content-Length: {queryString.Length}" }; var result = new HTTPClient().Request(HTTPClient.Method.Post, "index.php", headers, queryString); [/csharp] [/codeblocks] diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml index d403acf90c..5a0b12e198 100644 --- a/doc/classes/HTTPRequest.xml +++ b/doc/classes/HTTPRequest.xml @@ -57,7 +57,7 @@ // Perform a POST request. The URL below returns JSON as of writing. // Note: Don't make simultaneous requests using a single HTTPRequest node. // The snippet below is provided for reference only. - string body = new JSON().Stringify(new Godot.Collections.Dictionary + string body = new Json().Stringify(new Godot.Collections.Dictionary { { "name", "Godette" } }); @@ -69,14 +69,14 @@ } // Called when the HTTP request is completed. - private void HttpRequestCompleted(int result, int responseCode, string[] headers, byte[] body) + private void HttpRequestCompleted(long result, long responseCode, string[] headers, byte[] body) { - var json = new JSON(); - json.Parse(body.GetStringFromUTF8()); - var response = json.GetData() as Godot.Collections.Dictionary; + var json = new Json(); + json.Parse(body.GetStringFromUtf8()); + var response = json.GetData().AsGodotDictionary(); // Will print the user agent string used by the HTTPRequest node (as recognized by httpbin.org). - GD.Print((response["headers"] as Godot.Collections.Dictionary)["User-Agent"]); + GD.Print((response["headers"].AsGodotDictionary())["User-Agent"]); } [/csharp] [/codeblocks] @@ -128,9 +128,9 @@ } // Called when the HTTP request is completed. - private void HttpRequestCompleted(int result, int responseCode, string[] headers, byte[] body) + private void HttpRequestCompleted(long result, long responseCode, string[] headers, byte[] body) { - if (result != (int)HTTPRequest.Result.Success) + if (result != (long)HTTPRequest.Result.Success) { GD.PushError("Image couldn't be downloaded. Try a different image."); } diff --git a/doc/classes/HashingContext.xml b/doc/classes/HashingContext.xml index 7c2be6f817..5223cbf52f 100644 --- a/doc/classes/HashingContext.xml +++ b/doc/classes/HashingContext.xml @@ -8,7 +8,7 @@ The [enum HashType] enum shows the supported hashing algorithms. [codeblocks] [gdscript] - const CHUNK_SIZE = 102 + const CHUNK_SIZE = 1024 func hash_file(path): # Check that file exists. @@ -32,17 +32,16 @@ public void HashFile(string path) { - var ctx = new HashingContext(); - var file = new File(); - // Start a SHA-256 context. - ctx.Start(HashingContext.HashType.Sha256); // Check that file exists. - if (!file.FileExists(path)) + if (!FileAccess.FileExists(path)) { return; } + // Start a SHA-256 context. + var ctx = new HashingContext(); + ctx.Start(HashingContext.HashType.Sha256); // Open the file to hash. - file.Open(path, File.ModeFlags.Read); + using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read); // Update the context after reading each chunk. while (!file.EofReached()) { @@ -51,8 +50,7 @@ // Get the computed hash. byte[] res = ctx.Finish(); // Print the result as hex string and array. - - GD.PrintT(res.HexEncode(), res); + GD.PrintT(res.HexEncode(), (Variant)res); } [/csharp] [/codeblocks] diff --git a/doc/classes/InputEventMIDI.xml b/doc/classes/InputEventMIDI.xml index 67e7ced2e8..e4ba380741 100644 --- a/doc/classes/InputEventMIDI.xml +++ b/doc/classes/InputEventMIDI.xml @@ -35,9 +35,9 @@ GD.Print(OS.GetConnectedMidiInputs()); } - public override void _Input(InputEvent inputEvent) + public override void _Input(InputEvent @event) { - if (inputEvent is InputEventMIDI midiEvent) + if (@event is InputEventMIDI midiEvent) { PrintMIDIInfo(midiEvent); } @@ -46,14 +46,14 @@ private void PrintMIDIInfo(InputEventMIDI midiEvent) { GD.Print(midiEvent); - GD.Print("Channel " + midiEvent.Channel); - GD.Print("Message " + midiEvent.Message); - GD.Print("Pitch " + midiEvent.Pitch); - GD.Print("Velocity " + midiEvent.Velocity); - GD.Print("Instrument " + midiEvent.Instrument); - GD.Print("Pressure " + midiEvent.Pressure); - GD.Print("Controller number: " + midiEvent.ControllerNumber); - GD.Print("Controller value: " + midiEvent.ControllerValue); + GD.Print($"Channel {midiEvent.Channel}"); + GD.Print($"Message {midiEvent.Message}"); + GD.Print($"Pitch {midiEvent.Pitch}"); + GD.Print($"Velocity {midiEvent.Velocity}"); + GD.Print($"Instrument {midiEvent.Instrument}"); + GD.Print($"Pressure {midiEvent.Pressure}"); + GD.Print($"Controller number: {midiEvent.ControllerNumber}"); + GD.Print($"Controller value: {midiEvent.ControllerValue}"); } [/csharp] [/codeblocks] diff --git a/doc/classes/Label3D.xml b/doc/classes/Label3D.xml index fb3c949e48..cfb47ff4c3 100644 --- a/doc/classes/Label3D.xml +++ b/doc/classes/Label3D.xml @@ -32,6 +32,12 @@ </method> </methods> <members> + <member name="alpha_antialiasing_edge" type="float" setter="set_alpha_antialiasing_edge" getter="get_alpha_antialiasing_edge" default="0.0"> + Threshold at which antialiasing will be applied on the alpha channel. + </member> + <member name="alpha_antialiasing_mode" type="int" setter="set_alpha_antialiasing" getter="get_alpha_antialiasing" enum="BaseMaterial3D.AlphaAntiAliasing" default="0"> + The type of alpha antialiasing to apply. See [enum BaseMaterial3D.AlphaAntiAliasing]. + </member> <member name="alpha_cut" type="int" setter="set_alpha_cut_mode" getter="get_alpha_cut_mode" enum="Label3D.AlphaCutMode" default="0"> The alpha cutting mode to use for the sprite. See [enum AlphaCutMode] for possible values. </member> diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml index 674adb1772..260efb0eab 100644 --- a/doc/classes/MainLoop.xml +++ b/doc/classes/MainLoop.xml @@ -29,29 +29,28 @@ [/gdscript] [csharp] using Godot; - using System; - public class CustomMainLoop : MainLoop + public partial class CustomMainLoop : MainLoop { - public float TimeElapsed = 0; + private double _timeElapsed = 0; public override void _Initialize() { GD.Print("Initialized:"); - GD.Print($" Starting Time: {TimeElapsed}"); + GD.Print($" Starting Time: {_timeElapsed}"); } - public override bool _Process(float delta) + public override bool _Process(double delta) { - TimeElapsed += delta; + _timeElapsed += delta; // Return true to end the main loop. - return Input.GetMouseButtonMask() != 0 || Input.IsKeyPressed((int)KeyList.Escape); + return Input.GetMouseButtonMask() != 0 || Input.IsKeyPressed(Key.Escape); } private void _Finalize() { GD.Print("Finalized:"); - GD.Print($" End Time: {TimeElapsed}"); + GD.Print($" End Time: {_timeElapsed}"); } } [/csharp] diff --git a/doc/classes/MultiplayerAPIExtension.xml b/doc/classes/MultiplayerAPIExtension.xml index c4012a920a..b853c32407 100644 --- a/doc/classes/MultiplayerAPIExtension.xml +++ b/doc/classes/MultiplayerAPIExtension.xml @@ -99,7 +99,7 @@ </description> </method> <method name="_object_configuration_add" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="object" type="Object" /> <param index="1" name="configuration" type="Variant" /> <description> @@ -107,7 +107,7 @@ </description> </method> <method name="_object_configuration_remove" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="object" type="Object" /> <param index="1" name="configuration" type="Variant" /> <description> @@ -115,13 +115,13 @@ </description> </method> <method name="_poll" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <description> Callback for [method MultiplayerAPI.poll]. </description> </method> <method name="_rpc" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="peer" type="int" /> <param index="1" name="object" type="Object" /> <param index="2" name="method" type="StringName" /> diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml index 6ae4dc4177..92fd8bcc6a 100644 --- a/doc/classes/NavigationAgent2D.xml +++ b/doc/classes/NavigationAgent2D.xml @@ -111,6 +111,21 @@ <member name="avoidance_enabled" type="bool" setter="set_avoidance_enabled" getter="get_avoidance_enabled" default="false"> If [code]true[/code] the agent is registered for an RVO avoidance callback on the [NavigationServer2D]. When [method NavigationAgent2D.set_velocity] is used and the processing is completed a [code]safe_velocity[/code] Vector2 is received with a signal connection to [signal velocity_computed]. Avoidance processing with many registered agents has a significant performance cost and should only be enabled on agents that currently require it. </member> + <member name="debug_enabled" type="bool" setter="set_debug_enabled" getter="get_debug_enabled" default="false"> + If [code]true[/code] shows debug visuals for this agent. + </member> + <member name="debug_path_custom_color" type="Color" setter="set_debug_path_custom_color" getter="get_debug_path_custom_color" default="Color(1, 1, 1, 1)"> + If [member debug_use_custom] is [code]true[/code] uses this color for this agent instead of global color. + </member> + <member name="debug_path_custom_line_width" type="float" setter="set_debug_path_custom_line_width" getter="get_debug_path_custom_line_width" default="1.0"> + If [member debug_use_custom] is [code]true[/code] uses this line width for rendering paths for this agent instead of global line width. + </member> + <member name="debug_path_custom_point_size" type="float" setter="set_debug_path_custom_point_size" getter="get_debug_path_custom_point_size" default="4.0"> + If [member debug_use_custom] is [code]true[/code] uses this rasterized point size for rendering path points for this agent instead of global point size. + </member> + <member name="debug_use_custom" type="bool" setter="set_debug_use_custom" getter="get_debug_use_custom" default="false"> + If [code]true[/code] uses the defined [member debug_path_custom_color] for this agent instead of global color. + </member> <member name="max_neighbors" type="int" setter="set_max_neighbors" getter="get_max_neighbors" default="10"> The maximum number of neighbors for the agent to consider. </member> diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml index a22cd6dd46..0ed11bc477 100644 --- a/doc/classes/NavigationAgent3D.xml +++ b/doc/classes/NavigationAgent3D.xml @@ -114,6 +114,18 @@ <member name="avoidance_enabled" type="bool" setter="set_avoidance_enabled" getter="get_avoidance_enabled" default="false"> If [code]true[/code] the agent is registered for an RVO avoidance callback on the [NavigationServer3D]. When [method NavigationAgent3D.set_velocity] is used and the processing is completed a [code]safe_velocity[/code] Vector3 is received with a signal connection to [signal velocity_computed]. Avoidance processing with many registered agents has a significant performance cost and should only be enabled on agents that currently require it. </member> + <member name="debug_enabled" type="bool" setter="set_debug_enabled" getter="get_debug_enabled" default="false"> + If [code]true[/code] shows debug visuals for this agent. + </member> + <member name="debug_path_custom_color" type="Color" setter="set_debug_path_custom_color" getter="get_debug_path_custom_color" default="Color(1, 1, 1, 1)"> + If [member debug_use_custom] is [code]true[/code] uses this color for this agent instead of global color. + </member> + <member name="debug_path_custom_point_size" type="float" setter="set_debug_path_custom_point_size" getter="get_debug_path_custom_point_size" default="4.0"> + If [member debug_use_custom] is [code]true[/code] uses this rasterized point size for rendering path points for this agent instead of global point size. + </member> + <member name="debug_use_custom" type="bool" setter="set_debug_use_custom" getter="get_debug_use_custom" default="false"> + If [code]true[/code] uses the defined [member debug_path_custom_color] for this agent instead of global color. + </member> <member name="ignore_y" type="bool" setter="set_ignore_y" getter="get_ignore_y" default="true"> Ignores collisions on the Y axis. Must be true to move on a horizontal plane. </member> diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index 16f6de5238..7270a19b4d 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -528,5 +528,10 @@ Emitted when a navigation map is updated, when a region moves or is modified. </description> </signal> + <signal name="navigation_debug_changed"> + <description> + Emitted when navigation debug settings are changed. Only available in debug builds. + </description> + </signal> </signals> </class> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index e4607456ca..e30ff6be19 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -110,7 +110,7 @@ [/gdscript] [csharp] [Tool] - public class MyNode2D : Node2D + public partial class MyNode2D : Node2D { private bool _holdingHammer; @@ -433,9 +433,9 @@ var button = new Button(); // Option 1: In C#, we can use signals as events and connect with this idiomatic syntax: button.ButtonDown += OnButtonDown; - // Option 2: Object.Connect() with a constructed Callable from a method group. + // Option 2: GodotObject.Connect() with a constructed Callable from a method group. button.Connect(Button.SignalName.ButtonDown, Callable.From(OnButtonDown)); - // Option 3: Object.Connect() with a constructed Callable using a target object and method name. + // Option 3: GodotObject.Connect() with a constructed Callable using a target object and method name. button.Connect(Button.SignalName.ButtonDown, new Callable(this, MethodName.OnButtonDown)); } @@ -700,10 +700,10 @@ sprite2d.is_class("Node3D") # Returns false [/gdscript] [csharp] - var sprite2d = new Sprite2D(); - sprite2d.IsClass("Sprite2D"); // Returns true - sprite2d.IsClass("Node"); // Returns true - sprite2d.IsClass("Node3D"); // Returns false + var sprite2D = new Sprite2D(); + sprite2D.IsClass("Sprite2D"); // Returns true + sprite2D.IsClass("Node"); // Returns true + sprite2D.IsClass("Node3D"); // Returns false [/csharp] [/codeblocks] [b]Note:[/b] This method ignores [code]class_name[/code] declarations in the object's script. @@ -747,10 +747,10 @@ player.SetScript(GD.Load("res://player.gd")); player.Notification(NotificationEnterTree); - // The call order is Object -> Node -> Node2D -> player.gd. + // The call order is GodotObject -> Node -> Node2D -> player.gd. - player.notification(NotificationEnterTree, true); - // The call order is player.gd -> Node2D -> Node -> Object. + player.Notification(NotificationEnterTree, true); + // The call order is player.gd -> Node2D -> Node -> GodotObject. [/csharp] [/codeblocks] </description> diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml index 7ca1d5d60d..493fc9e2a8 100644 --- a/doc/classes/PackedScene.xml +++ b/doc/classes/PackedScene.xml @@ -104,7 +104,7 @@ </method> </methods> <members> - <member name="_bundled" type="Dictionary" setter="_set_bundled_scene" getter="_get_bundled_scene" default="{ "conn_count": 0, "conns": PackedInt32Array(), "editable_instances": [], "names": PackedStringArray(), "node_count": 0, "node_paths": [], "nodes": PackedInt32Array(), "variants": [], "version": 2 }"> + <member name="_bundled" type="Dictionary" setter="_set_bundled_scene" getter="_get_bundled_scene" default="{ "conn_count": 0, "conns": PackedInt32Array(), "editable_instances": [], "names": PackedStringArray(), "node_count": 0, "node_paths": [], "nodes": PackedInt32Array(), "variants": [], "version": 3 }"> A dictionary representation of the scene contents. Available keys include "rnames" and "variants" for resources, "node_count", "nodes", "node_paths" for nodes, "editable_instances" for base scene children overrides, "conn_count" and "conns" for signal connections, and "version" for the format style of the PackedScene. </member> diff --git a/doc/classes/PhysicsPointQueryParameters2D.xml b/doc/classes/PhysicsPointQueryParameters2D.xml index 76dc816dab..15102830f8 100644 --- a/doc/classes/PhysicsPointQueryParameters2D.xml +++ b/doc/classes/PhysicsPointQueryParameters2D.xml @@ -11,6 +11,7 @@ <members> <member name="canvas_instance_id" type="int" setter="set_canvas_instance_id" getter="get_canvas_instance_id" default="0"> If different from [code]0[/code], restricts the query to a specific canvas layer specified by its instance ID. See [method Object.get_instance_id]. + If [code]0[/code], restricts the query to the Viewport's default canvas layer. </member> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> If [code]true[/code], the query will take [Area2D]s into account. diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index f1316fa991..93e88347d4 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -984,25 +984,23 @@ <constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3" enum="AreaParameter"> Constant to set/get whether the gravity vector of an area is a direction, or a center point. </constant> - <constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="4" enum="AreaParameter"> - Constant to set/get the falloff factor for point gravity of an area. The greater this value is, the faster the strength of gravity decreases with the square of distance. + <constant name="AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE" value="4" enum="AreaParameter"> + Constant to set/get the distance at which the gravity strength is equal to the gravity controlled by [constant AREA_PARAM_GRAVITY]. For example, on a planet 100 pixels in radius with a surface gravity of 4.0 px/s², set the gravity to 4.0 and the unit distance to 100.0. The gravity will have falloff according to the inverse square law, so in the example, at 200 pixels from the center the gravity will be 1.0 px/s² (twice the distance, 1/4th the gravity), at 50 pixels it will be 16.0 px/s² (half the distance, 4x the gravity), and so on. + The above is true only when the unit distance is a positive number. When the unit distance is set to 0.0, the gravity will be constant regardless of distance. </constant> - <constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="5" enum="AreaParameter"> - This constant was used to set/get the falloff factor for point gravity. It has been superseded by [constant AREA_PARAM_GRAVITY_DISTANCE_SCALE]. - </constant> - <constant name="AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE" value="6" enum="AreaParameter"> + <constant name="AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE" value="5" enum="AreaParameter"> Constant to set/get linear damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. </constant> - <constant name="AREA_PARAM_LINEAR_DAMP" value="7" enum="AreaParameter"> + <constant name="AREA_PARAM_LINEAR_DAMP" value="6" enum="AreaParameter"> Constant to set/get the linear damping factor of an area. </constant> - <constant name="AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE" value="8" enum="AreaParameter"> + <constant name="AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE" value="7" enum="AreaParameter"> Constant to set/get angular damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. </constant> - <constant name="AREA_PARAM_ANGULAR_DAMP" value="9" enum="AreaParameter"> + <constant name="AREA_PARAM_ANGULAR_DAMP" value="8" enum="AreaParameter"> Constant to set/get the angular damping factor of an area. </constant> - <constant name="AREA_PARAM_PRIORITY" value="10" enum="AreaParameter"> + <constant name="AREA_PARAM_PRIORITY" value="9" enum="AreaParameter"> Constant to set/get the priority (order of processing) of an area. </constant> <constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0" enum="AreaSpaceOverrideMode"> diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index e62bda0dd3..5b261d8414 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -1315,37 +1315,35 @@ <constant name="AREA_PARAM_GRAVITY_IS_POINT" value="3" enum="AreaParameter"> Constant to set/get whether the gravity vector of an area is a direction, or a center point. </constant> - <constant name="AREA_PARAM_GRAVITY_DISTANCE_SCALE" value="4" enum="AreaParameter"> - Constant to set/get the falloff factor for point gravity of an area. The greater this value is, the faster the strength of gravity decreases with the square of distance. + <constant name="AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE" value="4" enum="AreaParameter"> + Constant to set/get the distance at which the gravity strength is equal to the gravity controlled by [constant AREA_PARAM_GRAVITY]. For example, on a planet 100 meters in radius with a surface gravity of 4.0 m/s², set the gravity to 4.0 and the unit distance to 100.0. The gravity will have falloff according to the inverse square law, so in the example, at 200 meters from the center the gravity will be 1.0 m/s² (twice the distance, 1/4th the gravity), at 50 meters it will be 16.0 m/s² (half the distance, 4x the gravity), and so on. + The above is true only when the unit distance is a positive number. When this is set to 0.0, the gravity will be constant regardless of distance. </constant> - <constant name="AREA_PARAM_GRAVITY_POINT_ATTENUATION" value="5" enum="AreaParameter"> - This constant was used to set/get the falloff factor for point gravity. It has been superseded by [constant AREA_PARAM_GRAVITY_DISTANCE_SCALE]. - </constant> - <constant name="AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE" value="6" enum="AreaParameter"> + <constant name="AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE" value="5" enum="AreaParameter"> Constant to set/get linear damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. </constant> - <constant name="AREA_PARAM_LINEAR_DAMP" value="7" enum="AreaParameter"> + <constant name="AREA_PARAM_LINEAR_DAMP" value="6" enum="AreaParameter"> Constant to set/get the linear damping factor of an area. </constant> - <constant name="AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE" value="8" enum="AreaParameter"> + <constant name="AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE" value="7" enum="AreaParameter"> Constant to set/get angular damping override mode in an area. See [enum AreaSpaceOverrideMode] for possible values. </constant> - <constant name="AREA_PARAM_ANGULAR_DAMP" value="9" enum="AreaParameter"> + <constant name="AREA_PARAM_ANGULAR_DAMP" value="8" enum="AreaParameter"> Constant to set/get the angular damping factor of an area. </constant> - <constant name="AREA_PARAM_PRIORITY" value="10" enum="AreaParameter"> + <constant name="AREA_PARAM_PRIORITY" value="9" enum="AreaParameter"> Constant to set/get the priority (order of processing) of an area. </constant> - <constant name="AREA_PARAM_WIND_FORCE_MAGNITUDE" value="11" enum="AreaParameter"> + <constant name="AREA_PARAM_WIND_FORCE_MAGNITUDE" value="10" enum="AreaParameter"> Constant to set/get the magnitude of area-specific wind force. </constant> - <constant name="AREA_PARAM_WIND_SOURCE" value="12" enum="AreaParameter"> + <constant name="AREA_PARAM_WIND_SOURCE" value="11" enum="AreaParameter"> Constant to set/get the 3D vector that specifies the origin from which an area-specific wind blows. </constant> - <constant name="AREA_PARAM_WIND_DIRECTION" value="13" enum="AreaParameter"> + <constant name="AREA_PARAM_WIND_DIRECTION" value="12" enum="AreaParameter"> Constant to set/get the 3D vector that specifies the direction in which an area-specific wind blows. </constant> - <constant name="AREA_PARAM_WIND_ATTENUATION_FACTOR" value="14" enum="AreaParameter"> + <constant name="AREA_PARAM_WIND_ATTENUATION_FACTOR" value="13" enum="AreaParameter"> Constant to set/get the exponential rate at which wind force decreases with distance from its origin. </constant> <constant name="AREA_SPACE_OVERRIDE_DISABLED" value="0" enum="AreaSpaceOverrideMode"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index f1ada58e0d..e429759e93 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -426,6 +426,9 @@ <member name="debug/gdscript/warnings/redundant_await" type="int" setter="" getter="" default="1"> When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a function that is not a coroutine is called with await. </member> + <member name="debug/gdscript/warnings/renamed_in_godot_4_hint" type="bool" setter="" getter="" default="1"> + When enabled, using a property, enum, or function that was renamed since Godot 3 will produce a hint if an error occurs. + </member> <member name="debug/gdscript/warnings/return_value_discarded" type="int" setter="" getter="" default="0"> When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a function without using its return value (by assigning it to a variable or using it as a function argument). Such return values are sometimes used to denote possible errors using the [enum Error] enum. </member> @@ -474,6 +477,9 @@ <member name="debug/gdscript/warnings/unsafe_property_access" type="int" setter="" getter="" default="0"> When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when accessing a property whose presence is not guaranteed at compile-time in the class. </member> + <member name="debug/gdscript/warnings/unsafe_void_return" type="int" setter="" getter="" default="0"> + When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when returning a call from a [code]void[/code] function when such call cannot be guaranteed to be also [code]void[/code]. + </member> <member name="debug/gdscript/warnings/unused_local_constant" type="int" setter="" getter="" default="1"> When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a local constant is never used. </member> @@ -522,9 +528,21 @@ <member name="debug/shapes/collision/shape_color" type="Color" setter="" getter="" default="Color(0, 0.6, 0.7, 0.42)"> Color of the collision shapes, visible when "Visible Collision Shapes" is enabled in the Debug menu. </member> + <member name="debug/shapes/navigation/agent_path_color" type="Color" setter="" getter="" default="Color(1, 0, 0, 1)"> + Color to display enabled navigation agent paths when an agent has debug enabled. + </member> + <member name="debug/shapes/navigation/agent_path_point_size" type="float" setter="" getter="" default="4.0"> + Rasterized size (pixel) used to render navigation agent path points when an agent has debug enabled. + </member> <member name="debug/shapes/navigation/edge_connection_color" type="Color" setter="" getter="" default="Color(1, 0, 1, 1)"> Color to display edge connections between navigation regions, visible when "Visible Navigation" is enabled in the Debug menu. </member> + <member name="debug/shapes/navigation/enable_agent_paths" type="bool" setter="" getter="" default="true"> + If enabled, displays navigation agent paths when an agent has debug enabled. + </member> + <member name="debug/shapes/navigation/enable_agent_paths_xray" type="bool" setter="" getter="" default="true"> + If enabled, displays navigation agent paths through geometry when an agent has debug enabled. + </member> <member name="debug/shapes/navigation/enable_edge_connections" type="bool" setter="" getter="" default="true"> If enabled, displays edge connections between navigation regions when "Visible Navigation" is enabled in the Debug menu. </member> @@ -1737,7 +1755,7 @@ [/gdscript] [csharp] // Set the default gravity strength to 980. - PhysicsServer2D.AreaSetParam(GetViewport().FindWorld2d().Space, PhysicsServer2D.AreaParameter.Gravity, 980); + PhysicsServer2D.AreaSetParam(GetViewport().FindWorld2D().Space, PhysicsServer2D.AreaParameter.Gravity, 980); [/csharp] [/codeblocks] </member> @@ -1751,7 +1769,7 @@ [/gdscript] [csharp] // Set the default gravity direction to `Vector2(0, 1)`. - PhysicsServer2D.AreaSetParam(GetViewport().FindWorld2d().Space, PhysicsServer2D.AreaParameter.GravityVector, Vector2.Down) + PhysicsServer2D.AreaSetParam(GetViewport().FindWorld2D().Space, PhysicsServer2D.AreaParameter.GravityVector, Vector2.Down) [/csharp] [/codeblocks] </member> diff --git a/doc/classes/ReflectionProbe.xml b/doc/classes/ReflectionProbe.xml index fee48dd246..fa0b1ab00b 100644 --- a/doc/classes/ReflectionProbe.xml +++ b/doc/classes/ReflectionProbe.xml @@ -13,13 +13,13 @@ </tutorials> <members> <member name="ambient_color" type="Color" setter="set_ambient_color" getter="get_ambient_color" default="Color(0, 0, 0, 1)"> - The custom ambient color to use within the [ReflectionProbe]'s [member extents]. Only effective if [member ambient_mode] is [constant AMBIENT_COLOR]. + The custom ambient color to use within the [ReflectionProbe]'s [member size]. Only effective if [member ambient_mode] is [constant AMBIENT_COLOR]. </member> <member name="ambient_color_energy" type="float" setter="set_ambient_color_energy" getter="get_ambient_color_energy" default="1.0"> - The custom ambient color energy to use within the [ReflectionProbe]'s [member extents]. Only effective if [member ambient_mode] is [constant AMBIENT_COLOR]. + The custom ambient color energy to use within the [ReflectionProbe]'s [member size]. Only effective if [member ambient_mode] is [constant AMBIENT_COLOR]. </member> <member name="ambient_mode" type="int" setter="set_ambient_mode" getter="get_ambient_mode" enum="ReflectionProbe.AmbientMode" default="1"> - The ambient color to use within the [ReflectionProbe]'s [member extents]. The ambient color will smoothly blend with other [ReflectionProbe]s and the rest of the scene (outside the [ReflectionProbe]'s [member extents]). + The ambient color to use within the [ReflectionProbe]'s [member size]. The ambient color will smoothly blend with other [ReflectionProbe]s and the rest of the scene (outside the [ReflectionProbe]'s [member size]). </member> <member name="box_projection" type="bool" setter="set_enable_box_projection" getter="is_box_projection_enabled" default="false"> If [code]true[/code], enables box projection. This makes reflections look more correct in rectangle-shaped rooms by offsetting the reflection center depending on the camera's location. @@ -31,10 +31,6 @@ <member name="enable_shadows" type="bool" setter="set_enable_shadows" getter="are_shadows_enabled" default="false"> If [code]true[/code], computes shadows in the reflection probe. This makes the reflection probe slower to render; you may want to disable this if using the [constant UPDATE_ALWAYS] [member update_mode]. </member> - <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(10, 10, 10)"> - The size of the reflection probe. The larger the extents, the more space covered by the probe, which will lower the perceived resolution. It is best to keep the extents only as large as you need them. - [b]Note:[/b] To better fit areas that are not aligned to the grid, you can rotate the [ReflectionProbe] node. - </member> <member name="intensity" type="float" setter="set_intensity" getter="get_intensity" default="1.0"> Defines the reflection intensity. Intensity modulates the strength of the reflection. </member> @@ -43,7 +39,7 @@ </member> <member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="0.0"> The maximum distance away from the [ReflectionProbe] an object can be before it is culled. Decrease this to improve performance, especially when using the [constant UPDATE_ALWAYS] [member update_mode]. - [b]Note:[/b] The maximum reflection distance is always at least equal to the [member extents]. This means that decreasing [member max_distance] will not always cull objects from reflections, especially if the reflection probe's [member extents] are already large. + [b]Note:[/b] The maximum reflection distance is always at least equal to the probe's extents. This means that decreasing [member max_distance] will not always cull objects from reflections, especially if the reflection probe's [member size] is already large. </member> <member name="mesh_lod_threshold" type="float" setter="set_mesh_lod_threshold" getter="get_mesh_lod_threshold" default="1.0"> The automatic LOD bias to use for meshes rendered within the [ReflectionProbe] (this is analog to [member Viewport.mesh_lod_threshold]). Higher values will use less detailed versions of meshes that have LOD variations generated. If set to [code]0.0[/code], automatic LOD is disabled. Increase [member mesh_lod_threshold] to improve performance at the cost of geometry detail, especially when using the [constant UPDATE_ALWAYS] [member update_mode]. @@ -52,6 +48,10 @@ <member name="origin_offset" type="Vector3" setter="set_origin_offset" getter="get_origin_offset" default="Vector3(0, 0, 0)"> Sets the origin offset to be used when this [ReflectionProbe] is in [member box_projection] mode. This can be set to a non-zero value to ensure a reflection fits a rectangle-shaped room, while reducing the number of objects that "get in the way" of the reflection. </member> + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(20, 20, 20)"> + The size of the reflection probe. The larger the size, the more space covered by the probe, which will lower the perceived resolution. It is best to keep the size only as large as you need it. + [b]Note:[/b] To better fit areas that are not aligned to the grid, you can rotate the [ReflectionProbe] node. + </member> <member name="update_mode" type="int" setter="set_update_mode" getter="get_update_mode" enum="ReflectionProbe.UpdateMode" default="0"> Sets how frequently the [ReflectionProbe] is updated. Can be [constant UPDATE_ONCE] or [constant UPDATE_ALWAYS]. </member> @@ -64,13 +64,13 @@ Update the probe every frame. This provides better results for fast-moving dynamic objects (such as cars). However, it has a significant performance cost. Due to the cost, it's recommended to only use one ReflectionProbe with [constant UPDATE_ALWAYS] at most per scene. For all other use cases, use [constant UPDATE_ONCE]. </constant> <constant name="AMBIENT_DISABLED" value="0" enum="AmbientMode"> - Do not apply any ambient lighting inside the [ReflectionProbe]'s [member extents]. + Do not apply any ambient lighting inside the [ReflectionProbe]'s [member size]. </constant> <constant name="AMBIENT_ENVIRONMENT" value="1" enum="AmbientMode"> - Apply automatically-sourced environment lighting inside the [ReflectionProbe]'s [member extents]. + Apply automatically-sourced environment lighting inside the [ReflectionProbe]'s [member size]. </constant> <constant name="AMBIENT_COLOR" value="2" enum="AmbientMode"> - Apply custom ambient lighting inside the [ReflectionProbe]'s [member extents]. See [member ambient_color] and [member ambient_color_energy]. + Apply custom ambient lighting inside the [ReflectionProbe]'s [member size]. See [member ambient_color] and [member ambient_color_energy]. </constant> </constants> </class> diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index f318430611..82a2871949 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -1,8 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="RenderingDevice" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> + Abstraction for working with modern low-level graphics APIs. </brief_description> <description> + [RenderingDevice] is an abstraction for working with modern low-level graphics APIs such as Vulkan. + On startup, Godot creates a global [RenderingDevice] which can be retrieved using [method RenderingServer.get_rendering_device]. This global RenderingDevice performs drawing to the screen. + Internally, [RenderingDevice] is used in Godot to provide support for several modern low-level graphics APIs while reducing the amount of code duplication required. + [b]Local RenderingDevices:[/b] Using [method RenderingServer.create_local_rendering_device], you can create "secondary" rendering devices to perform drawing and GPU compute operations on separate threads. + [b]Note:[/b] [RenderingDevice] is not available when running in headless mode or when using the OpenGL renderer. </description> <tutorials> </tutorials> @@ -1162,20 +1168,28 @@ <constant name="BARRIER_MASK_NO_BARRIER" value="8" enum="BarrierMask" is_bitfield="true"> </constant> <constant name="TEXTURE_TYPE_1D" value="0" enum="TextureType"> + 1-dimensional texture. </constant> <constant name="TEXTURE_TYPE_2D" value="1" enum="TextureType"> + 2-dimensional texture. </constant> <constant name="TEXTURE_TYPE_3D" value="2" enum="TextureType"> + 3-dimensional texture. </constant> <constant name="TEXTURE_TYPE_CUBE" value="3" enum="TextureType"> + [Cubemap] texture. </constant> <constant name="TEXTURE_TYPE_1D_ARRAY" value="4" enum="TextureType"> + Array of 1-dimensional textures. </constant> <constant name="TEXTURE_TYPE_2D_ARRAY" value="5" enum="TextureType"> + Array of 2-dimensional textures. </constant> <constant name="TEXTURE_TYPE_CUBE_ARRAY" value="6" enum="TextureType"> + Array of [Cubemap] textures. </constant> <constant name="TEXTURE_TYPE_MAX" value="7" enum="TextureType"> + Represents the size of the [enum TextureType] enum. </constant> <constant name="TEXTURE_SAMPLES_1" value="0" enum="TextureSamples"> </constant> @@ -1192,6 +1206,7 @@ <constant name="TEXTURE_SAMPLES_64" value="6" enum="TextureSamples"> </constant> <constant name="TEXTURE_SAMPLES_MAX" value="7" enum="TextureSamples"> + Represents the size of the [enum TextureSamples] enum. </constant> <constant name="TEXTURE_USAGE_SAMPLING_BIT" value="1" enum="TextureUsageBits" is_bitfield="true"> </constant> @@ -1236,8 +1251,10 @@ <constant name="TEXTURE_SLICE_3D" value="2" enum="TextureSliceType"> </constant> <constant name="SAMPLER_FILTER_NEAREST" value="0" enum="SamplerFilter"> + Nearest-neighbor sampler filtering. Sampling at higher resolutions than the source will result in a pixelated look. </constant> <constant name="SAMPLER_FILTER_LINEAR" value="1" enum="SamplerFilter"> + Bilinear sampler filtering. Sampling at higher resolutions than the source will result in a blurry look. </constant> <constant name="SAMPLER_REPEAT_MODE_REPEAT" value="0" enum="SamplerRepeatMode"> </constant> @@ -1298,8 +1315,10 @@ <constant name="UNIFORM_TYPE_MAX" value="10" enum="UniformType"> </constant> <constant name="RENDER_PRIMITIVE_POINTS" value="0" enum="RenderPrimitive"> + Point rendering primitive (with constant size, regardless of distance from camera). </constant> <constant name="RENDER_PRIMITIVE_LINES" value="1" enum="RenderPrimitive"> + Line rendering primitive. </constant> <constant name="RENDER_PRIMITIVE_LINES_WITH_ADJACENCY" value="2" enum="RenderPrimitive"> </constant> @@ -1380,6 +1399,7 @@ <constant name="LOGIC_OP_NO_OP" value="5" enum="LogicOperation"> </constant> <constant name="LOGIC_OP_XOR" value="6" enum="LogicOperation"> + Exclusive or (XOR) logic operation. </constant> <constant name="LOGIC_OP_OR" value="7" enum="LogicOperation"> </constant> @@ -1442,16 +1462,22 @@ <constant name="BLEND_FACTOR_MAX" value="19" enum="BlendFactor"> </constant> <constant name="BLEND_OP_ADD" value="0" enum="BlendOperation"> + Additive blending operation ([code]source + destination[/code]). </constant> <constant name="BLEND_OP_SUBTRACT" value="1" enum="BlendOperation"> + Subtractive blending operation ([code]source - destination[/code]). </constant> <constant name="BLEND_OP_REVERSE_SUBTRACT" value="2" enum="BlendOperation"> + Reverse subtractive blending operation ([code]destination - source[/code]). </constant> <constant name="BLEND_OP_MINIMUM" value="3" enum="BlendOperation"> + Minimum blending operation (keep the lowest value of the two). </constant> <constant name="BLEND_OP_MAXIMUM" value="4" enum="BlendOperation"> + Maximum blending operation (keep the highest value of the two). </constant> <constant name="BLEND_OP_MAX" value="5" enum="BlendOperation"> + Represents the size of the [enum BlendOperation] enum. </constant> <constant name="DYNAMIC_STATE_LINE_WIDTH" value="1" enum="PipelineDynamicStateFlags" is_bitfield="true"> </constant> @@ -1544,12 +1570,16 @@ <constant name="LIMIT_MAX_TEXTURE_ARRAY_LAYERS" value="10" enum="Limit"> </constant> <constant name="LIMIT_MAX_TEXTURE_SIZE_1D" value="11" enum="Limit"> + Maximum supported 1-dimensional texture size (in pixels on a single axis). </constant> <constant name="LIMIT_MAX_TEXTURE_SIZE_2D" value="12" enum="Limit"> + Maximum supported 2-dimensional texture size (in pixels on a single axis). </constant> <constant name="LIMIT_MAX_TEXTURE_SIZE_3D" value="13" enum="Limit"> + Maximum supported 3-dimensional texture size (in pixels on a single axis). </constant> <constant name="LIMIT_MAX_TEXTURE_SIZE_CUBE" value="14" enum="Limit"> + Maximum supported cubemap texture size (in pixels on a single axis of a single face). </constant> <constant name="LIMIT_MAX_TEXTURES_PER_SHADER_STAGE" value="15" enum="Limit"> </constant> @@ -1596,14 +1626,19 @@ <constant name="LIMIT_MAX_VIEWPORT_DIMENSIONS_Y" value="36" enum="Limit"> </constant> <constant name="MEMORY_TEXTURES" value="0" enum="MemoryType"> + Memory taken by textures. </constant> <constant name="MEMORY_BUFFERS" value="1" enum="MemoryType"> + Memory taken by buffers. </constant> <constant name="MEMORY_TOTAL" value="2" enum="MemoryType"> + Total memory taken. This is greater than the sum of [constant MEMORY_TEXTURES] and [constant MEMORY_BUFFERS], as it also includes miscellaneous memory usage. </constant> <constant name="INVALID_ID" value="-1"> + Returned by functions that return an ID if a value is invalid. </constant> <constant name="INVALID_FORMAT_ID" value="-1"> + Returned by functions that return a format ID if a value is invalid. </constant> </constants> </class> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index fc08a16619..4e3a1bc0ef 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -4,10 +4,10 @@ Server for anything visible. </brief_description> <description> - Server for anything visible. The rendering server is the API backend for everything visible. The whole scene system mounts on it to display. + The rendering server is the API backend for everything visible. The whole scene system mounts on it to display. The rendering server is completely opaque, the internals are entirely implementation specific and cannot be accessed. - The rendering server can be used to bypass the scene system entirely. - Resources are created using the [code]*_create[/code] functions. + The rendering server can be used to bypass the scene/[Node] system entirely. + Resources are created using the [code]*_create[/code] functions. These functions return [RID]s which are not references to the objects themselves, but opaque [i]pointers[/i] towards these objects. All objects are drawn to a viewport. You can use the [Viewport] attached to the [SceneTree] or you can create one yourself with [method viewport_create]. When using a custom scenario or canvas, the scenario or canvas needs to be attached to the viewport using [method viewport_set_scenario] or [method viewport_attach_canvas]. In 3D, all visual objects must be associated with a scenario. The scenario is a visual representation of the world. If accessing the rendering server from a running game, the scenario can be accessed from the scene tree from any [Node3D] node with [method Node3D.get_world_3d]. Otherwise, a scenario can be created with [method scenario_create]. Similarly, in 2D, a canvas is needed to draw all canvas items. @@ -25,6 +25,7 @@ <param index="1" name="material_overrides" type="RID[]" /> <param index="2" name="image_size" type="Vector2i" /> <description> + Bakes the material data of the Mesh passed in the [param base] parameter with optional [param material_overrides] to a set of [Image]s of size [param image_size]. Returns an array of [Image]s containing material properties as specified in [enum BakeChannels]. </description> </method> <method name="camera_attributes_create"> @@ -43,6 +44,7 @@ <param index="4" name="speed" type="float" /> <param index="5" name="scale" type="float" /> <description> + Sets the parameters to use with the auto-exposure effect. These parameters take on the same meaning as their counterparts in [CameraAttributes] and [CameraAttributesPractical]. </description> </method> <method name="camera_attributes_set_dof_blur"> @@ -56,12 +58,14 @@ <param index="6" name="near_transition" type="float" /> <param index="7" name="amount" type="float" /> <description> + Sets the parameters to use with the DOF blur effect. These parameters take on the same meaning as their counterparts in [CameraAttributesPractical]. </description> </method> <method name="camera_attributes_set_dof_blur_bokeh_shape"> <return type="void" /> <param index="0" name="shape" type="int" enum="RenderingServer.DOFBokehShape" /> <description> + Sets the shape of the DOF bokeh pattern. Different shapes may be used to achieve artistic effect, or to meet performance targets. For more detail on available options see [enum DOFBokehShape]. </description> </method> <method name="camera_attributes_set_dof_blur_quality"> @@ -69,6 +73,7 @@ <param index="0" name="quality" type="int" enum="RenderingServer.DOFBlurQuality" /> <param index="1" name="use_jitter" type="bool" /> <description> + Sets the quality level of the DOF blur effect to one of the options in [enum DOFBlurQuality]. [param use_jitter] can be used to jitter samples taken during the blur pass to hide artifacts at the cost of looking more fuzzy. </description> </method> <method name="camera_attributes_set_exposure"> @@ -102,6 +107,7 @@ <param index="0" name="camera" type="RID" /> <param index="1" name="effects" type="RID" /> <description> + Sets the camera_attributes created with [method camera_attributes_create] to the given camera. </description> </method> <method name="camera_set_cull_mask"> @@ -192,6 +198,7 @@ <param index="2" name="radius" type="float" /> <param index="3" name="color" type="Color" /> <description> + Draws a circle on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_circle]. </description> </method> <method name="canvas_item_add_clip_ignore"> @@ -199,6 +206,7 @@ <param index="0" name="item" type="RID" /> <param index="1" name="ignore" type="bool" /> <description> + If [param ignore] is [code]true[/code], ignore clipping on items drawn with this canvas item until this is called again with [param ignore] set to false. </description> </method> <method name="canvas_item_add_lcd_texture_rect_region"> @@ -209,6 +217,7 @@ <param index="3" name="src_rect" type="Rect2" /> <param index="4" name="modulate" type="Color" /> <description> + See also [method CanvasItem.draw_lcd_texture_rect_region]. </description> </method> <method name="canvas_item_add_line"> @@ -220,6 +229,7 @@ <param index="4" name="width" type="float" default="-1.0" /> <param index="5" name="antialiased" type="bool" default="false" /> <description> + Draws a line on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_line]. </description> </method> <method name="canvas_item_add_mesh"> @@ -230,6 +240,7 @@ <param index="3" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> <param index="4" name="texture" type="RID" /> <description> + Draws a mesh created with [method mesh_create] with given [param transform], [param modulate] color, and [param texture]. This is used internally by [MeshInstance2D]. </description> </method> <method name="canvas_item_add_msdf_texture_rect_region"> @@ -243,6 +254,7 @@ <param index="6" name="px_range" type="float" default="1.0" /> <param index="7" name="scale" type="float" default="1.0" /> <description> + See also [method CanvasItem.draw_msdf_texture_rect_region]. </description> </method> <method name="canvas_item_add_multimesh"> @@ -251,6 +263,7 @@ <param index="1" name="mesh" type="RID" /> <param index="2" name="texture" type="RID" /> <description> + Draws a 2D [MultiMesh] on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_multimesh]. </description> </method> <method name="canvas_item_add_nine_patch"> @@ -266,6 +279,7 @@ <param index="8" name="draw_center" type="bool" default="true" /> <param index="9" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> <description> + Draws a nine-patch rectangle on the [CanvasItem] pointed to by the [param item] [RID]. </description> </method> <method name="canvas_item_add_particles"> @@ -274,6 +288,7 @@ <param index="1" name="particles" type="RID" /> <param index="2" name="texture" type="RID" /> <description> + Draws particles on the [CanvasItem] pointed to by the [param item] [RID]. </description> </method> <method name="canvas_item_add_polygon"> @@ -284,6 +299,7 @@ <param index="3" name="uvs" type="PackedVector2Array" default="PackedVector2Array()" /> <param index="4" name="texture" type="RID" /> <description> + Draws a 2D polygon on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_polygon]. </description> </method> <method name="canvas_item_add_polyline"> @@ -294,6 +310,7 @@ <param index="3" name="width" type="float" default="-1.0" /> <param index="4" name="antialiased" type="bool" default="false" /> <description> + Draws a 2D polyline on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_polyline]. </description> </method> <method name="canvas_item_add_primitive"> @@ -304,6 +321,7 @@ <param index="3" name="uvs" type="PackedVector2Array" /> <param index="4" name="texture" type="RID" /> <description> + Draws a 2D primitive on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_primitive]. </description> </method> <method name="canvas_item_add_rect"> @@ -312,6 +330,7 @@ <param index="1" name="rect" type="Rect2" /> <param index="2" name="color" type="Color" /> <description> + Draws a rectangle on the [CanvasItem] pointed to by the [param item] [RID]. See also [method CanvasItem.draw_rect]. </description> </method> <method name="canvas_item_add_set_transform"> @@ -319,6 +338,7 @@ <param index="0" name="item" type="RID" /> <param index="1" name="transform" type="Transform2D" /> <description> + Sets a [Transform2D] that will be used to transform subsequent canvas item commands. </description> </method> <method name="canvas_item_add_texture_rect"> @@ -368,6 +388,7 @@ <method name="canvas_item_create"> <return type="RID" /> <description> + Creates a new [CanvasItem] instance and returns its [RID]. </description> </method> <method name="canvas_item_set_canvas_group_mode"> @@ -877,13 +898,6 @@ <description> </description> </method> - <method name="decal_set_extents"> - <return type="void" /> - <param index="0" name="decal" type="RID" /> - <param index="1" name="extents" type="Vector3" /> - <description> - </description> - </method> <method name="decal_set_fade"> <return type="void" /> <param index="0" name="decal" type="RID" /> @@ -906,6 +920,13 @@ <description> </description> </method> + <method name="decal_set_size"> + <return type="void" /> + <param index="0" name="decal" type="RID" /> + <param index="1" name="size" type="Vector3" /> + <description> + </description> + </method> <method name="decal_set_texture"> <return type="void" /> <param index="0" name="decal" type="RID" /> @@ -1218,14 +1239,6 @@ Creates a new fog volume and allocates an RID. </description> </method> - <method name="fog_volume_set_extents"> - <return type="void" /> - <param index="0" name="fog_volume" type="RID" /> - <param index="1" name="extents" type="Vector3" /> - <description> - Sets the size of the fog volume when shape is [constant RenderingServer.FOG_VOLUME_SHAPE_ELLIPSOID], [constant RenderingServer.FOG_VOLUME_SHAPE_CONE], [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER] or [constant RenderingServer.FOG_VOLUME_SHAPE_BOX]. - </description> - </method> <method name="fog_volume_set_material"> <return type="void" /> <param index="0" name="fog_volume" type="RID" /> @@ -1242,6 +1255,14 @@ Sets the shape of the fog volume to either [constant RenderingServer.FOG_VOLUME_SHAPE_ELLIPSOID], [constant RenderingServer.FOG_VOLUME_SHAPE_CONE], [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER], [constant RenderingServer.FOG_VOLUME_SHAPE_BOX] or [constant RenderingServer.FOG_VOLUME_SHAPE_WORLD]. </description> </method> + <method name="fog_volume_set_size"> + <return type="void" /> + <param index="0" name="fog_volume" type="RID" /> + <param index="1" name="size" type="Vector3" /> + <description> + Sets the size of the fog volume when shape is [constant RenderingServer.FOG_VOLUME_SHAPE_ELLIPSOID], [constant RenderingServer.FOG_VOLUME_SHAPE_CONE], [constant RenderingServer.FOG_VOLUME_SHAPE_CYLINDER] or [constant RenderingServer.FOG_VOLUME_SHAPE_BOX]. + </description> + </method> <method name="force_draw"> <return type="void" /> <param index="0" name="swap_buffers" type="bool" default="true" /> @@ -1792,6 +1813,7 @@ <method name="lightmap_create"> <return type="RID" /> <description> + Creates a new [LightmapGI] instance. </description> </method> <method name="lightmap_get_probe_capture_bsp_tree" qualifiers="const"> @@ -2655,14 +2677,6 @@ If [code]true[/code], computes shadows in the reflection probe. This makes the reflection much slower to compute. Equivalent to [member ReflectionProbe.enable_shadows]. </description> </method> - <method name="reflection_probe_set_extents"> - <return type="void" /> - <param index="0" name="probe" type="RID" /> - <param index="1" name="extents" type="Vector3" /> - <description> - Sets the size of the area that the reflection probe will capture. Equivalent to [member ReflectionProbe.extents]. - </description> - </method> <method name="reflection_probe_set_intensity"> <return type="void" /> <param index="0" name="probe" type="RID" /> @@ -2701,6 +2715,14 @@ <description> </description> </method> + <method name="reflection_probe_set_size"> + <return type="void" /> + <param index="0" name="probe" type="RID" /> + <param index="1" name="size" type="Vector3" /> + <description> + Sets the size of the area that the reflection probe will capture. Equivalent to [member ReflectionProbe.size]. + </description> + </method> <method name="reflection_probe_set_update_mode"> <return type="void" /> <param index="0" name="probe" type="RID" /> @@ -3245,12 +3267,12 @@ <description> </description> </method> - <method name="viewport_set_disable_environment"> + <method name="viewport_set_environment_mode"> <return type="void" /> <param index="0" name="viewport" type="RID" /> - <param index="1" name="disabled" type="bool" /> + <param index="1" name="mode" type="int" enum="RenderingServer.ViewportEnvironmentMode" /> <description> - If [code]true[/code], rendering of a viewport's environment is disabled. + Sets the viewport's environment mode which allows enabling or disabling rendering of 3D environment over 2D canvas. When disabled, 2D will not be affected by the environment. When enabled, 2D will be affected by the environment if the environment background mode is [constant ENV_BG_CANVAS]. The default behavior is to inherit the setting from the viewport's parent. If the topmost parent is also set to [constant VIEWPORT_ENVIRONMENT_INHERIT], then the behavior will be the same as if it was set to [constant VIEWPORT_ENVIRONMENT_ENABLED]. </description> </method> <method name="viewport_set_fsr_sharpness"> @@ -4091,10 +4113,10 @@ [FogVolume] will be shaped like an ellipsoid (stretched sphere). </constant> <constant name="FOG_VOLUME_SHAPE_CONE" value="1" enum="FogVolumeShape"> - [FogVolume] will be shaped like a cone pointing upwards (in local coordinates). The cone's angle is set automatically to fill the extents. The cone will be adjusted to fit within the extents. Rotate the [FogVolume] node to reorient the cone. Non-uniform scaling via extents is not supported (scale the [FogVolume] node instead). + [FogVolume] will be shaped like a cone pointing upwards (in local coordinates). The cone's angle is set automatically to fill the size. The cone will be adjusted to fit within the size. Rotate the [FogVolume] node to reorient the cone. Non-uniform scaling via size is not supported (scale the [FogVolume] node instead). </constant> <constant name="FOG_VOLUME_SHAPE_CYLINDER" value="2" enum="FogVolumeShape"> - [FogVolume] will be shaped like an upright cylinder (in local coordinates). Rotate the [FogVolume] node to reorient the cylinder. The cylinder will be adjusted to fit within the extents. Non-uniform scaling via extents is not supported (scale the [FogVolume] node instead). + [FogVolume] will be shaped like an upright cylinder (in local coordinates). Rotate the [FogVolume] node to reorient the cylinder. The cylinder will be adjusted to fit within the size. Non-uniform scaling via size is not supported (scale the [FogVolume] node instead). </constant> <constant name="FOG_VOLUME_SHAPE_BOX" value="3" enum="FogVolumeShape"> [FogVolume] will be shaped like a box. @@ -4135,6 +4157,18 @@ <constant name="VIEWPORT_CLEAR_ONLY_NEXT_FRAME" value="2" enum="ViewportClearMode"> The viewport is cleared once, then the clear mode is set to [constant VIEWPORT_CLEAR_NEVER]. </constant> + <constant name="VIEWPORT_ENVIRONMENT_DISABLED" value="0" enum="ViewportEnvironmentMode"> + Disable rendering of 3D environment over 2D canvas. + </constant> + <constant name="VIEWPORT_ENVIRONMENT_ENABLED" value="1" enum="ViewportEnvironmentMode"> + Enable rendering of 3D environment over 2D canvas. + </constant> + <constant name="VIEWPORT_ENVIRONMENT_INHERIT" value="2" enum="ViewportEnvironmentMode"> + Inherit enable/disable value from parent. If topmost parent is also set to inherit, then this has the same behavior as [constant VIEWPORT_ENVIRONMENT_ENABLED]. + </constant> + <constant name="VIEWPORT_ENVIRONMENT_MAX" value="3" enum="ViewportEnvironmentMode"> + Max value of [enum ViewportEnvironmentMode] enum. + </constant> <constant name="VIEWPORT_SDF_OVERSIZE_100_PERCENT" value="0" enum="ViewportSDFOversize"> </constant> <constant name="VIEWPORT_SDF_OVERSIZE_120_PERCENT" value="1" enum="ViewportSDFOversize"> @@ -4553,12 +4587,16 @@ Fade-in the given instance's dependencies when reaching its visibility range limits. </constant> <constant name="BAKE_CHANNEL_ALBEDO_ALPHA" value="0" enum="BakeChannels"> + Index of [Image] in array of [Image]s returned by [method bake_render_uv2]. Image uses [constant Image.FORMAT_RGBA8] and contains albedo color in the [code].rgb[/code] channels and alpha in the [code].a[/code] channel. </constant> <constant name="BAKE_CHANNEL_NORMAL" value="1" enum="BakeChannels"> + Index of [Image] in array of [Image]s returned by [method bake_render_uv2]. Image uses [constant Image.FORMAT_RGBA8] and contains the per-pixel normal of the object in the [code].rgb[/code] channels and nothing in the [code].a[/code] channel. The per-pixel normal is encoded as [code]normal * 0.5 + 0.5[/code]. </constant> <constant name="BAKE_CHANNEL_ORM" value="2" enum="BakeChannels"> + Index of [Image] in array of [Image]s returned by [method bake_render_uv2]. Image uses [constant Image.FORMAT_RGBA8] and contains ambient occlusion (from material and decals only) in the [code].r[/code] channel, roughness in the [code].g[/code] channel, metallic in the [code].b[/code] channel and sub surface scattering amount in the [code].a[/code] channel. </constant> <constant name="BAKE_CHANNEL_EMISSION" value="3" enum="BakeChannels"> + Index of [Image] in array of [Image]s returned by [method bake_render_uv2]. Image uses [constant Image.FORMAT_RGBAH] and contains emission color in the [code].rgb[/code] channels and nothing in the [code].a[/code] channel. </constant> <constant name="CANVAS_TEXTURE_CHANNEL_DIFFUSE" value="0" enum="CanvasTextureChannel"> </constant> diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml index bb55123b37..1d509d2938 100644 --- a/doc/classes/ResourceFormatLoader.xml +++ b/doc/classes/ResourceFormatLoader.xml @@ -88,7 +88,7 @@ </description> </method> <method name="_rename_dependencies" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="path" type="String" /> <param index="1" name="renames" type="Dictionary" /> <description> diff --git a/doc/classes/ResourceFormatSaver.xml b/doc/classes/ResourceFormatSaver.xml index b0c57bc7cb..7e8e2ec67d 100644 --- a/doc/classes/ResourceFormatSaver.xml +++ b/doc/classes/ResourceFormatSaver.xml @@ -34,7 +34,7 @@ </description> </method> <method name="_save" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="resource" type="Resource" /> <param index="1" name="path" type="String" /> <param index="2" name="flags" type="int" /> diff --git a/doc/classes/RichTextEffect.xml b/doc/classes/RichTextEffect.xml index c01546524d..333d34d1b7 100644 --- a/doc/classes/RichTextEffect.xml +++ b/doc/classes/RichTextEffect.xml @@ -13,7 +13,7 @@ [/gdscript] [csharp] // The RichTextEffect will be usable like this: `[example]Some text[/example]` - public string bbcode = "example"; + string bbcode = "example"; [/csharp] [/codeblocks] [b]Note:[/b] As soon as a [RichTextLabel] contains at least one [RichTextEffect], it will continuously process the effect unless the project is paused. This may impact battery life negatively. diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index bf19ebc23a..6adb37a3f7 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -74,10 +74,10 @@ print("end") [/gdscript] [csharp] - public async void SomeFunction() + public async Task SomeFunction() { GD.Print("start"); - await ToSignal(GetTree().CreateTimer(1.0f), "timeout"); + await ToSignal(GetTree().CreateTimer(1.0f), SceneTreeTimer.SignalName.Timeout); GD.Print("end"); } [/csharp] diff --git a/doc/classes/SceneTreeTimer.xml b/doc/classes/SceneTreeTimer.xml index f28e65c5bf..42b070d7d9 100644 --- a/doc/classes/SceneTreeTimer.xml +++ b/doc/classes/SceneTreeTimer.xml @@ -14,10 +14,10 @@ print("Timer ended.") [/gdscript] [csharp] - public async void SomeFunction() + public async Task SomeFunction() { GD.Print("Timer started."); - await ToSignal(GetTree().CreateTimer(1.0f), "timeout"); + await ToSignal(GetTree().CreateTimer(1.0f), SceneTreeTimer.SignalName.Timeout); GD.Print("Timer ended."); } [/csharp] diff --git a/doc/classes/Sprite2D.xml b/doc/classes/Sprite2D.xml index 235fef0bdd..033dbf51f3 100644 --- a/doc/classes/Sprite2D.xml +++ b/doc/classes/Sprite2D.xml @@ -23,11 +23,11 @@ print("A click!") [/gdscript] [csharp] - public override void _Input(InputEvent inputEvent) + public override void _Input(InputEvent @event) { - if (inputEvent is InputEventMouseButton inputEventMouse) + if (@event is InputEventMouseButton inputEventMouse) { - if (inputEventMouse.Pressed && inputEventMouse.ButtonIndex == (int)ButtonList.Left) + if (inputEventMouse.Pressed && inputEventMouse.ButtonIndex == MouseButton.Left) { if (GetRect().HasPoint(ToLocal(inputEventMouse.Position))) { diff --git a/doc/classes/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml index 7ff45edcbc..e1f3a52a1d 100644 --- a/doc/classes/SpriteBase3D.xml +++ b/doc/classes/SpriteBase3D.xml @@ -38,6 +38,12 @@ </method> </methods> <members> + <member name="alpha_antialiasing_edge" type="float" setter="set_alpha_antialiasing_edge" getter="get_alpha_antialiasing_edge" default="0.0"> + Threshold at which antialiasing will be applied on the alpha channel. + </member> + <member name="alpha_antialiasing_mode" type="int" setter="set_alpha_antialiasing" getter="get_alpha_antialiasing" enum="BaseMaterial3D.AlphaAntiAliasing" default="0"> + The type of alpha antialiasing to apply. See [enum BaseMaterial3D.AlphaAntiAliasing]. + </member> <member name="alpha_cut" type="int" setter="set_alpha_cut_mode" getter="get_alpha_cut_mode" enum="SpriteBase3D.AlphaCutMode" default="0"> The alpha cutting mode to use for the sprite. See [enum AlphaCutMode] for possible values. </member> diff --git a/doc/classes/StreamPeer.xml b/doc/classes/StreamPeer.xml index f05b5f7dbf..969cbac57d 100644 --- a/doc/classes/StreamPeer.xml +++ b/doc/classes/StreamPeer.xml @@ -223,7 +223,7 @@ put_data("Hello world".to_utf8()) [/gdscript] [csharp] - PutData("Hello World".ToUTF8()); + PutData("Hello World".ToUtf8()); [/csharp] [/codeblocks] </description> diff --git a/doc/classes/SubViewport.xml b/doc/classes/SubViewport.xml index 7020cae1de..bb76a82ef3 100644 --- a/doc/classes/SubViewport.xml +++ b/doc/classes/SubViewport.xml @@ -26,6 +26,7 @@ </member> <member name="size" type="Vector2i" setter="set_size" getter="get_size" default="Vector2i(512, 512)"> The width and height of the sub-viewport. Must be set to a value greater than or equal to 2 pixels on both dimensions. Otherwise, nothing will be displayed. + [b]Note:[/b] If the parent node is a [SubViewportContainer] and its [member SubViewportContainer.stretch] is [code]true[/code], the viewport size cannot be changed manually. </member> <member name="size_2d_override" type="Vector2i" setter="set_size_2d_override" getter="get_size_2d_override" default="Vector2i(0, 0)"> The 2D size override of the sub-viewport. If either the width or height is [code]0[/code], the override is disabled. diff --git a/doc/classes/SubViewportContainer.xml b/doc/classes/SubViewportContainer.xml index 77aa7e3ff4..11137222a9 100644 --- a/doc/classes/SubViewportContainer.xml +++ b/doc/classes/SubViewportContainer.xml @@ -13,6 +13,7 @@ <members> <member name="stretch" type="bool" setter="set_stretch" getter="is_stretch_enabled" default="false"> If [code]true[/code], the sub-viewport will be automatically resized to the control's size. + [b]Note:[/b] If [code]true[/code], this will prohibit changing [member SubViewport.size] of its children manually. </member> <member name="stretch_shrink" type="int" setter="set_stretch_shrink" getter="get_stretch_shrink" default="1"> Divides the sub-viewport's effective resolution by this value while preserving its scale. This can be used to speed up rendering. diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index cf28dafcc9..02a2789ea5 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -410,11 +410,6 @@ Emitted when an item is collapsed by a click on the folding arrow. </description> </signal> - <signal name="item_custom_button_pressed"> - <description> - Emitted when a custom button is pressed (i.e. in a [constant TreeItem.CELL_MODE_CUSTOM] mode cell). - </description> - </signal> <signal name="item_edited"> <description> Emitted when an item is edited. diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml index 9bb92cf362..16e4ce3714 100644 --- a/doc/classes/Tween.xml +++ b/doc/classes/Tween.xml @@ -77,13 +77,13 @@ tween = create_tween() [/gdscript] [csharp] - private Tween tween; + private Tween _tween; public void Animate() { - if (tween != null) - tween.Kill(); // Abort the previous animation - tween = CreateTween(); + if (_tween != null) + _tween.Kill(); // Abort the previous animation + _tween = CreateTween(); } [/csharp] [/codeblocks] diff --git a/doc/classes/UDPServer.xml b/doc/classes/UDPServer.xml index c3a3a49a80..8151ecb625 100644 --- a/doc/classes/UDPServer.xml +++ b/doc/classes/UDPServer.xml @@ -9,7 +9,8 @@ Below a small example of how it can be used: [codeblocks] [gdscript] - class_name Server + # server_node.gd + class_name ServerNode extends Node var server := UDPServer.new() @@ -34,35 +35,35 @@ pass # Do something with the connected peers. [/gdscript] [csharp] + // ServerNode.cs using Godot; - using System; using System.Collections.Generic; - public class Server : Node + public partial class ServerNode : Node { - public UDPServer Server = new UDPServer(); - public List<PacketPeerUDP> Peers = new List<PacketPeerUDP>(); + private UdpServer _server = new UdpServer(); + private List<PacketPeerUdp> _peers = new List<PacketPeerUdp>(); public override void _Ready() { - Server.Listen(4242); + _server.Listen(4242); } - public override void _Process(float delta) + public override void _Process(double delta) { - Server.Poll(); // Important! - if (Server.IsConnectionAvailable()) + _server.Poll(); // Important! + if (_server.IsConnectionAvailable()) { - PacketPeerUDP peer = Server.TakeConnection(); + PacketPeerUdp peer = _server.TakeConnection(); byte[] packet = peer.GetPacket(); - GD.Print($"Accepted Peer: {peer.GetPacketIp()}:{peer.GetPacketPort()}"); - GD.Print($"Received Data: {packet.GetStringFromUTF8()}"); + GD.Print($"Accepted Peer: {peer.GetPacketIP()}:{peer.GetPacketPort()}"); + GD.Print($"Received Data: {packet.GetStringFromUtf8()}"); // Reply so it knows we received the message. peer.PutPacket(packet); // Keep a reference so we can keep contacting the remote peer. - Peers.Add(peer); + _peers.Add(peer); } - foreach (var peer in Peers) + foreach (var peer in _peers) { // Do something with the peers. } @@ -72,7 +73,8 @@ [/codeblocks] [codeblocks] [gdscript] - class_name Client + # client_node.gd + class_name ClientNode extends Node var udp := PacketPeerUDP.new() @@ -90,30 +92,30 @@ connected = true [/gdscript] [csharp] + // ClientNode.cs using Godot; - using System; - public class Client : Node + public partial class ClientNode : Node { - public PacketPeerUDP Udp = new PacketPeerUDP(); - public bool Connected = false; + private PacketPeerUdp _udp = new PacketPeerUdp(); + private bool _connected = false; public override void _Ready() { - Udp.ConnectToHost("127.0.0.1", 4242); + _udp.ConnectToHost("127.0.0.1", 4242); } - public override void _Process(float delta) + public override void _Process(double delta) { - if (!Connected) + if (!_connected) { // Try to contact server - Udp.PutPacket("The Answer Is..42!".ToUTF8()); + _udp.PutPacket("The Answer Is..42!".ToUtf8()); } - if (Udp.GetAvailablePacketCount() > 0) + if (_udp.GetAvailablePacketCount() > 0) { - GD.Print($"Connected: {Udp.GetPacket().GetStringFromUTF8()}"); - Connected = true; + GD.Print($"Connected: {_udp.GetPacket().GetStringFromUtf8()}"); + _connected = true; } } } diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml index 6c151ef958..e43bceb941 100644 --- a/doc/classes/UndoRedo.xml +++ b/doc/classes/UndoRedo.xml @@ -27,11 +27,11 @@ undo_redo.commit_action() [/gdscript] [csharp] - public UndoRedo UndoRedo; + private UndoRedo _undoRedo; public override void _Ready() { - UndoRedo = GetUndoRedo(); // Method of EditorPlugin. + _undoRedo = GetUndoRedo(); // Method of EditorPlugin. } public void DoSomething() @@ -47,12 +47,12 @@ private void OnMyButtonPressed() { var node = GetNode<Node2D>("MyNode2D"); - UndoRedo.CreateAction("Move the node"); - UndoRedo.AddDoMethod(this, MethodName.DoSomething); - UndoRedo.AddUndoMethod(this, MethodName.UndoSomething); - UndoRedo.AddDoProperty(node, Node2D.PropertyName.Position, new Vector2(100, 100)); - UndoRedo.AddUndoProperty(node, Node2D.PropertyName.Position, node.Position); - UndoRedo.CommitAction(); + _undoRedo.CreateAction("Move the node"); + _undoRedo.AddDoMethod(new Callable(this, MethodName.DoSomething)); + _undoRedo.AddUndoMethod(new Callable(this, MethodName.UndoSomething)); + _undoRedo.AddDoProperty(node, "position", new Vector2(100, 100)); + _undoRedo.AddUndoProperty(node, "position", node.Position); + _undoRedo.CommitAction(); } [/csharp] [/codeblocks] diff --git a/doc/classes/VideoStream.xml b/doc/classes/VideoStream.xml index 2797ad3513..648c3edd73 100644 --- a/doc/classes/VideoStream.xml +++ b/doc/classes/VideoStream.xml @@ -8,4 +8,18 @@ </description> <tutorials> </tutorials> + <methods> + <method name="_instantiate_playback" qualifiers="virtual"> + <return type="VideoStreamPlayback" /> + <description> + Called when the video starts playing, to initialize and return a subclass of [VideoStreamPlayback]. + </description> + </method> + </methods> + <members> + <member name="file" type="String" setter="set_file" getter="get_file" default=""""> + The video file path or URI that this [VideoStream] resource handles. + For [VideoStreamTheora], this filename should be an Ogg Theora video file with the [code].ogv[/code] extension. + </member> + </members> </class> diff --git a/doc/classes/VideoStreamPlayback.xml b/doc/classes/VideoStreamPlayback.xml new file mode 100644 index 0000000000..8d8b4fe5b1 --- /dev/null +++ b/doc/classes/VideoStreamPlayback.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VideoStreamPlayback" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Internal class used by [VideoStream] to manage playback state when played from a [VideoStreamPlayer]. + </brief_description> + <description> + This class is intended to be overridden by video decoder extensions with custom implementations of [VideoStream]. + </description> + <tutorials> + </tutorials> + <methods> + <method name="_get_channels" qualifiers="virtual const"> + <return type="int" /> + <description> + Returns the number of audio channels. + </description> + </method> + <method name="_get_length" qualifiers="virtual const"> + <return type="float" /> + <description> + Returns the video duration in seconds, if known, or 0 if unknown. + </description> + </method> + <method name="_get_mix_rate" qualifiers="virtual const"> + <return type="int" /> + <description> + Returns the audio sample rate used for mixing. + </description> + </method> + <method name="_get_playback_position" qualifiers="virtual const"> + <return type="float" /> + <description> + Return the current playback timestamp. Called in response to the [member VideoStreamPlayer.stream_position] getter. + </description> + </method> + <method name="_get_texture" qualifiers="virtual const"> + <return type="Texture2D" /> + <description> + Allocates a [Texture2D] in which decoded video frames will be drawn. + </description> + </method> + <method name="_is_paused" qualifiers="virtual const"> + <return type="bool" /> + <description> + Returns the paused status, as set by [method _set_paused]. + </description> + </method> + <method name="_is_playing" qualifiers="virtual const"> + <return type="bool" /> + <description> + Returns the playback state, as determined by calls to [method _play] and [method _stop]. + </description> + </method> + <method name="_play" qualifiers="virtual"> + <return type="void" /> + <description> + Called in response to [member VideoStreamPlayer.autoplay] or [method VideoStreamPlayer.play]. Note that manual playback may also invoke [method _stop] multiple times before this method is called. [method _is_playing] should return true once playing. + </description> + </method> + <method name="_seek" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="time" type="float" /> + <description> + Seeks to [code]time[/code] seconds. Called in response to the [member VideoStreamPlayer.stream_position] setter. + </description> + </method> + <method name="_set_audio_track" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="idx" type="int" /> + <description> + Select the audio track [code]idx[/code]. Called when playback starts, and in response to the [member VideoStreamPlayer.audio_track] setter. + </description> + </method> + <method name="_set_paused" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="paused" type="bool" /> + <description> + Set the paused status of video playback. [method _is_paused] must return [code]paused[/code]. Called in response to the [member VideoStreamPlayer.paused] setter. + </description> + </method> + <method name="_stop" qualifiers="virtual"> + <return type="void" /> + <description> + Stops playback. May be called multiple times before [method _play], or in response to [method VideoStreamPlayer.stop]. [method _is_playing] should return false once stopped. + </description> + </method> + <method name="_update" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="delta" type="float" /> + <description> + Ticks video playback for [code]delta[/code] seconds. Called every frame as long as [method _is_paused] and [method _is_playing] return true. + </description> + </method> + <method name="mix_audio"> + <return type="int" /> + <param index="0" name="num_frames" type="int" /> + <param index="1" name="buffer" type="PackedFloat32Array" default="PackedFloat32Array()" /> + <param index="2" name="offset" type="int" default="0" /> + <description> + Render [code]num_frames[/code] audio frames (of [method _get_channels] floats each) from [code]buffer[/code], starting from index [code]offset[/code] in the array. Returns the number of audio frames rendered, or -1 on error. + </description> + </method> + </methods> +</class> diff --git a/doc/classes/VisualShaderNodeCustom.xml b/doc/classes/VisualShaderNodeCustom.xml index d96969b383..279295a434 100644 --- a/doc/classes/VisualShaderNodeCustom.xml +++ b/doc/classes/VisualShaderNodeCustom.xml @@ -81,7 +81,7 @@ </description> </method> <method name="_get_input_port_type" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="VisualShaderNode.PortType" /> <param index="0" name="port" type="int" /> <description> Override this method to define the returned type of each input port of the associated custom node (see [enum VisualShaderNode.PortType] for possible types). @@ -111,7 +111,7 @@ </description> </method> <method name="_get_output_port_type" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="VisualShaderNode.PortType" /> <param index="0" name="port" type="int" /> <description> Override this method to define the returned type of each output port of the associated custom node (see [enum VisualShaderNode.PortType] for possible types). @@ -119,7 +119,7 @@ </description> </method> <method name="_get_return_icon_type" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="VisualShaderNode.PortType" /> <description> Override this method to define the return icon of the associated custom node in the Visual Shader Editor's members dialog. Defining this method is [b]optional[/b]. If not overridden, no return icon is shown. diff --git a/doc/classes/VoxelGI.xml b/doc/classes/VoxelGI.xml index 394611b78f..4347c5845f 100644 --- a/doc/classes/VoxelGI.xml +++ b/doc/classes/VoxelGI.xml @@ -38,9 +38,9 @@ <member name="data" type="VoxelGIData" setter="set_probe_data" getter="get_probe_data"> The [VoxelGIData] resource that holds the data for this [VoxelGI]. </member> - <member name="extents" type="Vector3" setter="set_extents" getter="get_extents" default="Vector3(10, 10, 10)"> - The size of the area covered by the [VoxelGI]. If you make the extents larger without increasing the subdivisions with [member subdiv], the size of each cell will increase and result in lower detailed lighting. - [b]Note:[/b] Extents are clamped to 1.0 unit or more on each axis. + <member name="size" type="Vector3" setter="set_size" getter="get_size" default="Vector3(20, 20, 20)"> + The size of the area covered by the [VoxelGI]. If you make the size larger without increasing the subdivisions with [member subdiv], the size of each cell will increase and result in lower detailed lighting. + [b]Note:[/b] Size is clamped to 1.0 unit or more on each axis. </member> <member name="subdiv" type="int" setter="set_subdiv" getter="get_subdiv" enum="VoxelGI.Subdiv" default="1"> Number of times to subdivide the grid that the [VoxelGI] operates on. A higher number results in finer detail and thus higher visual quality, while lower numbers result in better performance. diff --git a/doc/classes/VoxelGIData.xml b/doc/classes/VoxelGIData.xml index bd9df18394..541a3bc4a6 100644 --- a/doc/classes/VoxelGIData.xml +++ b/doc/classes/VoxelGIData.xml @@ -26,8 +26,8 @@ <method name="get_bounds" qualifiers="const"> <return type="AABB" /> <description> - Returns the bounds of the baked voxel data as an [AABB], which should match [member VoxelGI.extents] after being baked (which only contains the size as a [Vector3]). - [b]Note:[/b] If the extents were modified without baking the VoxelGI data, then the value of [method get_bounds] and [member VoxelGI.extents] will not match. + Returns the bounds of the baked voxel data as an [AABB], which should match [member VoxelGI.size] after being baked (which only contains the size as a [Vector3]). + [b]Note:[/b] If the size was modified without baking the VoxelGI data, then the value of [method get_bounds] and [member VoxelGI.size] will not match. </description> </method> <method name="get_data_cells" qualifiers="const"> diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index c4ea11ab66..14e705a7e6 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -614,6 +614,12 @@ This signal can be used to handle window closing, e.g. by connecting it to [method hide]. </description> </signal> + <signal name="dpi_changed"> + <description> + Emitted when the [Window]'s DPI changes as a result of OS-level changes (e.g. moving the window from a Retina display to a lower resolution one). + [b]Note:[/b] Only implemented on macOS. + </description> + </signal> <signal name="files_dropped"> <param index="0" name="files" type="PackedStringArray" /> <description> diff --git a/doc/classes/XRInterfaceExtension.xml b/doc/classes/XRInterfaceExtension.xml index 5ad67a7ea9..b74ac1e469 100644 --- a/doc/classes/XRInterfaceExtension.xml +++ b/doc/classes/XRInterfaceExtension.xml @@ -64,7 +64,7 @@ </description> </method> <method name="_get_play_area_mode" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="XRInterface.PlayAreaMode" /> <description> Returns the [enum XRInterface.PlayAreaMode] that sets up our play area. </description> @@ -99,7 +99,7 @@ </description> </method> <method name="_get_tracking_status" qualifiers="virtual const"> - <return type="int" /> + <return type="int" enum="XRInterface.TrackingStatus" /> <description> Returns a [enum XRInterface.TrackingStatus] specifying the current status of our tracking. </description> @@ -177,7 +177,7 @@ </method> <method name="_set_play_area_mode" qualifiers="virtual const"> <return type="bool" /> - <param index="0" name="mode" type="int" /> + <param index="0" name="mode" type="int" enum="XRInterface.PlayAreaMode" /> <description> Set the play area mode for this interface. </description> diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp index e9eb11e2e3..c454da8e23 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.cpp @@ -44,10 +44,10 @@ OSStatus AudioDriverCoreAudio::input_device_address_cb(AudioObjectID inObjectID, void *inClientData) { AudioDriverCoreAudio *driver = static_cast<AudioDriverCoreAudio *>(inClientData); - // If our selected device is the Default call set_device to update the + // If our selected input device is the Default, call set_input_device to update the // kAudioOutputUnitProperty_CurrentDevice property - if (driver->capture_device_name == "Default") { - driver->capture_set_device("Default"); + if (driver->input_device_name == "Default") { + driver->set_input_device("Default"); } return noErr; @@ -58,10 +58,10 @@ OSStatus AudioDriverCoreAudio::output_device_address_cb(AudioObjectID inObjectID void *inClientData) { AudioDriverCoreAudio *driver = static_cast<AudioDriverCoreAudio *>(inClientData); - // If our selected device is the Default call set_device to update the + // If our selected output device is the Default call set_output_device to update the // kAudioOutputUnitProperty_CurrentDevice property - if (driver->device_name == "Default") { - driver->set_device("Default"); + if (driver->output_device_name == "Default") { + driver->set_output_device("Default"); } return noErr; @@ -495,7 +495,7 @@ Error AudioDriverCoreAudio::capture_stop() { #ifdef MACOS_ENABLED -PackedStringArray AudioDriverCoreAudio::_get_device_list(bool capture) { +PackedStringArray AudioDriverCoreAudio::_get_device_list(bool input) { PackedStringArray list; list.push_back("Default"); @@ -514,7 +514,7 @@ PackedStringArray AudioDriverCoreAudio::_get_device_list(bool capture) { UInt32 deviceCount = size / sizeof(AudioDeviceID); for (UInt32 i = 0; i < deviceCount; i++) { - prop.mScope = capture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + prop.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; prop.mSelector = kAudioDevicePropertyStreamConfiguration; AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, nullptr, &size); @@ -555,10 +555,10 @@ PackedStringArray AudioDriverCoreAudio::_get_device_list(bool capture) { return list; } -void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { +void AudioDriverCoreAudio::_set_device(const String &output_device, bool input) { AudioDeviceID deviceId; bool found = false; - if (device != "Default") { + if (output_device != "Default") { AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDevices; @@ -573,7 +573,7 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { UInt32 deviceCount = size / sizeof(AudioDeviceID); for (UInt32 i = 0; i < deviceCount && !found; i++) { - prop.mScope = capture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + prop.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; prop.mSelector = kAudioDevicePropertyStreamConfiguration; AudioObjectGetPropertyDataSize(audioDevices[i], &prop, 0, nullptr, &size); @@ -602,7 +602,7 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { ERR_FAIL_NULL_MSG(buffer, "Out of memory."); if (CFStringGetCString(cfname, buffer, maxSize, kCFStringEncodingUTF8)) { String name = String::utf8(buffer) + " (" + itos(audioDevices[i]) + ")"; - if (name == device) { + if (name == output_device) { deviceId = audioDevices[i]; found = true; } @@ -618,7 +618,7 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { if (!found) { // If we haven't found the desired device get the system default one UInt32 size = sizeof(AudioDeviceID); - UInt32 elem = capture ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice; + UInt32 elem = input ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice; AudioObjectPropertyAddress property = { elem, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, nullptr, &size, &deviceId); @@ -628,10 +628,10 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { } if (found) { - OSStatus result = AudioUnitSetProperty(capture ? input_unit : audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); + OSStatus result = AudioUnitSetProperty(input ? input_unit : audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); ERR_FAIL_COND(result != noErr); - if (capture) { + if (input) { // Reset audio input to keep synchronization. input_position = 0; input_size = 0; @@ -639,34 +639,34 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { } } -PackedStringArray AudioDriverCoreAudio::get_device_list() { +PackedStringArray AudioDriverCoreAudio::get_output_device_list() { return _get_device_list(); } -String AudioDriverCoreAudio::get_device() { - return device_name; +String AudioDriverCoreAudio::get_output_device() { + return output_device_name; } -void AudioDriverCoreAudio::set_device(String device) { - device_name = device; +void AudioDriverCoreAudio::set_output_device(String output_device) { + output_device_name = output_device; if (active) { - _set_device(device_name); + _set_device(output_device_name); } } -void AudioDriverCoreAudio::capture_set_device(const String &p_name) { - capture_device_name = p_name; +void AudioDriverCoreAudio::set_input_device(const String &p_name) { + input_device_name = p_name; if (active) { - _set_device(capture_device_name, true); + _set_device(input_device_name, true); } } -PackedStringArray AudioDriverCoreAudio::capture_get_device_list() { +PackedStringArray AudioDriverCoreAudio::get_input_device_list() { return _get_device_list(true); } -String AudioDriverCoreAudio::capture_get_device() { - return capture_device_name; +String AudioDriverCoreAudio::get_input_device() { + return input_device_name; } #endif diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h index 675265757b..2b192e630e 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.h +++ b/drivers/coreaudio/audio_driver_coreaudio.h @@ -47,8 +47,8 @@ class AudioDriverCoreAudio : public AudioDriver { bool active = false; Mutex mutex; - String device_name = "Default"; - String capture_device_name = "Default"; + String output_device_name = "Default"; + String input_device_name = "Default"; int mix_rate = 0; unsigned int channels = 2; @@ -60,7 +60,7 @@ class AudioDriverCoreAudio : public AudioDriver { #ifdef MACOS_ENABLED PackedStringArray _get_device_list(bool capture = false); - void _set_device(const String &device, bool capture = false); + void _set_device(const String &output_device, bool capture = false); static OSStatus input_device_address_cb(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, @@ -107,13 +107,13 @@ public: void stop(); #ifdef MACOS_ENABLED - virtual PackedStringArray get_device_list(); - virtual String get_device(); - virtual void set_device(String device); + virtual PackedStringArray get_output_device_list(); + virtual String get_output_device(); + virtual void set_output_device(String output_device); - virtual PackedStringArray capture_get_device_list(); - virtual void capture_set_device(const String &p_name); - virtual String capture_get_device(); + virtual PackedStringArray get_input_device_list(); + virtual void set_input_device(const String &p_name); + virtual String get_input_device(); #endif AudioDriverCoreAudio(); diff --git a/drivers/gles3/environment/fog.cpp b/drivers/gles3/environment/fog.cpp index 87470b454b..6083c4da46 100644 --- a/drivers/gles3/environment/fog.cpp +++ b/drivers/gles3/environment/fog.cpp @@ -49,7 +49,7 @@ void Fog::fog_volume_free(RID p_rid) { void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { } -void Fog::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) { +void Fog::fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) { } void Fog::fog_volume_set_material(RID p_fog_volume, RID p_material) { diff --git a/drivers/gles3/environment/fog.h b/drivers/gles3/environment/fog.h index 99f2e27c44..7dc0265917 100644 --- a/drivers/gles3/environment/fog.h +++ b/drivers/gles3/environment/fog.h @@ -49,7 +49,7 @@ public: virtual void fog_volume_free(RID p_rid) override; virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override; - virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override; + virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) override; virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override; virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override; virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override; diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index c65c396591..7f381b3f3e 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -1499,6 +1499,9 @@ void RasterizerCanvasGLES3::light_set_texture(RID p_rid, RID p_texture) { if (cl->texture == p_texture) { return; } + + ERR_FAIL_COND(p_texture.is_valid() && !texture_storage->owns_texture(p_texture)); + if (cl->texture.is_valid()) { texture_storage->texture_remove_from_texture_atlas(cl->texture); } diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 949f2953d3..1a18f35e64 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -731,6 +731,11 @@ void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, cons } } + if (p_render_data->view_count > 1) { + glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MULTIVIEW_UNIFORM_LOCATION, scene_state.multiview_buffer); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + if (!sky->radiance) { _invalidate_sky(sky); _update_dirty_skys(); @@ -738,7 +743,7 @@ void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, cons } } -void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier) { +void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier, bool p_use_multiview, bool p_flip_y) { GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); @@ -748,6 +753,11 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, GLES3::SkyMaterialData *material_data = nullptr; RID sky_material; + uint64_t spec_constants = p_use_multiview ? SkyShaderGLES3::USE_MULTIVIEW : 0; + if (p_flip_y) { + spec_constants |= SkyShaderGLES3::USE_INVERTED_Y; + } + RS::EnvironmentBG background = environment_get_background(p_env); if (sky) { @@ -792,16 +802,21 @@ void RasterizerSceneGLES3::_draw_sky(RID p_env, const Projection &p_projection, sky_transform.invert(); sky_transform = sky_transform * p_transform.basis; - bool success = material_storage->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); + bool success = material_storage->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); if (!success) { return; } - material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, sky_transform, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); - material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.columns[2][0], camera.columns[0][0], camera.columns[2][1], camera.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); - material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); - material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); - material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, sky_transform, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.columns[2][0], camera.columns[0][0], camera.columns[2][1], camera.columns[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + material_storage->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::LUMINANCE_MULTIPLIER, p_luminance_multiplier, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND, spec_constants); + + if (p_use_multiview) { + glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MULTIVIEW_UNIFORM_LOCATION, scene_state.multiview_buffer); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } glBindVertexArray(sky_globals.screen_triangle_array); glDrawArrays(GL_TRIANGLES, 0, 3); @@ -1975,7 +1990,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ scene_state.current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_DISABLED; scene_state.cull_mode = GLES3::SceneShaderData::CULL_BACK; - _draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform, sky_energy_multiplier); + _draw_sky(render_data.environment, render_data.cam_projection, render_data.cam_transform, sky_energy_multiplier, p_camera_data->view_count > 1, flip_y); } RENDER_TIMESTAMP("Render 3D Transparent Pass"); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 7977e562c0..ff043d67f6 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -83,6 +83,7 @@ enum SkyUniformLocation { SKY_EMPTY, // Unused, put here to avoid conflicts with SCENE_DATA_UNIFORM_LOCATION. SKY_MATERIAL_UNIFORM_LOCATION, SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION, + SKY_MULTIVIEW_UNIFORM_LOCATION, }; struct RenderDataGLES3 { @@ -570,7 +571,7 @@ protected: void _update_dirty_skys(); void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier); void _filter_sky_radiance(Sky *p_sky, int p_base_layer); - void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier); + void _draw_sky(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier, bool p_use_multiview, bool p_flip_y); void _free_sky_data(Sky *p_sky); public: diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index f977c8ceaf..0b389b0478 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -268,9 +268,11 @@ void main() { #ifdef USE_MULTIVIEW mat4 projection_matrix = multiview_data.projection_matrix_view[ViewIndex]; mat4 inv_projection_matrix = multiview_data.inv_projection_matrix_view[ViewIndex]; + vec3 eye_offset = multiview_data.eye_offset[ViewIndex].xyz; #else mat4 projection_matrix = scene_data.projection_matrix; mat4 inv_projection_matrix = scene_data.inv_projection_matrix; + vec3 eye_offset = vec3(0.0, 0.0, 0.0); #endif //USE_MULTIVIEW #ifdef USE_INSTANCING @@ -930,10 +932,12 @@ void main() { //lay out everything, whatever is unused is optimized away anyway vec3 vertex = vertex_interp; #ifdef USE_MULTIVIEW - vec3 view = -normalize(vertex_interp - multiview_data.eye_offset[ViewIndex].xyz); + vec3 eye_offset = multiview_data.eye_offset[ViewIndex].xyz; + vec3 view = -normalize(vertex_interp - eye_offset); mat4 projection_matrix = multiview_data.projection_matrix_view[ViewIndex]; mat4 inv_projection_matrix = multiview_data.inv_projection_matrix_view[ViewIndex]; #else + vec3 eye_offset = vec3(0.0, 0.0, 0.0); vec3 view = -normalize(vertex_interp); mat4 projection_matrix = scene_data.projection_matrix; mat4 inv_projection_matrix = scene_data.inv_projection_matrix; diff --git a/drivers/gles3/shaders/sky.glsl b/drivers/gles3/shaders/sky.glsl index 4c0fe47f6b..e59bca8b07 100644 --- a/drivers/gles3/shaders/sky.glsl +++ b/drivers/gles3/shaders/sky.glsl @@ -10,6 +10,9 @@ mode_cubemap_quarter_res = #define USE_CUBEMAP_PASS \n#define USE_QUARTER_RES_PA #[specializations] +USE_MULTIVIEW = false +USE_INVERTED_Y = true + #[vertex] layout(location = 0) in vec2 vertex_attrib; @@ -19,7 +22,11 @@ out vec2 uv_interp; void main() { uv_interp = vertex_attrib; +#ifdef USE_INVERTED_Y gl_Position = vec4(uv_interp, 1.0, 1.0); +#else + gl_Position = vec4(uv_interp.x, uv_interp.y * -1.0, 1.0, 1.0); +#endif } /* clang-format off */ @@ -37,6 +44,9 @@ uniform samplerCube radiance; //texunit:-1 #ifdef USE_CUBEMAP_PASS uniform samplerCube half_res; //texunit:-2 uniform samplerCube quarter_res; //texunit:-3 +#elif defined(USE_MULTIVIEW) +uniform sampler2DArray half_res; //texunit:-2 +uniform sampler2DArray quarter_res; //texunit:-3 #else uniform sampler2D half_res; //texunit:-2 uniform sampler2D quarter_res; //texunit:-3 @@ -102,6 +112,15 @@ uniform float fog_density; uniform float z_far; uniform uint directional_light_count; +#ifdef USE_MULTIVIEW +layout(std140) uniform MultiviewData { // ubo:5 + highp mat4 projection_matrix_view[MAX_VIEWS]; + highp mat4 inv_projection_matrix_view[MAX_VIEWS]; + highp vec4 eye_offset[MAX_VIEWS]; +} +multiview_data; +#endif + layout(location = 0) out vec4 frag_color; #ifdef USE_DEBANDING @@ -115,9 +134,20 @@ vec3 interleaved_gradient_noise(vec2 pos) { void main() { vec3 cube_normal; +#ifdef USE_MULTIVIEW + // In multiview our projection matrices will contain positional and rotational offsets that we need to properly unproject. + vec4 unproject = vec4(uv_interp.x, uv_interp.y, 1.0, 1.0); + vec4 unprojected = multiview_data.inv_projection_matrix_view[ViewIndex] * unproject; + cube_normal = unprojected.xyz / unprojected.w; + cube_normal += multiview_data.eye_offset[ViewIndex].xyz; +#else cube_normal.z = -1.0; cube_normal.x = (uv_interp.x + projection.x) / projection.y; cube_normal.y = (-uv_interp.y - projection.z) / projection.w; +#endif +#ifndef USE_INVERTED_Y + cube_normal.y *= -1.0; +#endif cube_normal = mat3(orientation) * cube_normal; cube_normal = normalize(cube_normal); @@ -146,12 +176,20 @@ void main() { #endif #else #ifdef USES_HALF_RES_COLOR +#ifdef USE_MULTIVIEW + half_res_color = textureLod(sampler2DArray(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(uv, ViewIndex), 0.0); +#else half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); #endif +#endif #ifdef USES_QUARTER_RES_COLOR +#ifdef USE_MULTIVIEW + quarter_res_color = textureLod(sampler2DArray(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(uv, ViewIndex), 0.0); +#else quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); #endif #endif +#endif { diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp index a325f79d8c..138498220d 100644 --- a/drivers/gles3/storage/light_storage.cpp +++ b/drivers/gles3/storage/light_storage.cpp @@ -403,7 +403,7 @@ void LightStorage::reflection_probe_set_ambient_energy(RID p_probe, float p_ener void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distance) { } -void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { +void LightStorage::reflection_probe_set_size(RID p_probe, const Vector3 &p_size) { } void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { @@ -436,7 +436,7 @@ uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const { return 0; } -Vector3 LightStorage::reflection_probe_get_extents(RID p_probe) const { +Vector3 LightStorage::reflection_probe_get_size(RID p_probe) const { return Vector3(); } diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h index 8b2bdaf872..f6f7628a90 100644 --- a/drivers/gles3/storage/light_storage.h +++ b/drivers/gles3/storage/light_storage.h @@ -113,7 +113,7 @@ struct ReflectionProbe { Color ambient_color; float ambient_color_energy = 1.0; float max_distance = 0; - Vector3 extents = Vector3(10, 10, 10); + Vector3 size = Vector3(20, 20, 20); Vector3 origin_offset; bool interior = false; bool box_projection = false; @@ -332,7 +332,7 @@ public: virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override; virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override; virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override; - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override; + virtual void reflection_probe_set_size(RID p_probe, const Vector3 &p_size) override; virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override; virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override; virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override; @@ -345,7 +345,7 @@ public: virtual AABB reflection_probe_get_aabb(RID p_probe) const override; virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override; virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override; - virtual Vector3 reflection_probe_get_extents(RID p_probe) const override; + virtual Vector3 reflection_probe_get_size(RID p_probe) const override; virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override; virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override; virtual bool reflection_probe_renders_shadows(RID p_probe) const override; diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 4fb780b665..aa8df606cf 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1639,6 +1639,7 @@ MaterialStorage::MaterialStorage() { actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "uint(0)"; actions.renames["VIEW_RIGHT"] = "uint(1)"; + actions.renames["EYE_OFFSET"] = "eye_offset"; //for light actions.renames["VIEW"] = "view"; diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index 97698af0a0..9c9c39cc0e 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -1547,7 +1547,7 @@ RID TextureStorage::decal_allocate() { void TextureStorage::decal_initialize(RID p_rid) { } -void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) { +void TextureStorage::decal_set_size(RID p_decal, const Vector3 &p_size) { } void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) { @@ -1822,6 +1822,10 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { rt->overridden.color = RID(); } else if (rt->color) { glDeleteTextures(1, &rt->color); + if (rt->texture.is_valid()) { + Texture *tex = get_texture(rt->texture); + tex->tex_id = 0; + } } rt->color = 0; diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index 522be64d35..017e74fc4d 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -574,7 +574,7 @@ public: virtual void decal_initialize(RID p_rid) override; virtual void decal_free(RID p_rid) override{}; - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override; + virtual void decal_set_size(RID p_decal, const Vector3 &p_size) override; virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override; virtual void decal_set_emission_energy(RID p_decal, float p_energy) override; virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index e14c3c7f7a..f96247a473 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -106,15 +106,15 @@ void AudioDriverPulseAudio::pa_server_info_cb(pa_context *c, const pa_server_inf ERR_FAIL_COND_MSG(!i, "PulseAudio server info is null."); AudioDriverPulseAudio *ad = static_cast<AudioDriverPulseAudio *>(userdata); - ad->capture_default_device = i->default_source_name; - ad->default_device = i->default_sink_name; + ad->default_input_device = i->default_source_name; + ad->default_output_device = i->default_sink_name; ad->pa_status++; } -Error AudioDriverPulseAudio::detect_channels(bool capture) { - pa_channel_map_init_stereo(capture ? &pa_rec_map : &pa_map); +Error AudioDriverPulseAudio::detect_channels(bool input) { + pa_channel_map_init_stereo(input ? &pa_rec_map : &pa_map); - String device = capture ? capture_device_name : device_name; + String device = input ? input_device_name : output_device_name; if (device == "Default") { // Get the default output device name pa_status = 0; @@ -136,7 +136,7 @@ Error AudioDriverPulseAudio::detect_channels(bool capture) { char dev[1024]; if (device == "Default") { - strcpy(dev, capture ? capture_default_device.utf8().get_data() : default_device.utf8().get_data()); + strcpy(dev, input ? default_input_device.utf8().get_data() : default_output_device.utf8().get_data()); } else { strcpy(dev, device.utf8().get_data()); } @@ -145,7 +145,7 @@ Error AudioDriverPulseAudio::detect_channels(bool capture) { // Now using the device name get the amount of channels pa_status = 0; pa_operation *pa_op; - if (capture) { + if (input) { pa_op = pa_context_get_source_info_by_name(pa_ctx, dev, &AudioDriverPulseAudio::pa_source_info_cb, (void *)this); } else { pa_op = pa_context_get_sink_info_by_name(pa_ctx, dev, &AudioDriverPulseAudio::pa_sink_info_cb, (void *)this); @@ -165,7 +165,7 @@ Error AudioDriverPulseAudio::detect_channels(bool capture) { return FAILED; } } else { - if (capture) { + if (input) { ERR_PRINT("pa_context_get_source_info_by_name error"); } else { ERR_PRINT("pa_context_get_sink_info_by_name error"); @@ -175,13 +175,13 @@ Error AudioDriverPulseAudio::detect_channels(bool capture) { return OK; } -Error AudioDriverPulseAudio::init_device() { - // If there is a specified device check that it is really present - if (device_name != "Default") { - PackedStringArray list = get_device_list(); - if (list.find(device_name) == -1) { - device_name = "Default"; - new_device = "Default"; +Error AudioDriverPulseAudio::init_output_device() { + // If there is a specified output device, check that it is really present + if (output_device_name != "Default") { + PackedStringArray list = get_output_device_list(); + if (list.find(output_device_name) == -1) { + output_device_name = "Default"; + new_output_device = "Default"; } } @@ -192,7 +192,7 @@ Error AudioDriverPulseAudio::init_device() { Error err = detect_channels(); if (err != OK) { // This most likely means there are no sinks. - ERR_PRINT("PulseAudio: init device failed to detect number of output channels"); + ERR_PRINT("PulseAudio: init_output_device failed to detect number of output channels"); return err; } @@ -256,7 +256,7 @@ Error AudioDriverPulseAudio::init_device() { attr.maxlength = (uint32_t)-1; attr.minreq = (uint32_t)-1; - const char *dev = device_name == "Default" ? nullptr : device_name.utf8().get_data(); + const char *dev = output_device_name == "Default" ? nullptr : output_device_name.utf8().get_data(); pa_stream_flags flags = pa_stream_flags(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE); int error_code = pa_stream_connect_playback(pa_str, dev, &attr, flags, nullptr, nullptr); ERR_FAIL_COND_V(error_code < 0, ERR_CANT_OPEN); @@ -346,7 +346,7 @@ Error AudioDriverPulseAudio::init() { return ERR_CANT_OPEN; } - init_device(); + init_output_device(); thread.start(AudioDriverPulseAudio::thread_func, this); return OK; @@ -448,18 +448,18 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { } } - // User selected a new device, finish the current one so we'll init the new device - if (ad->device_name != ad->new_device) { - ad->device_name = ad->new_device; - ad->finish_device(); + // User selected a new output device, finish the current one so we'll init the new output device + if (ad->output_device_name != ad->new_output_device) { + ad->output_device_name = ad->new_output_device; + ad->finish_output_device(); - Error err = ad->init_device(); + Error err = ad->init_output_device(); if (err != OK) { - ERR_PRINT("PulseAudio: init_device error"); - ad->device_name = "Default"; - ad->new_device = "Default"; + ERR_PRINT("PulseAudio: init_output_device error"); + ad->output_device_name = "Default"; + ad->new_output_device = "Default"; - err = ad->init_device(); + err = ad->init_output_device(); if (err != OK) { ad->active.clear(); ad->exit_thread.set(); @@ -471,11 +471,11 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { write_ofs = 0; } - // If we're using the default device check that the current device is still the default - if (ad->device_name == "Default") { + // If we're using the default output device, check that the current output device is still the default + if (ad->output_device_name == "Default") { uint64_t msec = OS::get_singleton()->get_ticks_msec(); if (msec > (default_device_msec + 1000)) { - String old_default_device = ad->default_device; + String old_default_device = ad->default_output_device; default_device_msec = msec; @@ -494,12 +494,12 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { ERR_PRINT("pa_context_get_server_info error: " + String(pa_strerror(pa_context_errno(ad->pa_ctx)))); } - if (old_default_device != ad->default_device) { - ad->finish_device(); + if (old_default_device != ad->default_output_device) { + ad->finish_output_device(); - Error err = ad->init_device(); + Error err = ad->init_output_device(); if (err != OK) { - ERR_PRINT("PulseAudio: init_device error"); + ERR_PRINT("PulseAudio: init_output_device error"); ad->active.clear(); ad->exit_thread.set(); break; @@ -541,18 +541,18 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { } } - // User selected a new device, finish the current one so we'll init the new device - if (ad->capture_device_name != ad->capture_new_device) { - ad->capture_device_name = ad->capture_new_device; - ad->capture_finish_device(); + // User selected a new input device, finish the current one so we'll init the new input device + if (ad->input_device_name != ad->new_input_device) { + ad->input_device_name = ad->new_input_device; + ad->finish_input_device(); - Error err = ad->capture_init_device(); + Error err = ad->init_input_device(); if (err != OK) { - ERR_PRINT("PulseAudio: capture_init_device error"); - ad->capture_device_name = "Default"; - ad->capture_new_device = "Default"; + ERR_PRINT("PulseAudio: init_input_device error"); + ad->input_device_name = "Default"; + ad->new_input_device = "Default"; - err = ad->capture_init_device(); + err = ad->init_input_device(); if (err != OK) { ad->active.clear(); ad->exit_thread.set(); @@ -596,7 +596,7 @@ void AudioDriverPulseAudio::pa_sinklist_cb(pa_context *c, const pa_sink_info *l, ad->pa_status++; } -PackedStringArray AudioDriverPulseAudio::get_device_list() { +PackedStringArray AudioDriverPulseAudio::get_output_device_list() { pa_devices.clear(); pa_devices.push_back("Default"); @@ -606,7 +606,7 @@ PackedStringArray AudioDriverPulseAudio::get_device_list() { lock(); - // Get the device list + // Get the output device list pa_status = 0; pa_operation *pa_op = pa_context_get_sink_info_list(pa_ctx, pa_sinklist_cb, (void *)this); if (pa_op) { @@ -627,13 +627,13 @@ PackedStringArray AudioDriverPulseAudio::get_device_list() { return pa_devices; } -String AudioDriverPulseAudio::get_device() { - return device_name; +String AudioDriverPulseAudio::get_output_device() { + return output_device_name; } -void AudioDriverPulseAudio::set_device(String device) { +void AudioDriverPulseAudio::set_output_device(String output_device) { lock(); - new_device = device; + new_output_device = output_device; unlock(); } @@ -645,7 +645,7 @@ void AudioDriverPulseAudio::unlock() { mutex.unlock(); } -void AudioDriverPulseAudio::finish_device() { +void AudioDriverPulseAudio::finish_output_device() { if (pa_str) { pa_stream_disconnect(pa_str); pa_stream_unref(pa_str); @@ -661,7 +661,7 @@ void AudioDriverPulseAudio::finish() { exit_thread.set(); thread.wait_to_finish(); - finish_device(); + finish_output_device(); if (pa_ctx) { pa_context_disconnect(pa_ctx); @@ -675,13 +675,13 @@ void AudioDriverPulseAudio::finish() { } } -Error AudioDriverPulseAudio::capture_init_device() { - // If there is a specified device check that it is really present - if (capture_device_name != "Default") { - PackedStringArray list = capture_get_device_list(); - if (list.find(capture_device_name) == -1) { - capture_device_name = "Default"; - capture_new_device = "Default"; +Error AudioDriverPulseAudio::init_input_device() { + // If there is a specified input device, check that it is really present + if (input_device_name != "Default") { + PackedStringArray list = get_input_device_list(); + if (list.find(input_device_name) == -1) { + input_device_name = "Default"; + new_input_device = "Default"; } } @@ -718,7 +718,7 @@ Error AudioDriverPulseAudio::capture_init_device() { ERR_FAIL_V(ERR_CANT_OPEN); } - const char *dev = capture_device_name == "Default" ? nullptr : capture_device_name.utf8().get_data(); + const char *dev = input_device_name == "Default" ? nullptr : input_device_name.utf8().get_data(); pa_stream_flags flags = pa_stream_flags(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE); int error_code = pa_stream_connect_record(pa_rec_str, dev, &attr, flags); if (error_code < 0) { @@ -734,7 +734,7 @@ Error AudioDriverPulseAudio::capture_init_device() { return OK; } -void AudioDriverPulseAudio::capture_finish_device() { +void AudioDriverPulseAudio::finish_input_device() { if (pa_rec_str) { int ret = pa_stream_disconnect(pa_rec_str); if (ret != 0) { @@ -745,25 +745,25 @@ void AudioDriverPulseAudio::capture_finish_device() { } } -Error AudioDriverPulseAudio::capture_start() { +Error AudioDriverPulseAudio::input_start() { lock(); - Error err = capture_init_device(); + Error err = init_input_device(); unlock(); return err; } -Error AudioDriverPulseAudio::capture_stop() { +Error AudioDriverPulseAudio::input_stop() { lock(); - capture_finish_device(); + finish_input_device(); unlock(); return OK; } -void AudioDriverPulseAudio::capture_set_device(const String &p_name) { +void AudioDriverPulseAudio::set_input_device(const String &p_name) { lock(); - capture_new_device = p_name; + new_input_device = p_name; unlock(); } @@ -782,7 +782,7 @@ void AudioDriverPulseAudio::pa_sourcelist_cb(pa_context *c, const pa_source_info ad->pa_status++; } -PackedStringArray AudioDriverPulseAudio::capture_get_device_list() { +PackedStringArray AudioDriverPulseAudio::get_input_device_list() { pa_rec_devices.clear(); pa_rec_devices.push_back("Default"); @@ -813,9 +813,9 @@ PackedStringArray AudioDriverPulseAudio::capture_get_device_list() { return pa_rec_devices; } -String AudioDriverPulseAudio::capture_get_device() { +String AudioDriverPulseAudio::get_input_device() { lock(); - String name = capture_device_name; + String name = input_device_name; unlock(); return name; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h index 16398e67eb..68df03cb60 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.h +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -51,13 +51,13 @@ class AudioDriverPulseAudio : public AudioDriver { pa_channel_map pa_map = {}; pa_channel_map pa_rec_map = {}; - String device_name = "Default"; - String new_device = "Default"; - String default_device; + String output_device_name = "Default"; + String new_output_device = "Default"; + String default_output_device; - String capture_device_name; - String capture_new_device; - String capture_default_device; + String input_device_name; + String new_input_device; + String default_input_device; Vector<int32_t> samples_in; Vector<int16_t> samples_out; @@ -83,11 +83,11 @@ class AudioDriverPulseAudio : public AudioDriver { static void pa_sinklist_cb(pa_context *c, const pa_sink_info *l, int eol, void *userdata); static void pa_sourcelist_cb(pa_context *c, const pa_source_info *l, int eol, void *userdata); - Error init_device(); - void finish_device(); + Error init_output_device(); + void finish_output_device(); - Error capture_init_device(); - void capture_finish_device(); + Error init_input_device(); + void finish_input_device(); Error detect_channels(bool capture = false); @@ -103,13 +103,13 @@ public: virtual int get_mix_rate() const; virtual SpeakerMode get_speaker_mode() const; - virtual PackedStringArray get_device_list(); - virtual String get_device(); - virtual void set_device(String device); + virtual PackedStringArray get_output_device_list(); + virtual String get_output_device(); + virtual void set_output_device(String output_device); - virtual PackedStringArray capture_get_device_list(); - virtual void capture_set_device(const String &p_name); - virtual String capture_get_device(); + virtual PackedStringArray get_input_device_list(); + virtual void set_input_device(const String &p_name); + virtual String get_input_device(); virtual void lock(); virtual void unlock(); @@ -117,8 +117,8 @@ public: virtual float get_latency(); - virtual Error capture_start(); - virtual Error capture_stop(); + virtual Error input_start(); + virtual Error input_stop(); AudioDriverPulseAudio(); ~AudioDriverPulseAudio() {} diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index b2745b1e86..42a2b85200 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -118,8 +118,8 @@ const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient); #define CAPTURE_BUFFER_CHANNELS 2 -static bool default_render_device_changed = false; -static bool default_capture_device_changed = false; +static bool default_output_device_changed = false; +static bool default_input_device_changed = false; // Silence warning due to a COM API weirdness (GH-35194). #if defined(__GNUC__) && !defined(__clang__) @@ -181,9 +181,9 @@ public: HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId) { if (role == eConsole) { if (flow == eRender) { - default_render_device_changed = true; + default_output_device_changed = true; } else if (flow == eCapture) { - default_capture_device_changed = true; + default_input_device_changed = true; } } @@ -201,10 +201,10 @@ public: static CMMNotificationClient notif_client; -Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_capture, bool p_reinit, bool p_no_audio_client_3) { +Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_input, bool p_reinit, bool p_no_audio_client_3) { WAVEFORMATEX *pwfex; IMMDeviceEnumerator *enumerator = nullptr; - IMMDevice *device = nullptr; + IMMDevice *output_device = nullptr; CoInitialize(nullptr); @@ -212,11 +212,11 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); if (p_device->device_name == "Default") { - hr = enumerator->GetDefaultAudioEndpoint(p_capture ? eCapture : eRender, eConsole, &device); + hr = enumerator->GetDefaultAudioEndpoint(p_input ? eCapture : eRender, eConsole, &output_device); } else { IMMDeviceCollection *devices = nullptr; - hr = enumerator->EnumAudioEndpoints(p_capture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices); + hr = enumerator->EnumAudioEndpoints(p_input ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); LPWSTR strId = nullptr; @@ -255,20 +255,20 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c } if (found) { - hr = enumerator->GetDevice(strId, &device); + hr = enumerator->GetDevice(strId, &output_device); } if (strId) { CoTaskMemFree(strId); } - if (device == nullptr) { - hr = enumerator->GetDefaultAudioEndpoint(p_capture ? eCapture : eRender, eConsole, &device); + if (output_device == nullptr) { + hr = enumerator->GetDefaultAudioEndpoint(p_input ? eCapture : eRender, eConsole, &output_device); } } if (p_reinit) { - // In case we're trying to re-initialize the device prevent throwing this error on the console, + // In case we're trying to re-initialize the device, prevent throwing this error on the console, // otherwise if there is currently no device available this will spam the console. if (hr != S_OK) { return ERR_CANT_OPEN; @@ -284,28 +284,28 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c ERR_PRINT("WASAPI: RegisterEndpointNotificationCallback error"); } - using_audio_client_3 = !p_capture; // IID_IAudioClient3 is only used for adjustable output latency (not input) + using_audio_client_3 = !p_input; // IID_IAudioClient3 is only used for adjustable output latency (not input) if (p_no_audio_client_3) { using_audio_client_3 = false; } if (using_audio_client_3) { - hr = device->Activate(IID_IAudioClient3, CLSCTX_ALL, nullptr, (void **)&p_device->audio_client); + hr = output_device->Activate(IID_IAudioClient3, CLSCTX_ALL, nullptr, (void **)&p_device->audio_client); if (hr != S_OK) { // IID_IAudioClient3 will never activate on OS versions before Windows 10. // Older Windows versions should fall back gracefully. using_audio_client_3 = false; - print_verbose("WASAPI: Couldn't activate device with IAudioClient3 interface, falling back to IAudioClient interface"); + print_verbose("WASAPI: Couldn't activate output_device with IAudioClient3 interface, falling back to IAudioClient interface"); } else { - print_verbose("WASAPI: Activated device using IAudioClient3 interface"); + print_verbose("WASAPI: Activated output_device using IAudioClient3 interface"); } } if (!using_audio_client_3) { - hr = device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, (void **)&p_device->audio_client); + hr = output_device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, (void **)&p_device->audio_client); } - SAFE_RELEASE(device) + SAFE_RELEASE(output_device) if (p_reinit) { if (hr != S_OK) { @@ -339,7 +339,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c WAVEFORMATEX *closest = nullptr; hr = p_device->audio_client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, pwfex, &closest); if (hr == S_FALSE) { - WARN_PRINT("WASAPI: Mix format is not supported by the Device"); + WARN_PRINT("WASAPI: Mix format is not supported by the output_device"); if (closest) { print_verbose("WASAPI: closest->wFormatTag = " + itos(closest->wFormatTag)); print_verbose("WASAPI: closest->nChannels = " + itos(closest->nChannels)); @@ -385,14 +385,14 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c pwfex->nSamplesPerSec = mix_rate; pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nChannels * (pwfex->wBitsPerSample / 8); } - hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_capture ? REFTIMES_PER_SEC : 0, 0, pwfex, nullptr); + hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_input ? REFTIMES_PER_SEC : 0, 0, pwfex, nullptr); ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_CANT_OPEN, "WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16) + "."); UINT32 max_frames; hr = p_device->audio_client->GetBufferSize(&max_frames); ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN); // Due to WASAPI Shared Mode we have no control of the buffer size - if (!p_capture) { + if (!p_input) { buffer_frames = max_frames; int64_t latency = 0; @@ -421,8 +421,8 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c if (hr != S_OK) { print_verbose("WASAPI: GetSharedModeEnginePeriod failed with error 0x" + String::num_uint64(hr, 16) + ", falling back to IAudioClient."); CoTaskMemFree(pwfex); - SAFE_RELEASE(device) - return audio_device_init(p_device, p_capture, p_reinit, true); + SAFE_RELEASE(output_device) + return audio_device_init(p_device, p_input, p_reinit, true); } // Period frames must be an integral multiple of fundamental_period_frames or IAudioClient3 initialization will fail, @@ -443,8 +443,8 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c if (hr != S_OK) { print_verbose("WASAPI: InitializeSharedAudioStream failed with error 0x" + String::num_uint64(hr, 16) + ", falling back to IAudioClient."); CoTaskMemFree(pwfex); - SAFE_RELEASE(device); - return audio_device_init(p_device, p_capture, p_reinit, true); + SAFE_RELEASE(output_device); + return audio_device_init(p_device, p_input, p_reinit, true); } else { uint32_t output_latency_in_frames; WAVEFORMATEX *current_pwfex; @@ -455,13 +455,13 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c } else { print_verbose("WASAPI: GetCurrentSharedModeEnginePeriod failed with error 0x" + String::num_uint64(hr, 16) + ", falling back to IAudioClient."); CoTaskMemFree(pwfex); - SAFE_RELEASE(device); - return audio_device_init(p_device, p_capture, p_reinit, true); + SAFE_RELEASE(output_device); + return audio_device_init(p_device, p_input, p_reinit, true); } } } - if (p_capture) { + if (p_input) { hr = p_device->audio_client->GetService(IID_IAudioCaptureClient, (void **)&p_device->capture_client); } else { hr = p_device->audio_client->GetService(IID_IAudioRenderClient, (void **)&p_device->render_client); @@ -470,12 +470,12 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c // Free memory CoTaskMemFree(pwfex); - SAFE_RELEASE(device) + SAFE_RELEASE(output_device) return OK; } -Error AudioDriverWASAPI::init_render_device(bool p_reinit) { +Error AudioDriverWASAPI::init_output_device(bool p_reinit) { Error err = audio_device_init(&audio_output, false, p_reinit); if (err != OK) { return err; @@ -507,7 +507,7 @@ Error AudioDriverWASAPI::init_render_device(bool p_reinit) { return OK; } -Error AudioDriverWASAPI::init_capture_device(bool p_reinit) { +Error AudioDriverWASAPI::init_input_device(bool p_reinit) { Error err = audio_device_init(&audio_input, true, p_reinit); if (err != OK) { return err; @@ -538,11 +538,11 @@ Error AudioDriverWASAPI::audio_device_finish(AudioDeviceWASAPI *p_device) { return OK; } -Error AudioDriverWASAPI::finish_render_device() { +Error AudioDriverWASAPI::finish_output_device() { return audio_device_finish(&audio_output); } -Error AudioDriverWASAPI::finish_capture_device() { +Error AudioDriverWASAPI::finish_input_device() { return audio_device_finish(&audio_input); } @@ -551,9 +551,9 @@ Error AudioDriverWASAPI::init() { target_latency_ms = GLOBAL_GET("audio/driver/output_latency"); - Error err = init_render_device(); + Error err = init_output_device(); if (err != OK) { - ERR_PRINT("WASAPI: init_render_device error"); + ERR_PRINT("WASAPI: init_output_device error"); } exit_thread.clear(); @@ -575,7 +575,7 @@ AudioDriver::SpeakerMode AudioDriverWASAPI::get_speaker_mode() const { return get_speaker_mode_by_total_channels(channels); } -PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_capture) { +PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_input) { PackedStringArray list; IMMDeviceCollection *devices = nullptr; IMMDeviceEnumerator *enumerator = nullptr; @@ -587,7 +587,7 @@ PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_capture) { HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&enumerator); ERR_FAIL_COND_V(hr != S_OK, PackedStringArray()); - hr = enumerator->EnumAudioEndpoints(p_capture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices); + hr = enumerator->EnumAudioEndpoints(p_input ? eCapture : eRender, DEVICE_STATE_ACTIVE, &devices); ERR_FAIL_COND_V(hr != S_OK, PackedStringArray()); UINT count = 0; @@ -595,13 +595,13 @@ PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_capture) { ERR_FAIL_COND_V(hr != S_OK, PackedStringArray()); for (ULONG i = 0; i < count; i++) { - IMMDevice *device = nullptr; + IMMDevice *output_device = nullptr; - hr = devices->Item(i, &device); + hr = devices->Item(i, &output_device); ERR_BREAK(hr != S_OK); IPropertyStore *props = nullptr; - hr = device->OpenPropertyStore(STGM_READ, &props); + hr = output_device->OpenPropertyStore(STGM_READ, &props); ERR_BREAK(hr != S_OK); PROPVARIANT propvar; @@ -614,7 +614,7 @@ PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_capture) { PropVariantClear(&propvar); props->Release(); - device->Release(); + output_device->Release(); } devices->Release(); @@ -622,11 +622,11 @@ PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_capture) { return list; } -PackedStringArray AudioDriverWASAPI::get_device_list() { +PackedStringArray AudioDriverWASAPI::get_output_device_list() { return audio_device_get_list(false); } -String AudioDriverWASAPI::get_device() { +String AudioDriverWASAPI::get_output_device() { lock(); String name = audio_output.device_name; unlock(); @@ -634,9 +634,9 @@ String AudioDriverWASAPI::get_device() { return name; } -void AudioDriverWASAPI::set_device(String device) { +void AudioDriverWASAPI::set_output_device(String output_device) { lock(); - audio_output.new_device = device; + audio_output.new_device = output_device; unlock(); } @@ -769,13 +769,13 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { avail_frames -= write_frames; written_frames += write_frames; } else if (hr == AUDCLNT_E_DEVICE_INVALIDATED) { - // Device is not valid anymore, reopen it + // output_device is not valid anymore, reopen it - Error err = ad->finish_render_device(); + Error err = ad->finish_output_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_render_device error"); + ERR_PRINT("WASAPI: finish_output_device error"); } else { - // We reopened the device and samples_in may have resized, so invalidate the current avail_frames + // We reopened the output device and samples_in may have resized, so invalidate the current avail_frames avail_frames = 0; } } else { @@ -790,37 +790,37 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { } if (invalidated) { - // Device is not valid anymore - WARN_PRINT("WASAPI: Current device invalidated, closing device"); + // output_device is not valid anymore + WARN_PRINT("WASAPI: Current output_device invalidated, closing output_device"); - Error err = ad->finish_render_device(); + Error err = ad->finish_output_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_render_device error"); + ERR_PRINT("WASAPI: finish_output_device error"); } } } - // If we're using the Default device and it changed finish it so we'll re-init the device - if (ad->audio_output.device_name == "Default" && default_render_device_changed) { - Error err = ad->finish_render_device(); + // If we're using the Default output device and it changed finish it so we'll re-init the output device + if (ad->audio_output.device_name == "Default" && default_output_device_changed) { + Error err = ad->finish_output_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_render_device error"); + ERR_PRINT("WASAPI: finish_output_device error"); } - default_render_device_changed = false; + default_output_device_changed = false; } - // User selected a new device, finish the current one so we'll init the new device + // User selected a new output device, finish the current one so we'll init the new output device if (ad->audio_output.device_name != ad->audio_output.new_device) { ad->audio_output.device_name = ad->audio_output.new_device; - Error err = ad->finish_render_device(); + Error err = ad->finish_output_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_render_device error"); + ERR_PRINT("WASAPI: finish_output_device error"); } } if (!ad->audio_output.audio_client) { - Error err = ad->init_render_device(true); + Error err = ad->init_output_device(true); if (err == OK) { ad->start(); } @@ -873,29 +873,29 @@ void AudioDriverWASAPI::thread_func(void *p_udata) { } } - // If we're using the Default device and it changed finish it so we'll re-init the device - if (ad->audio_input.device_name == "Default" && default_capture_device_changed) { - Error err = ad->finish_capture_device(); + // If we're using the Default output device and it changed finish it so we'll re-init the output device + if (ad->audio_input.device_name == "Default" && default_input_device_changed) { + Error err = ad->finish_input_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_capture_device error"); + ERR_PRINT("WASAPI: finish_input_device error"); } - default_capture_device_changed = false; + default_input_device_changed = false; } - // User selected a new device, finish the current one so we'll init the new device + // User selected a new input device, finish the current one so we'll init the new input device if (ad->audio_input.device_name != ad->audio_input.new_device) { ad->audio_input.device_name = ad->audio_input.new_device; - Error err = ad->finish_capture_device(); + Error err = ad->finish_input_device(); if (err != OK) { - ERR_PRINT("WASAPI: finish_capture_device error"); + ERR_PRINT("WASAPI: finish_input_device error"); } } if (!ad->audio_input.audio_client) { - Error err = ad->init_capture_device(true); + Error err = ad->init_input_device(true); if (err == OK) { - ad->capture_start(); + ad->input_start(); } } } @@ -933,14 +933,14 @@ void AudioDriverWASAPI::finish() { exit_thread.set(); thread.wait_to_finish(); - finish_capture_device(); - finish_render_device(); + finish_input_device(); + finish_output_device(); } -Error AudioDriverWASAPI::capture_start() { - Error err = init_capture_device(); +Error AudioDriverWASAPI::input_start() { + Error err = init_input_device(); if (err != OK) { - ERR_PRINT("WASAPI: init_capture_device error"); + ERR_PRINT("WASAPI: init_input_device error"); return err; } @@ -953,7 +953,7 @@ Error AudioDriverWASAPI::capture_start() { return OK; } -Error AudioDriverWASAPI::capture_stop() { +Error AudioDriverWASAPI::input_stop() { if (audio_input.active.is_set()) { audio_input.audio_client->Stop(); audio_input.active.clear(); @@ -964,17 +964,17 @@ Error AudioDriverWASAPI::capture_stop() { return FAILED; } -void AudioDriverWASAPI::capture_set_device(const String &p_name) { +void AudioDriverWASAPI::set_input_device(const String &p_name) { lock(); audio_input.new_device = p_name; unlock(); } -PackedStringArray AudioDriverWASAPI::capture_get_device_list() { +PackedStringArray AudioDriverWASAPI::get_input_device_list() { return audio_device_get_list(true); } -String AudioDriverWASAPI::capture_get_device() { +String AudioDriverWASAPI::get_input_device() { lock(); String name = audio_input.device_name; unlock(); diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h index 6eea24f78a..bf18ba8c99 100644 --- a/drivers/wasapi/audio_driver_wasapi.h +++ b/drivers/wasapi/audio_driver_wasapi.h @@ -47,8 +47,8 @@ class AudioDriverWASAPI : public AudioDriver { class AudioDeviceWASAPI { public: IAudioClient *audio_client = nullptr; - IAudioRenderClient *render_client = nullptr; - IAudioCaptureClient *capture_client = nullptr; + IAudioRenderClient *render_client = nullptr; // Output + IAudioCaptureClient *capture_client = nullptr; // Input SafeFlag active; WORD format_tag = 0; @@ -56,8 +56,8 @@ class AudioDriverWASAPI : public AudioDriver { unsigned int channels = 0; unsigned int frame_size = 0; - String device_name = "Default"; - String new_device = "Default"; + String device_name = "Default"; // Output OR Input + String new_device = "Default"; // Output OR Input AudioDeviceWASAPI() {} }; @@ -83,15 +83,15 @@ class AudioDriverWASAPI : public AudioDriver { static _FORCE_INLINE_ int32_t read_sample(WORD format_tag, int bits_per_sample, BYTE *buffer, int i); static void thread_func(void *p_udata); - Error init_render_device(bool p_reinit = false); - Error init_capture_device(bool p_reinit = false); + Error init_output_device(bool p_reinit = false); + Error init_input_device(bool p_reinit = false); - Error finish_render_device(); - Error finish_capture_device(); + Error finish_output_device(); + Error finish_input_device(); - Error audio_device_init(AudioDeviceWASAPI *p_device, bool p_capture, bool p_reinit, bool p_no_audio_client_3 = false); + Error audio_device_init(AudioDeviceWASAPI *p_device, bool p_input, bool p_reinit, bool p_no_audio_client_3 = false); Error audio_device_finish(AudioDeviceWASAPI *p_device); - PackedStringArray audio_device_get_list(bool p_capture); + PackedStringArray audio_device_get_list(bool p_input); public: virtual const char *get_name() const { @@ -103,18 +103,18 @@ public: virtual int get_mix_rate() const; virtual float get_latency(); virtual SpeakerMode get_speaker_mode() const; - virtual PackedStringArray get_device_list(); - virtual String get_device(); - virtual void set_device(String device); + virtual PackedStringArray get_output_device_list(); + virtual String get_output_device(); + virtual void set_output_device(String output_device); virtual void lock(); virtual void unlock(); virtual void finish(); - virtual Error capture_start(); - virtual Error capture_stop(); - virtual PackedStringArray capture_get_device_list(); - virtual void capture_set_device(const String &p_name); - virtual String capture_get_device(); + virtual Error input_start(); + virtual Error input_stop(); + virtual PackedStringArray get_input_device_list(); + virtual void set_input_device(const String &p_name); + virtual String get_input_device(); AudioDriverWASAPI(); }; diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index ae54c20fe2..146b5a794c 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -198,6 +198,14 @@ void ActionMapEditor::_tree_button_pressed(Object *p_item, int p_column, int p_i emit_signal(SNAME("action_edited"), action_name, action); } break; + case ActionMapEditor::BUTTON_REVERT_ACTION: { + ERR_FAIL_COND_MSG(!item->has_meta("__action_initial"), "Tree Item for action which can be reverted is expected to have meta value with initial value of action."); + + Dictionary action = item->get_meta("__action_initial").duplicate(); + String action_name = item->get_meta("__name"); + + emit_signal(SNAME("action_edited"), action_name, action); + } break; default: break; } @@ -427,6 +435,13 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info action_item->set_range(1, deadzone); // Third column - buttons + if (action_info.has_initial) { + bool deadzone_eq = action_info.action_initial["deadzone"] == action_info.action["deadzone"]; + bool events_eq = Shortcut::is_event_array_equal(action_info.action_initial["events"], action_info.action["events"]); + bool action_eq = deadzone_eq && events_eq; + action_item->set_meta("__action_initial", action_info.action_initial); + action_item->add_button(2, action_tree->get_theme_icon(SNAME("ReloadSmall"), SNAME("EditorIcons")), BUTTON_REVERT_ACTION, action_eq, action_eq ? TTR("Cannot Revert - Action is same as initial") : TTR("Revert Action")); + } action_item->add_button(2, action_tree->get_theme_icon(SNAME("Add"), SNAME("EditorIcons")), BUTTON_ADD_EVENT, false, TTR("Add Event")); action_item->add_button(2, action_tree->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), BUTTON_REMOVE_ACTION, !action_info.editable, action_info.editable ? TTR("Remove Action") : TTR("Cannot Remove Action")); diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h index 433a72a807..2848d23e83 100644 --- a/editor/action_map_editor.h +++ b/editor/action_map_editor.h @@ -49,6 +49,8 @@ public: struct ActionInfo { String name; Dictionary action; + bool has_initial = false; + Dictionary action_initial; Ref<Texture2D> icon = Ref<Texture2D>(); bool editable = true; @@ -60,6 +62,7 @@ private: BUTTON_EDIT_EVENT, BUTTON_REMOVE_ACTION, BUTTON_REMOVE_EVENT, + BUTTON_REVERT_ACTION, }; Vector<ActionInfo> actions_cache; diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 8dd087451c..ee4163bc14 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -2986,7 +2986,6 @@ bool AnimationTrackEdit::can_drop_data(const Point2 &p_point, const Variant &p_d } const_cast<AnimationTrackEdit *>(this)->queue_redraw(); - const_cast<AnimationTrackEdit *>(this)->emit_signal(SNAME("drop_attempted"), track); return true; } diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 28d687488c..b217cd57bf 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -670,7 +670,6 @@ void FindReplaceBar::set_text_edit(CodeTextEditor *p_text_editor) { void FindReplaceBar::_bind_methods() { ClassDB::bind_method("_search_current", &FindReplaceBar::search_current); - ADD_SIGNAL(MethodInfo("search")); ADD_SIGNAL(MethodInfo("error")); } diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index 5bdef32c60..d71ef78d88 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -461,7 +461,7 @@ void DocTools::generate(bool p_basic_types) { } if (default_value_valid && default_value.get_type() != Variant::OBJECT) { - prop.default_value = default_value.get_construct_string().replace("\n", " "); + prop.default_value = DocData::get_default_value_string(default_value); } StringName setter = ClassDB::get_property_setter(name, E.name); @@ -591,7 +591,7 @@ void DocTools::generate(bool p_basic_types) { tid.name = E; tid.type = "Color"; tid.data_type = "color"; - tid.default_value = Variant(ThemeDB::get_singleton()->get_default_theme()->get_color(E, cname)).get_construct_string().replace("\n", " "); + tid.default_value = DocData::get_default_value_string(ThemeDB::get_singleton()->get_default_theme()->get_color(E, cname)); c.theme_properties.push_back(tid); } @@ -772,8 +772,7 @@ void DocTools::generate(bool p_basic_types) { int darg_idx = mi.default_arguments.size() - mi.arguments.size() + j; if (darg_idx >= 0) { - Variant default_arg = mi.default_arguments[darg_idx]; - ad.default_value = default_arg.get_construct_string().replace("\n", " "); + ad.default_value = DocData::get_default_value_string(mi.default_arguments[darg_idx]); } method.arguments.push_back(ad); @@ -817,7 +816,7 @@ void DocTools::generate(bool p_basic_types) { DocData::PropertyDoc property; property.name = pi.name; property.type = Variant::get_type_name(pi.type); - property.default_value = v.get(pi.name).get_construct_string().replace("\n", " "); + property.default_value = DocData::get_default_value_string(v.get(pi.name)); c.properties.push_back(property); } @@ -948,8 +947,7 @@ void DocTools::generate(bool p_basic_types) { int darg_idx = j - (mi.arguments.size() - mi.default_arguments.size()); if (darg_idx >= 0) { - Variant default_arg = mi.default_arguments[darg_idx]; - ad.default_value = default_arg.get_construct_string().replace("\n", " "); + ad.default_value = DocData::get_default_value_string(mi.default_arguments[darg_idx]); } md.arguments.push_back(ad); @@ -993,8 +991,7 @@ void DocTools::generate(bool p_basic_types) { int darg_idx = j - (ai.arguments.size() - ai.default_arguments.size()); if (darg_idx >= 0) { - Variant default_arg = ai.default_arguments[darg_idx]; - ad.default_value = default_arg.get_construct_string().replace("\n", " "); + ad.default_value = DocData::get_default_value_string(ai.default_arguments[darg_idx]); } atd.arguments.push_back(ad); diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index bbd0a6bd70..4a1f0b4c09 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -620,12 +620,16 @@ void EditorFileDialog::_item_list_item_rmb_clicked(int p_item, const Vector2 &p_ if (allow_delete) { item_menu->add_icon_item(theme_cache.action_delete, TTR("Delete"), ITEM_MENU_DELETE, Key::KEY_DELETE); } + +#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) + // Opening the system file manager is not supported on the Android and web editors. if (single_item_selected) { item_menu->add_separator(); Dictionary item_meta = item_list->get_item_metadata(p_item); String item_text = item_meta["dir"] ? TTR("Open in File Manager") : TTR("Show in File Manager"); item_menu->add_icon_item(theme_cache.filesystem, item_text, ITEM_MENU_SHOW_IN_EXPLORER); } +#endif if (item_menu->get_item_count() > 0) { item_menu->set_position(item_list->get_screen_position() + p_pos); @@ -655,8 +659,11 @@ void EditorFileDialog::_item_list_empty_clicked(const Vector2 &p_pos, MouseButto item_menu->add_icon_item(theme_cache.folder, TTR("New Folder..."), ITEM_MENU_NEW_FOLDER, KeyModifierMask::CMD_OR_CTRL | Key::N); } item_menu->add_icon_item(theme_cache.reload, TTR("Refresh"), ITEM_MENU_REFRESH, Key::F5); +#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) + // Opening the system file manager is not supported on the Android and web editors. item_menu->add_separator(); item_menu->add_icon_item(theme_cache.filesystem, TTR("Open in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER); +#endif item_menu->set_position(item_list->get_screen_position() + p_pos); item_menu->reset_size(); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index ef33b82390..644c32e8a4 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1591,6 +1591,11 @@ void EditorFileSystem::_update_script_classes() { void EditorFileSystem::_update_pending_script_classes() { if (!update_script_paths.is_empty()) { _update_script_classes(); + } else { + // In case the class cache file was removed somehow, regenerate it. + if (!FileAccess::exists(ScriptServer::get_global_class_cache_file_path())) { + ScriptServer::save_global_classes(); + } } } diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index e11251596a..bb7098643a 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -2448,10 +2448,6 @@ void FindBar::_notification(int p_what) { } } -void FindBar::_bind_methods() { - ADD_SIGNAL(MethodInfo("search")); -} - void FindBar::set_rich_text_label(RichTextLabel *p_rich_text_label) { rich_text_label = p_rich_text_label; } diff --git a/editor/editor_help.h b/editor/editor_help.h index 9be17143c7..81cd6d6674 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -72,8 +72,6 @@ protected: bool _search(bool p_search_previous = false); - static void _bind_methods(); - public: void set_rich_text_label(RichTextLabel *p_rich_text_label); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 0166d4c719..42d8f48ea0 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1084,7 +1084,7 @@ void EditorInspectorPlugin::parse_group(Object *p_object, const String &p_group) GDVIRTUAL_CALL(_parse_group, p_object, p_group); } -bool EditorInspectorPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { +bool EditorInspectorPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { bool ret = false; GDVIRTUAL_CALL(_parse_property, p_object, p_type, p_path, p_hint, p_hint_text, p_usage, p_wide, ret); return ret; diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 6a1c77d376..eab495ef3d 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -227,7 +227,7 @@ protected: GDVIRTUAL1(_parse_begin, Object *) GDVIRTUAL2(_parse_category, Object *, String) GDVIRTUAL2(_parse_group, Object *, String) - GDVIRTUAL7R(bool, _parse_property, Object *, int, String, int, String, int, bool) + GDVIRTUAL7R(bool, _parse_property, Object *, Variant::Type, String, PropertyHint, String, BitField<PropertyUsageFlags>, bool) GDVIRTUAL1(_parse_end, Object *) public: @@ -239,7 +239,7 @@ public: virtual void parse_begin(Object *p_object); virtual void parse_category(Object *p_object, const String &p_category); virtual void parse_group(Object *p_object, const String &p_group); - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false); + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false); virtual void parse_end(Object *p_object); }; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 550c57121e..296181f79d 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -360,11 +360,6 @@ void EditorLog::_reset_message_counts() { } } -void EditorLog::_bind_methods() { - ADD_SIGNAL(MethodInfo("clear_request")); - ADD_SIGNAL(MethodInfo("copy_request")); -} - EditorLog::EditorLog() { save_state_timer = memnew(Timer); save_state_timer->set_wait_time(2); diff --git a/editor/editor_log.h b/editor/editor_log.h index 7a3c1c01b7..b875066afa 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -178,7 +178,6 @@ private: void _update_theme(); protected: - static void _bind_methods(); void _notification(int p_what); public: diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index a1028a14c5..f317c23b83 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -581,6 +581,7 @@ void EditorNode::_notification(int p_what) { ResourceImporterTexture::get_singleton()->update_imports(); + bottom_panel_updating = false; } break; case NOTIFICATION_ENTER_TREE: { @@ -643,7 +644,7 @@ void EditorNode::_notification(int p_what) { } RenderingServer::get_singleton()->viewport_set_disable_2d(get_scene_root()->get_viewport_rid(), true); - RenderingServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true); + RenderingServer::get_singleton()->viewport_set_environment_mode(get_viewport()->get_viewport_rid(), RenderingServer::VIEWPORT_ENVIRONMENT_DISABLED); feature_profile_manager->notify_changed(); @@ -2135,6 +2136,13 @@ void EditorNode::edit_item(Object *p_object, Object *p_editing_owner) { } } +void EditorNode::push_node_item(Node *p_node) { + if (p_node || Object::cast_to<Node>(InspectorDock::get_inspector_singleton()->get_edited_object())) { + // Don't push null if the currently edited object is not a Node. + push_item(p_node); + } +} + void EditorNode::push_item(Object *p_object, const String &p_property, bool p_inspector_only) { if (!p_object) { InspectorDock::get_inspector_singleton()->edit(nullptr); @@ -5601,12 +5609,16 @@ void EditorNode::remove_bottom_panel_item(Control *p_item) { } void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { + if (bottom_panel_updating) { + return; + } ERR_FAIL_INDEX(p_idx, bottom_panel_items.size()); if (bottom_panel_items[p_idx].control->is_visible() == p_enable) { return; } + bottom_panel_updating = true; if (p_enable) { for (int i = 0; i < bottom_panel_items.size(); i++) { bottom_panel_items[i].button->set_pressed(i == p_idx); @@ -6462,7 +6474,6 @@ void EditorNode::_bind_methods() { ClassDB::bind_method(D_METHOD("get_gui_base"), &EditorNode::get_gui_base); ADD_SIGNAL(MethodInfo("play_pressed")); - ADD_SIGNAL(MethodInfo("pause_pressed")); ADD_SIGNAL(MethodInfo("stop_pressed")); ADD_SIGNAL(MethodInfo("request_help_search")); ADD_SIGNAL(MethodInfo("script_add_function_request", PropertyInfo(Variant::OBJECT, "obj"), PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::PACKED_STRING_ARRAY, "args"))); diff --git a/editor/editor_node.h b/editor/editor_node.h index bb10abb589..914dab0254 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -460,6 +460,7 @@ private: EditorToaster *editor_toaster = nullptr; LinkButton *version_btn = nullptr; Button *bottom_panel_raise = nullptr; + bool bottom_panel_updating = false; Tree *disk_changed_list = nullptr; ConfirmationDialog *disk_changed = nullptr; @@ -797,6 +798,7 @@ public: void push_item(Object *p_object, const String &p_property = "", bool p_inspector_only = false); void edit_item(Object *p_object, Object *p_editing_owner); + void push_node_item(Node *p_node); void hide_unused_editors(const Object *p_editing_owner = nullptr); void select_editor_by_name(const String &p_name); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index f022027e65..c9eae77b53 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -4154,7 +4154,7 @@ bool EditorInspectorDefaultPlugin::can_handle(Object *p_object) { return true; // Can handle everything. } -bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { +bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { Control *editor = EditorInspectorDefaultPlugin::get_editor_for_property(p_object, p_type, p_path, p_hint, p_hint_text, p_usage, p_wide); if (editor) { add_property_editor(p_path, editor); @@ -4228,7 +4228,7 @@ static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const Stri return hint; } -EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { +EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { double default_float_step = EDITOR_GET("interface/inspector/default_float_step"); switch (p_type) { diff --git a/editor/editor_properties.h b/editor/editor_properties.h index d29ec12f97..14a2699ad8 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -863,9 +863,9 @@ class EditorInspectorDefaultPlugin : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override; - static EditorProperty *get_editor_for_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false); + static EditorProperty *get_editor_for_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false); }; #endif // EDITOR_PROPERTIES_H diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 28c0b047d8..b96ac9dbcb 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -158,17 +158,32 @@ EditorPropertyDictionaryObject::EditorPropertyDictionaryObject() { ///////////////////// ARRAY /////////////////////////// +void EditorPropertyArray::initialize_array(Variant &p_array) { + if (array_type == Variant::ARRAY && subtype != Variant::NIL) { + Array array; + StringName subtype_class; + Ref<Script> subtype_script; + if (subtype == Variant::OBJECT && !subtype_hint_string.is_empty()) { + if (ClassDB::class_exists(subtype_hint_string)) { + subtype_class = subtype_hint_string; + } + } + array.set_typed(subtype, subtype_class, subtype_script); + p_array = array; + } else { + VariantInternal::initialize(&p_array, array_type); + } +} + void EditorPropertyArray::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) { if (p_property.begins_with("indices")) { int index = p_property.get_slice("/", 1).to_int(); - Variant array = object->get_array(); + + Variant array = object->get_array().duplicate(); array.set(index, p_value); - emit_changed(get_edited_property(), array, "", true); - if (array.get_type() == Variant::ARRAY) { - array = array.call("duplicate"); // Duplicate, so undo/redo works better. - } object->set_array(array); + emit_changed(get_edited_property(), array, "", true); } } @@ -188,18 +203,12 @@ void EditorPropertyArray::_change_type_menu(int p_index) { } Variant value; - Callable::CallError ce; - Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce); - Variant array = object->get_array(); + VariantInternal::initialize(&value, Variant::Type(p_index)); + + Variant array = object->get_array().duplicate(); array.set(changing_type_index, value); emit_changed(get_edited_property(), array, "", true); - - if (array.get_type() == Variant::ARRAY) { - array = array.call("duplicate"); // Duplicate, so undo/redo works better. - } - - object->set_array(array); update_property(); } @@ -234,6 +243,8 @@ void EditorPropertyArray::update_property() { return; } + object->set_array(array); + int size = array.call("size"); int max_page = MAX(0, size - 1) / page_length; page_index = MIN(page_index, max_page); @@ -305,12 +316,6 @@ void EditorPropertyArray::update_property() { paginator->update(page_index, max_page); paginator->set_visible(max_page > 0); - if (array.get_type() == Variant::ARRAY) { - array = array.call("duplicate"); - } - - object->set_array(array); - int amount = MIN(size - offset, page_length); for (int i = 0; i < amount; i++) { bool reorder_is_from_current_page = reorder_from_index / page_length == page_index; @@ -401,7 +406,7 @@ void EditorPropertyArray::update_property() { } void EditorPropertyArray::_remove_pressed(int p_index) { - Variant array = object->get_array(); + Variant array = object->get_array().duplicate(); array.call("remove_at", p_index); emit_changed(get_edited_property(), array, "", false); @@ -469,8 +474,9 @@ void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_d // Handle the case where array is not initialized yet. if (!array.is_array()) { - Callable::CallError ce; - Variant::construct(array_type, array, nullptr, 0, ce); + initialize_array(array); + } else { + array = array.duplicate(); } // Loop the file array and add to existing array. @@ -483,13 +489,7 @@ void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_d } } - if (array.get_type() == Variant::ARRAY) { - array = array.call("duplicate"); - } - emit_changed(get_edited_property(), array, "", false); - object->set_array(array); - update_property(); } } @@ -536,10 +536,8 @@ void EditorPropertyArray::_notification(int p_what) { void EditorPropertyArray::_edit_pressed() { Variant array = get_edited_object()->get(get_edited_property()); - if (!array.is_array()) { - Callable::CallError ce; - Variant::construct(array_type, array, nullptr, 0, ce); - + if (!array.is_array() && edit->is_pressed()) { + initialize_array(array); get_edited_object()->set(get_edited_property(), array); } @@ -560,37 +558,10 @@ void EditorPropertyArray::_length_changed(double p_page) { return; } - Variant array = object->get_array(); - int previous_size = array.call("size"); - + Variant array = object->get_array().duplicate(); array.call("resize", int(p_page)); - if (array.get_type() == Variant::ARRAY) { - if (subtype != Variant::NIL) { - int size = array.call("size"); - for (int i = previous_size; i < size; i++) { - if (array.get(i).get_type() == Variant::NIL) { - Callable::CallError ce; - Variant r; - Variant::construct(subtype, r, nullptr, 0, ce); - array.set(i, r); - } - } - } - array = array.call("duplicate"); // Duplicate, so undo/redo works better. - } else { - int size = array.call("size"); - // Pool*Array don't initialize their elements, have to do it manually. - for (int i = previous_size; i < size; i++) { - Callable::CallError ce; - Variant r; - Variant::construct(array.get(i).get_type(), r, nullptr, 0, ce); - array.set(i, r); - } - } - emit_changed(get_edited_property(), array, "", false); - object->set_array(array); update_property(); } @@ -677,14 +648,13 @@ void EditorPropertyArray::_reorder_button_up() { if (reorder_from_index != reorder_to_index) { // Move the element. - Variant array = object->get_array(); + Variant array = object->get_array().duplicate(); Variant value_to_move = array.get(reorder_from_index); array.call("remove_at", reorder_from_index); array.call("insert", reorder_to_index, value_to_move); emit_changed(get_edited_property(), array, "", false); - object->set_array(array); update_property(); } @@ -742,14 +712,13 @@ void EditorPropertyDictionary::_property_changed(const String &p_property, Varia object->set_new_item_value(p_value); } else if (p_property.begins_with("indices")) { int index = p_property.get_slice("/", 1).to_int(); - Dictionary dict = object->get_dict(); + + Dictionary dict = object->get_dict().duplicate(); Variant key = dict.get_key_at_index(index); dict[key] = p_value; - emit_changed(get_edited_property(), dict, "", true); - - dict = dict.duplicate(); // Duplicate, so undo/redo works better. object->set_dict(dict); + emit_changed(get_edited_property(), dict, "", true); } } @@ -769,24 +738,19 @@ void EditorPropertyDictionary::_add_key_value() { return; } - Dictionary dict = object->get_dict(); - + Dictionary dict = object->get_dict().duplicate(); dict[object->get_new_item_key()] = object->get_new_item_value(); object->set_new_item_key(Variant()); object->set_new_item_value(Variant()); emit_changed(get_edited_property(), dict, "", false); - - dict = dict.duplicate(); // Duplicate, so undo/redo works better. - object->set_dict(dict); update_property(); } void EditorPropertyDictionary::_change_type_menu(int p_index) { if (changing_type_index < 0) { Variant value; - Callable::CallError ce; - Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce); + VariantInternal::initialize(&value, Variant::Type(p_index)); if (changing_type_index == -1) { object->set_new_item_key(value); } else { @@ -796,12 +760,10 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) { return; } - Dictionary dict = object->get_dict(); - + Dictionary dict = object->get_dict().duplicate(); if (p_index < Variant::VARIANT_MAX) { Variant value; - Callable::CallError ce; - Variant::construct(Variant::Type(p_index), value, nullptr, 0, ce); + VariantInternal::initialize(&value, Variant::Type(p_index)); Variant key = dict.get_key_at_index(changing_type_index); dict[key] = value; } else { @@ -810,9 +772,6 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) { } emit_changed(get_edited_property(), dict, "", false); - - dict = dict.duplicate(); // Duplicate, so undo/redo works better. - object->set_dict(dict); update_property(); } @@ -836,6 +795,7 @@ void EditorPropertyDictionary::update_property() { } Dictionary dict = updated_val; + object->set_dict(updated_val); edit->set_text(vformat(TTR("Dictionary (size %d)"), dict.size())); @@ -883,9 +843,6 @@ void EditorPropertyDictionary::update_property() { int amount = MIN(size - offset, page_length); int total_amount = page_index == max_page ? amount + 2 : amount; // For the "Add Key/Value Pair" box on last page. - dict = dict.duplicate(); - - object->set_dict(dict); VBoxContainer *add_vbox = nullptr; double default_float_step = EDITOR_GET("interface/inspector/default_float_step"); @@ -1225,9 +1182,8 @@ void EditorPropertyDictionary::_notification(int p_what) { void EditorPropertyDictionary::_edit_pressed() { Variant prop_val = get_edited_object()->get(get_edited_property()); - if (prop_val.get_type() == Variant::NIL) { - Callable::CallError ce; - Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce); + if (prop_val.get_type() == Variant::NIL && edit->is_pressed()) { + VariantInternal::initialize(&prop_val, Variant::DICTIONARY); get_edited_object()->set(get_edited_property(), prop_val); } @@ -1272,14 +1228,13 @@ EditorPropertyDictionary::EditorPropertyDictionary() { void EditorPropertyLocalizableString::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) { if (p_property.begins_with("indices")) { int index = p_property.get_slice("/", 1).to_int(); - Dictionary dict = object->get_dict(); + + Dictionary dict = object->get_dict().duplicate(); Variant key = dict.get_key_at_index(index); dict[key] = p_value; - emit_changed(get_edited_property(), dict, "", true); - - dict = dict.duplicate(); // Duplicate, so undo/redo works better. object->set_dict(dict); + emit_changed(get_edited_property(), dict, "", true); } } @@ -1288,29 +1243,22 @@ void EditorPropertyLocalizableString::_add_locale_popup() { } void EditorPropertyLocalizableString::_add_locale(const String &p_locale) { - Dictionary dict = object->get_dict(); - + Dictionary dict = object->get_dict().duplicate(); object->set_new_item_key(p_locale); object->set_new_item_value(String()); dict[object->get_new_item_key()] = object->get_new_item_value(); emit_changed(get_edited_property(), dict, "", false); - - dict = dict.duplicate(); // Duplicate, so undo/redo works better. - object->set_dict(dict); update_property(); } void EditorPropertyLocalizableString::_remove_item(Object *p_button, int p_index) { - Dictionary dict = object->get_dict(); + Dictionary dict = object->get_dict().duplicate(); Variant key = dict.get_key_at_index(p_index); dict.erase(key); emit_changed(get_edited_property(), dict, "", false); - - dict = dict.duplicate(); // Duplicate, so undo/redo works better. - object->set_dict(dict); update_property(); } @@ -1330,6 +1278,7 @@ void EditorPropertyLocalizableString::update_property() { } Dictionary dict = updated_val; + object->set_dict(dict); edit->set_text(vformat(TTR("Localizable String (size %d)"), dict.size())); @@ -1376,10 +1325,6 @@ void EditorPropertyLocalizableString::update_property() { int amount = MIN(size - offset, page_length); - dict = dict.duplicate(); - - object->set_dict(dict); - for (int i = 0; i < amount; i++) { String prop_name; Variant key; @@ -1451,9 +1396,8 @@ void EditorPropertyLocalizableString::_notification(int p_what) { void EditorPropertyLocalizableString::_edit_pressed() { Variant prop_val = get_edited_object()->get(get_edited_property()); - if (prop_val.get_type() == Variant::NIL) { - Callable::CallError ce; - Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce); + if (prop_val.get_type() == Variant::NIL && edit->is_pressed()) { + VariantInternal::initialize(&prop_val, Variant::DICTIONARY); get_edited_object()->set(get_edited_property(), prop_val); } diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h index 73a16e3687..3b880c60a8 100644 --- a/editor/editor_properties_array_dict.h +++ b/editor/editor_properties_array_dict.h @@ -102,6 +102,8 @@ class EditorPropertyArray : public EditorProperty { HBoxContainer *reorder_selected_element_hbox = nullptr; Button *reorder_selected_button = nullptr; + void initialize_array(Variant &p_array); + void _page_changed(int p_page); void _reorder_button_gui_input(const Ref<InputEvent> &p_event); diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index fe67813d65..a46484bb0e 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -814,7 +814,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & HashSet<String> paths; Vector<String> path_remaps; - paths.insert(ProjectSettings::get_singleton()->get_project_data_path().path_join("global_script_class_cache.cfg")); + paths.insert(ProjectSettings::get_singleton()->get_global_class_list_path()); if (p_preset->get_export_filter() == EditorExportPreset::EXPORT_ALL_RESOURCES) { //find stuff _export_find_resources(EditorFileSystem::get_singleton()->get_filesystem(), paths); diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index 52c192164f..e9ea0012be 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -754,22 +754,27 @@ void ProjectExportDialog::_fill_resource_tree() { include_margin->show(); _fill_tree(EditorFileSystem::get_singleton()->get_filesystem(), root, current, f); + + if (f == EditorExportPreset::EXPORT_CUSTOMIZED) { + _propagate_file_export_mode(include_files->get_root(), EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED); + } } void ProjectExportDialog::_setup_item_for_file_mode(TreeItem *p_item, EditorExportPreset::FileExportMode p_mode) { if (p_mode == EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED) { p_item->set_checked(0, false); p_item->set_cell_mode(1, TreeItem::CELL_MODE_STRING); - p_item->set_text(1, ""); p_item->set_editable(1, false); p_item->set_selectable(1, false); + p_item->set_custom_color(1, get_theme_color(SNAME("disabled_font_color"), SNAME("Editor"))); } else { p_item->set_checked(0, true); p_item->set_cell_mode(1, TreeItem::CELL_MODE_CUSTOM); - p_item->set_text(1, file_mode_popup->get_item_text(file_mode_popup->get_item_index(p_mode))); p_item->set_editable(1, true); p_item->set_selectable(1, true); + p_item->clear_custom_color(1); } + p_item->set_metadata(1, p_mode); } bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> ¤t, EditorExportPreset::ExportFilter p_export_filter) { @@ -824,6 +829,23 @@ bool ProjectExportDialog::_fill_tree(EditorFileSystemDirectory *p_dir, TreeItem return used; } +void ProjectExportDialog::_propagate_file_export_mode(TreeItem *p_item, EditorExportPreset::FileExportMode p_inherited_export_mode) { + EditorExportPreset::FileExportMode file_export_mode = (EditorExportPreset::FileExportMode)(int)p_item->get_metadata(1); + if (file_export_mode == EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED) { + file_export_mode = p_inherited_export_mode; + } + + if (file_export_mode == EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED) { + p_item->set_text(1, ""); + } else { + p_item->set_text(1, file_mode_popup->get_item_text(file_mode_popup->get_item_index(file_export_mode))); + } + + for (int i = 0; i < p_item->get_child_count(); i++) { + _propagate_file_export_mode(p_item->get_child(i), file_export_mode); + } +} + void ProjectExportDialog::_tree_changed() { if (updating) { return; @@ -847,8 +869,9 @@ void ProjectExportDialog::_tree_changed() { file_mode = current->get_file_export_mode(path, EditorExportPreset::MODE_FILE_STRIP); } - _setup_item_for_file_mode(item, file_mode); current->set_file_export_mode(path, file_mode); + _setup_item_for_file_mode(item, file_mode); + _propagate_file_export_mode(include_files->get_root(), EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED); } else { item->propagate_check(0); } @@ -890,9 +913,10 @@ void ProjectExportDialog::_set_file_export_mode(int p_id) { TreeItem *item = include_files->get_edited(); String path = item->get_metadata(0); - current->set_file_export_mode(path, (EditorExportPreset::FileExportMode)p_id); - - item->set_text(1, file_mode_popup->get_item_text(file_mode_popup->get_item_index(p_id))); + EditorExportPreset::FileExportMode file_export_mode = (EditorExportPreset::FileExportMode)p_id; + current->set_file_export_mode(path, file_export_mode); + item->set_metadata(1, file_export_mode); + _propagate_file_export_mode(include_files->get_root(), EditorExportPreset::MODE_FILE_NOT_CUSTOMIZED); } void ProjectExportDialog::_export_pck_zip() { diff --git a/editor/export/project_export.h b/editor/export/project_export.h index 63f8fc4a2e..e53e393432 100644 --- a/editor/export/project_export.h +++ b/editor/export/project_export.h @@ -118,6 +118,7 @@ private: void _fill_resource_tree(); void _setup_item_for_file_mode(TreeItem *p_item, EditorExportPreset::FileExportMode p_mode); bool _fill_tree(EditorFileSystemDirectory *p_dir, TreeItem *p_item, Ref<EditorExportPreset> ¤t, EditorExportPreset::ExportFilter p_export_filter); + void _propagate_file_export_mode(TreeItem *p_item, EditorExportPreset::FileExportMode p_inherited_export_mode); void _tree_changed(); void _check_propagated_to_item(Object *p_obj, int column); void _tree_popup_edited(bool p_arrow_clicked); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 378e06b4c9..92e3631015 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -2643,17 +2643,24 @@ void FileSystemDock::_file_and_folders_fill_popup(PopupMenu *p_popup, Vector<Str new_menu->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("Script..."), FILE_NEW_SCRIPT); new_menu->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("Resource..."), FILE_NEW_RESOURCE); new_menu->add_icon_item(get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")), TTR("TextFile..."), FILE_NEW_TEXTFILE); +#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) p_popup->add_separator(); +#endif } - String fpath = p_paths[0]; - bool is_directory = fpath.ends_with("/"); - String item_text = is_directory ? TTR("Open in File Manager") : TTR("Show in File Manager"); + const String fpath = p_paths[0]; + +#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) + // Opening the system file manager is not supported on the Android and web editors. + const bool is_directory = fpath.ends_with("/"); + const String item_text = is_directory ? TTR("Open in File Manager") : TTR("Show in File Manager"); p_popup->add_icon_shortcut(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_SHOW_IN_EXPLORER); p_popup->set_item_text(p_popup->get_item_index(FILE_SHOW_IN_EXPLORER), item_text); if (!is_directory) { p_popup->add_icon_shortcut(get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_GET_SHORTCUT("filesystem_dock/open_in_external_program"), FILE_OPEN_EXTERNAL); } +#endif + path = fpath; } } @@ -2697,8 +2704,11 @@ void FileSystemDock::_tree_empty_click(const Vector2 &p_pos, MouseButton p_butto tree_popup->add_icon_item(get_theme_icon(SNAME("Script"), SNAME("EditorIcons")), TTR("New Script..."), FILE_NEW_SCRIPT); tree_popup->add_icon_item(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")), TTR("New Resource..."), FILE_NEW_RESOURCE); tree_popup->add_icon_item(get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")), TTR("New TextFile..."), FILE_NEW_TEXTFILE); +#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) + // Opening the system file manager is not supported on the Android and web editors. tree_popup->add_separator(); tree_popup->add_icon_shortcut(get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), ED_GET_SHORTCUT("filesystem_dock/show_in_explorer"), FILE_SHOW_IN_EXPLORER); +#endif tree_popup->set_position(tree->get_screen_position() + p_pos); tree_popup->reset_size(); @@ -3120,8 +3130,11 @@ FileSystemDock::FileSystemDock() { ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), Key::KEY_DELETE); ED_SHORTCUT("filesystem_dock/rename", TTR("Rename..."), Key::F2); ED_SHORTCUT_OVERRIDE("filesystem_dock/rename", "macos", Key::ENTER); +#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) + // Opening the system file manager or opening in an external program is not supported on the Android and web editors. ED_SHORTCUT("filesystem_dock/show_in_explorer", TTR("Open in File Manager")); ED_SHORTCUT("filesystem_dock/open_in_external_program", TTR("Open in External Program")); +#endif VBoxContainer *top_vbc = memnew(VBoxContainer); add_child(top_vbc); diff --git a/editor/icons/AnimatableBody2D.svg b/editor/icons/AnimatableBody2D.svg index f4fed813c9..e6057feeff 100644 --- a/editor/icons/AnimatableBody2D.svg +++ b/editor/icons/AnimatableBody2D.svg @@ -1 +1 @@ -<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#8da5f3" fill-opacity=".99" stroke-width="1.08904"><path d="m10.86822576 4.28299076h1.99947744v1.99947744h-1.99947744z"/><path d="m10.86822576 10.84273776h1.99947744v1.99947744h-1.99947744z"/><path d="m4.71256576 10.84273776h1.99947744v1.99947744h-1.99947744z"/></g><g fill="none" stroke="#8da5f3"><path d="m1.635 8.161v4.848c0 .713.579 1.293 1.292 1.293h9.857c.713 0 1.291-.58 1.291-1.293v-9.854c0-.714-.578-1.293-1.291-1.293h-5.526" stroke-width="1.07" transform="matrix(.939225 0 0 .938055 1.27996 1.07595)"/><path d="m1.339 1.364 2.539 2.539" stroke-width=".74" transform="matrix(2.04823 .655864 .655864 2.04823 -1.51683 -1.5267)"/><path d="m1.436 1.461 1.168 1.168" stroke-width="1.18" transform="matrix(1.69185 0 0 1.69185 4.50755 -.792876)"/><path d="m1.385 1.41 1.219 1.219" stroke-width="1.22" transform="matrix(1.63859 0 0 1.63859 -.688679 4.82985)"/></g></svg> +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#8da5f3" stroke-width="1.08904"><path d="m10.86822576 4.28299076h1.99947744v1.99947744h-1.99947744z"/><path d="m10.86822576 10.84273776h1.99947744v1.99947744h-1.99947744z"/><path d="m4.71256576 10.84273776h1.99947744v1.99947744h-1.99947744z"/></g><g fill="none" stroke="#8da5f3"><path d="m1.635 8.161v4.848c0 .713.579 1.293 1.292 1.293h9.857c.713 0 1.291-.58 1.291-1.293v-9.854c0-.714-.578-1.293-1.291-1.293h-5.526" stroke-width="1.07" transform="matrix(.939225 0 0 .938055 1.27996 1.07595)"/><path d="m1.339 1.364 2.539 2.539" stroke-width=".74" transform="matrix(2.04823 .655864 .655864 2.04823 -1.51683 -1.5267)"/><path d="m1.436 1.461 1.168 1.168" stroke-width="1.18" transform="matrix(1.69185 0 0 1.69185 4.50755 -.792876)"/><path d="m1.385 1.41 1.219 1.219" stroke-width="1.22" transform="matrix(1.63859 0 0 1.63859 -.688679 4.82985)"/></g></svg> diff --git a/editor/icons/AnimatableBody3D.svg b/editor/icons/AnimatableBody3D.svg index 2e472f0625..0724e2cbfa 100644 --- a/editor/icons/AnimatableBody3D.svg +++ b/editor/icons/AnimatableBody3D.svg @@ -1 +1 @@ -<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f" fill-opacity=".99" stroke-width="1.08904"><path d="m10.86822576 4.28299076h1.99947744v1.99947744h-1.99947744z"/><path d="m10.86822576 10.84273776h1.99947744v1.99947744h-1.99947744z"/><path d="m4.71256576 10.84273776h1.99947744v1.99947744h-1.99947744z"/></g><g fill="none" stroke="#fc7f7f"><path d="m1.635 8.161v4.848c0 .713.579 1.293 1.292 1.293h9.857c.713 0 1.291-.58 1.291-1.293v-9.854c0-.714-.578-1.293-1.291-1.293h-5.526" stroke-width="1.07" transform="matrix(.939225 0 0 .938055 1.27996 1.07595)"/><path d="m1.339 1.364 2.539 2.539" stroke-width=".74" transform="matrix(2.04823 .655864 .655864 2.04823 -1.51683 -1.5267)"/><path d="m1.436 1.461 1.168 1.168" stroke-width="1.18" transform="matrix(1.69185 0 0 1.69185 4.50755 -.792876)"/><path d="m1.385 1.41 1.219 1.219" stroke-width="1.22" transform="matrix(1.63859 0 0 1.63859 -.688679 4.82985)"/></g></svg> +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="1.5" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#fc7f7f" stroke-width="1.08904"><path d="m10.86822576 4.28299076h1.99947744v1.99947744h-1.99947744z"/><path d="m10.86822576 10.84273776h1.99947744v1.99947744h-1.99947744z"/><path d="m4.71256576 10.84273776h1.99947744v1.99947744h-1.99947744z"/></g><g fill="none" stroke="#fc7f7f"><path d="m1.635 8.161v4.848c0 .713.579 1.293 1.292 1.293h9.857c.713 0 1.291-.58 1.291-1.293v-9.854c0-.714-.578-1.293-1.291-1.293h-5.526" stroke-width="1.07" transform="matrix(.939225 0 0 .938055 1.27996 1.07595)"/><path d="m1.339 1.364 2.539 2.539" stroke-width=".74" transform="matrix(2.04823 .655864 .655864 2.04823 -1.51683 -1.5267)"/><path d="m1.436 1.461 1.168 1.168" stroke-width="1.18" transform="matrix(1.69185 0 0 1.69185 4.50755 -.792876)"/><path d="m1.385 1.41 1.219 1.219" stroke-width="1.22" transform="matrix(1.63859 0 0 1.63859 -.688679 4.82985)"/></g></svg> diff --git a/editor/icons/AnimationLibrary.svg b/editor/icons/AnimationLibrary.svg index 0bac67d302..097a53a41d 100644 --- a/editor/icons/AnimationLibrary.svg +++ b/editor/icons/AnimationLibrary.svg @@ -1 +1 @@ -<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14.519 2.006A6 6 0 0 0 8.599 8a6 6 0 0 0 5.92 5.994v-1.01a1 1 0 0 1-.92-.984 1 1 0 0 1 .92-.984V4.984a1 1 0 0 1-.92-.984 1 1 0 0 1 .92-.984Zm-3.432 2.996a1 1 0 0 1 .547.133 1 1 0 0 1 .367 1.365 1 1 0 0 1-1.367.365A1 1 0 0 1 10.27 5.5a1 1 0 0 1 .818-.498ZM11.111 9a1 1 0 0 1 .89.5 1 1 0 0 1-.367 1.365 1 1 0 0 1-1.365-.365 1 1 0 0 1 .365-1.365A1 1 0 0 1 11.111 9Z" style="fill:#e0e0e0;fill-opacity:1"/><path d="M11.094 2.104a6 6 0 0 0-5.92 5.994 6 6 0 0 0 5.92 5.994v-.023a5.795 6.506 0 0 1-2.89-3.104 1 1 0 0 1-1.36-.367 1 1 0 0 1 .365-1.365 1 1 0 0 1 .475-.135 5.795 6.506 0 0 1-.076-.984 5.795 6.506 0 0 1 .082-1.027 1 1 0 0 1-.48-.124 1 1 0 0 1-.366-1.365 1 1 0 0 1 .818-.498 1 1 0 0 1 .547.133 1 1 0 0 1 .004.002 5.795 6.506 0 0 1 2.881-3.076z" style="fill:#e0e0e0;fill-opacity:1"/><path d="M7.616 2.104a6 6 0 0 0-5.92 5.994 6 6 0 0 0 5.92 5.994v-.023a5.795 6.506 0 0 1-2.89-3.104 1 1 0 0 1-1.36-.367 1 1 0 0 1 .366-1.365 1 1 0 0 1 .474-.135 5.795 6.506 0 0 1-.076-.984 5.795 6.506 0 0 1 .082-1.027 1 1 0 0 1-.48-.124 1 1 0 0 1-.366-1.365 1 1 0 0 1 .819-.498 1 1 0 0 1 .547.133 1 1 0 0 1 .003.002 5.795 6.506 0 0 1 2.881-3.076z" style="fill:#e0e0e0;fill-opacity:1"/></svg> +<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14.519 2.006A6 6 0 0 0 8.599 8a6 6 0 0 0 5.92 5.994v-1.01a1 1 0 0 1-.92-.984 1 1 0 0 1 .92-.984V4.984a1 1 0 0 1-.92-.984 1 1 0 0 1 .92-.984Zm-3.432 2.996a1 1 0 0 1 .547.133 1 1 0 0 1 .367 1.365 1 1 0 0 1-1.367.365A1 1 0 0 1 10.27 5.5a1 1 0 0 1 .818-.498ZM11.111 9a1 1 0 0 1 .89.5 1 1 0 0 1-.367 1.365 1 1 0 0 1-1.365-.365 1 1 0 0 1 .365-1.365A1 1 0 0 1 11.111 9Z" fill="#e0e0e0"/><path d="M11.094 2.104a6 6 0 0 0-5.92 5.994 6 6 0 0 0 5.92 5.994v-.023a5.795 6.506 0 0 1-2.89-3.104 1 1 0 0 1-1.36-.367 1 1 0 0 1 .365-1.365 1 1 0 0 1 .475-.135 5.795 6.506 0 0 1-.076-.984 5.795 6.506 0 0 1 .082-1.027 1 1 0 0 1-.48-.124 1 1 0 0 1-.366-1.365 1 1 0 0 1 .818-.498 1 1 0 0 1 .547.133 1 1 0 0 1 .004.002 5.795 6.506 0 0 1 2.881-3.076z" fill="#e0e0e0"/><path d="M7.616 2.104a6 6 0 0 0-5.92 5.994 6 6 0 0 0 5.92 5.994v-.023a5.795 6.506 0 0 1-2.89-3.104 1 1 0 0 1-1.36-.367 1 1 0 0 1 .366-1.365 1 1 0 0 1 .474-.135 5.795 6.506 0 0 1-.076-.984 5.795 6.506 0 0 1 .082-1.027 1 1 0 0 1-.48-.124 1 1 0 0 1-.366-1.365 1 1 0 0 1 .819-.498 1 1 0 0 1 .547.133 1 1 0 0 1 .003.002 5.795 6.506 0 0 1 2.881-3.076z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/CPUParticles2D.svg b/editor/icons/CPUParticles2D.svg index 2a2c616954..a446039b81 100644 --- a/editor/icons/CPUParticles2D.svg +++ b/editor/icons/CPUParticles2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4.5587261.60940813c-.4226244 0-.7617187.3410473-.7617187.76367177v.5078126c0 .1028478.020058.199689.056641.2890624h-1.1933597c-.4226245 0-.7617188.3390944-.7617188.7617188v.921875c-.040428-.00657-.0767989-.0234375-.1191406-.0234375h-.5078125c-.42262448 0-.76367188.3410475-.76367188.7636719v.3730468c0 .4226245.3410474.7617188.76367188.7617188h.5078125c.042396 0 .078663-.016851.1191406-.023437v4.4531248c-.040428-.0066-.076799-.02344-.1191406-.02344h-.5078125c-.42262448 0-.76367188.341047-.76367188.763672v.373047c0 .422625.3410474.761718.76367188.761718h.5078125c.042396 0 .078663-.01685.1191406-.02344v1.125c0 .422624.3390944.763672.7617188.763672h1.1367187v.457031c0 .422624.3390943.763672.7617187.763672h.3730469c.4226244 0 .7636719-.341048.7636719-.763672v-.457031h4.4062501v.457031c0 .422624.339094.763672.761719.763672h.373047c.422624 0 .763671-.341048.763671-.763672v-.457031h1.269532c.422625 0 .763672-.341048.763672-.763672v-1.111328c.01774.0012.03272.0098.05078.0098h.507812c.422624 0 .763672-.339093.763672-.761718v-.373047c0-.422624-.341048-.763672-.763672-.763672h-.507812c-.01803 0-.03307.0085-.05078.0098v-4.4258454c.01774.00122.03272.00977.05078.00977h.507812c.422624 0 .763672-.3390943.763672-.7617188v-.3730512c0-.4226244-.341048-.7636719-.763672-.7636719h-.507812c-.01803 0-.03307.00855-.05078.00977v-.9082075c0-.4226244-.341047-.7617187-.763672-.7617188h-1.328125c.03658-.089375.05859-.1862118.05859-.2890624v-.5078126c0-.42262437-.341047-.76367177-.763671-.76367177h-.373047c-.422625 0-.761719.3410474-.761719.76367177v.5078126c0 .1028478.02006.1996891.05664.2890624h-4.5214809c.036585-.0893749.0585938-.1862118.0585938-.2890624v-.5078126c0-.42262437-.3410475-.76367177-.7636719-.76367177zm3.2382813 2.35742177a3.279661 3.6440678 0 0 1 3.2128906 2.9394532 2.1864407 2.1864407 0 0 1 1.888672 2.1621094 2.1864407 2.1864407 0 0 1 -2.1875 2.1855475h-5.8300782a2.1864407 2.1864407 0 0 1 -2.1855469-2.1855475 2.1864407 2.1864407 0 0 1 1.8847656-2.1640626 3.279661 3.6440678 0 0 1 3.2167969-2.9375zm-2.9160156 8.0156251a.72881355.72881355 0 0 1 .7285156.728516.72881355.72881355 0 0 1 -.7285156.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm5.8300782 0a.72881355.72881355 0 0 1 .730469.728516.72881355.72881355 0 0 1 -.730469.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm-2.9140626.728516a.72881355.72881355 0 0 1 .7285156.730469.72881355.72881355 0 0 1 -.7285156.728515.72881355.72881355 0 0 1 -.7285156-.728515.72881355.72881355 0 0 1 .7285156-.730469z" fill="#8da5f3" fill-opacity=".992157"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4.5587261.60940813c-.4226244 0-.7617187.3410473-.7617187.76367177v.5078126c0 .1028478.020058.199689.056641.2890624h-1.1933597c-.4226245 0-.7617188.3390944-.7617188.7617188v.921875c-.040428-.00657-.0767989-.0234375-.1191406-.0234375h-.5078125c-.42262448 0-.76367188.3410475-.76367188.7636719v.3730468c0 .4226245.3410474.7617188.76367188.7617188h.5078125c.042396 0 .078663-.016851.1191406-.023437v4.4531248c-.040428-.0066-.076799-.02344-.1191406-.02344h-.5078125c-.42262448 0-.76367188.341047-.76367188.763672v.373047c0 .422625.3410474.761718.76367188.761718h.5078125c.042396 0 .078663-.01685.1191406-.02344v1.125c0 .422624.3390944.763672.7617188.763672h1.1367187v.457031c0 .422624.3390943.763672.7617187.763672h.3730469c.4226244 0 .7636719-.341048.7636719-.763672v-.457031h4.4062501v.457031c0 .422624.339094.763672.761719.763672h.373047c.422624 0 .763671-.341048.763671-.763672v-.457031h1.269532c.422625 0 .763672-.341048.763672-.763672v-1.111328c.01774.0012.03272.0098.05078.0098h.507812c.422624 0 .763672-.339093.763672-.761718v-.373047c0-.422624-.341048-.763672-.763672-.763672h-.507812c-.01803 0-.03307.0085-.05078.0098v-4.4258454c.01774.00122.03272.00977.05078.00977h.507812c.422624 0 .763672-.3390943.763672-.7617188v-.3730512c0-.4226244-.341048-.7636719-.763672-.7636719h-.507812c-.01803 0-.03307.00855-.05078.00977v-.9082075c0-.4226244-.341047-.7617187-.763672-.7617188h-1.328125c.03658-.089375.05859-.1862118.05859-.2890624v-.5078126c0-.42262437-.341047-.76367177-.763671-.76367177h-.373047c-.422625 0-.761719.3410474-.761719.76367177v.5078126c0 .1028478.02006.1996891.05664.2890624h-4.5214809c.036585-.0893749.0585938-.1862118.0585938-.2890624v-.5078126c0-.42262437-.3410475-.76367177-.7636719-.76367177zm3.2382813 2.35742177a3.279661 3.6440678 0 0 1 3.2128906 2.9394532 2.1864407 2.1864407 0 0 1 1.888672 2.1621094 2.1864407 2.1864407 0 0 1 -2.1875 2.1855475h-5.8300782a2.1864407 2.1864407 0 0 1 -2.1855469-2.1855475 2.1864407 2.1864407 0 0 1 1.8847656-2.1640626 3.279661 3.6440678 0 0 1 3.2167969-2.9375zm-2.9160156 8.0156251a.72881355.72881355 0 0 1 .7285156.728516.72881355.72881355 0 0 1 -.7285156.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm5.8300782 0a.72881355.72881355 0 0 1 .730469.728516.72881355.72881355 0 0 1 -.730469.730469.72881355.72881355 0 0 1 -.7285157-.730469.72881355.72881355 0 0 1 .7285157-.728516zm-2.9140626.728516a.72881355.72881355 0 0 1 .7285156.730469.72881355.72881355 0 0 1 -.7285156.728515.72881355.72881355 0 0 1 -.7285156-.728515.72881355.72881355 0 0 1 .7285156-.730469z" fill="#8da5f3"/></svg> diff --git a/editor/icons/CollisionPolygon2D.svg b/editor/icons/CollisionPolygon2D.svg index a882943847..215bcc0d08 100644 --- a/editor/icons/CollisionPolygon2D.svg +++ b/editor/icons/CollisionPolygon2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12l-6 6z" fill="none" stroke="#8da5f3" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2" transform="translate(0 -1036.4)"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12l-6 6z" fill="none" stroke="#8da5f3" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"/></svg> diff --git a/editor/icons/CollisionShape2D.svg b/editor/icons/CollisionShape2D.svg index 0acad74379..3f15d173b8 100644 --- a/editor/icons/CollisionShape2D.svg +++ b/editor/icons/CollisionShape2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12z" fill="none" stroke="#8da5f3" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2" transform="translate(0 -1036.4)"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m14 1050.4h-12v-12h12z" fill="none" stroke="#8da5f3" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"/></svg> diff --git a/editor/icons/DampedSpringJoint2D.svg b/editor/icons/DampedSpringJoint2D.svg index 99e1a1f1e1..cba54bbd99 100644 --- a/editor/icons/DampedSpringJoint2D.svg +++ b/editor/icons/DampedSpringJoint2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill-opacity=".98824"><path d="m4 3v2l8 3v-2zm0 5v2l8 3v-2z" fill="#4b70ea"/><path d="m4 3v2l8-2v-2zm0 5v2l8-2v-2zm0 5v2l8-2v-2z" fill="#8da5f3"/></g></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 3v2l8 3v-2zm0 5v2l8 3v-2z" fill="#4b70ea"/><path d="m4 3v2l8-2v-2zm0 5v2l8-2v-2zm0 5v2l8-2v-2z" fill="#8da5f3"/></svg> diff --git a/editor/icons/FontFile.svg b/editor/icons/FontFile.svg index c014299783..6b98c269f8 100644 --- a/editor/icons/FontFile.svg +++ b/editor/icons/FontFile.svg @@ -1 +1 @@ -<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M7.5 7.5h-1a.519.519 0 0 0-.281.084A.491.491 0 0 0 6 8v.5h-.5V9a1 1 0 0 1-1 1v1H8V9.854A1 1 0 0 1 7.5 9V7.5zM1.5 1v3h1a1 1 0 0 1 1-1h2v1.5h2V3h2a1 1 0 0 1 1 1h1V1h-10z" style="fill:#e0e0e0;fill-opacity:1"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6z" fill="#ff5f5f"/></svg> +<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M7.5 7.5h-1a.519.519 0 0 0-.281.084A.491.491 0 0 0 6 8v.5h-.5V9a1 1 0 0 1-1 1v1H8V9.854A1 1 0 0 1 7.5 9V7.5zM1.5 1v3h1a1 1 0 0 1 1-1h2v1.5h2V3h2a1 1 0 0 1 1 1h1V1h-10z" fill="#e0e0e0"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6z" fill="#ff5f5f"/></svg> diff --git a/editor/icons/FontVariation.svg b/editor/icons/FontVariation.svg index 39917bcba9..9488679af2 100644 --- a/editor/icons/FontVariation.svg +++ b/editor/icons/FontVariation.svg @@ -1 +1 @@ -<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M5.975 11 7.21 7.5H5.916a.478.478 0 0 0-.113.016.837.837 0 0 0-.127.043c-.044.018-.089.04-.133.066l-.043.027V9a1 1 0 0 1-1 1v1h1.475zM1.5 1v3h1a1 1 0 0 1 1-1h2v1.5h2V3h2a1 1 0 0 1 1 1h1V1h-10z" style="fill:#e0e0e0;fill-opacity:1"/><path d="m4.621 5-.705 2-.353 1h1a.84 1.192 49.998 0 1 1.353-1h2L5.8 13a.84 1.192 49.998 0 1-1.353 1l-.353 1h4l.353-1a.84 1.192 49.998 0 1-.647-1l2.116-6h2a.84 1.192 49.998 0 1 .647 1h1l.353-1 .705-2h-6z" fill="#ff5f5f"/></svg> +<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M5.975 11 7.21 7.5H5.916a.478.478 0 0 0-.113.016.837.837 0 0 0-.127.043c-.044.018-.089.04-.133.066l-.043.027V9a1 1 0 0 1-1 1v1h1.475zM1.5 1v3h1a1 1 0 0 1 1-1h2v1.5h2V3h2a1 1 0 0 1 1 1h1V1h-10z" fill="#e0e0e0"/><path d="m4.621 5-.705 2-.353 1h1a.84 1.192 49.998 0 1 1.353-1h2L5.8 13a.84 1.192 49.998 0 1-1.353 1l-.353 1h4l.353-1a.84 1.192 49.998 0 1-.647-1l2.116-6h2a.84 1.192 49.998 0 1 .647 1h1l.353-1 .705-2h-6z" fill="#ff5f5f"/></svg> diff --git a/editor/icons/GizmoDirectionalLight.svg b/editor/icons/GizmoDirectionalLight.svg index d943be79f0..cb80b31f91 100644 --- a/editor/icons/GizmoDirectionalLight.svg +++ b/editor/icons/GizmoDirectionalLight.svg @@ -1 +1 @@ -<svg height="128" viewBox="0 0 128 128" width="128" xmlns="http://www.w3.org/2000/svg"><path d="m64 4c-4.432 0-8 3.568-8 8v16c0 4.432 3.568 8 8 8s8-3.568 8-8v-16c0-4.432-3.568-8-8-8zm-36.77 15.223c-2.045 0-4.0893.78461-5.6562 2.3516-3.1339 3.1339-3.1339 8.1786 0 11.312l11.312 11.314c3.1339 3.1339 8.1806 3.1339 11.314 0s3.1339-8.1806 0-11.314l-11.314-11.312c-1.5669-1.5669-3.6113-2.3516-5.6562-2.3516zm73.539 0c-2.045 0-4.0893.78461-5.6562 2.3516l-11.314 11.312c-3.1339 3.1339-3.1339 8.1806 0 11.314s8.1806 3.1339 11.314 0l11.312-11.314c3.1339-3.1339 3.1339-8.1786 0-11.312-1.567-1.5669-3.6113-2.3516-5.6562-2.3516zm-36.77 20.777a24 24 0 0 0 -24 24 24 24 0 0 0 24 24 24 24 0 0 0 24-24 24 24 0 0 0 -24-24zm-52 16c-4.432 0-8 3.568-8 8s3.568 8 8 8h16c4.432 0 8-3.568 8-8s-3.568-8-8-8zm88 0c-4.432 0-8 3.568-8 8s3.568 8 8 8h16c4.432 0 8-3.568 8-8s-3.568-8-8-8zm-61.455 25.449c-2.045 0-4.0913.78266-5.6582 2.3496l-11.312 11.314c-3.1339 3.1339-3.1339 8.1786 0 11.312 3.1339 3.1339 8.1786 3.1339 11.312 0l11.314-11.312c3.1339-3.1339 3.1339-8.1806 0-11.314-1.5669-1.5669-3.6113-2.3496-5.6562-2.3496zm50.91 0c-2.045 0-4.0893.78266-5.6562 2.3496-3.1339 3.1339-3.1339 8.1806 0 11.314l11.314 11.312c3.1339 3.1339 8.1786 3.1339 11.312 0s3.1339-8.1786 0-11.312l-11.312-11.314c-1.5669-1.5669-3.6132-2.3496-5.6582-2.3496zm-25.455 10.551c-4.432 0-8 3.568-8 8v16c0 4.432 3.568 8 8 8s8-3.568 8-8v-16c0-4.432-3.568-8-8-8z" fill-opacity=".29412" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2"/><path d="m64 8c-2.216 0-4 1.784-4 4v16c0 2.216 1.784 4 4 4s4-1.784 4-4v-16c0-2.216-1.784-4-4-4zm-36.77 15.227c-1.0225 0-2.0447.39231-2.8281 1.1758-1.5669 1.5669-1.5669 4.0893 0 5.6562l11.312 11.314c1.5669 1.5669 4.0913 1.5669 5.6582 0s1.5669-4.0913 0-5.6582l-11.314-11.312c-.78348-.78348-1.8056-1.1758-2.8281-1.1758zm73.539 0c-1.0225 0-2.0446.39231-2.8281 1.1758l-11.314 11.312c-1.5669 1.5669-1.5669 4.0913 0 5.6582s4.0913 1.5669 5.6582 0l11.313-11.314c1.5669-1.5669 1.5669-4.0893 0-5.6562-.78348-.78348-1.8056-1.1758-2.8281-1.1758zm-36.77 20.773c-11.046.00001-20 8.9543-20 20 .000007 11.046 8.9543 20 20 20s20-8.9543 20-20c-.000008-11.046-8.9543-20-20-20zm-52 16c-2.216 0-4 1.784-4 4s1.784 4 4 4h16c2.216 0 4-1.784 4-4s-1.784-4-4-4zm88 0c-2.216 0-4 1.784-4 4s1.784 4 4 4h16c2.216 0 4-1.784 4-4s-1.784-4-4-4zm-61.455 25.453c-1.0225 0-2.0466.39035-2.8301 1.1738l-11.312 11.314c-1.5669 1.5669-1.5669 4.0893 0 5.6563 1.5669 1.5669 4.0893 1.5669 5.6562 0l11.314-11.313c1.5669-1.5669 1.5669-4.0913 0-5.6582-.78347-.78347-1.8056-1.1738-2.8281-1.1738zm50.91 0c-1.0225 0-2.0447.39035-2.8281 1.1738-1.5669 1.5669-1.5669 4.0913 0 5.6582l11.314 11.313c1.5669 1.5669 4.0893 1.5669 5.6563 0 1.5669-1.567 1.5669-4.0893 0-5.6563l-11.313-11.314c-.78347-.78347-1.8076-1.1738-2.8301-1.1738zm-25.455 10.547c-2.216 0-4 1.784-4 4v16c0 2.216 1.784 4 4 4s4-1.784 4-4v-16c0-2.216-1.784-4-4-4z" fill="#ffffff"/></svg> +<svg height="128" viewBox="0 0 128 128" width="128" xmlns="http://www.w3.org/2000/svg"><path d="m64 4c-4.432 0-8 3.568-8 8v16c0 4.432 3.568 8 8 8s8-3.568 8-8v-16c0-4.432-3.568-8-8-8zm-36.77 15.223c-2.045 0-4.0893.78461-5.6562 2.3516-3.1339 3.1339-3.1339 8.1786 0 11.312l11.312 11.314c3.1339 3.1339 8.1806 3.1339 11.314 0s3.1339-8.1806 0-11.314l-11.314-11.312c-1.5669-1.5669-3.6113-2.3516-5.6562-2.3516zm73.539 0c-2.045 0-4.0893.78461-5.6562 2.3516l-11.314 11.312c-3.1339 3.1339-3.1339 8.1806 0 11.314s8.1806 3.1339 11.314 0l11.312-11.314c3.1339-3.1339 3.1339-8.1786 0-11.312-1.567-1.5669-3.6113-2.3516-5.6562-2.3516zm-36.77 20.777a24 24 0 0 0 -24 24 24 24 0 0 0 24 24 24 24 0 0 0 24-24 24 24 0 0 0 -24-24zm-52 16c-4.432 0-8 3.568-8 8s3.568 8 8 8h16c4.432 0 8-3.568 8-8s-3.568-8-8-8zm88 0c-4.432 0-8 3.568-8 8s3.568 8 8 8h16c4.432 0 8-3.568 8-8s-3.568-8-8-8zm-61.455 25.449c-2.045 0-4.0913.78266-5.6582 2.3496l-11.312 11.314c-3.1339 3.1339-3.1339 8.1786 0 11.312 3.1339 3.1339 8.1786 3.1339 11.312 0l11.314-11.312c3.1339-3.1339 3.1339-8.1806 0-11.314-1.5669-1.5669-3.6113-2.3496-5.6562-2.3496zm50.91 0c-2.045 0-4.0893.78266-5.6562 2.3496-3.1339 3.1339-3.1339 8.1806 0 11.314l11.314 11.312c3.1339 3.1339 8.1786 3.1339 11.312 0s3.1339-8.1786 0-11.312l-11.312-11.314c-1.5669-1.5669-3.6132-2.3496-5.6582-2.3496zm-25.455 10.551c-4.432 0-8 3.568-8 8v16c0 4.432 3.568 8 8 8s8-3.568 8-8v-16c0-4.432-3.568-8-8-8z" fill-opacity=".29412" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/><path d="m64 8c-2.216 0-4 1.784-4 4v16c0 2.216 1.784 4 4 4s4-1.784 4-4v-16c0-2.216-1.784-4-4-4zm-36.77 15.227c-1.0225 0-2.0447.39231-2.8281 1.1758-1.5669 1.5669-1.5669 4.0893 0 5.6562l11.312 11.314c1.5669 1.5669 4.0913 1.5669 5.6582 0s1.5669-4.0913 0-5.6582l-11.314-11.312c-.78348-.78348-1.8056-1.1758-2.8281-1.1758zm73.539 0c-1.0225 0-2.0446.39231-2.8281 1.1758l-11.314 11.312c-1.5669 1.5669-1.5669 4.0913 0 5.6582s4.0913 1.5669 5.6582 0l11.313-11.314c1.5669-1.5669 1.5669-4.0893 0-5.6562-.78348-.78348-1.8056-1.1758-2.8281-1.1758zm-36.77 20.773c-11.046.00001-20 8.9543-20 20 .000007 11.046 8.9543 20 20 20s20-8.9543 20-20c-.000008-11.046-8.9543-20-20-20zm-52 16c-2.216 0-4 1.784-4 4s1.784 4 4 4h16c2.216 0 4-1.784 4-4s-1.784-4-4-4zm88 0c-2.216 0-4 1.784-4 4s1.784 4 4 4h16c2.216 0 4-1.784 4-4s-1.784-4-4-4zm-61.455 25.453c-1.0225 0-2.0466.39035-2.8301 1.1738l-11.312 11.314c-1.5669 1.5669-1.5669 4.0893 0 5.6563 1.5669 1.5669 4.0893 1.5669 5.6562 0l11.314-11.313c1.5669-1.5669 1.5669-4.0913 0-5.6582-.78347-.78347-1.8056-1.1738-2.8281-1.1738zm50.91 0c-1.0225 0-2.0447.39035-2.8281 1.1738-1.5669 1.5669-1.5669 4.0913 0 5.6582l11.314 11.313c1.5669 1.5669 4.0893 1.5669 5.6563 0 1.5669-1.567 1.5669-4.0893 0-5.6563l-11.313-11.314c-.78347-.78347-1.8076-1.1738-2.8301-1.1738zm-25.455 10.547c-2.216 0-4 1.784-4 4v16c0 2.216 1.784 4 4 4s4-1.784 4-4v-16c0-2.216-1.784-4-4-4z" fill="#ffffff"/></svg> diff --git a/editor/icons/GizmoLight.svg b/editor/icons/GizmoLight.svg index 0f74ebbd3d..ff224f32c9 100644 --- a/editor/icons/GizmoLight.svg +++ b/editor/icons/GizmoLight.svg @@ -1 +1 @@ -<svg height="128" viewBox="0 0 128 128" width="128" xmlns="http://www.w3.org/2000/svg"><path d="m64 2a44 44 0 0 0 -44 44 44 44 0 0 0 24 39.189v5.8105 5 3c0 5.0515 3.3756 9.2769 8 10.578v16.422h24v-16.422c4.6244-1.3012 8-5.5266 8-10.578v-3-5-5.8574a44 44 0 0 0 24-39.143 44 44 0 0 0 -44-44zm0 20a24 24 0 0 1 24 24 24 24 0 0 1 -24 24 24 24 0 0 1 -24-24 24 24 0 0 1 24-24z" fill-opacity=".29412" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2.2"/><path d="m64 6a40 40 0 0 0 -40 40 40 40 0 0 0 24 36.607v15.393a8 8 0 0 0 8 8h16a8 8 0 0 0 8-8v-15.363a40 40 0 0 0 24-36.637 40 40 0 0 0 -40-40zm0 12a28 28 0 0 1 28 28 28 28 0 0 1 -28 28 28 28 0 0 1 -28-28 28 28 0 0 1 28-28zm-8 96v8h16v-8z" fill="#ffffff"/></svg> +<svg height="128" viewBox="0 0 128 128" width="128" xmlns="http://www.w3.org/2000/svg"><path d="m64 2a44 44 0 0 0 -44 44 44 44 0 0 0 24 39.189v5.8105 5 3c0 5.0515 3.3756 9.2769 8 10.578v16.422h24v-16.422c4.6244-1.3012 8-5.5266 8-10.578v-3-5-5.8574a44 44 0 0 0 24-39.143 44 44 0 0 0 -44-44zm0 20a24 24 0 0 1 24 24 24 24 0 0 1 -24 24 24 24 0 0 1 -24-24 24 24 0 0 1 24-24z" fill-opacity=".29412" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.2"/><path d="m64 6a40 40 0 0 0 -40 40 40 40 0 0 0 24 36.607v15.393a8 8 0 0 0 8 8h16a8 8 0 0 0 8-8v-15.363a40 40 0 0 0 24-36.637 40 40 0 0 0 -40-40zm0 12a28 28 0 0 1 28 28 28 28 0 0 1 -28 28 28 28 0 0 1 -28-28 28 28 0 0 1 28-28zm-8 96v8h16v-8z" fill="#ffffff"/></svg> diff --git a/editor/icons/GradientTexture2D.svg b/editor/icons/GradientTexture2D.svg index ef40323b8c..77d38cc089 100644 --- a/editor/icons/GradientTexture2D.svg +++ b/editor/icons/GradientTexture2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <g fill="#e0e0e0"> <path d="M 2,1 C 1.447715,1 1,1.4477153 1,2 v 12.000001 c 0,0.552285 0.447715,1 1,1 h 11.999999 c 0.552285,0 1,-0.447715 1,-1 V 2 c 0,-0.5522847 -0.447715,-1 -1,-1 z m 1,2.0000001 h 9.999999 V 11.000001 H 3 Z" fill-opacity="0.99608"/> <path d="m 5.5,3.5 v 1 h 1 v -1 z m 1,1 v 1 h 1 v -1 z m 1,0 h 1 v 1 h -1 v 1 h 1 v 1 h 1 v 1 h 1 v -1 h 1 v 1 h 1 v -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 z m 4,4 h -1 v 1 h 1 z m 0,1 v 1 h 1 v -1 z m -1,0 h -1 v 1 h 1 z m -1,0 v -1 h -1 v 1 z m -1,-1 v -1 h -1 v 1 z m -1,0 h -1 v 1 h 1 z m 0,-1 v -1 h -1 v 1 z m -1,-1 v -1 h -1 v 1 z" /> </g> </svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g fill="#e0e0e0"><path d="M 2,1 C 1.447715,1 1,1.4477153 1,2 v 12.000001 c 0,0.552285 0.447715,1 1,1 h 11.999999 c 0.552285,0 1,-0.447715 1,-1 V 2 c 0,-0.5522847 -0.447715,-1 -1,-1 z m 1,2.0000001 h 9.999999 V 11.000001 H 3 Z"/><path d="m 5.5,3.5 v 1 h 1 v -1 z m 1,1 v 1 h 1 v -1 z m 1,0 h 1 v 1 h -1 v 1 h 1 v 1 h 1 v 1 h 1 v -1 h 1 v 1 h 1 v -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 z m 4,4 h -1 v 1 h 1 z m 0,1 v 1 h 1 v -1 z m -1,0 h -1 v 1 h 1 z m -1,0 v -1 h -1 v 1 z m -1,-1 v -1 h -1 v 1 z m -1,0 h -1 v 1 h 1 z m 0,-1 v -1 h -1 v 1 z m -1,-1 v -1 h -1 v 1 z" /></g></svg> diff --git a/editor/icons/GrooveJoint2D.svg b/editor/icons/GrooveJoint2D.svg index 0f7b84096c..0305d27685 100644 --- a/editor/icons/GrooveJoint2D.svg +++ b/editor/icons/GrooveJoint2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 1037.4h-5v6h-5v2h5v6h5zm-7 0h-7v14h7v-4h-5v-6h5z" fill="#8da5f3" fill-opacity=".98824" transform="translate(0 -1036.4)"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 1037.4h-5v6h-5v2h5v6h5zm-7 0h-7v14h7v-4h-5v-6h5z" fill="#8da5f3" transform="translate(0 -1036.4)"/></svg> diff --git a/editor/icons/GroupViewport.svg b/editor/icons/GroupViewport.svg index 1c22046ba1..331890e1de 100644 --- a/editor/icons/GroupViewport.svg +++ b/editor/icons/GroupViewport.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v4h4v-4zm6 0v6h-6v10h10v-6h6v-10zm4 4h2v2h-2zm2 8v4h4v-4z" fill-opacity=".39216" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".98824" stroke-width=".5"/><path d="m7 1v6h-6v8h8v-6h6v-8zm2 2h4v4h-4z" fill="#e0e0e0"/><path d="m1 1v2c0 .0000234.446 0 1 0s1 .0000234 1 0v-2c0-.00002341-.446 0-1 0s-1-.00002341-1 0zm12 0v2c0 .0000234.446 0 1 0s1 .0000234 1 0v-2c0-.00002341-.446 0-1 0s-1-.00002341-1 0zm-12 12v2c0 .000023.446 0 1 0s1 .000023 1 0v-2c0-.000023-.446 0-1 0s-1-.000023-1 0zm12 0v2c0 .000023.446 0 1 0s1 .000023 1 0v-2c0-.000023-.446 0-1 0s-1-.000023-1 0z" fill="#fff"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m0 0v4h4v-4zm6 0v6h-6v10h10v-6h6v-10zm4 4h2v2h-2zm2 8v4h4v-4z" fill-opacity=".39216" stroke-linecap="round" stroke-linejoin="round" stroke-width=".5"/><path d="m7 1v6h-6v8h8v-6h6v-8zm2 2h4v4h-4z" fill="#e0e0e0"/><path d="m1 1v2c0 .0000234.446 0 1 0s1 .0000234 1 0v-2c0-.00002341-.446 0-1 0s-1-.00002341-1 0zm12 0v2c0 .0000234.446 0 1 0s1 .0000234 1 0v-2c0-.00002341-.446 0-1 0s-1-.00002341-1 0zm-12 12v2c0 .000023.446 0 1 0s1 .000023 1 0v-2c0-.000023-.446 0-1 0s-1-.000023-1 0zm12 0v2c0 .000023.446 0 1 0s1 .000023 1 0v-2c0-.000023-.446 0-1 0s-1-.000023-1 0z" fill="#fff"/></svg> diff --git a/editor/icons/Keyboard.svg b/editor/icons/Keyboard.svg index b6d963f9d7..b00ed5dd21 100644 --- a/editor/icons/Keyboard.svg +++ b/editor/icons/Keyboard.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16"><path d="M6.584 5.135 6.17 4.059l-.412 1.076h.826zm3.203 2.976a1.032 1.032 0 0 0-.287.041.953.953 0 0 0-.09.034c-.028.012-.057.024-.084.039a.912.912 0 0 0-.152.107.988.988 0 0 0-.23.305.937.937 0 0 0-.04.097 1.017 1.017 0 0 0-.068.323 1.553 1.553 0 0 0 0 .244 1.374 1.374 0 0 0 .068.328 1.03 1.03 0 0 0 .201.336c.023.022.045.044.069.064a.96.96 0 0 0 .152.104c.027.015.056.027.084.039.03.012.06.024.09.033a.965.965 0 0 0 .19.035 1.028 1.028 0 0 0 .197 0 .974.974 0 0 0 .36-.107.876.876 0 0 0 .077-.049.872.872 0 0 0 .074-.055.882.882 0 0 0 .13-.136.978.978 0 0 0 .177-.368 1.225 1.225 0 0 0 .035-.224 1.61 1.61 0 0 0 0-.244 1.361 1.361 0 0 0-.035-.223 1.092 1.092 0 0 0-.121-.285.87.87 0 0 0-.12-.15.862.862 0 0 0-.14-.124c-.025-.017-.05-.035-.078-.05-.027-.015-.056-.027-.086-.04a.892.892 0 0 0-.373-.074z" style="fill-opacity:.99607843;fill:#e0e0e0"/><path d="M4 2c-.616-.02-1.084.59-1 1.178.003 3-.007 6 .005 9 .057.577.672.889 1.203.822 2.631-.003 5.263.006 7.894-.005a.973.973 0 0 0 .898-1.09c-.003-3.002.007-6.005-.005-9.007-.042-.592-.643-.976-1.203-.898H4Zm1.475.646H6.89l1.865 4.27H7.268l-.286-.744H5.36l-.287.744H3.61l1.866-4.27Zm4.312 4.301c1.069-.042 2.164.679 2.363 1.766.232 1.01-.34 2.144-1.326 2.502.296.465.837-.109 1.06-.007l.544.642c-.64.756-1.883.677-2.605.084-.394-.448-.866-.673-1.409-.887-1.175-.66-1.391-2.456-.43-3.39.463-.486 1.141-.716 1.803-.71Z" style="fill:#e0e0e0;fill-opacity:.996078"/><path fill="#e0e0e0" d="M1 4v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4Z" style="fill-opacity:.996"/></svg> +<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16"><path fill="#e0e0e0" d="M6.584 5.135 6.17 4.059l-.412 1.076h.826zm3.203 2.976a1.032 1.032 0 0 0-.287.041.953.953 0 0 0-.09.034c-.028.012-.057.024-.084.039a.912.912 0 0 0-.152.107.988.988 0 0 0-.23.305.937.937 0 0 0-.04.097 1.017 1.017 0 0 0-.068.323 1.553 1.553 0 0 0 0 .244 1.374 1.374 0 0 0 .068.328 1.03 1.03 0 0 0 .201.336c.023.022.045.044.069.064a.96.96 0 0 0 .152.104c.027.015.056.027.084.039.03.012.06.024.09.033a.965.965 0 0 0 .19.035 1.028 1.028 0 0 0 .197 0 .974.974 0 0 0 .36-.107.876.876 0 0 0 .077-.049.872.872 0 0 0 .074-.055.882.882 0 0 0 .13-.136.978.978 0 0 0 .177-.368 1.225 1.225 0 0 0 .035-.224 1.61 1.61 0 0 0 0-.244 1.361 1.361 0 0 0-.035-.223 1.092 1.092 0 0 0-.121-.285.87.87 0 0 0-.12-.15.862.862 0 0 0-.14-.124c-.025-.017-.05-.035-.078-.05-.027-.015-.056-.027-.086-.04a.892.892 0 0 0-.373-.074z"/><path fill="#e0e0e0" d="M4 2c-.616-.02-1.084.59-1 1.178.003 3-.007 6 .005 9 .057.577.672.889 1.203.822 2.631-.003 5.263.006 7.894-.005a.973.973 0 0 0 .898-1.09c-.003-3.002.007-6.005-.005-9.007-.042-.592-.643-.976-1.203-.898H4Zm1.475.646H6.89l1.865 4.27H7.268l-.286-.744H5.36l-.287.744H3.61l1.866-4.27Zm4.312 4.301c1.069-.042 2.164.679 2.363 1.766.232 1.01-.34 2.144-1.326 2.502.296.465.837-.109 1.06-.007l.544.642c-.64.756-1.883.677-2.605.084-.394-.448-.866-.673-1.409-.887-1.175-.66-1.391-2.456-.43-3.39.463-.486 1.141-.716 1.803-.71Z"/><path fill="#e0e0e0" d="M1 4v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4Z"/></svg> diff --git a/editor/icons/KeyboardError.svg b/editor/icons/KeyboardError.svg index e20d133155..5cd6de9de8 100644 --- a/editor/icons/KeyboardError.svg +++ b/editor/icons/KeyboardError.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16"><path d="M4 2c-.616-.02-1.084.59-1 1.178.003 3-.007 6 .005 9 .057.577.672.889 1.203.822 2.631-.003 5.263.006 7.894-.005a.973.973 0 0 0 .898-1.09c-.003-3.002.007-6.005-.005-9.007-.042-.592-.643-.976-1.203-.898H4Zm4.223 1.262c1.06.005 2.29.257 2.92 1.197.532.862.275 2.057-.484 2.703-.346.382-.862.629-1.075 1.117.055.345-.33.172-.537.213H7.148c-.037-.749.503-1.335 1.026-1.796.406-.253.744-1.002.129-1.22-.626-.25-1.374.117-1.645.715l-2.08-1.039c.599-1.147 1.868-1.818 3.136-1.872.17-.013.339-.018.509-.018Zm.127 5.697c.798-.057 1.616.616 1.54 1.45-.023.81-.841 1.413-1.623 1.328-.833.022-1.6-.771-1.443-1.613.097-.721.83-1.195 1.526-1.165z" style="fill:#ff5f5f;fill-opacity:1"/><path fill="#e0e0e0" d="M1 4v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4Z" style="fill-opacity:1;fill:#ff5f5f"/></svg> +<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16"><path fill="#ff5f5f" d="M4 2c-.616-.02-1.084.59-1 1.178.003 3-.007 6 .005 9 .057.577.672.889 1.203.822 2.631-.003 5.263.006 7.894-.005a.973.973 0 0 0 .898-1.09c-.003-3.002.007-6.005-.005-9.007-.042-.592-.643-.976-1.203-.898H4Zm4.223 1.262c1.06.005 2.29.257 2.92 1.197.532.862.275 2.057-.484 2.703-.346.382-.862.629-1.075 1.117.055.345-.33.172-.537.213H7.148c-.037-.749.503-1.335 1.026-1.796.406-.253.744-1.002.129-1.22-.626-.25-1.374.117-1.645.715l-2.08-1.039c.599-1.147 1.868-1.818 3.136-1.872.17-.013.339-.018.509-.018Zm.127 5.697c.798-.057 1.616.616 1.54 1.45-.023.81-.841 1.413-1.623 1.328-.833.022-1.6-.771-1.443-1.613.097-.721.83-1.195 1.526-1.165z"/><path fill="#ff5f5f" d="M1 4v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4Z"/></svg> diff --git a/editor/icons/KeyboardLabel.svg b/editor/icons/KeyboardLabel.svg index 07a687f447..25e02fd653 100644 --- a/editor/icons/KeyboardLabel.svg +++ b/editor/icons/KeyboardLabel.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M11.814 1.977c-.078 0-.157.008-.232.023H4c-.7-.034-1.143.765-1 1.39.008 2.95-.017 5.9.014 8.848.13.705.965.847 1.562.76 2.542-.008 5.085.02 7.627-.014.734-.1.9-.952.797-1.564-.003-2.84.006-5.68-.006-8.522-.035-.594-.628-.927-1.18-.921zM9.797 4.016l.572.58-.572.578-.57-.578.57-.58zm-.606 1.05.594.606-.594.601-.591-.601.591-.606zm1.213 0 .596.606-.596.601-.593-.601.593-.606zm.717 1.436h1.06c.053.217.093.428.122.63.028.201.043.395.043.58a2.363 2.363 0 0 1-.133.724 1.425 1.425 0 0 1-.31.515c-.249.265-.598.399-1.05.399-.331 0-.594-.08-.785-.235a1.091 1.091 0 0 1-.236-.275c-.063.1-.14.19-.236.265-.206.163-.467.245-.787.245-.252 0-.457-.057-.614-.166a2.75 2.75 0 0 1-.095.42 1.936 1.936 0 0 1-.403.722c-.2.22-.452.383-.756.49-.303.11-.654.166-1.052.166-.466 0-.865-.089-1.2-.265a1.817 1.817 0 0 1-.765-.752c-.18-.327-.27-.715-.27-1.164 0-.256.027-.525.082-.809.055-.284.126-.545.21-.781h1.001c-.062.232-.112.46-.15.684a3.87 3.87 0 0 0-.053.613c0 .37.1.643.3.82.204.177.523.264.96.264.222 0 .425-.03.61-.092a.97.97 0 0 0 .439-.299.803.803 0 0 0 .166-.521 5.463 5.463 0 0 0-.051-.725 11.61 11.61 0 0 0-.068-.482 26.51 26.51 0 0 0-.096-.606h1.135l.043.276c.047.32.123.532.228.634.105.1.24.15.402.15.165 0 .284-.04.358-.124.076-.086.115-.224.115-.412v-.524h1.027v.524c0 .203.032.351.096.447.065.095.202.142.412.142a.637.637 0 0 0 .33-.078c.089-.052.133-.15.133-.297 0-.128-.019-.295-.054-.498l-.108-.605z" style="fill:#e0e0e0;fill-opacity:.996078"/><path fill="#e0e0e0" d="M1 4v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4Z" style="fill-opacity:.996"/></svg> +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="M11.814 1.977c-.078 0-.157.008-.232.023H4c-.7-.034-1.143.765-1 1.39.008 2.95-.017 5.9.014 8.848.13.705.965.847 1.562.76 2.542-.008 5.085.02 7.627-.014.734-.1.9-.952.797-1.564-.003-2.84.006-5.68-.006-8.522-.035-.594-.628-.927-1.18-.921zM9.797 4.016l.572.58-.572.578-.57-.578.57-.58zm-.606 1.05.594.606-.594.601-.591-.601.591-.606zm1.213 0 .596.606-.596.601-.593-.601.593-.606zm.717 1.436h1.06c.053.217.093.428.122.63.028.201.043.395.043.58a2.363 2.363 0 0 1-.133.724 1.425 1.425 0 0 1-.31.515c-.249.265-.598.399-1.05.399-.331 0-.594-.08-.785-.235a1.091 1.091 0 0 1-.236-.275c-.063.1-.14.19-.236.265-.206.163-.467.245-.787.245-.252 0-.457-.057-.614-.166a2.75 2.75 0 0 1-.095.42 1.936 1.936 0 0 1-.403.722c-.2.22-.452.383-.756.49-.303.11-.654.166-1.052.166-.466 0-.865-.089-1.2-.265a1.817 1.817 0 0 1-.765-.752c-.18-.327-.27-.715-.27-1.164 0-.256.027-.525.082-.809.055-.284.126-.545.21-.781h1.001c-.062.232-.112.46-.15.684a3.87 3.87 0 0 0-.053.613c0 .37.1.643.3.82.204.177.523.264.96.264.222 0 .425-.03.61-.092a.97.97 0 0 0 .439-.299.803.803 0 0 0 .166-.521 5.463 5.463 0 0 0-.051-.725 11.61 11.61 0 0 0-.068-.482 26.51 26.51 0 0 0-.096-.606h1.135l.043.276c.047.32.123.532.228.634.105.1.24.15.402.15.165 0 .284-.04.358-.124.076-.086.115-.224.115-.412v-.524h1.027v.524c0 .203.032.351.096.447.065.095.202.142.412.142a.637.637 0 0 0 .33-.078c.089-.052.133-.15.133-.297 0-.128-.019-.295-.054-.498l-.108-.605z"/><path fill="#e0e0e0" d="M1 4v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4Z"/></svg> diff --git a/editor/icons/KeyboardPhysical.svg b/editor/icons/KeyboardPhysical.svg index 7d4b7e2999..877b9b89b9 100644 --- a/editor/icons/KeyboardPhysical.svg +++ b/editor/icons/KeyboardPhysical.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="M4 2a1 1 0 0 0-1 1v9.084c0 .506.448.916 1 .916h8c.552 0 1-.41 1-.916V3a1 1 0 0 0-1-1Zm2.762 1.768h2.476l3.264 7.464H9.898l-.502-1.3H6.561l-.502 1.3H3.498Zm1.217 2.474L7.254 8.12h1.45z" style="fill-opacity:.996"/><path fill="#e0e0e0" d="M1 4v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4Z" style="fill-opacity:.996"/></svg> +<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="M4 2a1 1 0 0 0-1 1v9.084c0 .506.448.916 1 .916h8c.552 0 1-.41 1-.916V3a1 1 0 0 0-1-1Zm2.762 1.768h2.476l3.264 7.464H9.898l-.502-1.3H6.561l-.502 1.3H3.498Zm1.217 2.474L7.254 8.12h1.45z"/><path fill="#e0e0e0" d="M1 4v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-1v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4Z"/></svg> diff --git a/editor/icons/LabelSettings.svg b/editor/icons/LabelSettings.svg index 4dc3b9e86e..f85165f805 100644 --- a/editor/icons/LabelSettings.svg +++ b/editor/icons/LabelSettings.svg @@ -1 +1 @@ -<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M6 3a1 1 0 0 0-.707.293l-4 4a1 1 0 0 0 0 1.414l4 4A1 1 0 0 0 6 13h2.076a3.766 3.766 0 0 1-.058-.496c-.003-.058-.006-.115-.006-.174a2.606 2.606 0 0 1 .05-.508 3.212 3.212 0 0 1 .133-.496 5.104 5.104 0 0 1 .451-.982 8.303 8.303 0 0 1 .422-.656 14.41 14.41 0 0 1 .489-.667c.172-.223.351-.45.535-.68.163-.203.327-.408.492-.618a27.639 27.639 0 0 0 .732-.977 16.04 16.04 0 0 0 .465-.697c.075-.12.147-.242.219-.365a12.399 12.399 0 0 0 .684 1.062 27.555 27.555 0 0 0 .73.977c.165.21.331.415.494.619a43.298 43.298 0 0 1 .787 1.013c.082.111.16.222.237.332L15 9.79V4a1 1 0 0 0-1-1H6zM5 7a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" style="fill:#8eef97;fill-opacity:1"/><path d="M9.184 13A2.99 2.99 0 0 0 12 15a2.99 2.99 0 0 0 2.816-2z" fill="#ff4596"/><path d="M9.23 11c-.136.326-.23.656-.23 1 0 .352.072.686.184 1h5.632c.112-.314.184-.648.184-1 0-.344-.094-.674-.23-1H9.23z" fill="#8045ff"/><path d="M10.564 9c-.552.69-1.058 1.342-1.334 2h5.54c-.276-.658-.782-1.31-1.335-2Z" fill="#45d7ff"/><path d="M12 7c-.43.746-.945 1.387-1.435 2h2.87c-.49-.613-1.005-1.254-1.435-2Z" fill="#45ffa2"/></svg> +<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M6 3a1 1 0 0 0-.707.293l-4 4a1 1 0 0 0 0 1.414l4 4A1 1 0 0 0 6 13h2.076a3.766 3.766 0 0 1-.058-.496c-.003-.058-.006-.115-.006-.174a2.606 2.606 0 0 1 .05-.508 3.212 3.212 0 0 1 .133-.496 5.104 5.104 0 0 1 .451-.982 8.303 8.303 0 0 1 .422-.656 14.41 14.41 0 0 1 .489-.667c.172-.223.351-.45.535-.68.163-.203.327-.408.492-.618a27.639 27.639 0 0 0 .732-.977 16.04 16.04 0 0 0 .465-.697c.075-.12.147-.242.219-.365a12.399 12.399 0 0 0 .684 1.062 27.555 27.555 0 0 0 .73.977c.165.21.331.415.494.619a43.298 43.298 0 0 1 .787 1.013c.082.111.16.222.237.332L15 9.79V4a1 1 0 0 0-1-1H6zM5 7a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#8eef97"/><path d="M9.184 13A2.99 2.99 0 0 0 12 15a2.99 2.99 0 0 0 2.816-2z" fill="#ff4596"/><path d="M9.23 11c-.136.326-.23.656-.23 1 0 .352.072.686.184 1h5.632c.112-.314.184-.648.184-1 0-.344-.094-.674-.23-1H9.23z" fill="#8045ff"/><path d="M10.564 9c-.552.69-1.058 1.342-1.334 2h5.54c-.276-.658-.782-1.31-1.335-2Z" fill="#45d7ff"/><path d="M12 7c-.43.746-.945 1.387-1.435 2h2.87c-.49-.613-1.005-1.254-1.435-2Z" fill="#45ffa2"/></svg> diff --git a/editor/icons/LightOccluder2D.svg b/editor/icons/LightOccluder2D.svg index ff2c4d4561..7765aecbc3 100644 --- a/editor/icons/LightOccluder2D.svg +++ b/editor/icons/LightOccluder2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1037.4c-2.7614 0-5 2.2386-5 5 .00253 1.9858 1.18 3.7819 3 4.5762v2.4238h4v-2.4199c1.8213-.7949 2.999-2.5929 3-4.5801 0-2.7614-2.2386-5-5-5zm0 2v6c-1.6569 0-3-1.3431-3-3s1.3431-3 3-3zm-1 11v1h2v-1z" fill="#8da5f3" fill-opacity=".98824" transform="translate(0 -1036.4)"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1037.4c-2.7614 0-5 2.2386-5 5 .00253 1.9858 1.18 3.7819 3 4.5762v2.4238h4v-2.4199c1.8213-.7949 2.999-2.5929 3-4.5801 0-2.7614-2.2386-5-5-5zm0 2v6c-1.6569 0-3-1.3431-3-3s1.3431-3 3-3zm-1 11v1h2v-1z" fill="#8da5f3" transform="translate(0 -1036.4)"/></svg> diff --git a/editor/icons/LockViewport.svg b/editor/icons/LockViewport.svg index c8b8a57be6..e1d26bc4b0 100644 --- a/editor/icons/LockViewport.svg +++ b/editor/icons/LockViewport.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 0a6 6 0 0 0 -6 6v1h-1v9h14v-9h-1v-1a6 6 0 0 0 -6-6zm0 4c1.1046 0 2 .89543 2 2v1h-4v-1c0-1.1046.89543-2 2-2z" fill-opacity=".39216" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="4"/><path d="m8 1a5 5 0 0 0 -5 5v2h-1v7h12v-7h-1v-2a5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3v2h-6v-2a3 3 0 0 1 3-3zm-1 7h2v3h-2z" fill="#e0e0e0"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 0a6 6 0 0 0 -6 6v1h-1v9h14v-9h-1v-1a6 6 0 0 0 -6-6zm0 4c1.1046 0 2 .89543 2 2v1h-4v-1c0-1.1046.89543-2 2-2z" fill-opacity=".39216" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/><path d="m8 1a5 5 0 0 0 -5 5v2h-1v7h12v-7h-1v-2a5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3v2h-6v-2a3 3 0 0 1 3-3zm-1 7h2v3h-2z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/Marker2D.svg b/editor/icons/Marker2D.svg index 191f0b2a03..aa7836c3ef 100644 --- a/editor/icons/Marker2D.svg +++ b/editor/icons/Marker2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v4h2v-4zm-6 6v2h4v-2zm10 0v2h4v-2zm-4 4v4h2v-4z" fill="#8da5f3" fill-opacity=".98824"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7 1v4h2v-4zm-6 6v2h4v-2zm10 0v2h4v-2zm-4 4v4h2v-4z" fill="#8da5f3"/></svg> diff --git a/editor/icons/MultiplayerSpawner.svg b/editor/icons/MultiplayerSpawner.svg index 68ffd3aab4..9e6d6a4a7c 100644 --- a/editor/icons/MultiplayerSpawner.svg +++ b/editor/icons/MultiplayerSpawner.svg @@ -1 +1 @@ -<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path style="fill:none;fill-opacity:.996078;stroke:#e0e0e0;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:16.5;stroke-opacity:1;paint-order:stroke markers fill" d="M4.936 7.429A4 4 0 0 1 8 6a4 4 0 0 1 3.064 1.429M1.872 4.858A8 8 0 0 1 8 2a8 8 0 0 1 6.128 2.858"/><path d="M7 9v2H5v2h2v2h2v-2h2v-2H9V9Z" fill="#5fff97"/></svg> +<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path style="fill:none;stroke:#e0e0e0;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:16.5;paint-order:stroke markers fill" d="M4.936 7.429A4 4 0 0 1 8 6a4 4 0 0 1 3.064 1.429M1.872 4.858A8 8 0 0 1 8 2a8 8 0 0 1 6.128 2.858"/><path d="M7 9v2H5v2h2v2h2v-2h2v-2H9V9Z" fill="#5fff97"/></svg> diff --git a/editor/icons/MultiplayerSynchronizer.svg b/editor/icons/MultiplayerSynchronizer.svg index 1547ec5a2b..4137b9dba0 100644 --- a/editor/icons/MultiplayerSynchronizer.svg +++ b/editor/icons/MultiplayerSynchronizer.svg @@ -1 +1 @@ -<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path style="fill:#5fff97;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" d="M5 10h3l-2 4-2-4Z"/><path style="fill:#ff5f5f;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" d="M9 14h3l-2-4-2 4Z"/><path style="fill:none;fill-opacity:.996078;stroke:#e0e0e0;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:16.5;stroke-opacity:1;paint-order:stroke markers fill" d="M4.936 7.429A4 4 0 0 1 8 6a4 4 0 0 1 3.064 1.429M1.872 4.858A8 8 0 0 1 8 2a8 8 0 0 1 6.128 2.858"/></svg> +<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path style="fill:#5fff97;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke fill markers" d="M5 10h3l-2 4-2-4Z"/><path style="fill:#ff5f5f;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke fill markers" d="M9 14h3l-2-4-2 4Z"/><path style="fill:none;stroke:#e0e0e0;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:16.5;paint-order:stroke markers fill" d="M4.936 7.429A4 4 0 0 1 8 6a4 4 0 0 1 3.064 1.429M1.872 4.858A8 8 0 0 1 8 2a8 8 0 0 1 6.128 2.858"/></svg> diff --git a/editor/icons/Navigation2D.svg b/editor/icons/Navigation2D.svg index aa3e258eae..286fcb8d4c 100644 --- a/editor/icons/Navigation2D.svg +++ b/editor/icons/Navigation2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1050.4 5-2 5 2-5-12z" fill="#8da5f3" fill-opacity=".98824" fill-rule="evenodd" transform="translate(0 -1036.4)"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1050.4 5-2 5 2-5-12z" fill="#8da5f3" fill-rule="evenodd" transform="translate(0 -1036.4)"/></svg> diff --git a/editor/icons/NavigationAgent2D.svg b/editor/icons/NavigationAgent2D.svg index 05aeb95e12..c5b543e638 100644 --- a/editor/icons/NavigationAgent2D.svg +++ b/editor/icons/NavigationAgent2D.svg @@ -1 +1 @@ -<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1v2.5c1.371 0 2.5 1.129 2.5 2.5s-1.129 2.5-2.5 2.5v6.5c2-3 5.007-6.03 5-9 0-3-2-5-5-5z" fill="#8da5f3" fill-opacity=".988235"/><path d="m8 1c-3 0-5 2-5 5s3 6 5 9v-6.5c-1.371 0-2.5-1.129-2.5-2.5s1.129-2.5 2.5-2.5z" fill="#e0e0e0"/></svg> +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1v2.5c1.371 0 2.5 1.129 2.5 2.5s-1.129 2.5-2.5 2.5v6.5c2-3 5.007-6.03 5-9 0-3-2-5-5-5z" fill="#8da5f3"/><path d="m8 1c-3 0-5 2-5 5s3 6 5 9v-6.5c-1.371 0-2.5-1.129-2.5-2.5s1.129-2.5 2.5-2.5z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/NavigationObstacle2D.svg b/editor/icons/NavigationObstacle2D.svg index a5073898f4..af88325240 100644 --- a/editor/icons/NavigationObstacle2D.svg +++ b/editor/icons/NavigationObstacle2D.svg @@ -1 +1 @@ -<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 .875c-.625 0-1.25.375-1.5 1.125l-3 10h4.5v-3h-2.5l1-4h1.5zm-6 12.125c-1 0-1 2 0 2h6v-2z" fill="#e0e0e0"/><path d="m8 .875v4.125h1.5l1 4h-2.5v3h4.5l-3-10c-.25-.75-.875-1.125-1.5-1.125zm0 12.125v2h6c1 0 1-2 0-2z" fill="#8da5f3" fill-opacity=".988235"/></svg> +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 .875c-.625 0-1.25.375-1.5 1.125l-3 10h4.5v-3h-2.5l1-4h1.5zm-6 12.125c-1 0-1 2 0 2h6v-2z" fill="#e0e0e0"/><path d="m8 .875v4.125h1.5l1 4h-2.5v3h4.5l-3-10c-.25-.75-.875-1.125-1.5-1.125zm0 12.125v2h6c1 0 1-2 0-2z" fill="#8da5f3"/></svg> diff --git a/editor/icons/NavigationRegion2D.svg b/editor/icons/NavigationRegion2D.svg index 8efd836075..30e2138e82 100644 --- a/editor/icons/NavigationRegion2D.svg +++ b/editor/icons/NavigationRegion2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.1339223.0000569-.2535666.0306675-.3652344.0742188-.022275.0088111-.0410424.0209185-.0625.03125-.0889622.0424668-.1681009.0954994-.2382812.1601562-.0215322.0195204-.0427394.0372854-.0625.0585938-.0741112.0810923-.13722.1698052-.1816406.2695312-.0034324.0076504-.0084746.0137334-.0117188.0214844l-.0019531.0019531c-.0452252.1091882-.0629923.2268973-.0683594.3457031-.0005086.0130821-.0078112.023903-.0078125.0371094v12c.0000552.552262.4477381.999945 1 1h4.8847656a2.1184381 2.1184381 0 0 1 .1328125-.744141l2.9999999-7.9999996a2.1184381 2.1184381 0 0 1 2.007813-1.3730469 2.1184381 2.1184381 0 0 1 1.957031 1.3730469l1.017578 2.7128906v-6.96875c-.000001-.0132064-.007305-.0240273-.007812-.0371094-.005369-.1188058-.023135-.2365149-.06836-.3457031l-.001953-.0019531c-.003155-.0075626-.008384-.0139987-.011719-.0214844-.044421-.099726-.107529-.188439-.18164-.2695312-.019761-.0213083-.040968-.0390734-.0625-.0585938-.070181-.0646568-.149319-.1176895-.238282-.1601562-.021457-.0103315-.040225-.022439-.0625-.03125-.111667-.0435511-.231312-.0741619-.365234-.0742188zm10 6-3 8 3-2 3 2z" fill="#8da5f3" fill-opacity=".98824" fill-rule="evenodd"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2 1c-.1339223.0000569-.2535666.0306675-.3652344.0742188-.022275.0088111-.0410424.0209185-.0625.03125-.0889622.0424668-.1681009.0954994-.2382812.1601562-.0215322.0195204-.0427394.0372854-.0625.0585938-.0741112.0810923-.13722.1698052-.1816406.2695312-.0034324.0076504-.0084746.0137334-.0117188.0214844l-.0019531.0019531c-.0452252.1091882-.0629923.2268973-.0683594.3457031-.0005086.0130821-.0078112.023903-.0078125.0371094v12c.0000552.552262.4477381.999945 1 1h4.8847656a2.1184381 2.1184381 0 0 1 .1328125-.744141l2.9999999-7.9999996a2.1184381 2.1184381 0 0 1 2.007813-1.3730469 2.1184381 2.1184381 0 0 1 1.957031 1.3730469l1.017578 2.7128906v-6.96875c-.000001-.0132064-.007305-.0240273-.007812-.0371094-.005369-.1188058-.023135-.2365149-.06836-.3457031l-.001953-.0019531c-.003155-.0075626-.008384-.0139987-.011719-.0214844-.044421-.099726-.107529-.188439-.18164-.2695312-.019761-.0213083-.040968-.0390734-.0625-.0585938-.070181-.0646568-.149319-.1176895-.238282-.1601562-.021457-.0103315-.040225-.022439-.0625-.03125-.111667-.0435511-.231312-.0741619-.365234-.0742188zm10 6-3 8 3-2 3 2z" fill="#8da5f3" fill-rule="evenodd"/></svg> diff --git a/editor/icons/NewKey.svg b/editor/icons/NewKey.svg index fc8507e6c4..266b763329 100644 --- a/editor/icons/NewKey.svg +++ b/editor/icons/NewKey.svg @@ -1 +1 @@ -<svg enable-background="new 0 0 16 16" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".9961"><path d="m13 9h-2v2h-2v2h2v2h2v-2h2v-2h-2z"/><path d="m10 9.723c-.596-.347-1-.985-1-1.723 0-1.104.896-2 2-2s2 .896 2 2h1v2h.445c.344-.591.555-1.268.555-2 0-2.209-1.791-4-4-4-1.822.002-3.414 1.235-3.869 3h-6.131v2h1v2h3v-2h2.133c.16.62.466 1.169.867 1.627v-.627h2z"/></g></svg> +<svg enable-background="new 0 0 16 16" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m13 9h-2v2h-2v2h2v2h2v-2h2v-2h-2z"/><path d="m10 9.723c-.596-.347-1-.985-1-1.723 0-1.104.896-2 2-2s2 .896 2 2h1v2h.445c.344-.591.555-1.268.555-2 0-2.209-1.791-4-4-4-1.822.002-3.414 1.235-3.869 3h-6.131v2h1v2h3v-2h2.133c.16.62.466 1.169.867 1.627v-.627h2z"/></g></svg> diff --git a/editor/icons/OccluderPolygon2D.svg b/editor/icons/OccluderPolygon2D.svg index 7ab4240d2f..b8e67b76dd 100644 --- a/editor/icons/OccluderPolygon2D.svg +++ b/editor/icons/OccluderPolygon2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd" transform="translate(0 -1036.4)"><path d="m1 1045.4 6 6h8v-8l-6-6h-8z" fill="#4b70ea"/><path d="m1 1037.4h8l-3 4 3 4h-8z" fill="#8da5f3" fill-opacity=".98824"/></g></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd" transform="translate(0 -1036.4)"><path d="m1 1045.4 6 6h8v-8l-6-6h-8z" fill="#4b70ea"/><path d="m1 1037.4h8l-3 4 3 4h-8z" fill="#8da5f3"/></g></svg> diff --git a/editor/icons/ParallaxLayer.svg b/editor/icons/ParallaxLayer.svg index 58968b77fb..6945798e9c 100644 --- a/editor/icons/ParallaxLayer.svg +++ b/editor/icons/ParallaxLayer.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 1h10c.55228.0000096.99999.44772 1 1v10c-.00001.55228-.44772.99999-1 1h-10c-.55228-.00001-.99999-.44772-1-1v-10c.0000096-.55228.44772-.99999 1-1zm4 3-3 3 3 3zm2 0v6l3-3z" fill="#8da5f3" fill-opacity=".98824" fill-rule="evenodd" transform="translate(0 1036.4)"/></g></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm0 1h10c.55228.0000096.99999.44772 1 1v10c-.00001.55228-.44772.99999-1 1h-10c-.55228-.00001-.99999-.44772-1-1v-10c.0000096-.55228.44772-.99999 1-1zm4 3-3 3 3 3zm2 0v6l3-3z" fill="#8da5f3" fill-rule="evenodd" transform="translate(0 1036.4)"/></g></svg> diff --git a/editor/icons/Path2D.svg b/editor/icons/Path2D.svg index 494ca344be..cce8206df6 100644 --- a/editor/icons/Path2D.svg +++ b/editor/icons/Path2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 .84961 1.6328c-.19239.88508-.55317 1.3394-.98633 1.6426-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c.8927-.62488 1.5321-1.6538 1.8184-3.0977a2 2 0 0 0 1.1699-1.8164 2 2 0 0 0 -2-2z" fill="#8da5f3" fill-opacity=".98824"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 .84961 1.6328c-.19239.88508-.55317 1.3394-.98633 1.6426-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c.8927-.62488 1.5321-1.6538 1.8184-3.0977a2 2 0 0 0 1.1699-1.8164 2 2 0 0 0 -2-2z" fill="#8da5f3"/></svg> diff --git a/editor/icons/PathFollow2D.svg b/editor/icons/PathFollow2D.svg index a1fb97cf34..0e0cad6930 100644 --- a/editor/icons/PathFollow2D.svg +++ b/editor/icons/PathFollow2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 0-3 4h1.9473c-.1385 1.3203-.5583 1.9074-1.084 2.2754-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c1.0528-.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#8da5f3" fill-opacity=".98824"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 0-3 4h1.9473c-.1385 1.3203-.5583 1.9074-1.084 2.2754-.64426.451-1.7129.60547-2.9629.73047s-2.6814.22053-3.9121 1.082c-.89278.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -.84961-1.6328c.19235-.88496.55306-1.3373.98633-1.6406.64426-.451 1.7129-.60547 2.9629-.73047s2.6814-.22053 3.9121-1.082c1.0528-.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#8da5f3"/></svg> diff --git a/editor/icons/PinJoint2D.svg b/editor/icons/PinJoint2D.svg index fc7329e4f3..021af9c8f3 100644 --- a/editor/icons/PinJoint2D.svg +++ b/editor/icons/PinJoint2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1.2715-.70703.70703v1.4141l-2.1211 2.123 4.2422 4.2422 2.1211-2.1211h1.4141l.70703-.70703-5.6562-5.6582zm-3.5352 4.9512-3.5352.70703 7.0703 7.0703.70703-3.5352-4.2422-4.2422zm-1.4141 4.2422-1.4141 1.4141-.70703 2.1211 2.1211-.70703 1.4141-1.4141-1.4141-1.4141z" fill="#8da5f3" fill-opacity=".98824" fill-rule="evenodd"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 1.2715-.70703.70703v1.4141l-2.1211 2.123 4.2422 4.2422 2.1211-2.1211h1.4141l.70703-.70703-5.6562-5.6582zm-3.5352 4.9512-3.5352.70703 7.0703 7.0703.70703-3.5352-4.2422-4.2422zm-1.4141 4.2422-1.4141 1.4141-.70703 2.1211 2.1211-.70703 1.4141-1.4141-1.4141-1.4141z" fill="#8da5f3" fill-rule="evenodd"/></svg> diff --git a/editor/icons/PingPongLoop.svg b/editor/icons/PingPongLoop.svg index c44f889b49..61a701a81e 100644 --- a/editor/icons/PingPongLoop.svg +++ b/editor/icons/PingPongLoop.svg @@ -1 +1 @@ -<svg enable-background="new 0 0 16 16" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".9961"><path d="m10 7h-4v-2l-4 3 4 3v-2h4v2l4-3-4-3z"/><path d="m0 1v14h2v-7-7z"/><path d="m14 1v7 7h2v-14z"/></g></svg> +<svg enable-background="new 0 0 16 16" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m10 7h-4v-2l-4 3 4 3v-2h4v2l4-3-4-3z"/><path d="m0 1v14h2v-7-7z"/><path d="m14 1v7 7h2v-14z"/></g></svg> diff --git a/editor/icons/PlayRemote.svg b/editor/icons/PlayRemote.svg index ea2195294f..f69414e856 100644 --- a/editor/icons/PlayRemote.svg +++ b/editor/icons/PlayRemote.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16"><path d="m12.998 2.548-9.996.005a2.006 2.006 0 0 0-2.006 2v4.61c0 1.107.898 2.003 2.006 2.003h3.996v.9h-1.68v.381H3.001v2h2.315v.38h5.366v-.38H13v-2.004h-2.315v-.378H9.004v-.9h3.994a2.006 2.006 0 0 0 2.006-2.003v-4.61c0-1.106-.9-2.003-2.006-2.003zm-7.496 1.31 5 3-5 3z" style="fill:#e0e0e0;fill-opacity:1"/></svg> +<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="16" height="16"><path d="m12.998 2.548-9.996.005a2.006 2.006 0 0 0-2.006 2v4.61c0 1.107.898 2.003 2.006 2.003h3.996v.9h-1.68v.381H3.001v2h2.315v.38h5.366v-.38H13v-2.004h-2.315v-.378H9.004v-.9h3.994a2.006 2.006 0 0 0 2.006-2.003v-4.61c0-1.106-.9-2.003-2.006-2.003zm-7.496 1.31 5 3-5 3z" fill="#e0e0e0"/></svg> diff --git a/editor/icons/PointLight2D.svg b/editor/icons/PointLight2D.svg index 1a3222c79e..e4352ff6cd 100644 --- a/editor/icons/PointLight2D.svg +++ b/editor/icons/PointLight2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a5 5 0 0 0 -5 5 5 5 0 0 0 3 4.5762v2.4238h4v-2.4199a5 5 0 0 0 3-4.5801 5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3zm-1 11v1h2v-1z" fill="#8da5f3" fill-opacity=".98824"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a5 5 0 0 0 -5 5 5 5 0 0 0 3 4.5762v2.4238h4v-2.4199a5 5 0 0 0 3-4.5801 5 5 0 0 0 -5-5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3-3 3 3 0 0 1 3-3zm-1 11v1h2v-1z" fill="#8da5f3"/></svg> diff --git a/editor/icons/RemoteTransform2D.svg b/editor/icons/RemoteTransform2D.svg index 9d03db5c3b..bbe4109cd2 100644 --- a/editor/icons/RemoteTransform2D.svg +++ b/editor/icons/RemoteTransform2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.8565 0-5.4995 1.5262-6.9277 4a1 1 0 0 0 .36523 1.3672 1 1 0 0 0 1.3672-.36719c1.0726-1.8578 3.0501-3 5.1953-3s4.1227 1.1422 5.1953 3a1 1 0 0 0 1.3672.36719 1 1 0 0 0 .36523-1.3672c-1.4283-2.4738-4.0712-4-6.9277-4zm0 4c-1.8056 0-3.396 1.2207-3.8633 2.9648a1 1 0 0 0 .70703 1.2246 1 1 0 0 0 1.2246-.70703c.23553-.8791 1.0216-1.4824 1.9316-1.4824s1.6961.60332 1.9316 1.4824a1 1 0 0 0 1.2246.70703 1 1 0 0 0 .70703-1.2246c-.46732-1.7441-2.0577-2.9648-3.8633-2.9648zm0 4c-.554 0-1 .446-1 1v1h-3a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2-3.4648h-3v-1c0-.554-.446-1-1-1z" fill="#8da5f3" fill-opacity=".98824"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-2.8565 0-5.4995 1.5262-6.9277 4a1 1 0 0 0 .36523 1.3672 1 1 0 0 0 1.3672-.36719c1.0726-1.8578 3.0501-3 5.1953-3s4.1227 1.1422 5.1953 3a1 1 0 0 0 1.3672.36719 1 1 0 0 0 .36523-1.3672c-1.4283-2.4738-4.0712-4-6.9277-4zm0 4c-1.8056 0-3.396 1.2207-3.8633 2.9648a1 1 0 0 0 .70703 1.2246 1 1 0 0 0 1.2246-.70703c.23553-.8791 1.0216-1.4824 1.9316-1.4824s1.6961.60332 1.9316 1.4824a1 1 0 0 0 1.2246.70703 1 1 0 0 0 .70703-1.2246c-.46732-1.7441-2.0577-2.9648-3.8633-2.9648zm0 4c-.554 0-1 .446-1 1v1h-3a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2-3.4648h-3v-1c0-.554-.446-1-1-1z" fill="#8da5f3"/></svg> diff --git a/editor/icons/RigidBody2D.svg b/editor/icons/RigidBody2D.svg index 5d08e991ae..ea317ce94c 100644 --- a/editor/icons/RigidBody2D.svg +++ b/editor/icons/RigidBody2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 1.2227 3.9531 7 7 0 0 0 .30273.4082c.000785-.00256.0011667-.005252.0019532-.007812a7 7 0 0 0 5.4727 2.6465 7 7 0 0 0 3.2422-.80273c.001375.000393.002531.00156.003906.001953a7 7 0 0 0 .035156-.021485 7 7 0 0 0 .42578-.25 7 7 0 0 0 .16992-.10352 7 7 0 0 0 .36914-.26953 7 7 0 0 0 .20508-.15625 7 7 0 0 0 .3418-.30859 7 7 0 0 0 .16406-.1543 7 7 0 0 0 .33008-.36133 7 7 0 0 0 .14062-.16016 7 7 0 0 0 .27734-.37305 7 7 0 0 0 .13867-.19531 7 7 0 0 0 .21875-.36133 7 7 0 0 0 .14258-.25 7 7 0 0 0 .15625-.33398 7 7 0 0 0 .13867-.31055 7 7 0 0 0 .10742-.30859 7 7 0 0 0 .11914-.35352 7 7 0 0 0 .087891-.36914 7 7 0 0 0 .066406-.29297 7 7 0 0 0 .056641-.40039 7 7 0 0 0 .037109-.3125 7 7 0 0 0 .025391-.55273 7 7 0 0 0 -4.3926-6.4922 7 7 0 0 0 -.001953 0 7 7 0 0 0 -.66016-.22852 7 7 0 0 0 -.0058594-.0019531 7 7 0 0 0 -.55078-.13086 7 7 0 0 0 -.14062-.03125 7 7 0 0 0 -.55078-.072266 7 7 0 0 0 -.14258-.017578 7 7 0 0 0 -.55469-.025391zm1.9512 1.334a6 6 0 0 1 4.0488 5.666h-7a2 2 0 0 0 -.94922-1.6992c1.3464-2.0289 2.6038-3.2631 3.9004-3.9668zm-6.8281 2.1797c.14632.65093.35776 1.2833.68359 1.8848a2 2 0 0 0 -.80664 1.6016h-1a6 6 0 0 1 1.123-3.4863zm1.877 1.4863a2 2 0 0 0 -.10938.0039062 2 2 0 0 1 .10938-.0039062zm-.18945.011719a2 2 0 0 0 -.12109.013672 2 2 0 0 1 .12109-.013672zm-.44141.09375a2 2 0 0 0 -.056641.019531 2 2 0 0 1 .056641-.019531zm-1.3594 2.0605a2 2 0 0 0 .013672.11914 2 2 0 0 1 -.013672-.11914zm.027344.20898a2 2 0 0 0 .017578.080078 2 2 0 0 1 -.017578-.080078zm.73438 1.1992a2 2 0 0 0 1.2285.42578 2 2 0 0 0 1.0508-.30078c1.345 2.0268 2.6013 3.2645 3.8965 3.9688a6 6 0 0 1 -1.9473.33203 6 6 0 0 1 -5.0547-2.7695c.23771-.5785.50336-1.1403.82617-1.6563z" fill="#8da5f3" fill-opacity=".98824"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 1.2227 3.9531 7 7 0 0 0 .30273.4082c.000785-.00256.0011667-.005252.0019532-.007812a7 7 0 0 0 5.4727 2.6465 7 7 0 0 0 3.2422-.80273c.001375.000393.002531.00156.003906.001953a7 7 0 0 0 .035156-.021485 7 7 0 0 0 .42578-.25 7 7 0 0 0 .16992-.10352 7 7 0 0 0 .36914-.26953 7 7 0 0 0 .20508-.15625 7 7 0 0 0 .3418-.30859 7 7 0 0 0 .16406-.1543 7 7 0 0 0 .33008-.36133 7 7 0 0 0 .14062-.16016 7 7 0 0 0 .27734-.37305 7 7 0 0 0 .13867-.19531 7 7 0 0 0 .21875-.36133 7 7 0 0 0 .14258-.25 7 7 0 0 0 .15625-.33398 7 7 0 0 0 .13867-.31055 7 7 0 0 0 .10742-.30859 7 7 0 0 0 .11914-.35352 7 7 0 0 0 .087891-.36914 7 7 0 0 0 .066406-.29297 7 7 0 0 0 .056641-.40039 7 7 0 0 0 .037109-.3125 7 7 0 0 0 .025391-.55273 7 7 0 0 0 -4.3926-6.4922 7 7 0 0 0 -.001953 0 7 7 0 0 0 -.66016-.22852 7 7 0 0 0 -.0058594-.0019531 7 7 0 0 0 -.55078-.13086 7 7 0 0 0 -.14062-.03125 7 7 0 0 0 -.55078-.072266 7 7 0 0 0 -.14258-.017578 7 7 0 0 0 -.55469-.025391zm1.9512 1.334a6 6 0 0 1 4.0488 5.666h-7a2 2 0 0 0 -.94922-1.6992c1.3464-2.0289 2.6038-3.2631 3.9004-3.9668zm-6.8281 2.1797c.14632.65093.35776 1.2833.68359 1.8848a2 2 0 0 0 -.80664 1.6016h-1a6 6 0 0 1 1.123-3.4863zm1.877 1.4863a2 2 0 0 0 -.10938.0039062 2 2 0 0 1 .10938-.0039062zm-.18945.011719a2 2 0 0 0 -.12109.013672 2 2 0 0 1 .12109-.013672zm-.44141.09375a2 2 0 0 0 -.056641.019531 2 2 0 0 1 .056641-.019531zm-1.3594 2.0605a2 2 0 0 0 .013672.11914 2 2 0 0 1 -.013672-.11914zm.027344.20898a2 2 0 0 0 .017578.080078 2 2 0 0 1 -.017578-.080078zm.73438 1.1992a2 2 0 0 0 1.2285.42578 2 2 0 0 0 1.0508-.30078c1.345 2.0268 2.6013 3.2645 3.8965 3.9688a6 6 0 0 1 -1.9473.33203 6 6 0 0 1 -5.0547-2.7695c.23771-.5785.50336-1.1403.82617-1.6563z" fill="#8da5f3"/></svg> diff --git a/editor/icons/StaticBody2D.svg b/editor/icons/StaticBody2D.svg index 359d4d858c..4d7c575dc0 100644 --- a/editor/icons/StaticBody2D.svg +++ b/editor/icons/StaticBody2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m3 1a2 2 0 0 0 -1.4141.58594 2 2 0 0 0 -.58594 1.4141v10a2 2 0 0 0 .58594 1.4141 2 2 0 0 0 1.4141.58594h10a2 2 0 0 0 2-2v-10a2 2 0 0 0 -2-2h-10zm0 1h10a1 1 0 0 1 1 1v10a1 1 0 0 1 -1 1h-10a1 1 0 0 1 -1-1v-10a1 1 0 0 1 1-1zm0 1v2h2v-2zm8 0v2h2v-2zm-8 8v2h2v-2zm8 0v2h2v-2z" fill="#8da5f3" fill-opacity=".98824" transform="translate(0 1036.4)"/></g></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m3 1a2 2 0 0 0 -1.4141.58594 2 2 0 0 0 -.58594 1.4141v10a2 2 0 0 0 .58594 1.4141 2 2 0 0 0 1.4141.58594h10a2 2 0 0 0 2-2v-10a2 2 0 0 0 -2-2h-10zm0 1h10a1 1 0 0 1 1 1v10a1 1 0 0 1 -1 1h-10a1 1 0 0 1 -1-1v-10a1 1 0 0 1 1-1zm0 1v2h2v-2zm8 0v2h2v-2zm-8 8v2h2v-2zm8 0v2h2v-2z" fill="#8da5f3" transform="translate(0 1036.4)"/></g></svg> diff --git a/editor/icons/StyleBoxGridVisible.svg b/editor/icons/StyleBoxGridVisible.svg index 64419f4938..b13ee1023a 100644 --- a/editor/icons/StyleBoxGridVisible.svg +++ b/editor/icons/StyleBoxGridVisible.svg @@ -1 +1 @@ -<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><rect style="fill:#000;stroke-width:6.081;stroke-linejoin:round;stroke-miterlimit:5;fill-opacity:.75294119" width="16.131" height="16.131" x="-.008" y="-.006" rx="0" ry="1.188"/><path style="fill:#656565;fill-opacity:1;stroke-width:6.081;stroke-linejoin:round;stroke-miterlimit:5" d="M11.92 1.37v2.835h.549V1.37zm-5.7.017v2.818h.55V1.387zm8.776 3.18v1.595H11.92v3.57h.549V6.523h3.076V4.566ZM1.599 6.161v.361h2.717v-.36Zm4.621 0v3.57h.55V6.523h3.21v-.36Zm8.833 3.932v1.601H11.92v3.336h-1.39v.362h1.939v-3.335H15.6v-1.963ZM1.63 11.695v.362h2.685v-.362zm4.59 0v3.328H4.864v.362h1.904v-3.328H9.98v-.362z"/><path style="fill:#e0e0e0;fill-opacity:1;stroke-width:6.081;stroke-linejoin:round;stroke-miterlimit:5" d="M9.98 1.008v3.197H6.22v-3.18H4.316v3.18H1.051v1.957h3.265v3.57H1.082v1.963h3.234v3.328H6.22v-3.327h3.76v3.333h1.94v-3.334h3.133V9.733H11.92v-3.57h3.076V4.204H11.92V1.008zM6.22 6.162h3.76v3.57H6.22Z"/></svg> +<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><rect style="fill:#000;stroke-width:6.081;stroke-linejoin:round;stroke-miterlimit:5;fill-opacity:.75294119" width="16.131" height="16.131" x="-.008" y="-.006" rx="0" ry="1.188"/><path style="fill:#656565;stroke-width:6.081;stroke-linejoin:round;stroke-miterlimit:5" d="M11.92 1.37v2.835h.549V1.37zm-5.7.017v2.818h.55V1.387zm8.776 3.18v1.595H11.92v3.57h.549V6.523h3.076V4.566ZM1.599 6.161v.361h2.717v-.36Zm4.621 0v3.57h.55V6.523h3.21v-.36Zm8.833 3.932v1.601H11.92v3.336h-1.39v.362h1.939v-3.335H15.6v-1.963ZM1.63 11.695v.362h2.685v-.362zm4.59 0v3.328H4.864v.362h1.904v-3.328H9.98v-.362z"/><path style="fill:#e0e0e0;stroke-width:6.081;stroke-linejoin:round;stroke-miterlimit:5" d="M9.98 1.008v3.197H6.22v-3.18H4.316v3.18H1.051v1.957h3.265v3.57H1.082v1.963h3.234v3.328H6.22v-3.327h3.76v3.333h1.94v-3.334h3.133V9.733H11.92v-3.57h3.076V4.204H11.92V1.008zM6.22 6.162h3.76v3.57H6.22Z"/></svg> diff --git a/editor/icons/SystemFont.svg b/editor/icons/SystemFont.svg index a6f62d56d3..25415a2a76 100644 --- a/editor/icons/SystemFont.svg +++ b/editor/icons/SystemFont.svg @@ -1 +1 @@ -<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path style="fill:#e0e0e0;fill-opacity:1;stroke-width:.714755" d="m5.787 1-.402 1.613c-.352.265-.71.122-1.012-.111l-.904-.541L2.46 2.973l.853 1.425c-.058.438-.412.586-.79.635-.343.065-.674.216-1.024.213V6.72c.367 0 .715.157 1.074.224.371.032.716.243.727.65l-.84 1.4 1.008 1.01c.443-.266.895-.53 1.33-.802.349-.044.675.139.674.506l.314 1.258c.459-.059 1.099.115 1.45-.082.117-.475.242-.954.35-1.428A.67.67 0 0 1 8 9.195V7.5H6.5a.519.519 0 0 0-.281.084A.491.491 0 0 0 6 8v.5H4v-4h5.75c-.005-.22.107-.434.254-.625l.543-.902L9.535 1.96l-1.426.853c-.437-.058-.588-.412-.636-.79L7.217 1h-1.43z"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6z" fill="#ff5f5f"/></svg> +<svg height="16" width="16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path style="fill:#e0e0e0;stroke-width:.714755" d="m5.787 1-.402 1.613c-.352.265-.71.122-1.012-.111l-.904-.541L2.46 2.973l.853 1.425c-.058.438-.412.586-.79.635-.343.065-.674.216-1.024.213V6.72c.367 0 .715.157 1.074.224.371.032.716.243.727.65l-.84 1.4 1.008 1.01c.443-.266.895-.53 1.33-.802.349-.044.675.139.674.506l.314 1.258c.459-.059 1.099.115 1.45-.082.117-.475.242-.954.35-1.428A.67.67 0 0 1 8 9.195V7.5H6.5a.519.519 0 0 0-.281.084A.491.491 0 0 0 6 8v.5H4v-4h5.75c-.005-.22.107-.434.254-.625l.543-.902L9.535 1.96l-1.426.853c-.437-.058-.588-.412-.636-.79L7.217 1h-1.43z"/><path d="M4.5 5v3h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1-1 1v1h4v-1a1 1 0 0 1-1-1V7h2a1 1 0 0 1 1 1h1V5h-6z" fill="#ff5f5f"/></svg> diff --git a/editor/icons/Texture3D.svg b/editor/icons/Texture3D.svg index a313613b26..d121c02f2b 100644 --- a/editor/icons/Texture3D.svg +++ b/editor/icons/Texture3D.svg @@ -1 +1 @@ -<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m2 1c-.552 0-1 .448-1 1v12c0 .552.448 1 1 1h12c.552 0 1-.448 1-1v-12c0-.552-.448-1-1-1zm1 2h10v8h-10z"/><g fill-opacity=".99"><path d="m4.973 10.075c-.134 0-.275-.012-.424-.036-.149-.018-.293-.044-.432-.08-.14-.035-.266-.074-.381-.115-.114-.041-.203-.08-.268-.115l.216-1.1c.129.065.293.136.492.213.204.071.455.106.753.106.342 0 .593-.076.752-.23s.239-.361.239-.621c0-.159-.03-.292-.09-.399-.054-.112-.131-.201-.231-.266-.099-.071-.218-.118-.357-.142-.134-.029-.279-.044-.432-.044h-.433v-1.064h.492c.109 0 .214-.012.313-.036.104-.023.196-.062.276-.115.079-.059.141-.136.186-.23.05-.101.075-.225.075-.373 0-.112-.02-.21-.06-.292-.04-.083-.092-.151-.157-.204-.059-.054-.131-.092-.216-.116-.079-.029-.161-.044-.246-.044-.213 0-.412.038-.596.115-.178.077-.342.172-.491.284l-.395-.966c.079-.06.171-.122.275-.187.11-.065.229-.124.358-.177s.266-.098.41-.133c.149-.035.305-.053.469-.053.303 0 .564.044.783.133.223.083.407.204.551.363.144.154.251.337.321.55.069.207.104.435.104.683 0 .242-.057.479-.172.709-.114.225-.268.396-.462.515.269.13.475.325.619.585.149.254.223.561.223.922 0 .284-.039.547-.119.789-.079.237-.203.443-.372.621-.169.171-.385.307-.649.408-.258.094-.566.142-.924.142z"/><path d="m9.268 8.815c.055.006.117.012.186.018h.261c.581 0 1.011-.174 1.289-.523.284-.349.425-.831.425-1.445 0-.645-.134-1.132-.402-1.463-.269-.331-.693-.497-1.274-.497-.08 0-.162.003-.246.009-.085 0-.164.006-.239.018zm3.361-1.95c0 .532-.07.996-.209 1.392s-.338.724-.596.984c-.253.26-.564.455-.931.585-.368.13-.78.195-1.237.195-.209 0-.452-.011-.731-.035-.278-.018-.551-.059-.819-.124v-5.986c.268-.059.546-.097.834-.115.293-.023.544-.035.753-.035.442 0 .842.059 1.2.177.362.118.673.305.931.559s.457.579.596.975.209.872.209 1.428z"/></g></g></svg> +<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-rule="nonzero"><path d="m2 1c-.552 0-1 .448-1 1v12c0 .552.448 1 1 1h12c.552 0 1-.448 1-1v-12c0-.552-.448-1-1-1zm1 2h10v8h-10z"/><path d="m4.973 10.075c-.134 0-.275-.012-.424-.036-.149-.018-.293-.044-.432-.08-.14-.035-.266-.074-.381-.115-.114-.041-.203-.08-.268-.115l.216-1.1c.129.065.293.136.492.213.204.071.455.106.753.106.342 0 .593-.076.752-.23s.239-.361.239-.621c0-.159-.03-.292-.09-.399-.054-.112-.131-.201-.231-.266-.099-.071-.218-.118-.357-.142-.134-.029-.279-.044-.432-.044h-.433v-1.064h.492c.109 0 .214-.012.313-.036.104-.023.196-.062.276-.115.079-.059.141-.136.186-.23.05-.101.075-.225.075-.373 0-.112-.02-.21-.06-.292-.04-.083-.092-.151-.157-.204-.059-.054-.131-.092-.216-.116-.079-.029-.161-.044-.246-.044-.213 0-.412.038-.596.115-.178.077-.342.172-.491.284l-.395-.966c.079-.06.171-.122.275-.187.11-.065.229-.124.358-.177s.266-.098.41-.133c.149-.035.305-.053.469-.053.303 0 .564.044.783.133.223.083.407.204.551.363.144.154.251.337.321.55.069.207.104.435.104.683 0 .242-.057.479-.172.709-.114.225-.268.396-.462.515.269.13.475.325.619.585.149.254.223.561.223.922 0 .284-.039.547-.119.789-.079.237-.203.443-.372.621-.169.171-.385.307-.649.408-.258.094-.566.142-.924.142z"/><path d="m9.268 8.815c.055.006.117.012.186.018h.261c.581 0 1.011-.174 1.289-.523.284-.349.425-.831.425-1.445 0-.645-.134-1.132-.402-1.463-.269-.331-.693-.497-1.274-.497-.08 0-.162.003-.246.009-.085 0-.164.006-.239.018zm3.361-1.95c0 .532-.07.996-.209 1.392s-.338.724-.596.984c-.253.26-.564.455-.931.585-.368.13-.78.195-1.237.195-.209 0-.452-.011-.731-.035-.278-.018-.551-.059-.819-.124v-5.986c.268-.059.546-.097.834-.115.293-.023.544-.035.753-.035.442 0 .842.059 1.2.177.362.118.673.305.931.559s.457.579.596.975.209.872.209 1.428z"/></g></svg> diff --git a/editor/icons/TileMap.svg b/editor/icons/TileMap.svg index 291d02b858..d3432f41ac 100644 --- a/editor/icons/TileMap.svg +++ b/editor/icons/TileMap.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2z" fill="#8da5f3" fill-opacity=".98824"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2z" fill="#8da5f3"/></svg> diff --git a/editor/icons/ToolBoneSelect.svg b/editor/icons/ToolBoneSelect.svg index cc12b69a82..5e9178ee94 100644 --- a/editor/icons/ToolBoneSelect.svg +++ b/editor/icons/ToolBoneSelect.svg @@ -1 +1 @@ -<svg enable-background="new 0 0 16 16" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".9961"><path d="m16 11.46-6.142-2.527-1.572-.647.647 1.572 2.527 6.142.913-2.72 1.815 1.817.91-.909-1.818-1.815z"/><path d="m7.784 11.008-.886-2.152c-.23-.56-.102-1.203.327-1.631.287-.287.67-.439 1.061-.439.192 0 .386.037.57.113l2.151.885.17-.17c.977.645 2.271.516 3.1-.311.964-.963.964-2.524 0-3.488-.377-.377-.867-.622-1.396-.697-.074-.529-.318-1.019-.695-1.397-.455-.453-1.067-.711-1.707-.721-.667-.01-1.309.25-1.782.72-.828.829-.96 2.126-.314 3.105l-3.558 3.561c-.978-.646-2.274-.515-3.103.312-.963.962-.963 2.524 0 3.487.378.377.868.621 1.396.695.075.529.319 1.02.696 1.396.963.964 2.525.964 3.488 0 .828-.828.96-2.125.314-3.104z"/></g></svg> +<svg enable-background="new 0 0 16 16" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m16 11.46-6.142-2.527-1.572-.647.647 1.572 2.527 6.142.913-2.72 1.815 1.817.91-.909-1.818-1.815z"/><path d="m7.784 11.008-.886-2.152c-.23-.56-.102-1.203.327-1.631.287-.287.67-.439 1.061-.439.192 0 .386.037.57.113l2.151.885.17-.17c.977.645 2.271.516 3.1-.311.964-.963.964-2.524 0-3.488-.377-.377-.867-.622-1.396-.697-.074-.529-.318-1.019-.695-1.397-.455-.453-1.067-.711-1.707-.721-.667-.01-1.309.25-1.782.72-.828.829-.96 2.126-.314 3.105l-3.558 3.561c-.978-.646-2.274-.515-3.103.312-.963.962-.963 2.524 0 3.487.378.377.868.621 1.396.695.075.529.319 1.02.696 1.396.963.964 2.525.964 3.488 0 .828-.828.96-2.125.314-3.104z"/></g></svg> diff --git a/editor/icons/TouchScreenButton.svg b/editor/icons/TouchScreenButton.svg index 7e3e232867..731743694d 100644 --- a/editor/icons/TouchScreenButton.svg +++ b/editor/icons/TouchScreenButton.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a1 1 0 0 0 -1 1v2a1 1 0 0 0 1 1h2v-1h-1-1v-2h8v2h-2v1h2a1 1 0 0 0 1-1v-2a1 1 0 0 0 -1-1zm4 2a1 1 0 0 0 -1 1v7 .033203l-2.4746-1.8086c-.52015-.3803-1.1948-.4556-1.6504 0-.45566.4556-.45561 1.1948 0 1.6504l4.125 4.125h6c1.1046 0 2-.8954 2-2v-5h-6v-4a1 1 0 0 0 -1-1z" fill="#8da5f3" fill-opacity=".98824"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1a1 1 0 0 0 -1 1v2a1 1 0 0 0 1 1h2v-1h-1-1v-2h8v2h-2v1h2a1 1 0 0 0 1-1v-2a1 1 0 0 0 -1-1zm4 2a1 1 0 0 0 -1 1v7 .033203l-2.4746-1.8086c-.52015-.3803-1.1948-.4556-1.6504 0-.45566.4556-.45561 1.1948 0 1.6504l4.125 4.125h6c1.1046 0 2-.8954 2-2v-5h-6v-4a1 1 0 0 0 -1-1z" fill="#8da5f3"/></svg> diff --git a/editor/icons/VisibleOnScreenEnabler2D.svg b/editor/icons/VisibleOnScreenEnabler2D.svg index 989675f44f..434083b7c6 100644 --- a/editor/icons/VisibleOnScreenEnabler2D.svg +++ b/editor/icons/VisibleOnScreenEnabler2D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v3h1v-2h2v-1zm11 0v1h2v2h1v-3zm-4 1c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.55273c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-7 6v3h3v-1h-2v-2zm13 0v2h-2v1h3v-3z" fill="#8da5f3" fill-opacity=".98824" fill-rule="evenodd"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v3h1v-2h2v-1zm11 0v1h2v2h1v-3zm-4 1c-2.5567 0-5.7907 1.9477-6.9551 5.7051a1.0001 1.0001 0 0 0 -.0058594.57031c1.1244 3.9354 4.4609 5.7246 6.9609 5.7246s5.8365-1.7892 6.9609-5.7246a1.0001 1.0001 0 0 0 0-.55273c-1.1003-3.7876-4.4066-5.7227-6.9609-5.7227zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4zm0 2a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0 -2-2zm-7 6v3h3v-1h-2v-2zm13 0v2h-2v1h3v-3z" fill="#8da5f3" fill-rule="evenodd"/></svg> diff --git a/editor/icons/YSort.svg b/editor/icons/YSort.svg index 31e5d9a67e..8394a3bb9b 100644 --- a/editor/icons/YSort.svg +++ b/editor/icons/YSort.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 1-3 3h2v8h-2l3 3 3-3h-2v-8h2zm5 1v2h6v-2zm0 5v2h4v-2zm0 5v2h2v-2z" fill="#8da5f3" fill-opacity=".98824"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m4 1-3 3h2v8h-2l3 3 3-3h-2v-8h2zm5 1v2h6v-2zm0 5v2h4v-2zm0 5v2h2v-2z" fill="#8da5f3"/></svg> diff --git a/editor/icons/ZoomLess.svg b/editor/icons/ZoomLess.svg index 18b052c32a..53298ed6ed 100644 --- a/editor/icons/ZoomLess.svg +++ b/editor/icons/ZoomLess.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"><circle cx="8" cy="1044.4" fill-opacity=".39216" r="8" stroke-opacity=".98824"/><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-4 6h8v2h-8z" fill="#e0e0e0" transform="translate(0 1036.4)"/></g></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"><circle cx="8" cy="1044.4" fill-opacity=".39216" r="8"/><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-4 6h8v2h-8z" fill="#e0e0e0" transform="translate(0 1036.4)"/></g></svg> diff --git a/editor/icons/ZoomMore.svg b/editor/icons/ZoomMore.svg index fdc80611da..2b84e822e6 100644 --- a/editor/icons/ZoomMore.svg +++ b/editor/icons/ZoomMore.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"><circle cx="8" cy="1044.4" fill-opacity=".39216" r="8" stroke-opacity=".98824"/><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-1 3h2v3h3v2h-3v3h-2v-3h-3v-2h3z" fill="#e0e0e0" transform="translate(0 1036.4)"/></g></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"><circle cx="8" cy="1044.4" fill-opacity=".39216" r="8"/><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-1 3h2v3h3v2h-3v3h-2v-3h-3v-2h3z" fill="#e0e0e0" transform="translate(0 1036.4)"/></g></svg> diff --git a/editor/icons/ZoomReset.svg b/editor/icons/ZoomReset.svg index f6793b6816..ffb0d42563 100644 --- a/editor/icons/ZoomReset.svg +++ b/editor/icons/ZoomReset.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"><circle cx="8" cy="1044.4" fill-opacity=".39216" r="8" stroke-opacity=".98824"/><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-.029297 3.002a1.0001 1.0001 0 0 1 1.0293.99805v7h-2v-5.1309l-1.4453.96289-1.1094-1.6641 3-2a1.0001 1.0001 0 0 1 .52539-.16602z" fill="#e0e0e0" transform="translate(0 1036.4)"/></g></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round" stroke-linejoin="round" stroke-width="2" transform="translate(0 -1036.4)"><circle cx="8" cy="1044.4" fill-opacity=".39216" r="8"/><path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7zm-.029297 3.002a1.0001 1.0001 0 0 1 1.0293.99805v7h-2v-5.1309l-1.4453.96289-1.1094-1.6641 3-2a1.0001 1.0001 0 0 1 .52539-.16602z" fill="#e0e0e0" transform="translate(0 1036.4)"/></g></svg> diff --git a/editor/import/editor_import_plugin.cpp b/editor/import/editor_import_plugin.cpp index fb14dcf888..ef3d3d1276 100644 --- a/editor/import/editor_import_plugin.cpp +++ b/editor/import/editor_import_plugin.cpp @@ -172,17 +172,15 @@ Error EditorImportPlugin::import(const String &p_source_file, const String &p_sa ++E; } - int err = 0; + Error err = OK; if (GDVIRTUAL_CALL(_import, p_source_file, p_save_path, options, platform_variants, gen_files, err)) { - Error ret_err = Error(err); - for (int i = 0; i < platform_variants.size(); i++) { r_platform_variants->push_back(platform_variants[i]); } for (int i = 0; i < gen_files.size(); i++) { r_gen_files->push_back(gen_files[i]); } - return ret_err; + return err; } ERR_FAIL_V_MSG(ERR_METHOD_NOT_FOUND, "Unimplemented _import in add-on."); } diff --git a/editor/import/editor_import_plugin.h b/editor/import/editor_import_plugin.h index 0f79ba4783..bf912058a2 100644 --- a/editor/import/editor_import_plugin.h +++ b/editor/import/editor_import_plugin.h @@ -51,7 +51,7 @@ protected: GDVIRTUAL0RC(float, _get_priority) GDVIRTUAL0RC(int, _get_import_order) GDVIRTUAL3RC(bool, _get_option_visibility, String, StringName, Dictionary) - GDVIRTUAL5RC(int, _import, String, String, Dictionary, TypedArray<String>, TypedArray<String>) + GDVIRTUAL5RC(Error, _import, String, String, Dictionary, TypedArray<String>, TypedArray<String>) public: EditorImportPlugin(); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index aa5f9ff29a..d0f04cb46f 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -54,7 +54,7 @@ #include "scene/resources/world_boundary_shape_3d.h" uint32_t EditorSceneFormatImporter::get_import_flags() const { - int ret; + uint32_t ret; if (GDVIRTUAL_CALL(_get_import_flags, ret)) { return ret; } @@ -1085,10 +1085,10 @@ Node *ResourceImporterScene::_post_fix_animations(Node *p_node, Node *p_root, co return p_node; } -Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps) { +Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps, float p_applied_root_scale) { // children first for (int i = 0; i < p_node->get_child_count(); i++) { - Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_occluder_arrays, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps); + Node *r = _post_fix_node(p_node->get_child(i), p_root, collision_map, r_occluder_arrays, r_scanned_meshes, p_node_data, p_material_data, p_animation_data, p_animation_fps, p_applied_root_scale); if (!r) { i--; //was erased } @@ -1231,7 +1231,8 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< } else { shapes = get_collision_shapes( m->get_mesh(), - node_settings); + node_settings, + p_applied_root_scale); } if (shapes.size()) { @@ -1242,6 +1243,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< p_node->add_child(col, true); col->set_owner(p_node->get_owner()); col->set_transform(get_collision_shapes_transform(node_settings)); + col->set_position(p_applied_root_scale * col->get_position()); base = col; } break; case MESH_PHYSICS_RIGID_BODY_AND_MESH: { @@ -1249,6 +1251,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< rigid_body->set_name(p_node->get_name()); p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); + rigid_body->set_position(p_applied_root_scale * rigid_body->get_position()); p_node = rigid_body; mi->set_transform(Transform3D()); rigid_body->add_child(mi, true); @@ -1258,6 +1261,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< case MESH_PHYSICS_STATIC_COLLIDER_ONLY: { StaticBody3D *col = memnew(StaticBody3D); col->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); + col->set_position(p_applied_root_scale * col->get_position()); col->set_name(p_node->get_name()); p_node->replace_by(col); memdelete(p_node); @@ -1267,6 +1271,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< case MESH_PHYSICS_AREA_ONLY: { Area3D *area = memnew(Area3D); area->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); + area->set_position(p_applied_root_scale * area->get_position()); area->set_name(p_node->get_name()); p_node->replace_by(area); memdelete(p_node); @@ -2284,7 +2289,14 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file, const HashM ERR_FAIL_COND_V(!importer.is_valid(), nullptr); Error err = OK; - Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, p_options, nullptr, &err); + HashMap<StringName, Variant> options_dupe = p_options; + + // By default, the GLTF importer will extract embedded images into files on disk + // However, we do not want the advanced settings dialog to be able to write files on disk. + // To avoid this and also avoid compressing to basis every time, we are using the uncompressed option. + options_dupe["gltf/embedded_image_handling"] = 3; // Embed as Uncompressed defined in GLTFState::GLTFHandleBinary::HANDLE_BINARY_EMBED_AS_UNCOMPRESSED + + Node *scene = importer->import_scene(p_source_file, EditorSceneFormatImporter::IMPORT_ANIMATION | EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS, options_dupe, nullptr, &err); if (!scene || err != OK) { return nullptr; } @@ -2398,7 +2410,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p fps = (float)p_options[SNAME("animation/fps")]; } _pre_fix_animations(scene, scene, node_data, animation_data, fps); - _post_fix_node(scene, scene, collision_map, occluder_arrays, scanned_meshes, node_data, material_data, animation_data, fps); + _post_fix_node(scene, scene, collision_map, occluder_arrays, scanned_meshes, node_data, material_data, animation_data, fps, apply_root ? root_scale : 1.0); _post_fix_animations(scene, scene, node_data, animation_data, fps); String root_type = p_options["nodes/root_type"]; @@ -2615,8 +2627,58 @@ Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t Error error; Ref<PackedScene> ps = ResourceFormatLoaderText::singleton->load(p_path, p_path, &error); ERR_FAIL_COND_V_MSG(!ps.is_valid(), nullptr, "Cannot load scene as text resource from path '" + p_path + "'."); - Node *scene = ps->instantiate(); + TypedArray<Node> nodes = scene->find_children("*", "MeshInstance3D"); + for (int32_t node_i = 0; node_i < nodes.size(); node_i++) { + MeshInstance3D *mesh_3d = cast_to<MeshInstance3D>(nodes[node_i]); + Ref<ImporterMesh> mesh; + mesh.instantiate(); + // Ignore the aabb, it will be recomputed. + ImporterMeshInstance3D *importer_mesh_3d = memnew(ImporterMeshInstance3D); + importer_mesh_3d->set_name(mesh_3d->get_name()); + importer_mesh_3d->set_transform(mesh_3d->get_relative_transform(mesh_3d->get_parent())); + importer_mesh_3d->set_skin(mesh_3d->get_skin()); + importer_mesh_3d->set_skeleton_path(mesh_3d->get_skeleton_path()); + Ref<ArrayMesh> array_mesh_3d_mesh = mesh_3d->get_mesh(); + if (array_mesh_3d_mesh.is_valid()) { + // For the MeshInstance3D nodes, we need to convert the ArrayMesh to an ImporterMesh specially. + mesh->set_name(array_mesh_3d_mesh->get_name()); + for (int32_t blend_i = 0; blend_i < array_mesh_3d_mesh->get_blend_shape_count(); blend_i++) { + mesh->add_blend_shape(array_mesh_3d_mesh->get_blend_shape_name(blend_i)); + } + for (int32_t surface_i = 0; surface_i < array_mesh_3d_mesh->get_surface_count(); surface_i++) { + mesh->add_surface(array_mesh_3d_mesh->surface_get_primitive_type(surface_i), + array_mesh_3d_mesh->surface_get_arrays(surface_i), + array_mesh_3d_mesh->surface_get_blend_shape_arrays(surface_i), + array_mesh_3d_mesh->surface_get_lods(surface_i), + array_mesh_3d_mesh->surface_get_material(surface_i), + array_mesh_3d_mesh->surface_get_name(surface_i), + array_mesh_3d_mesh->surface_get_format(surface_i)); + } + mesh->set_blend_shape_mode(array_mesh_3d_mesh->get_blend_shape_mode()); + importer_mesh_3d->set_mesh(mesh); + mesh_3d->replace_by(importer_mesh_3d); + continue; + } + Ref<Mesh> mesh_3d_mesh = mesh_3d->get_mesh(); + if (mesh_3d_mesh.is_valid()) { + // For the MeshInstance3D nodes, we need to convert the Mesh to an ImporterMesh specially. + mesh->set_name(mesh_3d_mesh->get_name()); + for (int32_t surface_i = 0; surface_i < mesh_3d_mesh->get_surface_count(); surface_i++) { + mesh->add_surface(mesh_3d_mesh->surface_get_primitive_type(surface_i), + mesh_3d_mesh->surface_get_arrays(surface_i), + Array(), + mesh_3d_mesh->surface_get_lods(surface_i), + mesh_3d_mesh->surface_get_material(surface_i), + mesh_3d_mesh->surface_get_material(surface_i).is_valid() ? mesh_3d_mesh->surface_get_material(surface_i)->get_name() : String(), + mesh_3d_mesh->surface_get_format(surface_i)); + } + importer_mesh_3d->set_mesh(mesh); + mesh_3d->replace_by(importer_mesh_3d); + continue; + } + } + ERR_FAIL_COND_V(!scene, nullptr); return scene; diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 2d08d4df50..d6d83a45d3 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -56,7 +56,7 @@ protected: Node *import_scene_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options); Ref<Animation> import_animation_wrapper(const String &p_path, uint32_t p_flags, Dictionary p_options); - GDVIRTUAL0RC(int, _get_import_flags) + GDVIRTUAL0RC(uint32_t, _get_import_flags) GDVIRTUAL0RC(Vector<String>, _get_extensions) GDVIRTUAL3R(Object *, _import_scene, String, uint32_t, Dictionary) GDVIRTUAL1(_get_import_options, String) @@ -279,7 +279,7 @@ public: Node *_pre_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &r_collision_map, Pair<PackedVector3Array, PackedInt32Array> *r_occluder_arrays, List<Pair<NodePath, Node *>> &r_node_renames); Node *_pre_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps); - Node *_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); + Node *_post_fix_node(Node *p_node, Node *p_root, HashMap<Ref<ImporterMesh>, Vector<Ref<Shape3D>>> &collision_map, Pair<PackedVector3Array, PackedInt32Array> &r_occluder_arrays, HashSet<Ref<ImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps, float p_applied_root_scale); Node *_post_fix_animations(Node *p_node, Node *p_root, const Dictionary &p_node_data, const Dictionary &p_animation_data, float p_animation_fps); Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks); @@ -298,7 +298,7 @@ public: ResourceImporterScene(bool p_animation_import = false); template <class M> - static Vector<Ref<Shape3D>> get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options); + static Vector<Ref<Shape3D>> get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options, float p_applied_root_scale); template <class M> static Transform3D get_collision_shapes_transform(const M &p_options); @@ -314,7 +314,7 @@ public: }; template <class M> -Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options) { +Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options, float p_applied_root_scale) { ShapeType generate_shape_type = SHAPE_TYPE_DECOMPOSE_CONVEX; if (p_options.has(SNAME("physics/shape_type"))) { generate_shape_type = (ShapeType)p_options[SNAME("physics/shape_type")].operator int(); @@ -409,7 +409,7 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> Ref<BoxShape3D> box; box.instantiate(); if (p_options.has(SNAME("primitive/size"))) { - box->set_size(p_options[SNAME("primitive/size")]); + box->set_size(p_options[SNAME("primitive/size")].operator Vector3() * p_applied_root_scale); } Vector<Ref<Shape3D>> shapes; @@ -420,7 +420,7 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> Ref<SphereShape3D> sphere; sphere.instantiate(); if (p_options.has(SNAME("primitive/radius"))) { - sphere->set_radius(p_options[SNAME("primitive/radius")]); + sphere->set_radius(p_options[SNAME("primitive/radius")].operator float() * p_applied_root_scale); } Vector<Ref<Shape3D>> shapes; @@ -430,10 +430,10 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> Ref<CylinderShape3D> cylinder; cylinder.instantiate(); if (p_options.has(SNAME("primitive/height"))) { - cylinder->set_height(p_options[SNAME("primitive/height")]); + cylinder->set_height(p_options[SNAME("primitive/height")].operator float() * p_applied_root_scale); } if (p_options.has(SNAME("primitive/radius"))) { - cylinder->set_radius(p_options[SNAME("primitive/radius")]); + cylinder->set_radius(p_options[SNAME("primitive/radius")].operator float() * p_applied_root_scale); } Vector<Ref<Shape3D>> shapes; @@ -443,10 +443,10 @@ Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<Mesh> Ref<CapsuleShape3D> capsule; capsule.instantiate(); if (p_options.has(SNAME("primitive/height"))) { - capsule->set_height(p_options[SNAME("primitive/height")]); + capsule->set_height(p_options[SNAME("primitive/height")].operator float() * p_applied_root_scale); } if (p_options.has(SNAME("primitive/radius"))) { - capsule->set_radius(p_options[SNAME("primitive/radius")]); + capsule->set_radius(p_options[SNAME("primitive/radius")].operator float() * p_applied_root_scale); } Vector<Ref<Shape3D>> shapes; diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 044f7475c2..8d26feebf4 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -441,7 +441,7 @@ void SceneImportSettings::_update_view_gizmos() { // This collider_view doesn't have a mesh so we need to generate a new one. // Generate the mesh collider. - Vector<Ref<Shape3D>> shapes = ResourceImporterScene::get_collision_shapes(mesh_node->get_mesh(), e.value.settings); + Vector<Ref<Shape3D>> shapes = ResourceImporterScene::get_collision_shapes(mesh_node->get_mesh(), e.value.settings, 1.0); const Transform3D transform = ResourceImporterScene::get_collision_shapes_transform(e.value.settings); Ref<ArrayMesh> collider_view_mesh; diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index 33aebe5883..df94815105 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -38,6 +38,7 @@ #include "editor/editor_undo_redo_manager.h" #include "scene/animation/animation_blend_tree.h" #include "scene/gui/check_box.h" +#include "scene/gui/option_button.h" #include "scene/gui/panel_container.h" StringName AnimationNodeBlendSpace1DEditor::get_blend_position_path() const { @@ -335,6 +336,7 @@ void AnimationNodeBlendSpace1DEditor::_update_space() { min_value->set_value(blend_space->get_min_space()); sync->set_pressed(blend_space->is_using_sync()); + interpolation->select(blend_space->get_blend_mode()); label_value->set_text(blend_space->get_value_label()); @@ -361,6 +363,8 @@ void AnimationNodeBlendSpace1DEditor::_config_changed(double) { undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap()); undo_redo->add_do_method(blend_space.ptr(), "set_use_sync", sync->is_pressed()); undo_redo->add_undo_method(blend_space.ptr(), "set_use_sync", blend_space->is_using_sync()); + undo_redo->add_do_method(blend_space.ptr(), "set_blend_mode", interpolation->get_selected()); + undo_redo->add_undo_method(blend_space.ptr(), "set_blend_mode", blend_space->get_blend_mode()); undo_redo->add_do_method(this, "_update_space"); undo_redo->add_undo_method(this, "_update_space"); undo_redo->commit_action(); @@ -579,6 +583,10 @@ void AnimationNodeBlendSpace1DEditor::_notification(int p_what) { tool_erase->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); snap->set_icon(get_theme_icon(SNAME("SnapGrid"), SNAME("EditorIcons"))); open_editor->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); + interpolation->clear(); + interpolation->add_icon_item(get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")), "", 0); + interpolation->add_icon_item(get_theme_icon(SNAME("TrackDiscrete"), SNAME("EditorIcons")), "", 1); + interpolation->add_icon_item(get_theme_icon(SNAME("TrackCapture"), SNAME("EditorIcons")), "", 2); } break; case NOTIFICATION_PROCESS: { @@ -639,6 +647,7 @@ void AnimationNodeBlendSpace1DEditor::edit(const Ref<AnimationNode> &p_node) { min_value->set_editable(!read_only); max_value->set_editable(!read_only); sync->set_disabled(read_only); + interpolation->set_disabled(read_only); } AnimationNodeBlendSpace1DEditor *AnimationNodeBlendSpace1DEditor::singleton = nullptr; @@ -707,6 +716,13 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { top_hb->add_child(sync); sync->connect("toggled", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed)); + top_hb->add_child(memnew(VSeparator)); + + top_hb->add_child(memnew(Label(TTR("Blend:")))); + interpolation = memnew(OptionButton); + top_hb->add_child(interpolation); + interpolation->connect("item_selected", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_config_changed)); + edit_hb = memnew(HBoxContainer); top_hb->add_child(edit_hb); edit_hb->add_child(memnew(VSeparator)); diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h index e71a4bd1b9..90104fc310 100644 --- a/editor/plugins/animation_blend_space_1d_editor.h +++ b/editor/plugins/animation_blend_space_1d_editor.h @@ -41,6 +41,7 @@ #include "scene/gui/tree.h" class CheckBox; +class OptionButton; class PanelContainer; class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { @@ -66,6 +67,7 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { SpinBox *min_value = nullptr; CheckBox *sync = nullptr; + OptionButton *interpolation = nullptr; HBoxContainer *edit_hb = nullptr; SpinBox *edit_value = nullptr; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index e09636d297..0f9ce89f02 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -5401,11 +5401,13 @@ void CanvasItemEditorPlugin::make_visible(bool p_visible) { canvas_item_editor->show(); canvas_item_editor->set_physics_process(true); RenderingServer::get_singleton()->viewport_set_disable_2d(EditorNode::get_singleton()->get_scene_root()->get_viewport_rid(), false); + RenderingServer::get_singleton()->viewport_set_environment_mode(EditorNode::get_singleton()->get_scene_root()->get_viewport_rid(), RS::VIEWPORT_ENVIRONMENT_ENABLED); } else { canvas_item_editor->hide(); canvas_item_editor->set_physics_process(false); RenderingServer::get_singleton()->viewport_set_disable_2d(EditorNode::get_singleton()->get_scene_root()->get_viewport_rid(), true); + RenderingServer::get_singleton()->viewport_set_environment_mode(EditorNode::get_singleton()->get_scene_root()->get_viewport_rid(), RS::VIEWPORT_ENVIRONMENT_DISABLED); } } diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp index 470b90aa7f..3bf2b95c26 100644 --- a/editor/plugins/control_editor_plugin.cpp +++ b/editor/plugins/control_editor_plugin.cpp @@ -423,7 +423,7 @@ void EditorInspectorPluginControl::parse_group(Object *p_object, const String &p add_custom_control(pos_warning); } -bool EditorInspectorPluginControl::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { +bool EditorInspectorPluginControl::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { Control *control = Object::cast_to<Control>(p_object); if (!control) { return false; diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h index 779637317d..19e004a390 100644 --- a/editor/plugins/control_editor_plugin.h +++ b/editor/plugins/control_editor_plugin.h @@ -129,7 +129,7 @@ class EditorInspectorPluginControl : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; virtual void parse_group(Object *p_object, const String &p_group) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override; }; // Toolbar controls. diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp index db4a103624..d5f3b897c9 100644 --- a/editor/plugins/font_config_plugin.cpp +++ b/editor/plugins/font_config_plugin.cpp @@ -874,7 +874,7 @@ bool EditorInspectorPluginFontVariation::can_handle(Object *p_object) { return (Object::cast_to<FontVariation>(p_object) != nullptr) || (Object::cast_to<DynamicFontImportSettingsData>(p_object) != nullptr); } -bool EditorInspectorPluginFontVariation::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { +bool EditorInspectorPluginFontVariation::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { if (p_path == "variation_opentype") { add_property_editor(p_path, memnew(EditorPropertyOTVariation)); return true; @@ -976,7 +976,7 @@ void EditorInspectorPluginFontPreview::parse_begin(Object *p_object) { add_custom_control(editor); } -bool EditorInspectorPluginFontPreview::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { +bool EditorInspectorPluginFontPreview::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { return false; } @@ -1035,7 +1035,7 @@ bool EditorInspectorPluginSystemFont::can_handle(Object *p_object) { return Object::cast_to<SystemFont>(p_object) != nullptr; } -bool EditorInspectorPluginSystemFont::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { +bool EditorInspectorPluginSystemFont::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { if (p_path == "font_names") { EditorPropertyFontNamesArray *editor = memnew(EditorPropertyFontNamesArray); editor->setup(p_type, p_hint_text); diff --git a/editor/plugins/font_config_plugin.h b/editor/plugins/font_config_plugin.h index 150e97f7e2..6cea5967b2 100644 --- a/editor/plugins/font_config_plugin.h +++ b/editor/plugins/font_config_plugin.h @@ -212,7 +212,7 @@ class EditorInspectorPluginFontVariation : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override; }; /*************************************************************************/ @@ -242,7 +242,7 @@ class EditorInspectorPluginFontPreview : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; virtual void parse_begin(Object *p_object) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override; }; /*************************************************************************/ @@ -269,7 +269,7 @@ class EditorInspectorPluginSystemFont : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override; }; /*************************************************************************/ diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp index 72c234c1d4..477a094d01 100644 --- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp @@ -77,7 +77,7 @@ void GPUParticlesCollisionSDF3DEditorPlugin::_notification(int p_what) { const Vector3i size = col_sdf->get_estimated_cell_size(); - const Vector3 extents = col_sdf->get_extents(); + const Vector3 extents = col_sdf->get_size() / 2; int data_size = 2; const double size_mb = size.x * size.y * size.z * data_size / (1024.0 * 1024.0); diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index e11dc1c81d..e48a5bb95d 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -1805,7 +1805,7 @@ void Camera3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, } else { Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(0, 0, -1), Vector3(4096, 0, -1), s[0], s[1], ra, rb); - float d = ra.x * 2.0; + float d = ra.x * 2; if (Node3DEditor::get_singleton()->is_snap_enabled()) { d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); } @@ -2099,7 +2099,7 @@ void OccluderInstance3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, Ref<BoxOccluder3D> bo = o; Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); - float d = ra[p_id]; + float d = ra[p_id] * 2; if (snap_enabled) { d = Math::snapped(d, snap); } @@ -2109,7 +2109,7 @@ void OccluderInstance3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, } Vector3 he = bo->get_size(); - he[p_id] = d * 2; + he[p_id] = d; bo->set_size(he); } @@ -3184,7 +3184,7 @@ String GPUParticlesCollision3DGizmoPlugin::get_handle_name(const EditorNode3DGiz } if (Object::cast_to<GPUParticlesCollisionBox3D>(cs) || Object::cast_to<GPUParticlesAttractorBox3D>(cs) || Object::cast_to<GPUParticlesAttractorVectorField3D>(cs) || Object::cast_to<GPUParticlesCollisionSDF3D>(cs) || Object::cast_to<GPUParticlesCollisionHeightField3D>(cs)) { - return "Extents"; + return "Size"; } return ""; @@ -3198,7 +3198,7 @@ Variant GPUParticlesCollision3DGizmoPlugin::get_handle_value(const EditorNode3DG } if (Object::cast_to<GPUParticlesCollisionBox3D>(cs) || Object::cast_to<GPUParticlesAttractorBox3D>(cs) || Object::cast_to<GPUParticlesAttractorVectorField3D>(cs) || Object::cast_to<GPUParticlesCollisionSDF3D>(cs) || Object::cast_to<GPUParticlesCollisionHeightField3D>(cs)) { - return Vector3(p_gizmo->get_node_3d()->call("get_extents")); + return Vector3(p_gizmo->get_node_3d()->call("get_size")); } return Variant(); @@ -3235,7 +3235,7 @@ void GPUParticlesCollision3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_g axis[p_id] = 1.0; Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); - float d = ra[p_id]; + float d = ra[p_id] * 2; if (Node3DEditor::get_singleton()->is_snap_enabled()) { d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); } @@ -3244,9 +3244,9 @@ void GPUParticlesCollision3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_g d = 0.001; } - Vector3 he = sn->call("get_extents"); + Vector3 he = sn->call("get_size"); he[p_id] = d; - sn->call("set_extents", he); + sn->call("set_size", he); } } @@ -3268,14 +3268,14 @@ void GPUParticlesCollision3DGizmoPlugin::commit_handle(const EditorNode3DGizmo * if (Object::cast_to<GPUParticlesCollisionBox3D>(sn) || Object::cast_to<GPUParticlesAttractorBox3D>(sn) || Object::cast_to<GPUParticlesAttractorVectorField3D>(sn) || Object::cast_to<GPUParticlesCollisionSDF3D>(sn) || Object::cast_to<GPUParticlesCollisionHeightField3D>(sn)) { if (p_cancel) { - sn->call("set_extents", p_restore); + sn->call("set_size", p_restore); return; } EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Change Box Shape Extents")); - ur->add_do_method(sn, "set_extents", sn->call("get_extents")); - ur->add_undo_method(sn, "set_extents", p_restore); + ur->create_action(TTR("Change Box Shape Size")); + ur->add_do_method(sn, "set_size", sn->call("get_size")); + ur->add_undo_method(sn, "set_size", p_restore); ur->commit_action(); } } @@ -3342,8 +3342,8 @@ void GPUParticlesCollision3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { if (Object::cast_to<GPUParticlesCollisionBox3D>(cs) || Object::cast_to<GPUParticlesAttractorBox3D>(cs) || Object::cast_to<GPUParticlesAttractorVectorField3D>(cs) || Object::cast_to<GPUParticlesCollisionSDF3D>(cs) || Object::cast_to<GPUParticlesCollisionHeightField3D>(cs)) { Vector<Vector3> lines; AABB aabb; - aabb.position = -cs->call("get_extents").operator Vector3(); - aabb.size = aabb.position * -2; + aabb.size = cs->call("get_size").operator Vector3(); + aabb.position = aabb.size / -2; for (int i = 0; i < 12; i++) { Vector3 a, b; @@ -3356,7 +3356,7 @@ void GPUParticlesCollision3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { for (int i = 0; i < 3; i++) { Vector3 ax; - ax[i] = cs->call("get_extents").operator Vector3()[i]; + ax[i] = cs->call("get_size").operator Vector3()[i] / 2; handles.push_back(ax); } @@ -3442,11 +3442,11 @@ int ReflectionProbeGizmoPlugin::get_priority() const { String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { switch (p_id) { case 0: - return "Extents X"; + return "Size X"; case 1: - return "Extents Y"; + return "Size Y"; case 2: - return "Extents Z"; + return "Size Z"; case 3: return "Origin X"; case 4: @@ -3460,7 +3460,7 @@ String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gi Variant ReflectionProbeGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_node_3d()); - return AABB(probe->get_extents(), probe->get_origin_offset()); + return AABB(probe->get_origin_offset(), probe->get_size()); } void ReflectionProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { @@ -3470,7 +3470,7 @@ void ReflectionProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, in Transform3D gi = gt.affine_inverse(); if (p_id < 3) { - Vector3 extents = probe->get_extents(); + Vector3 size = probe->get_size(); Vector3 ray_from = p_camera->project_ray_origin(p_point); Vector3 ray_dir = p_camera->project_ray_normal(p_point); @@ -3482,7 +3482,7 @@ void ReflectionProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, in Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_id]; + float d = ra[p_id] * 2; if (Node3DEditor::get_singleton()->is_snap_enabled()) { d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); } @@ -3491,8 +3491,8 @@ void ReflectionProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, in d = 0.001; } - extents[p_id] = d; - probe->set_extents(extents); + size[p_id] = d; + probe->set_size(size); } else { p_id -= 3; @@ -3526,17 +3526,17 @@ void ReflectionProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, AABB restore = p_restore; if (p_cancel) { - probe->set_extents(restore.position); - probe->set_origin_offset(restore.size); + probe->set_origin_offset(restore.position); + probe->set_size(restore.size); return; } EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Change Probe Extents")); - ur->add_do_method(probe, "set_extents", probe->get_extents()); + ur->create_action(TTR("Change Probe Size")); + ur->add_do_method(probe, "set_size", probe->get_size()); ur->add_do_method(probe, "set_origin_offset", probe->get_origin_offset()); - ur->add_undo_method(probe, "set_extents", restore.position); - ur->add_undo_method(probe, "set_origin_offset", restore.size); + ur->add_undo_method(probe, "set_size", restore.size); + ur->add_undo_method(probe, "set_origin_offset", restore.position); ur->commit_action(); } @@ -3547,11 +3547,11 @@ void ReflectionProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> lines; Vector<Vector3> internal_lines; - Vector3 extents = probe->get_extents(); + Vector3 size = probe->get_size(); AABB aabb; - aabb.position = -extents; - aabb.size = extents * 2; + aabb.position = -size / 2; + aabb.size = size; for (int i = 0; i < 12; i++) { Vector3 a, b; @@ -3593,7 +3593,7 @@ void ReflectionProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { if (p_gizmo->is_selected()) { Ref<Material> solid_material = get_material("reflection_probe_solid_material", p_gizmo); - p_gizmo->add_solid_box(solid_material, probe->get_extents() * 2.0); + p_gizmo->add_solid_box(solid_material, probe->get_size()); } p_gizmo->add_unscaled_billboard(icon, 0.05); @@ -3627,11 +3627,11 @@ int DecalGizmoPlugin::get_priority() const { String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { switch (p_id) { case 0: - return "Extents X"; + return "Size X"; case 1: - return "Extents Y"; + return "Size Y"; case 2: - return "Extents Z"; + return "Size Z"; } return ""; @@ -3639,7 +3639,7 @@ String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p Variant DecalGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { Decal *decal = Object::cast_to<Decal>(p_gizmo->get_node_3d()); - return decal->get_extents(); + return decal->get_size(); } void DecalGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { @@ -3648,7 +3648,7 @@ void DecalGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bo Transform3D gi = gt.affine_inverse(); - Vector3 extents = decal->get_extents(); + Vector3 size = decal->get_size(); Vector3 ray_from = p_camera->project_ray_origin(p_point); Vector3 ray_dir = p_camera->project_ray_normal(p_point); @@ -3660,7 +3660,7 @@ void DecalGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bo Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_id]; + float d = ra[p_id] * 2; if (Node3DEditor::get_singleton()->is_snap_enabled()) { d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); } @@ -3669,8 +3669,8 @@ void DecalGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bo d = 0.001; } - extents[p_id] = d; - decal->set_extents(extents); + size[p_id] = d; + decal->set_size(size); } void DecalGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { @@ -3679,14 +3679,14 @@ void DecalGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Vector3 restore = p_restore; if (p_cancel) { - decal->set_extents(restore); + decal->set_size(restore); return; } EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Change Decal Extents")); - ur->add_do_method(decal, "set_extents", decal->get_extents()); - ur->add_undo_method(decal, "set_extents", restore); + ur->create_action(TTR("Change Decal Size")); + ur->add_do_method(decal, "set_size", decal->get_size()); + ur->add_undo_method(decal, "set_size", restore); ur->commit_action(); } @@ -3696,11 +3696,11 @@ void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->clear(); Vector<Vector3> lines; - Vector3 extents = decal->get_extents(); + Vector3 size = decal->get_size(); AABB aabb; - aabb.position = -extents; - aabb.size = extents * 2; + aabb.position = -size / 2; + aabb.size = size; for (int i = 0; i < 12; i++) { Vector3 a, b; @@ -3718,8 +3718,9 @@ void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { } } - lines.push_back(Vector3(0, extents.y, 0)); - lines.push_back(Vector3(0, extents.y * 1.2, 0)); + float half_size_y = size.y / 2; + lines.push_back(Vector3(0, half_size_y, 0)); + lines.push_back(Vector3(0, half_size_y * 1.2, 0)); Vector<Vector3> handles; @@ -3767,11 +3768,11 @@ int VoxelGIGizmoPlugin::get_priority() const { String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { switch (p_id) { case 0: - return "Extents X"; + return "Size X"; case 1: - return "Extents Y"; + return "Size Y"; case 2: - return "Extents Z"; + return "Size Z"; } return ""; @@ -3779,7 +3780,7 @@ String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int Variant VoxelGIGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_node_3d()); - return probe->get_extents(); + return probe->get_size(); } void VoxelGIGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { @@ -3788,7 +3789,7 @@ void VoxelGIGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D gt = probe->get_global_transform(); Transform3D gi = gt.affine_inverse(); - Vector3 extents = probe->get_extents(); + Vector3 size = probe->get_size(); Vector3 ray_from = p_camera->project_ray_origin(p_point); Vector3 ray_dir = p_camera->project_ray_normal(p_point); @@ -3800,7 +3801,7 @@ void VoxelGIGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_id]; + float d = ra[p_id] * 2; if (Node3DEditor::get_singleton()->is_snap_enabled()) { d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); } @@ -3809,8 +3810,8 @@ void VoxelGIGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, d = 0.001; } - extents[p_id] = d; - probe->set_extents(extents); + size[p_id] = d; + probe->set_size(size); } void VoxelGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { @@ -3819,14 +3820,14 @@ void VoxelGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_i Vector3 restore = p_restore; if (p_cancel) { - probe->set_extents(restore); + probe->set_size(restore); return; } EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Change Probe Extents")); - ur->add_do_method(probe, "set_extents", probe->get_extents()); - ur->add_undo_method(probe, "set_extents", restore); + ur->create_action(TTR("Change Probe Size")); + ur->add_do_method(probe, "set_size", probe->get_size()); + ur->add_undo_method(probe, "set_size", restore); ur->commit_action(); } @@ -3840,11 +3841,11 @@ void VoxelGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->clear(); Vector<Vector3> lines; - Vector3 extents = probe->get_extents(); + Vector3 size = probe->get_size(); static const int subdivs[VoxelGI::SUBDIV_MAX] = { 64, 128, 256, 512 }; - AABB aabb = AABB(-extents, extents * 2); + AABB aabb = AABB(-size / 2, size); int subdiv = subdivs[probe->get_subdiv()]; float cell_size = aabb.get_longest_axis_size() / subdiv; @@ -4363,7 +4364,7 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i Ref<BoxShape3D> bs = s; Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); - float d = ra[p_id]; + float d = ra[p_id] * 2; if (Node3DEditor::get_singleton()->is_snap_enabled()) { d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); } @@ -4373,7 +4374,7 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i } Vector3 he = bs->get_size(); - he[p_id] = d * 2; + he[p_id] = d; bs->set_size(he); } @@ -5902,11 +5903,11 @@ int FogVolumeGizmoPlugin::get_priority() const { } String FogVolumeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { - return "Extents"; + return "Size"; } Variant FogVolumeGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { - return Vector3(p_gizmo->get_node_3d()->call("get_extents")); + return Vector3(p_gizmo->get_node_3d()->call("get_size")); } void FogVolumeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { @@ -5924,7 +5925,7 @@ void FogVolumeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id axis[p_id] = 1.0; Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); - float d = ra[p_id]; + float d = ra[p_id] * 2; if (Node3DEditor::get_singleton()->is_snap_enabled()) { d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); } @@ -5933,23 +5934,23 @@ void FogVolumeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id d = 0.001; } - Vector3 he = sn->call("get_extents"); + Vector3 he = sn->call("get_size"); he[p_id] = d; - sn->call("set_extents", he); + sn->call("set_size", he); } void FogVolumeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { Node3D *sn = p_gizmo->get_node_3d(); if (p_cancel) { - sn->call("set_extents", p_restore); + sn->call("set_size", p_restore); return; } EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Change Fog Volume Extents")); - ur->add_do_method(sn, "set_extents", sn->call("get_extents")); - ur->add_undo_method(sn, "set_extents", p_restore); + ur->create_action(TTR("Change Fog Volume Size")); + ur->add_do_method(sn, "set_size", sn->call("get_size")); + ur->add_undo_method(sn, "set_size", p_restore); ur->commit_action(); } @@ -5968,8 +5969,8 @@ void FogVolumeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> lines; AABB aabb; - aabb.position = -cs->call("get_extents").operator Vector3(); - aabb.size = aabb.position * -2; + aabb.size = cs->call("get_size").operator Vector3(); + aabb.position = aabb.size / -2; for (int i = 0; i < 12; i++) { Vector3 a, b; @@ -5982,7 +5983,7 @@ void FogVolumeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { for (int i = 0; i < 3; i++) { Vector3 ax; - ax[i] = cs->call("get_extents").operator Vector3()[i]; + ax[i] = cs->call("get_size").operator Vector3()[i] / 2; handles.push_back(ax); } diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp index d894ba4c4a..e8abecd115 100644 --- a/editor/plugins/root_motion_editor_plugin.cpp +++ b/editor/plugins/root_motion_editor_plugin.cpp @@ -229,7 +229,7 @@ bool EditorInspectorRootMotionPlugin::can_handle(Object *p_object) { return true; // Can handle everything. } -bool EditorInspectorRootMotionPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { +bool EditorInspectorRootMotionPlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { if (p_path == "root_motion_track" && p_object->is_class("AnimationTree") && p_type == Variant::NODE_PATH) { EditorPropertyRootMotion *editor = memnew(EditorPropertyRootMotion); add_property_editor(p_path, editor); diff --git a/editor/plugins/root_motion_editor_plugin.h b/editor/plugins/root_motion_editor_plugin.h index f9b1a9f478..d27f0d30cc 100644 --- a/editor/plugins/root_motion_editor_plugin.h +++ b/editor/plugins/root_motion_editor_plugin.h @@ -63,7 +63,7 @@ class EditorInspectorRootMotionPlugin : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override; }; #endif // ROOT_MOTION_EDITOR_PLUGIN_H diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index a7b32ce0c3..14b5f7cefb 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -425,6 +425,7 @@ void SpriteFramesEditor::_notification(int p_what) { _update_stop_icon(); autoplay->set_icon(get_theme_icon(SNAME("AutoPlay"), SNAME("EditorIcons"))); + anim_loop->set_icon(get_theme_icon(SNAME("Loop"), SNAME("EditorIcons"))); play->set_icon(get_theme_icon(SNAME("PlayStart"), SNAME("EditorIcons"))); play_from->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons"))); play_bw->set_icon(get_theme_icon(SNAME("PlayStartBackwards"), SNAME("EditorIcons"))); @@ -1114,18 +1115,19 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) { } for (int i = 0; i < frames->get_frame_count(edited_anim); i++) { - String name; + String name = itos(i); Ref<Texture2D> texture = frames->get_frame_texture(edited_anim, i); float duration = frames->get_frame_duration(edited_anim, i); - String duration_string; - if (duration != 1.0f) { - duration_string = String::utf8(" [ ×") + String::num_real(frames->get_frame_duration(edited_anim, i)) + " ]"; - } if (texture.is_null()) { - name = itos(i) + ": " + TTR("(empty)") + duration_string; - } else { - name = itos(i) + ": " + texture->get_name() + duration_string; + texture = empty_icon; + name += ": " + TTR("(empty)"); + } else if (!texture->get_name().is_empty()) { + name += ": " + texture->get_name(); + } + + if (duration != 1.0f) { + name += String::utf8(" [× ") + String::num(duration, 2) + "]"; } frame_list->add_item(name, texture); @@ -1523,12 +1525,33 @@ SpriteFramesEditor::SpriteFramesEditor() { autoplay_container = memnew(HBoxContainer); hbc_animlist->add_child(autoplay_container); + autoplay_container->add_child(memnew(VSeparator)); + autoplay = memnew(Button); autoplay->set_flat(true); autoplay->set_tooltip_text(TTR("Autoplay on Load")); autoplay_container->add_child(autoplay); + hbc_animlist->add_child(memnew(VSeparator)); + + anim_loop = memnew(Button); + anim_loop->set_toggle_mode(true); + anim_loop->set_flat(true); + anim_loop->set_tooltip_text(TTR("Animation Looping")); + anim_loop->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_loop_changed)); + hbc_animlist->add_child(anim_loop); + + anim_speed = memnew(SpinBox); + anim_speed->set_suffix(TTR("FPS")); + anim_speed->set_min(0); + anim_speed->set_max(120); + anim_speed->set_step(0.01); + anim_speed->set_custom_arrow_step(1); + anim_speed->set_tooltip_text(TTR("Animation Speed")); + anim_speed->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_animation_speed_changed)); + hbc_animlist->add_child(anim_speed); + anim_search_box = memnew(LineEdit); sub_vb->add_child(anim_search_box); anim_search_box->set_h_size_flags(SIZE_EXPAND_FILL); @@ -1549,23 +1572,6 @@ SpriteFramesEditor::SpriteFramesEditor() { delete_anim->set_shortcut_context(animations); delete_anim->set_shortcut(ED_SHORTCUT("sprite_frames/delete_animation", TTR("Delete Animation"), Key::KEY_DELETE)); - HBoxContainer *hbc_anim_speed = memnew(HBoxContainer); - hbc_anim_speed->add_child(memnew(Label(TTR("Speed:")))); - vbc_animlist->add_child(hbc_anim_speed); - anim_speed = memnew(SpinBox); - anim_speed->set_suffix(TTR("FPS")); - anim_speed->set_min(0); - anim_speed->set_max(120); - anim_speed->set_step(0.01); - anim_speed->set_h_size_flags(SIZE_EXPAND_FILL); - hbc_anim_speed->add_child(anim_speed); - anim_speed->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_animation_speed_changed)); - - anim_loop = memnew(CheckButton); - anim_loop->set_text(TTR("Loop")); - vbc_animlist->add_child(anim_loop); - anim_loop->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_loop_changed)); - VBoxContainer *vbc = memnew(VBoxContainer); add_child(vbc); vbc->set_h_size_flags(SIZE_EXPAND_FILL); @@ -1667,6 +1673,7 @@ SpriteFramesEditor::SpriteFramesEditor() { frame_duration->set_min(SPRITE_FRAME_MINIMUM_DURATION); // Avoid zero div. frame_duration->set_max(10); frame_duration->set_step(0.01); + frame_duration->set_custom_arrow_step(0.1); frame_duration->set_allow_lesser(false); frame_duration->set_allow_greater(true); hbc->add_child(frame_duration); @@ -1946,9 +1953,7 @@ void SpriteFramesEditorPlugin::make_visible(bool p_visible) { EditorNode::get_singleton()->make_bottom_panel_item_visible(frames_editor); } else { button->hide(); - if (frames_editor->is_visible_in_tree()) { - EditorNode::get_singleton()->hide_bottom_panel(); - } + frames_editor->edit(Ref<SpriteFrames>()); } } diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index 19ecfb00ed..1dfb909388 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -73,6 +73,7 @@ class SpriteFramesEditor : public HSplitContainer { Ref<Texture2D> autoplay_icon; Ref<Texture2D> stop_icon; Ref<Texture2D> pause_icon; + Ref<Texture2D> empty_icon = memnew(ImageTexture); HBoxContainer *playback_container = nullptr; Button *stop = nullptr; @@ -100,13 +101,14 @@ class SpriteFramesEditor : public HSplitContainer { Button *add_anim = nullptr; Button *delete_anim = nullptr; + SpinBox *anim_speed = nullptr; + Button *anim_loop = nullptr; + HBoxContainer *autoplay_container = nullptr; Button *autoplay = nullptr; - LineEdit *anim_search_box = nullptr; + LineEdit *anim_search_box = nullptr; Tree *animations = nullptr; - SpinBox *anim_speed = nullptr; - CheckButton *anim_loop = nullptr; EditorFileDialog *file = nullptr; diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index c5aa60c816..7fa16e6cc6 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -1224,7 +1224,7 @@ void EditorInspectorPluginTextureRegion::_region_edit(Object *p_object) { texture_region_editor->edit(p_object); } -bool EditorInspectorPluginTextureRegion::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { +bool EditorInspectorPluginTextureRegion::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { if ((p_type == Variant::RECT2 || p_type == Variant::RECT2I)) { if (((Object::cast_to<Sprite2D>(p_object) || Object::cast_to<Sprite3D>(p_object) || Object::cast_to<NinePatchRect>(p_object) || Object::cast_to<StyleBoxTexture>(p_object)) && p_path == "region_rect") || (Object::cast_to<AtlasTexture>(p_object) && p_path == "region")) { Button *button = EditorInspector::create_inspector_action_button(TTR("Edit Region")); diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index ba64a04084..c303cec3f5 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -156,7 +156,7 @@ class EditorInspectorPluginTextureRegion : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) override; EditorInspectorPluginTextureRegion(); }; diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index 840a3911af..912fdb03a9 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -2773,7 +2773,7 @@ bool EditorInspectorPluginTileData::can_handle(Object *p_object) { return Object::cast_to<TileSetAtlasSourceEditor::AtlasTileProxyObject>(p_object) != nullptr; } -bool EditorInspectorPluginTileData::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { +bool EditorInspectorPluginTileData::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { Vector<String> components = String(p_path).split("/", true, 2); if (components.size() == 2 && components[0].begins_with("occlusion_layer_") && components[0].trim_prefix("occlusion_layer_").is_valid_int()) { // Occlusion layers. diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h index a4826bc56f..5141824f79 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.h +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h @@ -312,7 +312,7 @@ class EditorInspectorPluginTileData : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override; }; #endif // TILE_SET_ATLAS_SOURCE_EDITOR_H diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index af70e64b6a..59b5795ae3 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -5536,6 +5536,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("ViewIndex", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ViewMonoLeft", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ViewRight", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("EyeOffset", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "eye_offset", "EYE_OFFSET"), { "eye_offset" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("NodePositionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("CameraPositionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("CameraDirectionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); @@ -5554,6 +5555,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("ViewIndex", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ViewMonoLeft", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ViewRight", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("EyeOffset", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "eye_offset", "EYE_OFFSET"), { "eye_offset" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("NodePositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("CameraPositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("CameraDirectionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); @@ -5647,7 +5649,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("WorldPosition", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "world_position", "WORLD_POSITION"), { "world_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG)); add_options.push_back(AddOption("ObjectPosition", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "object_position", "OBJECT_POSITION"), { "object_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG)); add_options.push_back(AddOption("UVW", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "uvw", "UVW"), { "uvw" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG)); - add_options.push_back(AddOption("Extents", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "extents", "EXTENTS"), { "extents" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG)); + add_options.push_back(AddOption("Size", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "size", "SIZE"), { "size" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG)); add_options.push_back(AddOption("SDF", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "sdf", "SDF"), { "sdf" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FOG, Shader::MODE_FOG)); add_options.push_back(AddOption("Time", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "time", "TIME"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FOG, Shader::MODE_FOG)); @@ -6568,7 +6570,7 @@ bool EditorInspectorVisualShaderModePlugin::can_handle(Object *p_object) { return true; // Can handle everything. } -bool EditorInspectorVisualShaderModePlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { +bool EditorInspectorVisualShaderModePlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) { if (p_path == "mode" && p_object->is_class("VisualShader") && p_type == Variant::INT) { EditorPropertyVisualShaderMode *mode_editor = memnew(EditorPropertyVisualShaderMode); Vector<String> options = p_hint_text.split(","); diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 519a390ccc..142c8167a8 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -561,7 +561,7 @@ class EditorInspectorVisualShaderModePlugin : public EditorInspectorPlugin { public: virtual bool can_handle(Object *p_object) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override; }; class VisualShaderNodePortPreview : public Control { diff --git a/editor/plugins/voxel_gi_editor_plugin.cpp b/editor/plugins/voxel_gi_editor_plugin.cpp index f9f72fee77..1087a50df6 100644 --- a/editor/plugins/voxel_gi_editor_plugin.cpp +++ b/editor/plugins/voxel_gi_editor_plugin.cpp @@ -101,12 +101,12 @@ void VoxelGIEditorPlugin::_notification(int p_what) { // Set information tooltip on the Bake button. This information is useful // to optimize performance (video RAM size) and reduce light leaking (individual cell size). - const Vector3i size = voxel_gi->get_estimated_cell_size(); + const Vector3i cell_size = voxel_gi->get_estimated_cell_size(); - const Vector3 extents = voxel_gi->get_extents(); + const Vector3 half_size = voxel_gi->get_size() / 2; const int data_size = 4; - const double size_mb = size.x * size.y * size.z * data_size / (1024.0 * 1024.0); + const double size_mb = cell_size.x * cell_size.y * cell_size.z * data_size / (1024.0 * 1024.0); // Add a qualitative measurement to help the user assess whether a VoxelGI node is using a lot of VRAM. String size_quality; if (size_mb < 16.0) { @@ -118,8 +118,8 @@ void VoxelGIEditorPlugin::_notification(int p_what) { } String text; - text += vformat(TTR("Subdivisions: %s"), vformat(String::utf8("%d × %d × %d"), size.x, size.y, size.z)) + "\n"; - text += vformat(TTR("Cell size: %s"), vformat(String::utf8("%.3f × %.3f × %.3f"), extents.x / size.x, extents.y / size.y, extents.z / size.z)) + "\n"; + text += vformat(TTR("Subdivisions: %s"), vformat(String::utf8("%d × %d × %d"), cell_size.x, cell_size.y, cell_size.z)) + "\n"; + text += vformat(TTR("Cell size: %s"), vformat(String::utf8("%.3f × %.3f × %.3f"), half_size.x / cell_size.x, half_size.y / cell_size.y, half_size.z / cell_size.z)) + "\n"; text += vformat(TTR("Video RAM size: %s MB (%s)"), String::num(size_mb, 2), size_quality); // Only update the tooltip when needed to avoid constant redrawing. diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp index 37f941c7b2..9695a7042d 100644 --- a/editor/progress_dialog.cpp +++ b/editor/progress_dialog.cpp @@ -257,6 +257,7 @@ ProgressDialog::ProgressDialog() { add_child(main); main->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); set_exclusive(true); + set_flag(Window::FLAG_POPUP, false); last_progress_tick = 0; singleton = this; cancel_hb = memnew(HBoxContainer); diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index 93d3a323ea..d3e16211f7 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -32,10 +32,11 @@ #include "modules/modules_enabled.gen.h" -const int ERROR_CODE = 77; - +#ifndef DISABLE_DEPRECATED #ifdef MODULE_REGEX_ENABLED +const int ERROR_CODE = 77; + #include "modules/regex/regex.h" #include "core/io/dir_access.h" @@ -44,7 +45,7 @@ const int ERROR_CODE = 77; #include "core/templates/list.h" #include "core/templates/local_vector.h" -static const char *enum_renames[][2] = { +const char *ProjectConverter3To4::enum_renames[][2] = { //// constants { "TYPE_COLOR_ARRAY", "TYPE_PACKED_COLOR_ARRAY" }, { "TYPE_FLOAT64_ARRAY", "TYPE_PACKED_FLOAT64_ARRAY" }, @@ -164,7 +165,7 @@ static const char *enum_renames[][2] = { { nullptr, nullptr }, }; -static const char *gdscript_function_renames[][2] = { +const char *ProjectConverter3To4::gdscript_function_renames[][2] = { // { "_set_name", "get_tracker_name"}, // XRPositionalTracker - CameraFeed use this // { "_unhandled_input", "_unhandled_key_input"}, // BaseButton, ViewportContainer broke Node, FileDialog,SubViewportContainer // { "create_gizmo", "_create_gizmo"}, // EditorNode3DGizmoPlugin - may be used @@ -240,6 +241,9 @@ static const char *gdscript_function_renames[][2] = { { "can_generate_small_preview", "_can_generate_small_preview" }, // EditorResourcePreviewGenerator { "can_instance", "can_instantiate" }, // PackedScene, Script { "canvas_light_set_scale", "canvas_light_set_texture_scale" }, // RenderingServer + { "capture_get_device", "get_input_device" }, // AudioServer + { "capture_get_device_list", "get_input_device_list" }, // AudioServer + { "capture_set_device", "set_input_device" }, // AudioServer { "center_viewport_to_cursor", "center_viewport_to_caret" }, // TextEdit { "change_scene", "change_scene_to_file" }, // SceneTree { "change_scene_to", "change_scene_to_packed" }, // SceneTree @@ -300,6 +304,8 @@ static const char *gdscript_function_renames[][2] = { { "get_cursor_position", "get_caret_column" }, // LineEdit { "get_d", "get_distance" }, // LineShape2D { "get_depth_bias_enable", "get_depth_bias_enabled" }, // RDPipelineRasterizationState + { "get_device", "get_output_device" }, // AudioServer + { "get_device_list", "get_output_device_list" }, // AudioServer { "get_drag_data", "_get_drag_data" }, // Control { "get_editor_viewport", "get_editor_main_screen" }, // EditorPlugin { "get_enabled_focus_mode", "get_focus_mode" }, // BaseButton @@ -311,8 +317,8 @@ static const char *gdscript_function_renames[][2] = { { "get_font_types", "get_font_type_list" }, // Theme { "get_frame_color", "get_color" }, // ColorRect { "get_global_rate_scale", "get_playback_speed_scale" }, // AudioServer - { "get_gravity_distance_scale", "get_gravity_point_distance_scale" }, //Area2D - { "get_gravity_vector", "get_gravity_direction" }, //Area2D + { "get_gravity_distance_scale", "get_gravity_point_unit_distance" }, // Area(2D/3D) + { "get_gravity_vector", "get_gravity_direction" }, // Area(2D/3D) { "get_h_scrollbar", "get_h_scroll_bar" }, //ScrollContainer { "get_hand", "get_tracker_hand" }, // XRPositionalTracker { "get_handle_name", "_get_handle_name" }, // EditorNode3DGizmo @@ -498,6 +504,7 @@ static const char *gdscript_function_renames[][2] = { { "set_cursor_position", "set_caret_column" }, // LineEdit { "set_d", "set_distance" }, // WorldMarginShape2D { "set_depth_bias_enable", "set_depth_bias_enabled" }, // RDPipelineRasterizationState + { "set_device", "set_output_device" }, // AudioServer { "set_doubleclick", "set_double_click" }, // InputEventMouseButton { "set_draw_red", "set_draw_warning" }, // EditorProperty { "set_enable_follow_smoothing", "set_position_smoothing_enabled" }, // Camera2D @@ -509,8 +516,8 @@ static const char *gdscript_function_renames[][2] = { { "set_follow_smoothing", "set_position_smoothing_speed" }, // Camera2D { "set_frame_color", "set_color" }, // ColorRect { "set_global_rate_scale", "set_playback_speed_scale" }, // AudioServer - { "set_gravity_distance_scale", "set_gravity_point_distance_scale" }, // Area2D - { "set_gravity_vector", "set_gravity_direction" }, // Area2D + { "set_gravity_distance_scale", "set_gravity_point_unit_distance" }, // Area(2D/3D) + { "set_gravity_vector", "set_gravity_direction" }, // Area(2D/3D) { "set_h_drag_enabled", "set_drag_horizontal_enabled" }, // Camera2D { "set_icon_align", "set_icon_alignment" }, // Button { "set_interior_ambient", "set_ambient_color" }, // ReflectionProbe @@ -619,7 +626,7 @@ static const char *gdscript_function_renames[][2] = { }; // gdscript_function_renames clone with CamelCase -static const char *csharp_function_renames[][2] = { +const char *ProjectConverter3To4::csharp_function_renames[][2] = { // { "_SetName", "GetTrackerName"}, // XRPositionalTracker - CameraFeed use this // { "_UnhandledInput", "_UnhandledKeyInput"}, // BaseButton, ViewportContainer broke Node, FileDialog,SubViewportContainer // { "CreateGizmo", "_CreateGizmo"}, // EditorNode3DGizmoPlugin - may be used @@ -696,6 +703,9 @@ static const char *csharp_function_renames[][2] = { { "CanGenerateSmallPreview", "_CanGenerateSmallPreview" }, // EditorResourcePreviewGenerator { "CanInstance", "CanInstantiate" }, // PackedScene, Script { "CanvasLightSetScale", "CanvasLightSetTextureScale" }, // RenderingServer + { "CaptureGetDevice", "GetInputDevice" }, // AudioServer + { "CaptureGetDeviceList", "GetInputDeviceList" }, // AudioServer + { "CaptureSetDevice", "SetInputDevice" }, // AudioServer { "CenterViewportToCursor", "CenterViewportToCaret" }, // TextEdit { "ChangeScene", "ChangeSceneToFile" }, // SceneTree { "ChangeSceneTo", "ChangeSceneToPacked" }, // SceneTree @@ -753,6 +763,8 @@ static const char *csharp_function_renames[][2] = { { "GetCursorPosition", "GetCaretColumn" }, // LineEdit { "GetD", "GetDistance" }, // LineShape2D { "GetDepthBiasEnable", "GetDepthBiasEnabled" }, // RDPipelineRasterizationState + { "GetDevice", "GetOutputDevice" }, // AudioServer + { "GetDeviceList", "GetOutputDeviceList" }, // AudioServer { "GetDragDataFw", "_GetDragDataFw" }, // ScriptEditor { "GetEditorViewport", "GetViewport" }, // EditorPlugin { "GetEnabledFocusMode", "GetFocusMode" }, // BaseButton @@ -941,6 +953,7 @@ static const char *csharp_function_renames[][2] = { { "SetCursorPosition", "SetCaretColumn" }, // LineEdit { "SetD", "SetDistance" }, // WorldMarginShape2D { "SetDepthBiasEnable", "SetDepthBiasEnabled" }, // RDPipelineRasterizationState + { "SetDevice", "SetOutputDevice" }, // AudioServer { "SetDoubleclick", "SetDoubleClick" }, // InputEventMouseButton { "SetEnableFollowSmoothing", "SetFollowSmoothingEnabled" }, // Camera2D { "SetEnabledFocusMode", "SetFocusMode" }, // BaseButton @@ -1056,7 +1069,7 @@ static const char *csharp_function_renames[][2] = { }; // Some needs to be disabled, because users can use this names as variables -static const char *gdscript_properties_renames[][2] = { +const char *ProjectConverter3To4::gdscript_properties_renames[][2] = { // // { "d", "distance" }, //WorldMarginShape2D - TODO, looks that polish letters Ä… Ä™ are treaten as space, not as letter, so `bÄ™dÄ…` are renamed to `bÄ™distanceÄ…` // // {"alt","alt_pressed"}, // This may broke a lot of comments and user variables // // {"command","command_pressed"},// This may broke a lot of comments and user variables @@ -1069,6 +1082,7 @@ static const char *gdscript_properties_renames[][2] = { // // {"shift","shift_pressed"},// This may broke a lot of comments and user variables // { "autowrap", "autowrap_mode" }, // Label // { "cast_to", "target_position" }, // RayCast2D, RayCast3D + // { "device", "output_device"}, // AudioServer - Too vague, most likely breaks comments & variables // { "doubleclick", "double_click" }, // InputEventMouseButton // { "group", "button_group" }, // BaseButton // { "process_mode", "process_callback" }, // AnimationTree, Camera2D @@ -1084,6 +1098,7 @@ static const char *gdscript_properties_renames[][2] = { { "bbcode_text", "text" }, // RichTextLabel { "bg", "panel" }, // Theme { "bg_focus", "focus" }, // Theme + { "capture_device", "input_device" }, // AudioServer { "caret_blink_speed", "caret_blink_interval" }, // TextEdit, LineEdit { "caret_moving_by_right_click", "caret_move_on_right_click" }, // TextEdit { "caret_position", "caret_column" }, // LineEdit @@ -1111,8 +1126,8 @@ static const char *gdscript_properties_renames[][2] = { { "files_disabled", "file_disabled_color" }, // Theme { "folder_icon_modulate", "folder_icon_color" }, // Theme { "global_rate_scale", "playback_speed_scale" }, // AudioServer - { "gravity_distance_scale", "gravity_point_distance_scale" }, // Area2D - { "gravity_vec", "gravity_direction" }, // Area2D + { "gravity_distance_scale", "gravity_point_unit_distance" }, // Area(2D/3D) + { "gravity_vec", "gravity_direction" }, // Area(2D/3D) { "hint_tooltip", "tooltip_text" }, // Control { "hseparation", "h_separation" }, // Theme { "icon_align", "icon_alignment" }, // Button @@ -1173,7 +1188,7 @@ static const char *gdscript_properties_renames[][2] = { }; // Some needs to be disabled, because users can use this names as variables -static const char *csharp_properties_renames[][2] = { +const char *ProjectConverter3To4::csharp_properties_renames[][2] = { // // { "D", "Distance" }, //WorldMarginShape2D - TODO, looks that polish letters Ä… Ä™ are treaten as space, not as letter, so `bÄ™dÄ…` are renamed to `bÄ™distanceÄ…` // // {"Alt","AltPressed"}, // This may broke a lot of comments and user variables // // {"Command","CommandPressed"},// This may broke a lot of comments and user variables @@ -1278,7 +1293,7 @@ static const char *csharp_properties_renames[][2] = { { nullptr, nullptr }, }; -static const char *gdscript_signals_renames[][2] = { +const char *ProjectConverter3To4::gdscript_signals_renames[][2] = { // {"instantiate","instance"}, // FileSystemDock // { "hide", "hidden" }, // CanvasItem - function with same name exists // { "tween_all_completed","loop_finished"}, // Tween - TODO, not sure @@ -1303,7 +1318,7 @@ static const char *gdscript_signals_renames[][2] = { { nullptr, nullptr }, }; -static const char *csharp_signals_renames[][2] = { +const char *ProjectConverter3To4::csharp_signals_renames[][2] = { // {"Instantiate","Instance"}, // FileSystemDock // { "Hide", "Hidden" }, // CanvasItem - function with same name exists // { "TweenAllCompleted","LoopFinished"}, // Tween - TODO, not sure @@ -1327,7 +1342,7 @@ static const char *csharp_signals_renames[][2] = { }; -static const char *project_settings_renames[][2] = { +const char *ProjectConverter3To4::project_settings_renames[][2] = { { "audio/channel_disable_threshold_db", "audio/buses/channel_disable_threshold_db" }, { "audio/channel_disable_time", "audio/buses/channel_disable_time" }, { "audio/default_bus_layout", "audio/buses/default_bus_layout" }, @@ -1372,7 +1387,7 @@ static const char *project_settings_renames[][2] = { { nullptr, nullptr }, }; -static const char *input_map_renames[][2] = { +const char *ProjectConverter3To4::input_map_renames[][2] = { { ",\"alt\":", ",\"alt_pressed\":" }, { ",\"shift\":", ",\"shift_pressed\":" }, { ",\"control\":", ",\"ctrl_pressed\":" }, @@ -1384,7 +1399,7 @@ static const char *input_map_renames[][2] = { { nullptr, nullptr }, }; -static const char *builtin_types_renames[][2] = { +const char *ProjectConverter3To4::builtin_types_renames[][2] = { { "PoolByteArray", "PackedByteArray" }, { "PoolColorArray", "PackedColorArray" }, { "PoolIntArray", "PackedInt32Array" }, @@ -1398,7 +1413,7 @@ static const char *builtin_types_renames[][2] = { { nullptr, nullptr }, }; -static const char *shaders_renames[][2] = { +const char *ProjectConverter3To4::shaders_renames[][2] = { { "ALPHA_SCISSOR", "ALPHA_SCISSOR_THRESHOLD" }, { "CAMERA_MATRIX", "INV_VIEW_MATRIX" }, { "INV_CAMERA_MATRIX", "VIEW_MATRIX" }, @@ -1416,7 +1431,7 @@ static const char *shaders_renames[][2] = { { nullptr, nullptr }, }; -static const char *class_renames[][2] = { +const char *ProjectConverter3To4::class_renames[][2] = { // { "BulletPhysicsDirectBodyState", "BulletPhysicsDirectBodyState3D" }, // Class is not visible in ClassDB // { "BulletPhysicsServer", "BulletPhysicsServer3D" }, // Class is not visible in ClassDB // { "GDScriptFunctionState", "Node3D" }, // TODO - not sure to which should be changed @@ -1641,7 +1656,7 @@ static const char *class_renames[][2] = { { nullptr, nullptr }, }; -static const char *color_renames[][2] = { +const char *ProjectConverter3To4::ProjectConverter3To4::color_renames[][2] = { { "aliceblue", "ALICE_BLUE" }, { "antiquewhite", "ANTIQUE_WHITE" }, { "aqua", "AQUA" }, @@ -4350,3 +4365,4 @@ int ProjectConverter3To4::validate_conversion() { } #endif // MODULE_REGEX_ENABLED +#endif // DISABLE_DEPRECATED diff --git a/editor/project_converter_3_to_4.h b/editor/project_converter_3_to_4.h index b3aa52f1e3..6ec2dd188d 100644 --- a/editor/project_converter_3_to_4.h +++ b/editor/project_converter_3_to_4.h @@ -29,6 +29,7 @@ /**************************************************************************/ #ifndef PROJECT_CONVERTER_3_TO_4_H +#ifndef DISABLE_DEPRECATED #define PROJECT_CONVERTER_3_TO_4_H #include "core/io/file_access.h" @@ -41,6 +42,19 @@ class RegEx; class ProjectConverter3To4 { public: class RegExContainer; + static const char *enum_renames[][2]; + static const char *gdscript_function_renames[][2]; + static const char *csharp_function_renames[][2]; + static const char *gdscript_properties_renames[][2]; + static const char *csharp_properties_renames[][2]; + static const char *gdscript_signals_renames[][2]; + static const char *csharp_signals_renames[][2]; + static const char *project_settings_renames[][2]; + static const char *input_map_renames[][2]; + static const char *builtin_types_renames[][2]; + static const char *shaders_renames[][2]; + static const char *class_renames[][2]; + static const char *color_renames[][2]; private: uint64_t maximum_file_size; @@ -97,4 +111,6 @@ public: int convert(); }; +#endif // DISABLE_DEPRECATED + #endif // PROJECT_CONVERTER_3_TO_4_H diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index c4f5eb777e..105e3a5d47 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1503,8 +1503,13 @@ void ProjectList::create_project_item_control(int p_index) { path_hb->add_child(show); if (!item.missing) { +#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED) show->connect("pressed", callable_mp(this, &ProjectList::_show_project).bind(item.path)); show->set_tooltip_text(TTR("Show in File Manager")); +#else + // Opening the system file manager is not supported on the Android and web editors. + show->hide(); +#endif } else { show->set_tooltip_text(TTR("Error: Project is missing on the filesystem.")); } diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 560549d249..a43745b70f 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -370,17 +370,7 @@ void ProjectSettingsEditor::_action_edited(const String &p_name, const Dictionar } else { // Events changed - int act_event_count = ((Array)p_action["events"]).size(); - int old_event_count = ((Array)old_val["events"]).size(); - - if (act_event_count == old_event_count) { - undo_redo->create_action(TTR("Edit Input Action Event")); - } else if (act_event_count > old_event_count) { - undo_redo->create_action(TTR("Add Input Action Event")); - } else { - undo_redo->create_action(TTR("Remove Input Action Event")); - } - + undo_redo->create_action(TTR("Change Input Action Event(s)")); undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", property_name, p_action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", property_name, old_val); } @@ -527,6 +517,8 @@ void ProjectSettingsEditor::_update_action_map_editor() { if (is_builtin_input) { action_info.editable = false; action_info.icon = builtin_icon; + action_info.has_initial = true; + action_info.action_initial = ProjectSettings::get_singleton()->property_get_revert(property_name); } actions.push_back(action_info); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 86e77fbbbe..d8f1d92e44 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1427,7 +1427,14 @@ void SceneTreeDock::_script_open_request(const Ref<Script> &p_script) { } void SceneTreeDock::_push_item(Object *p_object) { - EditorNode::get_singleton()->push_item(p_object); + Node *node = Object::cast_to<Node>(p_object); + if (node || !p_object) { + // Assume that null object is a Node. + EditorNode::get_singleton()->push_node_item(node); + } else { + EditorNode::get_singleton()->push_item(p_object); + } + if (p_object == nullptr) { EditorNode::get_singleton()->hide_unused_editors(this); } diff --git a/misc/scripts/codespell.sh b/misc/scripts/codespell.sh index 44084b3348..0551492420 100755 --- a/misc/scripts/codespell.sh +++ b/misc/scripts/codespell.sh @@ -1,5 +1,8 @@ #!/bin/sh -SKIP_LIST="./.*,./bin,./editor/project_converter_3_to_4.cpp,./platform/web/node_modules,./platform/android/java/lib/src/com,./thirdparty,*.gen.*,*.po,*.pot,*.rc,package-lock.json,./core/string/locales.h,./AUTHORS.md,./COPYRIGHT.txt,./DONORS.md,./misc/dist/linux/org.godotengine.Godot.desktop,./misc/scripts/codespell.sh" -IGNORE_LIST="alo,ba,childs,complies,curvelinear,doubleclick,expct,fave,findn,gird,gud,inout,lod,nd,numer,ois,readded,ro,sav,statics,te,varius,varn,wan" +SKIP_LIST="./.*,./bin,./thirdparty,*.desktop,*.gen.*,*.po,*.pot,*.rc,./AUTHORS.md,./COPYRIGHT.txt,./DONORS.md," +SKIP_LIST+="./core/string/locales.h,./editor/project_converter_3_to_4.cpp,./misc/scripts/codespell.sh," +SKIP_LIST+="./platform/android/java/lib/src/com,./platform/web/node_modules,./platform/web/package-lock.json," + +IGNORE_LIST="alo,ba,complies,curvelinear,doubleclick,expct,fave,findn,gird,gud,inout,lod,nd,numer,ois,readded,ro,sav,statics,te,varius,varn,wan" codespell -w -q 3 -S "${SKIP_LIST}" -L "${IGNORE_LIST}" --builtin "clear,rare,en-GB_to_en-US" diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 9cc3d0413d..13c7a8202c 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -558,7 +558,7 @@ void CSGShape3D::_notification(int p_what) { set_collision_layer(collision_layer); set_collision_mask(collision_mask); set_collision_priority(collision_priority); - _update_collision_faces(); + _make_dirty(); } } break; @@ -1763,7 +1763,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { } } - if (!path) { + if (!path || !path->is_inside_tree()) { return new_brush; } diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 7f9d4ae253..32acad76aa 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -227,18 +227,6 @@ [/codeblock] </description> </method> - <method name="str" qualifiers="vararg"> - <return type="String" /> - <description> - Converts one or more arguments to a [String] in the best way possible. - [codeblock] - var a = [10, 20, 30] - var b = str(a); - len(a) # Returns 3 - len(b) # Returns 12 - [/codeblock] - </description> - </method> <method name="type_exists"> <return type="bool" /> <param index="0" name="type" type="StringName" /> @@ -563,6 +551,7 @@ [/codeblock] [b]Note:[/b] Only the script can have a custom icon. Inner classes are not supported. [b]Note:[/b] As annotations describe their subject, the [code]@icon[/code] annotation must be placed before the class definition and inheritance. + [b]Note:[/b] Unlike other annotations, the argument of the [code]@icon[/code] annotation must be a string literal (constant expressions are not supported). </description> </annotation> <annotation name="@onready"> diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index d9b8a540c0..8324cb0fe0 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -706,11 +706,7 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc } members_cache.push_back(member.variable->export_info); - Variant default_value; - if (member.variable->initializer && member.variable->initializer->is_constant) { - default_value = member.variable->initializer->reduced_value; - GDScriptCompiler::convert_to_initializer_type(default_value, member.variable); - } + Variant default_value = analyzer.make_variable_default_value(member.variable); member_default_values_cache[member.variable->identifier->name] = default_value; } break; case GDScriptParser::ClassNode::Member::SIGNAL: { @@ -1525,41 +1521,24 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) { HashMap<StringName, GDScript::MemberInfo>::Iterator E = script->member_indices.find(p_name); if (E) { const GDScript::MemberInfo *member = &E->value; - if (member->setter) { - const Variant *val = &p_value; + Variant value = p_value; + if (member->data_type.has_type && !member->data_type.is_type(value)) { + const Variant *args = &p_value; Callable::CallError err; - callp(member->setter, &val, 1, err); - if (err.error == Callable::CallError::CALL_OK) { - return true; //function exists, call was successful - } else { + Variant::construct(member->data_type.builtin_type, value, &args, 1, err); + if (err.error != Callable::CallError::CALL_OK || !member->data_type.is_type(value)) { return false; } + } + if (member->setter) { + const Variant *args = &value; + Callable::CallError err; + callp(member->setter, &args, 1, err); + return err.error == Callable::CallError::CALL_OK; } else { - if (member->data_type.has_type) { - if (member->data_type.builtin_type == Variant::ARRAY && member->data_type.has_container_element_type()) { - // Typed array. - if (p_value.get_type() == Variant::ARRAY) { - return VariantInternal::get_array(&members.write[member->index])->typed_assign(p_value); - } else { - return false; - } - } else if (!member->data_type.is_type(p_value)) { - // Try conversion - Callable::CallError ce; - const Variant *value = &p_value; - Variant converted; - Variant::construct(member->data_type.builtin_type, converted, &value, 1, ce); - if (ce.error == Callable::CallError::CALL_OK) { - members.write[member->index] = converted; - return true; - } else { - return false; - } - } - } - members.write[member->index] = p_value; + members.write[member->index] = value; + return true; } - return true; } } @@ -2458,21 +2437,25 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b GDScriptParser parser; err = parser.parse(source, p_path, false); - if (err) { - return String(); - } - - GDScriptAnalyzer analyzer(&parser); - err = analyzer.resolve_inheritance(); - if (err) { - return String(); - } const GDScriptParser::ClassNode *c = parser.get_tree(); - - if (r_base_type) { - *r_base_type = c->get_datatype().native_type; - } + if (!c) { + return String(); // No class parsed. + } + + /* **WARNING** + * + * This function is written with the goal to be *extremely* error tolerant, as such + * it should meet the following requirements: + * + * - It must not rely on the analyzer (in fact, the analyzer must not be used here), + * because at the time global classes are parsed, the dependencies may not be present + * yet, hence the function will fail (which is unintended). + * - It must not fail even if the parsing fails, because even if the file is broken, + * it should attempt its best to retrieve the inheritance metadata. + * + * Before changing this function, please ask the current maintainer of EditorFileSystem. + */ if (r_icon_path) { if (c->icon_path.is_empty() || c->icon_path.is_absolute_path()) { @@ -2481,7 +2464,73 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b *r_icon_path = p_path.get_base_dir().path_join(c->icon_path).simplify_path(); } } + if (r_base_type) { + const GDScriptParser::ClassNode *subclass = c; + String path = p_path; + GDScriptParser subparser; + while (subclass) { + if (subclass->extends_used) { + if (!subclass->extends_path.is_empty()) { + if (subclass->extends.size() == 0) { + get_global_class_name(subclass->extends_path, r_base_type); + subclass = nullptr; + break; + } else { + Vector<StringName> extend_classes = subclass->extends; + + Ref<FileAccess> subfile = FileAccess::open(subclass->extends_path, FileAccess::READ); + if (subfile.is_null()) { + break; + } + String subsource = subfile->get_as_utf8_string(); + + if (subsource.is_empty()) { + break; + } + String subpath = subclass->extends_path; + if (subpath.is_relative_path()) { + subpath = path.get_base_dir().path_join(subpath).simplify_path(); + } + if (OK != subparser.parse(subsource, subpath, false)) { + break; + } + path = subpath; + subclass = subparser.get_tree(); + + while (extend_classes.size() > 0) { + bool found = false; + for (int i = 0; i < subclass->members.size(); i++) { + if (subclass->members[i].type != GDScriptParser::ClassNode::Member::CLASS) { + continue; + } + + const GDScriptParser::ClassNode *inner_class = subclass->members[i].m_class; + if (inner_class->identifier->name == extend_classes[0]) { + extend_classes.remove_at(0); + found = true; + subclass = inner_class; + break; + } + } + if (!found) { + subclass = nullptr; + break; + } + } + } + } else if (subclass->extends.size() == 1) { + *r_base_type = subclass->extends[0]; + subclass = nullptr; + } else { + break; + } + } else { + *r_base_type = "RefCounted"; + subclass = nullptr; + } + } + } return c->identifier != nullptr ? String(c->identifier->name) : String(); } diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 8dd65a700a..1c2b743909 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -580,6 +580,7 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type if (result.builtin_type == Variant::ARRAY) { GDScriptParser::DataType container_type = type_from_metatype(resolve_datatype(p_type->container_type)); if (container_type.kind != GDScriptParser::DataType::VARIANT) { + container_type.is_constant = false; result.set_container_element_type(container_type); } } @@ -1571,18 +1572,18 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi if (p_assignable->initializer->type == GDScriptParser::Node::ARRAY) { GDScriptParser::ArrayNode *array = static_cast<GDScriptParser::ArrayNode *>(p_assignable->initializer); - if ((p_assignable->infer_datatype && array->elements.size() > 0) || (has_specified_type && specified_type.has_container_element_type())) { - update_array_literal_element_type(specified_type, array); + if (has_specified_type && specified_type.has_container_element_type()) { + update_array_literal_element_type(array, specified_type.get_container_element_type()); } } - if (is_constant) { - if (p_assignable->initializer->type == GDScriptParser::Node::ARRAY) { - const_fold_array(static_cast<GDScriptParser::ArrayNode *>(p_assignable->initializer), true); - } else if (p_assignable->initializer->type == GDScriptParser::Node::DICTIONARY) { - const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(p_assignable->initializer), true); - } - if (!p_assignable->initializer->is_constant) { + if (is_constant && !p_assignable->initializer->is_constant) { + bool is_initializer_value_reduced = false; + Variant initializer_value = make_expression_reduced_value(p_assignable->initializer, is_initializer_value_reduced); + if (is_initializer_value_reduced) { + p_assignable->initializer->is_constant = true; + p_assignable->initializer->reduced_value = initializer_value; + } else { push_error(vformat(R"(Assigned value for %s "%s" isn't a constant expression.)", p_kind, p_assignable->identifier->name), p_assignable->initializer); } } @@ -1630,6 +1631,8 @@ void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assi } else { push_error(vformat(R"(Cannot assign a value of type %s to %s "%s" with specified type %s.)", initializer_type.to_string(), p_kind, p_assignable->identifier->name, specified_type.to_string()), p_assignable->initializer); } + } else if (specified_type.has_container_element_type() && !initializer_type.has_container_element_type()) { + mark_node_unsafe(p_assignable->initializer); #ifdef DEBUG_ENABLED } else if (specified_type.builtin_type == Variant::INT && initializer_type.builtin_type == Variant::FLOAT) { parser->push_warning(p_assignable->initializer, GDScriptWarning::NARROWING_CONVERSION); @@ -1969,20 +1972,40 @@ void GDScriptAnalyzer::resolve_return(GDScriptParser::ReturnNode *p_return) { } if (p_return->return_value != nullptr) { - reduce_expression(p_return->return_value); - if (p_return->return_value->type == GDScriptParser::Node::ARRAY) { - // Check if assigned value is an array literal, so we can make it a typed array too if appropriate. - if (has_expected_type && expected_type.has_container_element_type() && p_return->return_value->type == GDScriptParser::Node::ARRAY) { - update_array_literal_element_type(expected_type, static_cast<GDScriptParser::ArrayNode *>(p_return->return_value)); + bool is_void_function = has_expected_type && expected_type.is_hard_type() && expected_type.kind == GDScriptParser::DataType::BUILTIN && expected_type.builtin_type == Variant::NIL; + bool is_call = p_return->return_value->type == GDScriptParser::Node::CALL; + if (is_void_function && is_call) { + // Pretend the call is a root expression to allow those that are "void". + reduce_call(static_cast<GDScriptParser::CallNode *>(p_return->return_value), false, true); + } else { + reduce_expression(p_return->return_value); + } + if (is_void_function) { + p_return->void_return = true; + const GDScriptParser::DataType &return_type = p_return->return_value->datatype; + if (is_call && !return_type.is_hard_type()) { + String function_name = parser->current_function->identifier ? parser->current_function->identifier->name.operator String() : String("<anonymous function>"); + String called_function_name = static_cast<GDScriptParser::CallNode *>(p_return->return_value)->function_name.operator String(); +#ifdef DEBUG_ENABLED + parser->push_warning(p_return, GDScriptWarning::UNSAFE_VOID_RETURN, function_name, called_function_name); +#endif + mark_node_unsafe(p_return); + } else if (!is_call) { + push_error("A void function cannot return a value.", p_return); } + result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; + result.kind = GDScriptParser::DataType::BUILTIN; + result.builtin_type = Variant::NIL; + result.is_constant = true; + } else { + if (p_return->return_value->type == GDScriptParser::Node::ARRAY && has_expected_type && expected_type.has_container_element_type()) { + update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_return->return_value), expected_type.get_container_element_type()); + } + if (has_expected_type && expected_type.is_hard_type() && p_return->return_value->is_constant) { + update_const_expression_builtin_type(p_return->return_value, expected_type, "return"); + } + result = p_return->return_value->get_datatype(); } - if (has_expected_type && expected_type.is_hard_type() && expected_type.kind == GDScriptParser::DataType::BUILTIN && expected_type.builtin_type == Variant::NIL) { - push_error("A void function cannot return a value.", p_return); - } - if (has_expected_type && expected_type.is_hard_type() && p_return->return_value->is_constant) { - update_const_expression_builtin_type(p_return->return_value, expected_type, "return"); - } - result = p_return->return_value->get_datatype(); } else { // Return type is null by default. result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; @@ -2183,49 +2206,26 @@ void GDScriptAnalyzer::update_const_expression_builtin_type(GDScriptParser::Expr // When an array literal is stored (or passed as function argument) to a typed context, we then assume the array is typed. // This function determines which type is that (if any). -void GDScriptAnalyzer::update_array_literal_element_type(const GDScriptParser::DataType &p_base_type, GDScriptParser::ArrayNode *p_array_literal) { - GDScriptParser::DataType array_type = p_array_literal->get_datatype(); - if (p_array_literal->elements.size() == 0) { - // Empty array literal, just make the same type as the storage. - array_type.set_container_element_type(p_base_type.get_container_element_type()); - } else { - // Check if elements match. - bool all_same_type = true; - bool all_have_type = true; - - GDScriptParser::DataType element_type; - for (int i = 0; i < p_array_literal->elements.size(); i++) { - if (i == 0) { - element_type = p_array_literal->elements[0]->get_datatype(); - } else { - GDScriptParser::DataType this_element_type = p_array_literal->elements[i]->get_datatype(); - if (this_element_type.has_no_type()) { - all_same_type = false; - all_have_type = false; - break; - } else if (element_type != this_element_type) { - if (!is_type_compatible(element_type, this_element_type, false)) { - if (is_type_compatible(this_element_type, element_type, false)) { - // This element is a super-type to the previous type, so we use the super-type. - element_type = this_element_type; - } else { - // It's incompatible. - all_same_type = false; - break; - } - } - } - } +void GDScriptAnalyzer::update_array_literal_element_type(GDScriptParser::ArrayNode *p_array, const GDScriptParser::DataType &p_element_type) { + for (int i = 0; i < p_array->elements.size(); i++) { + GDScriptParser::ExpressionNode *element_node = p_array->elements[i]; + if (element_node->is_constant) { + update_const_expression_builtin_type(element_node, p_element_type, "include"); } - if (all_same_type) { - element_type.is_constant = false; - array_type.set_container_element_type(element_type); - } else if (all_have_type) { - push_error(vformat(R"(Variant array is not compatible with an array of type "%s".)", p_base_type.get_container_element_type().to_string()), p_array_literal); + const GDScriptParser::DataType &element_type = element_node->get_datatype(); + if (element_type.has_no_type() || element_type.is_variant() || !element_type.is_hard_type()) { + mark_node_unsafe(element_node); + continue; + } + if (!is_type_compatible(p_element_type, element_type, true, p_array)) { + push_error(vformat(R"(Cannot have an element of type "%s" in an array of type "Array[%s]".)", element_type.to_string(), p_element_type.to_string()), element_node); + return; } } - // Update the type on the value itself. - p_array_literal->set_datatype(array_type); + + GDScriptParser::DataType array_type = p_array->get_datatype(); + array_type.set_container_element_type(p_element_type); + p_array->set_datatype(array_type); } void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assignment) { @@ -2243,8 +2243,8 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig } // Check if assigned value is an array literal, so we can make it a typed array too if appropriate. - if (assignee_type.has_container_element_type() && p_assignment->assigned_value->type == GDScriptParser::Node::ARRAY) { - update_array_literal_element_type(assignee_type, static_cast<GDScriptParser::ArrayNode *>(p_assignment->assigned_value)); + if (p_assignment->assigned_value->type == GDScriptParser::Node::ARRAY && assignee_type.has_container_element_type()) { + update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_assignment->assigned_value), assignee_type.get_container_element_type()); } if (p_assignment->operation == GDScriptParser::AssignmentNode::OP_NONE && assignee_type.is_hard_type() && p_assignment->assigned_value->is_constant) { @@ -2322,6 +2322,9 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig // weak non-variant assignee and incompatible result downgrades_assignee = true; } + } else if (assignee_type.has_container_element_type() && !op_type.has_container_element_type()) { + // typed array assignee and untyped array result + mark_node_unsafe(p_assignment); } } } @@ -2484,6 +2487,62 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o p_binary_op->set_datatype(result); } +#ifdef TOOLS_ENABLED +#ifndef DISABLE_DEPRECATED +const char *GDScriptAnalyzer::get_rename_from_map(const char *map[][2], String key) { + for (int index = 0; map[index][0]; index++) { + if (map[index][0] == key) { + return map[index][1]; + } + } + return nullptr; +} + +// Checks if an identifier/function name has been renamed in Godot 4, uses ProjectConverter3To4 for rename map. +// Returns the new name if found, nullptr otherwise. +const char *GDScriptAnalyzer::check_for_renamed_identifier(String identifier, GDScriptParser::Node::Type type) { + switch (type) { + case GDScriptParser::Node::IDENTIFIER: { + // Check properties + const char *result = get_rename_from_map(ProjectConverter3To4::gdscript_properties_renames, identifier); + if (result) { + return result; + } + // Check enum values + result = get_rename_from_map(ProjectConverter3To4::enum_renames, identifier); + if (result) { + return result; + } + // Check color constants + result = get_rename_from_map(ProjectConverter3To4::color_renames, identifier); + if (result) { + return result; + } + // Check type names + result = get_rename_from_map(ProjectConverter3To4::class_renames, identifier); + if (result) { + return result; + } + return get_rename_from_map(ProjectConverter3To4::builtin_types_renames, identifier); + } + case GDScriptParser::Node::CALL: { + const char *result = get_rename_from_map(ProjectConverter3To4::gdscript_function_renames, identifier); + if (result) { + return result; + } + // Built-in Types are mistaken for function calls when the built-in type is not found. + // Check built-in types if function rename not found + return get_rename_from_map(ProjectConverter3To4::builtin_types_renames, identifier); + } + // Signal references don't get parsed through the GDScriptAnalyzer. No support for signal rename hints. + default: + // No rename found, return null + return nullptr; + } +} +#endif // DISABLE_DEPRECATED +#endif // TOOLS_ENABLED + void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_await, bool p_is_root) { bool all_is_constant = true; HashMap<int, GDScriptParser::ArrayNode *> arrays; // For array literal to potentially type when passing. @@ -2822,7 +2881,7 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a for (const KeyValue<int, GDScriptParser::ArrayNode *> &E : arrays) { int index = E.key; if (index < par_types.size() && par_types[index].has_container_element_type()) { - update_array_literal_element_type(par_types[index], E.value); + update_array_literal_element_type(E.value, par_types[index].get_container_element_type()); } } validate_call_arg(par_types, default_arg_count, is_vararg, p_call); @@ -2901,7 +2960,22 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a } if (!found && (is_self || (base_type.is_hard_type() && base_type.kind == GDScriptParser::DataType::BUILTIN))) { String base_name = is_self && !p_call->is_super ? "self" : base_type.to_string(); +#ifdef TOOLS_ENABLED +#ifndef DISABLE_DEPRECATED + String rename_hint = String(); + if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GD4_HINT)).booleanize()) { + const char *renamed_function_name = check_for_renamed_identifier(p_call->function_name, p_call->type); + if (renamed_function_name) { + rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", String(renamed_function_name) + "()"); + } + } + push_error(vformat(R"*(Function "%s()" not found in base %s.%s)*", p_call->function_name, base_name, rename_hint), p_call->is_super ? p_call : p_call->callee); +#else // !DISABLE_DEPRECATED + push_error(vformat(R"*(Function "%s()" not found in base %s.)*", p_call->function_name, base_name), p_call->is_super ? p_call : p_call->callee); +#endif // DISABLE_DEPRECATED +#else push_error(vformat(R"*(Function "%s()" not found in base %s.)*", p_call->function_name, base_name), p_call->is_super ? p_call : p_call->callee); +#endif } else if (!found && (!p_call->is_super && base_type.is_hard_type() && base_type.kind == GDScriptParser::DataType::NATIVE && base_type.is_meta_type)) { push_error(vformat(R"*(Static function "%s()" not found in base "%s".)*", p_call->function_name, base_type.native_type), p_call); } @@ -2933,6 +3007,10 @@ void GDScriptAnalyzer::reduce_cast(GDScriptParser::CastNode *p_cast) { } } + if (p_cast->operand->type == GDScriptParser::Node::ARRAY && cast_type.has_container_element_type()) { + update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_cast->operand), cast_type.get_container_element_type()); + } + if (!cast_type.is_variant()) { GDScriptParser::DataType op_type = p_cast->operand->get_datatype(); if (op_type.is_variant() || !op_type.is_hard_type()) { @@ -3038,10 +3116,12 @@ void GDScriptAnalyzer::reduce_identifier_from_base_set_class(GDScriptParser::Ide p_identifier->set_datatype(p_identifier_datatype); Error err = OK; - GDScript *scr = GDScriptCache::get_shallow_script(p_identifier_datatype.script_path, err).ptr(); - ERR_FAIL_COND_MSG(err != OK, vformat(R"(Error while getting cache for script "%s".)", p_identifier_datatype.script_path)); - scr = scr->find_class(p_identifier_datatype.class_type->fqcn); - p_identifier->reduced_value = scr; + Ref<GDScript> scr = GDScriptCache::get_shallow_script(p_identifier_datatype.script_path, err); + if (err) { + push_error(vformat(R"(Error while getting cache for script "%s".)", p_identifier_datatype.script_path), p_identifier); + return; + } + p_identifier->reduced_value = scr->find_class(p_identifier_datatype.class_type->fqcn); p_identifier->is_constant = true; } @@ -3085,7 +3165,22 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod p_identifier->reduced_value = result; p_identifier->set_datatype(type_from_variant(result, p_identifier)); } else if (base.is_hard_type()) { - push_error(vformat(R"(Cannot find constant "%s" on type "%s".)", name, base.to_string()), p_identifier); +#ifdef TOOLS_ENABLED +#ifndef DISABLE_DEPRECATED + String rename_hint = String(); + if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GD4_HINT)).booleanize()) { + const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type); + if (renamed_identifier_name) { + rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", renamed_identifier_name); + } + } + push_error(vformat(R"(Cannot find constant "%s" on base "%s".%s)", name, base.to_string(), rename_hint), p_identifier); +#else // !DISABLE_DEPRECATED + push_error(vformat(R"(Cannot find constant "%s" on base "%s".)", name, base.to_string()), p_identifier); +#endif // DISABLE_DEPRECATED +#else + push_error(vformat(R"(Cannot find constant "%s" on base "%s".)", name, base.to_string()), p_identifier); +#endif } } else { switch (base.builtin_type) { @@ -3114,7 +3209,22 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod } } if (base.is_hard_type()) { +#ifdef TOOLS_ENABLED +#ifndef DISABLE_DEPRECATED + String rename_hint = String(); + if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GD4_HINT)).booleanize()) { + const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type); + if (renamed_identifier_name) { + rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", renamed_identifier_name); + } + } + push_error(vformat(R"(Cannot find property "%s" on base "%s".%s)", name, base.to_string(), rename_hint), p_identifier); +#else // !DISABLE_DEPRECATED + push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier); +#endif // DISABLE_DEPRECATED +#else push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier); +#endif } } } @@ -3453,7 +3563,22 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident if (GDScriptUtilityFunctions::function_exists(name)) { push_error(vformat(R"(Built-in function "%s" cannot be used as an identifier.)", name), p_identifier); } else { +#ifdef TOOLS_ENABLED +#ifndef DISABLE_DEPRECATED + String rename_hint = String(); + if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GD4_HINT)).booleanize()) { + const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type); + if (renamed_identifier_name) { + rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", renamed_identifier_name); + } + } + push_error(vformat(R"(Identifier "%s" not declared in the current scope.%s)", name, rename_hint), p_identifier); +#else // !DISABLE_DEPRECATED + push_error(vformat(R"(Identifier "%s" not declared in the current scope.)", name), p_identifier); +#endif // DISABLE_DEPRECATED +#else push_error(vformat(R"(Identifier "%s" not declared in the current scope.)", name), p_identifier); +#endif } GDScriptParser::DataType dummy; dummy.kind = GDScriptParser::DataType::VARIANT; @@ -3585,12 +3710,6 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri reduce_identifier(static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base), true); } else { reduce_expression(p_subscript->base); - - if (p_subscript->base->type == GDScriptParser::Node::ARRAY) { - const_fold_array(static_cast<GDScriptParser::ArrayNode *>(p_subscript->base), false); - } else if (p_subscript->base->type == GDScriptParser::Node::DICTIONARY) { - const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(p_subscript->base), false); - } } GDScriptParser::DataType result_type; @@ -3915,58 +4034,146 @@ void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op) p_unary_op->set_datatype(result); } -void GDScriptAnalyzer::const_fold_array(GDScriptParser::ArrayNode *p_array, bool p_is_const) { +Variant GDScriptAnalyzer::make_expression_reduced_value(GDScriptParser::ExpressionNode *p_expression, bool &is_reduced) { + Variant value; + + if (p_expression->is_constant) { + is_reduced = true; + value = p_expression->reduced_value; + } else if (p_expression->type == GDScriptParser::Node::ARRAY) { + value = make_array_reduced_value(static_cast<GDScriptParser::ArrayNode *>(p_expression), is_reduced); + } else if (p_expression->type == GDScriptParser::Node::DICTIONARY) { + value = make_dictionary_reduced_value(static_cast<GDScriptParser::DictionaryNode *>(p_expression), is_reduced); + } else if (p_expression->type == GDScriptParser::Node::SUBSCRIPT) { + value = make_subscript_reduced_value(static_cast<GDScriptParser::SubscriptNode *>(p_expression), is_reduced); + } + + return value; +} + +Variant GDScriptAnalyzer::make_array_reduced_value(GDScriptParser::ArrayNode *p_array, bool &is_reduced) { + Array array = p_array->get_datatype().has_container_element_type() ? make_array_from_element_datatype(p_array->get_datatype().get_container_element_type()) : Array(); + + array.resize(p_array->elements.size()); for (int i = 0; i < p_array->elements.size(); i++) { GDScriptParser::ExpressionNode *element = p_array->elements[i]; - if (element->type == GDScriptParser::Node::ARRAY) { - const_fold_array(static_cast<GDScriptParser::ArrayNode *>(element), p_is_const); - } else if (element->type == GDScriptParser::Node::DICTIONARY) { - const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(element), p_is_const); + bool is_element_value_reduced = false; + Variant element_value = make_expression_reduced_value(element, is_element_value_reduced); + if (!is_element_value_reduced) { + return Variant(); } - if (!element->is_constant) { - return; - } + array[i] = element_value; } - Array array; - array.resize(p_array->elements.size()); - for (int i = 0; i < p_array->elements.size(); i++) { - array[i] = p_array->elements[i]->reduced_value; - } - if (p_is_const) { - array.make_read_only(); - } - p_array->is_constant = true; - p_array->reduced_value = array; + array.make_read_only(); + + is_reduced = true; + return array; } -void GDScriptAnalyzer::const_fold_dictionary(GDScriptParser::DictionaryNode *p_dictionary, bool p_is_const) { +Variant GDScriptAnalyzer::make_dictionary_reduced_value(GDScriptParser::DictionaryNode *p_dictionary, bool &is_reduced) { + Dictionary dictionary; + for (int i = 0; i < p_dictionary->elements.size(); i++) { const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i]; - if (element.value->type == GDScriptParser::Node::ARRAY) { - const_fold_array(static_cast<GDScriptParser::ArrayNode *>(element.value), p_is_const); - } else if (element.value->type == GDScriptParser::Node::DICTIONARY) { - const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(element.value), p_is_const); + bool is_element_key_reduced = false; + Variant element_key = make_expression_reduced_value(element.key, is_element_key_reduced); + if (!is_element_key_reduced) { + return Variant(); } - if (!element.key->is_constant || !element.value->is_constant) { - return; + bool is_element_value_reduced = false; + Variant element_value = make_expression_reduced_value(element.value, is_element_value_reduced); + if (!is_element_value_reduced) { + return Variant(); } + + dictionary[element_key] = element_value; } - Dictionary dict; - for (int i = 0; i < p_dictionary->elements.size(); i++) { - const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i]; - dict[element.key->reduced_value] = element.value->reduced_value; + dictionary.make_read_only(); + + is_reduced = true; + return dictionary; +} + +Variant GDScriptAnalyzer::make_subscript_reduced_value(GDScriptParser::SubscriptNode *p_subscript, bool &is_reduced) { + bool is_base_value_reduced = false; + Variant base_value = make_expression_reduced_value(p_subscript->base, is_base_value_reduced); + if (!is_base_value_reduced) { + return Variant(); + } + + if (p_subscript->is_attribute) { + bool is_valid = false; + Variant value = base_value.get_named(p_subscript->attribute->name, is_valid); + if (is_valid) { + is_reduced = true; + return value; + } else { + return Variant(); + } + } else { + bool is_index_value_reduced = false; + Variant index_value = make_expression_reduced_value(p_subscript->index, is_index_value_reduced); + if (!is_index_value_reduced) { + return Variant(); + } + + bool is_valid = false; + Variant value = base_value.get(index_value, &is_valid); + if (is_valid) { + is_reduced = true; + return value; + } else { + return Variant(); + } } - if (p_is_const) { - dict.make_read_only(); +} + +Array GDScriptAnalyzer::make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node) { + Array array; + + Ref<Script> script_type = p_element_datatype.script_type; + if (p_element_datatype.kind == GDScriptParser::DataType::CLASS && script_type.is_null()) { + Error err = OK; + Ref<GDScript> scr = GDScriptCache::get_shallow_script(p_element_datatype.script_path, err); + if (err) { + push_error(vformat(R"(Error while getting cache for script "%s".)", p_element_datatype.script_path), p_source_node); + return array; + } + script_type.reference_ptr(scr->find_class(p_element_datatype.class_type->fqcn)); } - p_dictionary->is_constant = true; - p_dictionary->reduced_value = dict; + + array.set_typed(p_element_datatype.builtin_type, p_element_datatype.native_type, script_type); + + return array; +} + +Variant GDScriptAnalyzer::make_variable_default_value(GDScriptParser::VariableNode *p_variable) { + Variant result = Variant(); + + if (p_variable->initializer) { + bool is_initializer_value_reduced = false; + Variant initializer_value = make_expression_reduced_value(p_variable->initializer, is_initializer_value_reduced); + if (is_initializer_value_reduced) { + result = initializer_value; + } + } else { + GDScriptParser::DataType datatype = p_variable->get_datatype(); + if (datatype.is_hard_type() && datatype.kind == GDScriptParser::DataType::BUILTIN && datatype.builtin_type != Variant::OBJECT) { + if (datatype.builtin_type == Variant::ARRAY && datatype.has_container_element_type()) { + result = make_array_from_element_datatype(datatype.get_container_element_type()); + } else { + VariantInternal::initialize(&result, datatype.builtin_type); + } + } + } + + return result; } GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_value, const GDScriptParser::Node *p_source) { @@ -4437,14 +4644,8 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ } if (valid && p_target.builtin_type == Variant::ARRAY && p_source.builtin_type == Variant::ARRAY) { // Check the element type. - if (p_target.has_container_element_type()) { - if (!p_source.has_container_element_type()) { - // TODO: Maybe this is valid but unsafe? - // Variant array can't be appended to typed array. - valid = false; - } else { - valid = is_type_compatible(p_target.get_container_element_type(), p_source.get_container_element_type(), p_allow_implicit_conversion); - } + if (p_target.has_container_element_type() && p_source.has_container_element_type()) { + valid = p_target.get_container_element_type() == p_source.get_container_element_type(); } } return valid; @@ -4546,7 +4747,7 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ return ClassDB::is_parent_class(src_native, GDScript::get_class_static()); } while (src_class != nullptr) { - if (src_class->fqcn == p_target.class_type->fqcn) { + if (src_class == p_target.class_type || src_class->fqcn == p_target.class_type->fqcn) { return true; } src_class = src_class->base_type.class_type; @@ -4646,11 +4847,6 @@ Ref<GDScriptParserRef> GDScriptAnalyzer::get_parser_for(const String &p_path) { } Error GDScriptAnalyzer::resolve_inheritance() { - // Apply annotations. - for (GDScriptParser::AnnotationNode *&E : parser->head->annotations) { - resolve_annotation(E); - E->apply(parser, parser->head); - } return resolve_class_inheritance(parser->head, true); } @@ -4684,6 +4880,12 @@ Error GDScriptAnalyzer::analyze() { return err; } + // Apply annotations. + for (GDScriptParser::AnnotationNode *&E : parser->head->annotations) { + resolve_annotation(E); + E->apply(parser, parser->head); + } + resolve_interface(); resolve_body(); if (!parser->errors.is_empty()) { diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index cd2c4c6569..b51564fb0a 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -37,6 +37,10 @@ #include "gdscript_cache.h" #include "gdscript_parser.h" +#ifdef TOOLS_ENABLED +#include "editor/project_converter_3_to_4.h" +#endif + class GDScriptAnalyzer { GDScriptParser *parser = nullptr; HashMap<String, Ref<GDScriptParserRef>> depended_parsers; @@ -102,10 +106,13 @@ class GDScriptAnalyzer { void reduce_ternary_op(GDScriptParser::TernaryOpNode *p_ternary_op, bool p_is_root = false); void reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op); - void const_fold_array(GDScriptParser::ArrayNode *p_array, bool p_is_const); - void const_fold_dictionary(GDScriptParser::DictionaryNode *p_dictionary, bool p_is_const); + Variant make_expression_reduced_value(GDScriptParser::ExpressionNode *p_expression, bool &is_reduced); + Variant make_array_reduced_value(GDScriptParser::ArrayNode *p_array, bool &is_reduced); + Variant make_dictionary_reduced_value(GDScriptParser::DictionaryNode *p_dictionary, bool &is_reduced); + Variant make_subscript_reduced_value(GDScriptParser::SubscriptNode *p_subscript, bool &is_reduced); // Helpers. + Array make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node = nullptr); GDScriptParser::DataType type_from_variant(const Variant &p_value, const GDScriptParser::Node *p_source); static GDScriptParser::DataType type_from_metatype(const GDScriptParser::DataType &p_meta_type); GDScriptParser::DataType type_from_property(const PropertyInfo &p_property, bool p_is_arg = false) const; @@ -117,7 +124,7 @@ class GDScriptAnalyzer { GDScriptParser::DataType get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, const GDScriptParser::DataType &p_b, bool &r_valid, const GDScriptParser::Node *p_source); GDScriptParser::DataType get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, bool &r_valid, const GDScriptParser::Node *p_source); void update_const_expression_builtin_type(GDScriptParser::ExpressionNode *p_expression, const GDScriptParser::DataType &p_type, const char *p_usage, bool p_is_cast = false); - void update_array_literal_element_type(const GDScriptParser::DataType &p_base_type, GDScriptParser::ArrayNode *p_array_literal); + void update_array_literal_element_type(GDScriptParser::ArrayNode *p_array, const GDScriptParser::DataType &p_element_type); bool is_type_compatible(const GDScriptParser::DataType &p_target, const GDScriptParser::DataType &p_source, bool p_allow_implicit_conversion = false, const GDScriptParser::Node *p_source_node = nullptr); void push_error(const String &p_message, const GDScriptParser::Node *p_origin = nullptr); void mark_node_unsafe(const GDScriptParser::Node *p_node); @@ -125,11 +132,18 @@ class GDScriptAnalyzer { void mark_lambda_use_self(); bool class_exists(const StringName &p_class) const; Ref<GDScriptParserRef> get_parser_for(const String &p_path); - static void reduce_identifier_from_base_set_class(GDScriptParser::IdentifierNode *p_identifier, GDScriptParser::DataType p_identifier_datatype); + void reduce_identifier_from_base_set_class(GDScriptParser::IdentifierNode *p_identifier, GDScriptParser::DataType p_identifier_datatype); #ifdef DEBUG_ENABLED bool is_shadowing(GDScriptParser::IdentifierNode *p_local, const String &p_context); #endif +#ifdef TOOLS_ENABLED +#ifndef DISABLE_DEPRECATED + const char *get_rename_from_map(const char *map[][2], String key); + const char *check_for_renamed_identifier(String identifier, GDScriptParser::Node::Type type); +#endif // DISABLE_DEPRECATED +#endif // TOOLS_ENABLED + public: Error resolve_inheritance(); Error resolve_interface(); @@ -137,6 +151,8 @@ public: Error resolve_dependencies(); Error analyze(); + Variant make_variable_default_value(GDScriptParser::VariableNode *p_variable); + GDScriptAnalyzer(GDScriptParser *p_parser); }; diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index e19dda090e..ec7a2b0f1c 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -826,9 +826,13 @@ void GDScriptByteCodeGenerator::write_assign_with_conversion(const Address &p_ta switch (p_target.type.kind) { case GDScriptDataType::BUILTIN: { if (p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) { + const GDScriptDataType &element_type = p_target.type.get_container_element_type(); append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY); append(p_target); append(p_source); + append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS)); + append(element_type.builtin_type); + append(element_type.native_type); } else { append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN); append(p_target); @@ -868,9 +872,13 @@ void GDScriptByteCodeGenerator::write_assign_with_conversion(const Address &p_ta void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Address &p_source) { if (p_target.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) { + const GDScriptDataType &element_type = p_target.type.get_container_element_type(); append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY); append(p_target); append(p_source); + append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS)); + append(element_type.builtin_type); + append(element_type.native_type); } else if (p_target.type.kind == GDScriptDataType::BUILTIN && p_source.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type != p_source.type.builtin_type) { // Need conversion. append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN); @@ -1326,14 +1334,7 @@ void GDScriptByteCodeGenerator::write_construct_typed_array(const Address &p_tar append(p_arguments[i]); } append(get_call_target(p_target)); - if (p_element_type.script_type) { - Variant script_type = Ref<Script>(p_element_type.script_type); - int addr = get_constant_pos(script_type); - addr |= GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS; - append(addr); - } else { - append(Address()); // null. - } + append(get_constant_pos(p_element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS)); append(p_arguments.size()); append(p_element_type.builtin_type); append(p_element_type.native_type); @@ -1608,14 +1609,10 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) { if (function->return_type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type()) { // Typed array. const GDScriptDataType &element_type = function->return_type.get_container_element_type(); - - Variant script = element_type.script_type; - int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS); - append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY); append(p_return_value); - append(script_idx); - append(element_type.kind == GDScriptDataType::BUILTIN ? element_type.builtin_type : Variant::OBJECT); + append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS)); + append(element_type.builtin_type); append(element_type.native_type); } else if (function->return_type.kind == GDScriptDataType::BUILTIN && p_return_value.type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type != p_return_value.type.builtin_type) { // Add conversion. @@ -1636,15 +1633,10 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) { case GDScriptDataType::BUILTIN: { if (function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type()) { const GDScriptDataType &element_type = function->return_type.get_container_element_type(); - - Variant script = function->return_type.script_type; - int script_idx = get_constant_pos(script); - script_idx |= (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS); - append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY); append(p_return_value); - append(script_idx); - append(element_type.kind == GDScriptDataType::BUILTIN ? element_type.builtin_type : Variant::OBJECT); + append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS)); + append(element_type.builtin_type); append(element_type.native_type); } else { append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_BUILTIN); diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 6acdc9f212..46cd4b0d55 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -1859,7 +1859,12 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui } } - gen->write_return(return_value); + if (return_n->void_return) { + // Always return "null", even if the expression is a call to a void function. + gen->write_return(codegen.add_constant(Variant())); + } else { + gen->write_return(return_value); + } if (return_value.mode == GDScriptCodeGenerator::Address::TEMPORARY) { codegen.generator->pop_temporary(); } @@ -1904,14 +1909,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui bool initialized = false; if (lv->initializer != nullptr) { - // For typed arrays we need to make sure this is already initialized correctly so typed assignment work. - if (local_type.has_type && local_type.builtin_type == Variant::ARRAY) { - if (local_type.has_container_element_type()) { - codegen.generator->write_construct_typed_array(local, local_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>()); - } else { - codegen.generator->write_construct_array(local, Vector<GDScriptCodeGenerator::Address>()); - } - } GDScriptCodeGenerator::Address src_address = _parse_expression(codegen, err, lv->initializer); if (err) { return err; @@ -2052,14 +2049,6 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ // Emit proper line change. codegen.generator->write_newline(field->initializer->start_line); - // For typed arrays we need to make sure this is already initialized correctly so typed assignment work. - if (field_type.has_type && field_type.builtin_type == Variant::ARRAY) { - if (field_type.has_container_element_type()) { - codegen.generator->write_construct_typed_array(dst_address, field_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>()); - } else { - codegen.generator->write_construct_array(dst_address, Vector<GDScriptCodeGenerator::Address>()); - } - } GDScriptCodeGenerator::Address src_address = _parse_expression(codegen, r_error, field->initializer, false, true); if (r_error) { memdelete(codegen.generator); @@ -2100,17 +2089,6 @@ GDScriptFunction *GDScriptCompiler::_parse_function(Error &r_error, GDScript *p_ return nullptr; } GDScriptCodeGenerator::Address dst_addr = codegen.parameters[parameter->identifier->name]; - - // For typed arrays we need to make sure this is already initialized correctly so typed assignment work. - GDScriptDataType par_type = dst_addr.type; - if (par_type.has_type && par_type.builtin_type == Variant::ARRAY) { - if (par_type.has_container_element_type()) { - codegen.generator->write_construct_typed_array(dst_addr, par_type.get_container_element_type(), Vector<GDScriptCodeGenerator::Address>()); - } else { - codegen.generator->write_construct_array(dst_addr, Vector<GDScriptCodeGenerator::Address>()); - } - } - codegen.generator->write_assign_default_parameter(dst_addr, src_addr, parameter->use_conversion_assign); if (src_addr.mode == GDScriptCodeGenerator::Address::TEMPORARY) { codegen.generator->pop_temporary(); diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index b5c8a6f478..d4f4358ac1 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -317,7 +317,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += " = "; text += DADDR(2); - incr += 3; + incr += 6; } break; case OPCODE_ASSIGN_TYPED_NATIVE: { text += "assign typed native ("; @@ -434,7 +434,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { int instr_var_args = _code_ptr[++ip]; int argc = _code_ptr[ip + 1 + instr_var_args]; - Ref<Script> script_type = get_constant(_code_ptr[ip + argc + 2]); + Ref<Script> script_type = get_constant(_code_ptr[ip + argc + 2] & GDScriptFunction::ADDR_MASK); Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + argc + 4]; StringName native_type = get_global_name(_code_ptr[ip + argc + 5]); @@ -463,7 +463,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += "]"; - incr += 3 + argc; + incr += 6 + argc; } break; case OPCODE_CONSTRUCT_DICTIONARY: { int instr_var_args = _code_ptr[++ip]; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 66374d0a6d..713ad3ed17 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -51,46 +51,8 @@ static HashMap<StringName, Variant::Type> builtin_types; Variant::Type GDScriptParser::get_builtin_type(const StringName &p_type) { if (builtin_types.is_empty()) { - builtin_types["bool"] = Variant::BOOL; - builtin_types["int"] = Variant::INT; - builtin_types["float"] = Variant::FLOAT; - builtin_types["String"] = Variant::STRING; - builtin_types["Vector2"] = Variant::VECTOR2; - builtin_types["Vector2i"] = Variant::VECTOR2I; - builtin_types["Rect2"] = Variant::RECT2; - builtin_types["Rect2i"] = Variant::RECT2I; - builtin_types["Transform2D"] = Variant::TRANSFORM2D; - builtin_types["Vector3"] = Variant::VECTOR3; - builtin_types["Vector3i"] = Variant::VECTOR3I; - builtin_types["Vector4"] = Variant::VECTOR4; - builtin_types["Vector4i"] = Variant::VECTOR4I; - builtin_types["AABB"] = Variant::AABB; - builtin_types["Plane"] = Variant::PLANE; - builtin_types["Quaternion"] = Variant::QUATERNION; - builtin_types["Basis"] = Variant::BASIS; - builtin_types["Transform3D"] = Variant::TRANSFORM3D; - builtin_types["Projection"] = Variant::PROJECTION; - builtin_types["Color"] = Variant::COLOR; - builtin_types["RID"] = Variant::RID; - builtin_types["Object"] = Variant::OBJECT; - builtin_types["StringName"] = Variant::STRING_NAME; - builtin_types["NodePath"] = Variant::NODE_PATH; - builtin_types["Dictionary"] = Variant::DICTIONARY; - builtin_types["Callable"] = Variant::CALLABLE; - builtin_types["Signal"] = Variant::SIGNAL; - builtin_types["Array"] = Variant::ARRAY; - builtin_types["PackedByteArray"] = Variant::PACKED_BYTE_ARRAY; - builtin_types["PackedInt32Array"] = Variant::PACKED_INT32_ARRAY; - builtin_types["PackedInt64Array"] = Variant::PACKED_INT64_ARRAY; - builtin_types["PackedFloat32Array"] = Variant::PACKED_FLOAT32_ARRAY; - builtin_types["PackedFloat64Array"] = Variant::PACKED_FLOAT64_ARRAY; - builtin_types["PackedStringArray"] = Variant::PACKED_STRING_ARRAY; - builtin_types["PackedVector2Array"] = Variant::PACKED_VECTOR2_ARRAY; - builtin_types["PackedVector3Array"] = Variant::PACKED_VECTOR3_ARRAY; - builtin_types["PackedColorArray"] = Variant::PACKED_COLOR_ARRAY; - // NIL is not here, hence the -1. - if (builtin_types.size() != Variant::VARIANT_MAX - 1) { - ERR_PRINT("Outdated parser: amount of built-in types don't match the amount of types in Variant."); + for (int i = 1; i < Variant::VARIANT_MAX; i++) { + builtin_types[Variant::get_type_name((Variant::Type)i)] = (Variant::Type)i; } } @@ -529,7 +491,12 @@ void GDScriptParser::parse_program() { AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE | AnnotationInfo::CLASS_LEVEL); if (annotation != nullptr) { if (annotation->applies_to(AnnotationInfo::SCRIPT)) { - head->annotations.push_back(annotation); + // `@icon` needs to be applied in the parser. See GH-72444. + if (annotation->name == SNAME("@icon")) { + annotation->apply(this, head); + } else { + head->annotations.push_back(annotation); + } } else { annotation_stack.push_back(annotation); // This annotation must appear after script-level annotations @@ -847,7 +814,7 @@ void GDScriptParser::parse_class_body(bool p_is_multiline) { if (previous.type != GDScriptTokenizer::Token::NEWLINE) { push_error(R"(Expected newline after a standalone annotation.)"); } - if (annotation->name == "@export_category" || annotation->name == "@export_group" || annotation->name == "@export_subgroup") { + if (annotation->name == SNAME("@export_category") || annotation->name == SNAME("@export_group") || annotation->name == SNAME("@export_subgroup")) { current_class->add_member_group(annotation); } else { // For potential non-group standalone annotations. @@ -982,14 +949,14 @@ GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_var // Run with a loop because order doesn't matter. for (int i = 0; i < 2; i++) { - if (function->name == "set") { + if (function->name == SNAME("set")) { if (setter_used) { push_error(R"(Properties can only have one setter.)"); } else { parse_property_setter(property); setter_used = true; } - } else if (function->name == "get") { + } else if (function->name == SNAME("get")) { if (getter_used) { push_error(R"(Properties can only have one getter.)"); } else { @@ -1474,7 +1441,7 @@ GDScriptParser::AnnotationNode *GDScriptParser::parse_annotation(uint32_t p_vali match(GDScriptTokenizer::Token::NEWLINE); // Newline after annotation is optional. if (valid) { - valid = validate_annotation_argument_count(annotation); + valid = validate_annotation_arguments(annotation); } return valid ? annotation : nullptr; @@ -2921,7 +2888,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre // Arguments. CompletionType ct = COMPLETION_CALL_ARGUMENTS; - if (call->function_name == "load") { + if (call->function_name == SNAME("load")) { ct = COMPLETION_RESOURCE_PATH; } push_completion_call(call); @@ -3589,7 +3556,7 @@ bool GDScriptParser::AnnotationNode::applies_to(uint32_t p_target_kinds) const { return (info->target_kind & p_target_kinds) > 0; } -bool GDScriptParser::validate_annotation_argument_count(AnnotationNode *p_annotation) { +bool GDScriptParser::validate_annotation_arguments(AnnotationNode *p_annotation) { ERR_FAIL_COND_V_MSG(!valid_annotations.has(p_annotation->name), false, vformat(R"(Annotation "%s" not found to validate.)", p_annotation->name)); const MethodInfo &info = valid_annotations[p_annotation->name].info; @@ -3604,6 +3571,27 @@ bool GDScriptParser::validate_annotation_argument_count(AnnotationNode *p_annota return false; } + // `@icon`'s argument needs to be resolved in the parser. See GH-72444. + if (p_annotation->name == SNAME("@icon")) { + ExpressionNode *argument = p_annotation->arguments[0]; + + if (argument->type != Node::LITERAL) { + push_error(R"(Argument 1 of annotation "@icon" must be a string literal.)", argument); + return false; + } + + Variant value = static_cast<LiteralNode *>(argument)->value; + + if (value.get_type() != Variant::STRING) { + push_error(R"(Argument 1 of annotation "@icon" must be a string literal.)", argument); + return false; + } + + p_annotation->resolved_arguments.push_back(value); + } + + // For other annotations, see `GDScriptAnalyzer::resolve_annotation()`. + return true; } diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 74e12d0b5e..07dac25ec5 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -190,7 +190,7 @@ public: case SCRIPT: return script_type == p_other.script_type; case CLASS: - return class_type == p_other.class_type; + return class_type == p_other.class_type || class_type->fqcn == p_other.class_type->fqcn; case RESOLVING: case UNRESOLVED: break; @@ -970,6 +970,7 @@ public: struct ReturnNode : public Node { ExpressionNode *return_value = nullptr; + bool void_return = false; ReturnNode() { type = RETURN; @@ -1401,7 +1402,7 @@ private: // Annotations AnnotationNode *parse_annotation(uint32_t p_valid_targets); bool register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, const Vector<Variant> &p_default_arguments = Vector<Variant>(), bool p_is_vararg = false); - bool validate_annotation_argument_count(AnnotationNode *p_annotation); + bool validate_annotation_arguments(AnnotationNode *p_annotation); void clear_unused_annotations(); bool tool_annotation(const AnnotationNode *p_annotation, Node *p_target); bool icon_annotation(const AnnotationNode *p_annotation, Node *p_target); diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index 10d83dcfe5..758b61bb31 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -112,28 +112,6 @@ struct GDScriptUtilityFunctionsDefinitions { *r_ret = String(result); } - static inline void str(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - if (p_arg_count < 1) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 1; - r_error.expected = 1; - *r_ret = Variant(); - return; - } - - String str; - for (int i = 0; i < p_arg_count; i++) { - String os = p_args[i]->operator String(); - - if (i == 0) { - str = os; - } else { - str += os; - } - } - *r_ret = str; - } - static inline void range(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { switch (p_arg_count) { case 0: { @@ -651,7 +629,6 @@ void GDScriptUtilityFunctions::register_functions() { REGISTER_VARIANT_FUNC(convert, true, VARARG("what"), ARG("type", Variant::INT)); REGISTER_FUNC(type_exists, true, Variant::BOOL, ARG("type", Variant::STRING_NAME)); REGISTER_FUNC(_char, true, Variant::STRING, ARG("char", Variant::INT)); - REGISTER_VARARG_FUNC(str, true, Variant::STRING); REGISTER_VARARG_FUNC(range, false, Variant::ARRAY); REGISTER_CLASS_FUNC(load, false, "Resource", ARG("path", Variant::STRING)); REGISTER_FUNC(inst_to_dict, false, Variant::DICTIONARY, ARG("instance", Variant::OBJECT)); diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 4ea4438b5e..e18a4a6190 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -47,6 +47,16 @@ static String _get_script_name(const Ref<Script> p_script) { } } +static String _get_element_type(Variant::Type builtin_type, const StringName &native_type, const Ref<Script> &script_type) { + if (script_type.is_valid() && script_type->is_valid()) { + return _get_script_name(script_type); + } else if (native_type != StringName()) { + return native_type.operator String(); + } else { + return Variant::get_type_name(builtin_type); + } +} + static String _get_var_type(const Variant *p_var) { String basestr; @@ -75,15 +85,8 @@ static String _get_var_type(const Variant *p_var) { basestr = "Array"; const Array *p_array = VariantInternal::get_array(p_var); Variant::Type builtin_type = (Variant::Type)p_array->get_typed_builtin(); - StringName native_type = p_array->get_typed_class_name(); - Ref<Script> script_type = p_array->get_typed_script(); - - if (script_type.is_valid() && script_type->is_valid()) { - basestr += "[" + _get_script_name(script_type) + "]"; - } else if (native_type != StringName()) { - basestr += "[" + native_type.operator String() + "]"; - } else if (builtin_type != Variant::NIL) { - basestr += "[" + Variant::get_type_name(builtin_type) + "]"; + if (builtin_type != Variant::NIL) { + basestr += "[" + _get_element_type(builtin_type, p_array->get_typed_class_name(), p_array->get_typed_script()) + "]"; } } else { basestr = Variant::get_type_name(p_var->get_type()); @@ -101,10 +104,7 @@ Variant GDScriptFunction::_get_default_variant_for_data_type(const GDScriptDataT // Typed array. if (p_data_type.has_container_element_type()) { const GDScriptDataType &element_type = p_data_type.get_container_element_type(); - array.set_typed( - element_type.kind == GDScriptDataType::BUILTIN ? element_type.builtin_type : Variant::OBJECT, - element_type.native_type, - element_type.script_type); + array.set_typed(element_type.builtin_type, element_type.native_type, element_type.script_type); } return array; @@ -131,6 +131,8 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const #ifdef DEBUG_ENABLED if (p_err.expected == Variant::OBJECT && argptrs[errorarg]->get_type() == p_err.expected) { err_text = "Invalid type in " + p_where + ". The Object-derived class of argument " + itos(errorarg + 1) + " (" + _get_var_type(argptrs[errorarg]) + ") is not a subclass of the expected argument class."; + } else if (p_err.expected == Variant::ARRAY && argptrs[errorarg]->get_type() == p_err.expected) { + err_text = "Invalid type in " + p_where + ". The array of argument " + itos(errorarg + 1) + " (" + _get_var_type(argptrs[errorarg]) + ") does not have the same element type as the expected typed array argument."; } else #endif // DEBUG_ENABLED { @@ -518,7 +520,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a if (!argument_types[i].is_type(*p_args[i], true)) { r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_err.argument = i; - r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT; + r_err.expected = argument_types[i].builtin_type; return _get_default_variant_for_data_type(return_type); } if (argument_types[i].kind == GDScriptDataType::BUILTIN) { @@ -1174,27 +1176,37 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_ASSIGN_TYPED_ARRAY) { - CHECK_SPACE(3); + CHECK_SPACE(6); GET_VARIANT_PTR(dst, 0); GET_VARIANT_PTR(src, 1); - Array *dst_arr = VariantInternal::get_array(dst); + GET_VARIANT_PTR(script_type, 2); + Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 4]; + int native_type_idx = _code_ptr[ip + 5]; + GD_ERR_BREAK(native_type_idx < 0 || native_type_idx >= _global_names_count); + const StringName native_type = _global_names_ptr[native_type_idx]; if (src->get_type() != Variant::ARRAY) { #ifdef DEBUG_ENABLED - err_text = "Trying to assign value of type '" + Variant::get_type_name(src->get_type()) + - "' to a variable of type '" + +"'."; -#endif + err_text = vformat(R"(Trying to assign a value of type "%s" to a variable of type "Array[%s]".)", + _get_var_type(src), _get_element_type(builtin_type, native_type, *script_type)); +#endif // DEBUG_ENABLED OPCODE_BREAK; } - if (!dst_arr->typed_assign(*src)) { + + Array *array = VariantInternal::get_array(src); + + if (array->get_typed_builtin() != ((uint32_t)builtin_type) || array->get_typed_class_name() != native_type || array->get_typed_script() != *script_type || array->get_typed_class_name() != native_type) { #ifdef DEBUG_ENABLED - err_text = "Trying to assign a typed array with an array of different type.'"; -#endif + err_text = vformat(R"(Trying to assign an array of type "%s" to a variable of type "Array[%s]".)", + _get_var_type(src), _get_element_type(builtin_type, native_type, *script_type)); +#endif // DEBUG_ENABLED OPCODE_BREAK; } - ip += 3; + *dst = *src; + + ip += 6; } DISPATCH_OPCODE; @@ -1469,9 +1481,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a const StringName native_type = _global_names_ptr[native_type_idx]; Array array; - array.set_typed(builtin_type, native_type, *script_type); array.resize(argc); - for (int i = 0; i < argc; i++) { array[i] = *(instruction_args[i]); } @@ -1479,7 +1489,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GET_INSTRUCTION_ARG(dst, argc); *dst = Variant(); // Clear potential previous typed array. - *dst = array; + *dst = Array(array, builtin_type, native_type, *script_type); ip += 4; } @@ -2486,30 +2496,25 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a if (r->get_type() != Variant::ARRAY) { #ifdef DEBUG_ENABLED - err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "Array[%s]".)", - Variant::get_type_name(r->get_type()), Variant::get_type_name(builtin_type)); -#endif + err_text = vformat(R"(Trying to return a value of type "%s" where expected return type is "Array[%s]".)", + _get_var_type(r), _get_element_type(builtin_type, native_type, *script_type)); +#endif // DEBUG_ENABLED OPCODE_BREAK; } - Array array; - array.set_typed(builtin_type, native_type, *script_type); + Array *array = VariantInternal::get_array(r); + if (array->get_typed_builtin() != ((uint32_t)builtin_type) || array->get_typed_class_name() != native_type || array->get_typed_script() != *script_type || array->get_typed_class_name() != native_type) { #ifdef DEBUG_ENABLED - bool valid = array.typed_assign(*VariantInternal::get_array(r)); -#else - array.typed_assign(*VariantInternal::get_array(r)); + err_text = vformat(R"(Trying to return an array of type "%s" where expected return type is "Array[%s]".)", + _get_var_type(r), _get_element_type(builtin_type, native_type, *script_type)); #endif // DEBUG_ENABLED - - // Assign the return value anyway since we want it to be the valid type. - retvalue = array; - -#ifdef DEBUG_ENABLED - if (!valid) { - err_text = "Trying to return a typed array with an array of different type.'"; OPCODE_BREAK; } + retvalue = *array; + +#ifdef DEBUG_ENABLED exit_ok = true; #endif // DEBUG_ENABLED OPCODE_BREAK; diff --git a/modules/gdscript/gdscript_warning.cpp b/modules/gdscript/gdscript_warning.cpp index 024fed8517..9436146bed 100644 --- a/modules/gdscript/gdscript_warning.cpp +++ b/modules/gdscript/gdscript_warning.cpp @@ -125,6 +125,10 @@ String GDScriptWarning::get_message() const { CHECK_SYMBOLS(4); return "The argument '" + symbols[0] + "' of the function '" + symbols[1] + "' requires a the subtype '" + symbols[2] + "' but the supertype '" + symbols[3] + "' was provided"; } break; + case UNSAFE_VOID_RETURN: { + CHECK_SYMBOLS(2); + return "The method '" + symbols[0] + "()' returns 'void' but it's trying to return a call to '" + symbols[1] + "()' that can't be ensured to also be 'void'."; + } break; case DEPRECATED_KEYWORD: { CHECK_SYMBOLS(2); return "The '" + symbols[0] + "' keyword is deprecated and will be removed in a future release, please replace its uses by '" + symbols[1] + "'."; @@ -163,6 +167,9 @@ String GDScriptWarning::get_message() const { CHECK_SYMBOLS(1); return vformat(R"(The identifier "%s" has misleading characters and might be confused with something else.)", symbols[0]); } + case RENAMED_IN_GD4_HINT: { + break; // Renamed identifier hint is taken care of by the GDScriptAnalyzer. No message needed here. + } case WARNING_MAX: break; // Can't happen, but silences warning } @@ -184,6 +191,9 @@ int GDScriptWarning::get_default_value(Code p_code) { PropertyInfo GDScriptWarning::get_property_info(Code p_code) { // Making this a separate function in case a warning needs different PropertyInfo in the future. + if (p_code == Code::RENAMED_IN_GD4_HINT) { + return PropertyInfo(Variant::BOOL, get_settings_path_from_code(p_code)); + } return PropertyInfo(Variant::INT, get_settings_path_from_code(p_code), PROPERTY_HINT_ENUM, "Ignore,Warn,Error"); } @@ -218,6 +228,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) { "UNSAFE_METHOD_ACCESS", "UNSAFE_CAST", "UNSAFE_CALL_ARGUMENT", + "UNSAFE_VOID_RETURN", "DEPRECATED_KEYWORD", "STANDALONE_TERNARY", "ASSERT_ALWAYS_TRUE", @@ -229,6 +240,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) { "INT_AS_ENUM_WITHOUT_MATCH", "STATIC_CALLED_ON_INSTANCE", "CONFUSABLE_IDENTIFIER", + "RENAMED_IN_GODOT_4_HINT" }; static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names."); diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h index 7492972c1a..fa2907cdae 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -69,6 +69,7 @@ public: UNSAFE_METHOD_ACCESS, // Function not found in the detected type (but can be in subtypes). UNSAFE_CAST, // Cast used in an unknown type. UNSAFE_CALL_ARGUMENT, // Function call argument is of a supertype of the require argument. + UNSAFE_VOID_RETURN, // Function returns void but returned a call to a function that can't be type checked. DEPRECATED_KEYWORD, // The keyword is deprecated and should be replaced. STANDALONE_TERNARY, // Return value of ternary expression is discarded. ASSERT_ALWAYS_TRUE, // Expression for assert argument is always true. @@ -80,6 +81,7 @@ public: INT_AS_ENUM_WITHOUT_MATCH, // An integer value was used as an enum value without matching enum member. STATIC_CALLED_ON_INSTANCE, // A static method was called on an instance of a class instead of on the class itself. CONFUSABLE_IDENTIFIER, // The identifier contains misleading characters that can be confused. E.g. "usеr" (has Cyrillic "е" instead of Latin "e"). + RENAMED_IN_GD4_HINT, // A variable or function that could not be found has been renamed in Godot 4 WARNING_MAX, }; diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index d2c8b5c317..5b8af0ff34 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -132,9 +132,10 @@ void finish_language() { StringName GDScriptTestRunner::test_function_name; -GDScriptTestRunner::GDScriptTestRunner(const String &p_source_dir, bool p_init_language) { +GDScriptTestRunner::GDScriptTestRunner(const String &p_source_dir, bool p_init_language, bool p_print_filenames) { test_function_name = StaticCString::create("test"); do_init_languages = p_init_language; + print_filenames = p_print_filenames; source_dir = p_source_dir; if (!source_dir.ends_with("/")) { @@ -194,6 +195,9 @@ int GDScriptTestRunner::run_tests() { int failed = 0; for (int i = 0; i < tests.size(); i++) { GDScriptTest test = tests[i]; + if (print_filenames) { + print_line(test.get_source_relative_filepath()); + } GDScriptTest::TestResult result = test.run_test(); String expected = FileAccess::get_file_as_string(test.get_output_file()); @@ -225,8 +229,13 @@ bool GDScriptTestRunner::generate_outputs() { } for (int i = 0; i < tests.size(); i++) { - OS::get_singleton()->print("."); GDScriptTest test = tests[i]; + if (print_filenames) { + print_line(test.get_source_relative_filepath()); + } else { + OS::get_singleton()->print("."); + } + bool result = test.generate_output(); if (!result) { @@ -337,15 +346,10 @@ GDScriptTest::GDScriptTest(const String &p_source_path, const String &p_output_p void GDScriptTestRunner::handle_cmdline() { List<String> cmdline_args = OS::get_singleton()->get_cmdline_args(); - // TODO: this could likely be ported to use test commands: - // https://github.com/godotengine/godot/pull/41355 - // Currently requires to startup the whole engine, which is slow. - String test_cmd = "--gdscript-test"; - String gen_cmd = "--gdscript-generate-tests"; for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) { String &cmd = E->get(); - if (cmd == test_cmd || cmd == gen_cmd) { + if (cmd == "--gdscript-generate-tests") { if (E->next() == nullptr) { ERR_PRINT("Needed a path for the test files."); exit(-1); @@ -353,14 +357,10 @@ void GDScriptTestRunner::handle_cmdline() { const String &path = E->next()->get(); - GDScriptTestRunner runner(path, false); - int failed = 0; - if (cmd == test_cmd) { - failed = runner.run_tests(); - } else { - bool completed = runner.generate_outputs(); - failed = completed ? 0 : -1; - } + GDScriptTestRunner runner(path, false, cmdline_args.find("--print-filenames") != nullptr); + + bool completed = runner.generate_outputs(); + int failed = completed ? 0 : -1; exit(failed); } } diff --git a/modules/gdscript/tests/gdscript_test_runner.h b/modules/gdscript/tests/gdscript_test_runner.h index b097f1b485..60b48c6a57 100644 --- a/modules/gdscript/tests/gdscript_test_runner.h +++ b/modules/gdscript/tests/gdscript_test_runner.h @@ -92,6 +92,7 @@ public: bool generate_output(); const String &get_source_file() const { return source_file; } + const String get_source_relative_filepath() const { return source_file.trim_prefix(base_dir); } const String &get_output_file() const { return output_file; } GDScriptTest(const String &p_source_path, const String &p_output_path, const String &p_base_dir); @@ -105,6 +106,7 @@ class GDScriptTestRunner { bool is_generating = false; bool do_init_languages = false; + bool print_filenames; // Whether filenames should be printed when generated/running tests bool make_tests(); bool make_tests_for_dir(const String &p_dir); @@ -117,7 +119,7 @@ public: int run_tests(); bool generate_outputs(); - GDScriptTestRunner(const String &p_source_dir, bool p_init_language); + GDScriptTestRunner(const String &p_source_dir, bool p_init_language, bool p_print_filenames = false); ~GDScriptTestRunner(); }; diff --git a/modules/gdscript/tests/gdscript_test_runner_suite.h b/modules/gdscript/tests/gdscript_test_runner_suite.h index aed0ac2baf..e27b6218f1 100644 --- a/modules/gdscript/tests/gdscript_test_runner_suite.h +++ b/modules/gdscript/tests/gdscript_test_runner_suite.h @@ -41,7 +41,8 @@ TEST_SUITE("[Modules][GDScript]") { // Allow the tests to fail, but do not ignore errors during development. // Update the scripts and expected output as needed. TEST_CASE("Script compilation and runtime") { - GDScriptTestRunner runner("modules/gdscript/tests/scripts", true); + bool print_filenames = OS::get_singleton()->get_cmdline_args().find("--print-filenames") != nullptr; + GDScriptTestRunner runner("modules/gdscript/tests/scripts", true, print_filenames); int fail_count = runner.run_tests(); INFO("Make sure `*.out` files have expected results."); REQUIRE_MESSAGE(fail_count == 0, "All GDScript tests should pass."); diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out b/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out index 6f7f0783f0..015ad756f8 100644 --- a/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out +++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out @@ -1,2 +1,2 @@ GDTEST_ANALYZER_ERROR -Cannot get index "true" from "[0, 1]". +Invalid index type "bool" for a base of type "Array". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.gd new file mode 100644 index 0000000000..ce50cccb3c --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.gd @@ -0,0 +1,4 @@ +func test(): + var differently: Array[float] = [1.0] + var typed: Array[int] = differently + print('not ok') diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.out new file mode 100644 index 0000000000..c6d39781ee --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Cannot assign a value of type Array[float] to variable "typed" with specified type Array[int]. diff --git a/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.gd index 9f86d0531c..9f86d0531c 100644 --- a/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.gd +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.gd diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.out new file mode 100644 index 0000000000..8530783673 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Cannot include a value of type "String" as "int". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.gd new file mode 100644 index 0000000000..25cde1d40b --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.gd @@ -0,0 +1,4 @@ +func test(): + var unconvertable := 1 + var typed: Array[Object] = [unconvertable] + print('not ok') diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.out new file mode 100644 index 0000000000..dfe3443761 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Cannot have an element of type "int" in an array of type "Array[Object]". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.gd new file mode 100644 index 0000000000..1a90bd121e --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.gd @@ -0,0 +1,7 @@ +func expect_typed(typed: Array[int]): + print(typed.size()) + +func test(): + var differently: Array[float] = [1.0] + expect_typed(differently) + print('not ok') diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.out new file mode 100644 index 0000000000..297e1283e8 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Invalid argument for "expect_typed()" function: argument 1 should be "Array[int]" but is "Array[float]". diff --git a/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.gd b/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.gd new file mode 100644 index 0000000000..df89137f40 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.gd @@ -0,0 +1,20 @@ +func test(): + return_call() + return_nothing() + return_side_effect() + var r = return_side_effect.call() # Untyped call to check return value. + prints(r, typeof(r) == TYPE_NIL) + print("end") + +func side_effect(v): + print("effect") + return v + +func return_call() -> void: + return print("hello") + +func return_nothing() -> void: + return + +func return_side_effect() -> void: + return side_effect("x") diff --git a/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.out b/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.out new file mode 100644 index 0000000000..7c0416371f --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.out @@ -0,0 +1,10 @@ +GDTEST_OK +>> WARNING +>> Line: 20 +>> UNSAFE_VOID_RETURN +>> The method 'return_side_effect()' returns 'void' but it's trying to return a call to 'side_effect()' that can't be ensured to also be 'void'. +hello +effect +effect +<null> true +end diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.out b/modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.out index 082e3ade19..2729c5b6c7 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.out +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.out @@ -2,7 +2,7 @@ GDTEST_OK [0] 0 [1] -2 +0 [2] 2 ok diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd new file mode 100644 index 0000000000..e1e6134fd4 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd @@ -0,0 +1,204 @@ +class A: pass +class B extends A: pass + +enum E { E0 = 391 } + +func floats_identity(floats: Array[float]): return floats + +class Members: + var one: Array[int] = [104] + var two: Array[int] = one + + func check_passing() -> bool: + assert(str(one) == '[104]') + assert(str(two) == '[104]') + two.push_back(582) + assert(str(one) == '[104, 582]') + assert(str(two) == '[104, 582]') + two = [486] + assert(str(one) == '[104, 582]') + assert(str(two) == '[486]') + return true + + +@warning_ignore("unsafe_method_access") +@warning_ignore("assert_always_true") +@warning_ignore("return_value_discarded") +func test(): + var untyped_basic = [459] + assert(str(untyped_basic) == '[459]') + assert(untyped_basic.get_typed_builtin() == TYPE_NIL) + + var inferred_basic := [366] + assert(str(inferred_basic) == '[366]') + assert(inferred_basic.get_typed_builtin() == TYPE_NIL) + + var typed_basic: Array = [521] + assert(str(typed_basic) == '[521]') + assert(typed_basic.get_typed_builtin() == TYPE_NIL) + + + var empty_floats: Array[float] = [] + assert(str(empty_floats) == '[]') + assert(empty_floats.get_typed_builtin() == TYPE_FLOAT) + + untyped_basic = empty_floats + assert(untyped_basic.get_typed_builtin() == TYPE_FLOAT) + + inferred_basic = empty_floats + assert(inferred_basic.get_typed_builtin() == TYPE_FLOAT) + + typed_basic = empty_floats + assert(typed_basic.get_typed_builtin() == TYPE_FLOAT) + + empty_floats.push_back(705.0) + untyped_basic.push_back(430.0) + inferred_basic.push_back(263.0) + typed_basic.push_back(518.0) + assert(str(empty_floats) == '[705, 430, 263, 518]') + assert(str(untyped_basic) == '[705, 430, 263, 518]') + assert(str(inferred_basic) == '[705, 430, 263, 518]') + assert(str(typed_basic) == '[705, 430, 263, 518]') + + + const constant_float := 950.0 + const constant_int := 170 + var typed_float := 954.0 + var filled_floats: Array[float] = [constant_float, constant_int, typed_float, empty_floats[1] + empty_floats[2]] + assert(str(filled_floats) == '[950, 170, 954, 693]') + assert(filled_floats.get_typed_builtin() == TYPE_FLOAT) + + var casted_floats := [empty_floats[2] * 2] as Array[float] + assert(str(casted_floats) == '[526]') + assert(casted_floats.get_typed_builtin() == TYPE_FLOAT) + + var returned_floats = (func () -> Array[float]: return [554]).call() + assert(str(returned_floats) == '[554]') + assert(returned_floats.get_typed_builtin() == TYPE_FLOAT) + + var passed_floats = floats_identity([663.0 if randf() > 0.5 else 663.0]) + assert(str(passed_floats) == '[663]') + assert(passed_floats.get_typed_builtin() == TYPE_FLOAT) + + var default_floats = (func (floats: Array[float] = [364.0]): return floats).call() + assert(str(default_floats) == '[364]') + assert(default_floats.get_typed_builtin() == TYPE_FLOAT) + + var typed_int := 556 + var converted_floats: Array[float] = [typed_int] + assert(str(converted_floats) == '[556]') + assert(converted_floats.get_typed_builtin() == TYPE_FLOAT) + + + const constant_basic = [228] + assert(str(constant_basic) == '[228]') + assert(constant_basic.get_typed_builtin() == TYPE_NIL) + + const constant_floats: Array[float] = [constant_float - constant_basic[0] - constant_int] + assert(str(constant_floats) == '[552]') + assert(constant_floats.get_typed_builtin() == TYPE_FLOAT) + + + var source_floats: Array[float] = [999.74] + untyped_basic = source_floats + var destination_floats: Array[float] = untyped_basic + destination_floats[0] -= 0.74 + assert(str(source_floats) == '[999]') + assert(str(untyped_basic) == '[999]') + assert(str(destination_floats) == '[999]') + assert(destination_floats.get_typed_builtin() == TYPE_FLOAT) + + + var duplicated_floats := empty_floats.duplicate().slice(2, 3) + duplicated_floats[0] *= 3 + assert(str(duplicated_floats) == '[789]') + assert(duplicated_floats.get_typed_builtin() == TYPE_FLOAT) + + + var b_objects: Array[B] = [B.new(), null] + assert(b_objects.size() == 2) + assert(b_objects.get_typed_builtin() == TYPE_OBJECT) + assert(b_objects.get_typed_script() == B) + + var a_objects: Array[A] = [A.new(), B.new(), null, b_objects[0]] + assert(a_objects.size() == 4) + assert(a_objects.get_typed_builtin() == TYPE_OBJECT) + assert(a_objects.get_typed_script() == A) + + var a_passed = (func check_a_passing(a_objects: Array[A]): return a_objects.size()).call(a_objects) + assert(a_passed == 4) + + var b_passed = (func check_b_passing(basic: Array): return basic[0] != null).call(b_objects) + assert(b_passed == true) + + + var empty_strings: Array[String] = [] + var empty_bools: Array[bool] = [] + var empty_basic_one := [] + var empty_basic_two := [] + assert(empty_strings == empty_bools) + assert(empty_basic_one == empty_basic_two) + assert(empty_strings.hash() == empty_bools.hash()) + assert(empty_basic_one.hash() == empty_basic_two.hash()) + + + var assign_source: Array[int] = [527] + var assign_target: Array[int] = [] + assign_target.assign(assign_source) + assert(str(assign_source) == '[527]') + assert(str(assign_target) == '[527]') + assign_source.push_back(657) + assert(str(assign_source) == '[527, 657]') + assert(str(assign_target) == '[527]') + + + var defaults_passed = (func check_defaults_passing(one: Array[int] = [], two := one): + one.push_back(887) + two.push_back(198) + assert(str(one) == '[887, 198]') + assert(str(two) == '[887, 198]') + two = [130] + assert(str(one) == '[887, 198]') + assert(str(two) == '[130]') + return true + ).call() + assert(defaults_passed == true) + + + var members := Members.new() + var members_passed := members.check_passing() + assert(members_passed == true) + + + var resized_basic: Array = [] + resized_basic.resize(1) + assert(typeof(resized_basic[0]) == TYPE_NIL) + assert(resized_basic[0] == null) + + var resized_ints: Array[int] = [] + resized_ints.resize(1) + assert(typeof(resized_ints[0]) == TYPE_INT) + assert(resized_ints[0] == 0) + + var resized_arrays: Array[Array] = [] + resized_arrays.resize(1) + assert(typeof(resized_arrays[0]) == TYPE_ARRAY) + resized_arrays[0].resize(1) + resized_arrays[0][0] = 523 + assert(str(resized_arrays) == '[[523]]') + + var resized_objects: Array[Object] = [] + resized_objects.resize(1) + assert(typeof(resized_objects[0]) == TYPE_NIL) + assert(resized_objects[0] == null) + + + var typed_enums: Array[E] = [] + typed_enums.resize(1) + assert(str(typed_enums) == '[0]') + typed_enums[0] = E.E0 + assert(str(typed_enums) == '[391]') + assert(typed_enums.get_typed_builtin() == TYPE_INT) + + + print('ok') diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.out b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.out new file mode 100644 index 0000000000..1b47ed10dc --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.out @@ -0,0 +1,2 @@ +GDTEST_OK +ok diff --git a/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out b/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out deleted file mode 100644 index ad2e6558d7..0000000000 --- a/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out +++ /dev/null @@ -1,2 +0,0 @@ -GDTEST_ANALYZER_ERROR -Cannot assign a value of type Array[String] to constant "arr" with specified type Array[int]. diff --git a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd index 0085b3f367..2470fe978e 100644 --- a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd +++ b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd @@ -1,5 +1,5 @@ # Error here. Annotations should be used before `class_name`, not after. -class_name HelloWorld +class_name WrongAnnotationPlace @icon("res://path/to/optional/icon.svg") func test(): diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.gd b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.gd new file mode 100644 index 0000000000..e9dbc1b640 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.gd @@ -0,0 +1,4 @@ +func test(): + var basic := [1] + var typed: Array[int] = basic + print('not ok') diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.out b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.out new file mode 100644 index 0000000000..bca700b4ec --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/typed_array_assign_basic_to_typed.gd +>> 3 +>> Trying to assign an array of type "Array" to a variable of type "Array[int]". diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.gd b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.gd new file mode 100644 index 0000000000..920352a6ea --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.gd @@ -0,0 +1,4 @@ +func test(): + var differently: Variant = [1.0] as Array[float] + var typed: Array[int] = differently + print('not ok') diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.out b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.out new file mode 100644 index 0000000000..402ab38fb3 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/typed_array_assign_differently_typed.gd +>> 3 +>> Trying to assign an array of type "Array[float]" to a variable of type "Array[int]". diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.gd b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.gd new file mode 100644 index 0000000000..e1fd0f7168 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.gd @@ -0,0 +1,7 @@ +func expect_typed(typed: Array[int]): + print(typed.size()) + +func test(): + var basic := [1] + expect_typed(basic) + print('not ok') diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.out b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.out new file mode 100644 index 0000000000..6f210e944e --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/typed_array_pass_basic_to_typed.gd +>> 6 +>> Invalid type in function 'expect_typed' in base 'RefCounted ()'. The array of argument 1 (Array) does not have the same element type as the expected typed array argument. diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.gd b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.gd new file mode 100644 index 0000000000..e2d2721e8c --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.gd @@ -0,0 +1,7 @@ +func expect_typed(typed: Array[int]): + print(typed.size()) + +func test(): + var differently: Variant = [1.0] as Array[float] + expect_typed(differently) + print('not ok') diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.out b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.out new file mode 100644 index 0000000000..3cd4e25bd8 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/typed_array_pass_differently_to_typed.gd +>> 6 +>> Invalid type in function 'expect_typed' in base 'RefCounted ()'. The array of argument 1 (Array[float]) does not have the same element type as the expected typed array argument. diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.gd b/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.gd new file mode 100644 index 0000000000..ec444b4ffa --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.gd @@ -0,0 +1,6 @@ +func test(): + var untyped: Variant = 32 + var typed: Array[int] = [untyped] + assert(typed.get_typed_builtin() == TYPE_INT) + assert(str(typed) == '[32]') + print('ok') diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.out b/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.out new file mode 100644 index 0000000000..1b47ed10dc --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.out @@ -0,0 +1,2 @@ +GDTEST_OK +ok diff --git a/modules/gltf/doc_classes/GLTFDocumentExtension.xml b/modules/gltf/doc_classes/GLTFDocumentExtension.xml index 6004de32f1..6e8340f618 100644 --- a/modules/gltf/doc_classes/GLTFDocumentExtension.xml +++ b/modules/gltf/doc_classes/GLTFDocumentExtension.xml @@ -22,7 +22,7 @@ </description> </method> <method name="_export_node" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="state" type="GLTFState" /> <param index="1" name="gltf_node" type="GLTFNode" /> <param index="2" name="json" type="Dictionary" /> @@ -33,7 +33,7 @@ </description> </method> <method name="_export_post" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="state" type="GLTFState" /> <description> Part of the export process. This method is run last, after all other parts of the export process. @@ -41,7 +41,7 @@ </description> </method> <method name="_export_preflight" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="state" type="GLTFState" /> <param index="1" name="root" type="Node" /> <description> @@ -67,7 +67,7 @@ </description> </method> <method name="_import_node" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="state" type="GLTFState" /> <param index="1" name="gltf_node" type="GLTFNode" /> <param index="2" name="json" type="Dictionary" /> @@ -78,7 +78,7 @@ </description> </method> <method name="_import_post" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="state" type="GLTFState" /> <param index="1" name="root" type="Node" /> <description> @@ -87,7 +87,7 @@ </description> </method> <method name="_import_post_parse" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="state" type="GLTFState" /> <description> Part of the import process. This method is run after [method _generate_scene_node] and before [method _import_node]. @@ -95,7 +95,7 @@ </description> </method> <method name="_import_preflight" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="state" type="GLTFState" /> <param index="1" name="extensions" type="PackedStringArray" /> <description> @@ -104,7 +104,7 @@ </description> </method> <method name="_parse_node_extensions" qualifiers="virtual"> - <return type="int" /> + <return type="int" enum="Error" /> <param index="0" name="state" type="GLTFState" /> <param index="1" name="gltf_node" type="GLTFNode" /> <param index="2" name="extensions" type="Dictionary" /> diff --git a/modules/gltf/doc_classes/GLTFState.xml b/modules/gltf/doc_classes/GLTFState.xml index b8943795a0..b322c07cec 100644 --- a/modules/gltf/doc_classes/GLTFState.xml +++ b/modules/gltf/doc_classes/GLTFState.xml @@ -264,10 +264,16 @@ </members> <constants> <constant name="HANDLE_BINARY_DISCARD_TEXTURES" value="0"> + Discards all embedded textures and uses untextured materials. </constant> <constant name="HANDLE_BINARY_EXTRACT_TEXTURES" value="1"> + Extracts embedded textures to be reimported and compressed. Editor only. Acts as uncompressed at runtime. </constant> <constant name="HANDLE_BINARY_EMBED_AS_BASISU" value="2"> + Embeds textures VRAM compressed with Basis Universal into the generated scene. + </constant> + <constant name="HANDLE_BINARY_EMBED_AS_UNCOMPRESSED" value="3"> + Embeds textures compressed losslessly into the generated scene, matching old behavior. </constant> </constants> </class> diff --git a/modules/gltf/editor/editor_import_blend_runner.cpp b/modules/gltf/editor/editor_import_blend_runner.cpp new file mode 100644 index 0000000000..c203a91834 --- /dev/null +++ b/modules/gltf/editor/editor_import_blend_runner.cpp @@ -0,0 +1,314 @@ +/**************************************************************************/ +/* editor_import_blend_runner.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "editor_import_blend_runner.h" + +#ifdef TOOLS_ENABLED + +#include "core/io/http_client.h" +#include "editor/editor_file_system.h" +#include "editor/editor_node.h" +#include "editor/editor_settings.h" + +static constexpr char PYTHON_SCRIPT_RPC[] = R"( +import bpy, sys, threading +from xmlrpc.server import SimpleXMLRPCServer +req = threading.Condition() +res = threading.Condition() +info = None +def xmlrpc_server(): + server = SimpleXMLRPCServer(('127.0.0.1', %d)) + server.register_function(export_gltf) + server.serve_forever() +def export_gltf(opts): + with req: + global info + info = ('export_gltf', opts) + req.notify() + with res: + res.wait() +if bpy.app.version < (3, 0, 0): + print('Blender 3.0 or higher is required.', file=sys.stderr) +threading.Thread(target=xmlrpc_server).start() +while True: + with req: + while info is None: + req.wait() + method, opts = info + if method == 'export_gltf': + try: + bpy.ops.wm.open_mainfile(filepath=opts['path']) + if opts['unpack_all']: + bpy.ops.file.unpack_all(method='USE_LOCAL') + bpy.ops.export_scene.gltf(**opts['gltf_options']) + except: + pass + info = None + with res: + res.notify() +)"; + +static constexpr char PYTHON_SCRIPT_DIRECT[] = R"( +import bpy, sys +opts = %s +if bpy.app.version < (3, 0, 0): + print('Blender 3.0 or higher is required.', file=sys.stderr) +bpy.ops.wm.open_mainfile(filepath=opts['path']) +if opts['unpack_all']: + bpy.ops.file.unpack_all(method='USE_LOCAL') +bpy.ops.export_scene.gltf(**opts['gltf_options']) +)"; + +String dict_to_python(const Dictionary &p_dict) { + String entries; + Array dict_keys = p_dict.keys(); + for (int i = 0; i < dict_keys.size(); i++) { + const String key = dict_keys[i]; + String value; + Variant raw_value = p_dict[key]; + + switch (raw_value.get_type()) { + case Variant::Type::BOOL: { + value = raw_value ? "True" : "False"; + break; + } + case Variant::Type::STRING: + case Variant::Type::STRING_NAME: { + value = raw_value; + value = vformat("'%s'", value.c_escape()); + break; + } + case Variant::Type::DICTIONARY: { + value = dict_to_python(raw_value); + break; + } + default: { + ERR_FAIL_V_MSG("", vformat("Unhandled Variant type %s for python dictionary", Variant::get_type_name(raw_value.get_type()))); + } + } + + entries += vformat("'%s': %s,", key, value); + } + return vformat("{%s}", entries); +} + +String dict_to_xmlrpc(const Dictionary &p_dict) { + String members; + Array dict_keys = p_dict.keys(); + for (int i = 0; i < dict_keys.size(); i++) { + const String key = dict_keys[i]; + String value; + Variant raw_value = p_dict[key]; + + switch (raw_value.get_type()) { + case Variant::Type::BOOL: { + value = vformat("<boolean>%d</boolean>", raw_value ? 1 : 0); + break; + } + case Variant::Type::STRING: + case Variant::Type::STRING_NAME: { + value = raw_value; + value = vformat("<string>%s</string>", value.xml_escape()); + break; + } + case Variant::Type::DICTIONARY: { + value = dict_to_xmlrpc(raw_value); + break; + } + default: { + ERR_FAIL_V_MSG("", vformat("Unhandled Variant type %s for XMLRPC", Variant::get_type_name(raw_value.get_type()))); + } + } + + members += vformat("<member><name>%s</name><value>%s</value></member>", key, value); + } + return vformat("<struct>%s</struct>", members); +} + +Error EditorImportBlendRunner::start_blender(const String &p_python_script, bool p_blocking) { + String blender_path = EDITOR_GET("filesystem/import/blender/blender3_path"); + +#ifdef WINDOWS_ENABLED + blender_path = blender_path.path_join("blender.exe"); +#else + blender_path = blender_path.path_join("blender"); +#endif + + List<String> args; + args.push_back("--background"); + args.push_back("--python-expr"); + args.push_back(p_python_script); + + Error err; + if (p_blocking) { + int exitcode = 0; + err = OS::get_singleton()->execute(blender_path, args, nullptr, &exitcode); + if (exitcode != 0) { + return FAILED; + } + } else { + err = OS::get_singleton()->create_process(blender_path, args, &blender_pid); + } + return err; +} + +Error EditorImportBlendRunner::do_import(const Dictionary &p_options) { + if (is_using_rpc()) { + return do_import_rpc(p_options); + } else { + return do_import_direct(p_options); + } +} + +Error EditorImportBlendRunner::do_import_rpc(const Dictionary &p_options) { + kill_timer->stop(); + + // Start Blender if not already running. + if (!is_running()) { + // Start an XML RPC server on the given port. + String python = vformat(PYTHON_SCRIPT_RPC, rpc_port); + Error err = start_blender(python, false); + if (err != OK || blender_pid == 0) { + return FAILED; + } + } + + // Convert options to XML body. + String xml_options = dict_to_xmlrpc(p_options); + String xml_body = vformat("<?xml version=\"1.0\"?><methodCall><methodName>export_gltf</methodName><params><param><value>%s</value></param></params></methodCall>", xml_options); + + // Connect to RPC server. + Ref<HTTPClient> client = HTTPClient::create(); + client->connect_to_host("127.0.0.1", rpc_port); + + bool done = false; + while (!done) { + HTTPClient::Status status = client->get_status(); + switch (status) { + case HTTPClient::STATUS_RESOLVING: + case HTTPClient::STATUS_CONNECTING: { + client->poll(); + break; + } + case HTTPClient::STATUS_CONNECTED: { + done = true; + break; + } + default: { + ERR_FAIL_V_MSG(ERR_CONNECTION_ERROR, vformat("Unexpected status during RPC connection: %d", status)); + } + } + } + + // Send XML request. + PackedByteArray xml_buffer = xml_body.to_utf8_buffer(); + Error err = client->request(HTTPClient::METHOD_POST, "/", Vector<String>(), xml_buffer.ptr(), xml_buffer.size()); + if (err != OK) { + ERR_FAIL_V_MSG(err, vformat("Unable to send RPC request: %d", err)); + } + + // Wait for response. + done = false; + while (!done) { + HTTPClient::Status status = client->get_status(); + switch (status) { + case HTTPClient::STATUS_REQUESTING: { + client->poll(); + break; + } + case HTTPClient::STATUS_BODY: { + client->poll(); + // Parse response here if needed. For now we can just ignore it. + done = true; + break; + } + default: { + ERR_FAIL_V_MSG(ERR_CONNECTION_ERROR, vformat("Unexpected status during RPC response: %d", status)); + } + } + } + + return OK; +} + +Error EditorImportBlendRunner::do_import_direct(const Dictionary &p_options) { + // Export glTF directly. + String python = vformat(PYTHON_SCRIPT_DIRECT, dict_to_python(p_options)); + Error err = start_blender(python, true); + if (err != OK) { + return err; + } + + return OK; +} + +void EditorImportBlendRunner::_resources_reimported(const PackedStringArray &p_files) { + if (is_running()) { + // After a batch of imports is done, wait a few seconds before trying to kill blender, + // in case of having multiple imports trigger in quick succession. + kill_timer->start(); + } +} + +void EditorImportBlendRunner::_kill_blender() { + kill_timer->stop(); + if (is_running()) { + OS::get_singleton()->kill(blender_pid); + } + blender_pid = 0; +} + +void EditorImportBlendRunner::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_PREDELETE: { + _kill_blender(); + break; + } + } +} + +EditorImportBlendRunner *EditorImportBlendRunner::singleton = nullptr; + +EditorImportBlendRunner::EditorImportBlendRunner() { + ERR_FAIL_COND_MSG(singleton != nullptr, "EditorImportBlendRunner already created."); + singleton = this; + + rpc_port = EDITOR_GET("filesystem/import/blender/rpc_port"); + + kill_timer = memnew(Timer); + add_child(kill_timer); + kill_timer->set_one_shot(true); + kill_timer->set_wait_time(EDITOR_GET("filesystem/import/blender/rpc_server_uptime")); + kill_timer->connect("timeout", callable_mp(this, &EditorImportBlendRunner::_kill_blender)); + + EditorFileSystem::get_singleton()->connect("resources_reimported", callable_mp(this, &EditorImportBlendRunner::_resources_reimported)); +} + +#endif // TOOLS_ENABLED diff --git a/modules/gltf/editor/editor_import_blend_runner.h b/modules/gltf/editor/editor_import_blend_runner.h new file mode 100644 index 0000000000..b2b82394e1 --- /dev/null +++ b/modules/gltf/editor/editor_import_blend_runner.h @@ -0,0 +1,69 @@ +/**************************************************************************/ +/* editor_import_blend_runner.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef EDITOR_IMPORT_BLEND_RUNNER_H +#define EDITOR_IMPORT_BLEND_RUNNER_H + +#ifdef TOOLS_ENABLED + +#include "core/os/os.h" +#include "scene/main/node.h" +#include "scene/main/timer.h" + +class EditorImportBlendRunner : public Node { + GDCLASS(EditorImportBlendRunner, Node); + + static EditorImportBlendRunner *singleton; + + Timer *kill_timer; + void _resources_reimported(const PackedStringArray &p_files); + void _kill_blender(); + void _notification(int p_what); + +protected: + int rpc_port = 0; + OS::ProcessID blender_pid = 0; + Error start_blender(const String &p_python_script, bool p_blocking); + Error do_import_direct(const Dictionary &p_options); + Error do_import_rpc(const Dictionary &p_options); + +public: + static EditorImportBlendRunner *get_singleton() { return singleton; } + + bool is_running() { return blender_pid != 0 && OS::get_singleton()->is_process_running(blender_pid); } + bool is_using_rpc() { return rpc_port != 0; } + Error do_import(const Dictionary &p_options); + + EditorImportBlendRunner(); +}; + +#endif // TOOLS_ENABLED + +#endif // EDITOR_IMPORT_BLEND_RUNNER_H diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 5415c5818f..520f33261a 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -34,6 +34,7 @@ #include "../gltf_defines.h" #include "../gltf_document.h" +#include "editor_import_blend_runner.h" #include "core/config/project_settings.h" #include "editor/editor_file_dialog.h" @@ -68,149 +69,129 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ // Handle configuration options. - String parameters_arg; + Dictionary request_options; + Dictionary parameters_map; + + parameters_map["filepath"] = sink_global; + parameters_map["export_keep_originals"] = true; + parameters_map["export_format"] = "GLTF_SEPARATE"; + parameters_map["export_yup"] = true; if (p_options.has(SNAME("blender/nodes/custom_properties")) && p_options[SNAME("blender/nodes/custom_properties")]) { - parameters_arg += "export_extras=True,"; + parameters_map["export_extras"] = true; } else { - parameters_arg += "export_extras=False,"; + parameters_map["export_extras"] = false; } if (p_options.has(SNAME("blender/meshes/skins"))) { int32_t skins = p_options["blender/meshes/skins"]; if (skins == BLEND_BONE_INFLUENCES_NONE) { - parameters_arg += "export_skins=False,"; + parameters_map["export_skins"] = false; } else if (skins == BLEND_BONE_INFLUENCES_COMPATIBLE) { - parameters_arg += "export_all_influences=False,export_skins=True,"; + parameters_map["export_skins"] = true; + parameters_map["export_all_influences"] = false; } else if (skins == BLEND_BONE_INFLUENCES_ALL) { - parameters_arg += "export_all_influences=True,export_skins=True,"; + parameters_map["export_skins"] = true; + parameters_map["export_all_influences"] = true; } } else { - parameters_arg += "export_skins=False,"; + parameters_map["export_skins"] = false; } if (p_options.has(SNAME("blender/materials/export_materials"))) { int32_t exports = p_options["blender/materials/export_materials"]; if (exports == BLEND_MATERIAL_EXPORT_PLACEHOLDER) { - parameters_arg += "export_materials='PLACEHOLDER',"; + parameters_map["export_materials"] = "PLACEHOLDER"; } else if (exports == BLEND_MATERIAL_EXPORT_EXPORT) { - parameters_arg += "export_materials='EXPORT',"; + parameters_map["export_materials"] = "EXPORT"; } } else { - parameters_arg += "export_materials='PLACEHOLDER',"; + parameters_map["export_materials"] = "PLACEHOLDER"; } if (p_options.has(SNAME("blender/nodes/cameras")) && p_options[SNAME("blender/nodes/cameras")]) { - parameters_arg += "export_cameras=True,"; + parameters_map["export_cameras"] = true; } else { - parameters_arg += "export_cameras=False,"; + parameters_map["export_cameras"] = false; } if (p_options.has(SNAME("blender/nodes/punctual_lights")) && p_options[SNAME("blender/nodes/punctual_lights")]) { - parameters_arg += "export_lights=True,"; + parameters_map["export_lights"] = true; } else { - parameters_arg += "export_lights=False,"; + parameters_map["export_lights"] = false; } if (p_options.has(SNAME("blender/meshes/colors")) && p_options[SNAME("blender/meshes/colors")]) { - parameters_arg += "export_colors=True,"; + parameters_map["export_colors"] = true; } else { - parameters_arg += "export_colors=False,"; + parameters_map["export_colors"] = false; } if (p_options.has(SNAME("blender/nodes/visible"))) { int32_t visible = p_options["blender/nodes/visible"]; if (visible == BLEND_VISIBLE_VISIBLE_ONLY) { - parameters_arg += "use_visible=True,"; + parameters_map["use_visible"] = true; } else if (visible == BLEND_VISIBLE_RENDERABLE) { - parameters_arg += "use_renderable=True,"; + parameters_map["use_renderable"] = true; } else if (visible == BLEND_VISIBLE_ALL) { - parameters_arg += "use_visible=False,use_renderable=False,"; + parameters_map["use_renderable"] = false; + parameters_map["use_visible"] = false; } } else { - parameters_arg += "use_visible=False,use_renderable=False,"; + parameters_map["use_renderable"] = false; + parameters_map["use_visible"] = false; } if (p_options.has(SNAME("blender/meshes/uvs")) && p_options[SNAME("blender/meshes/uvs")]) { - parameters_arg += "export_texcoords=True,"; + parameters_map["export_texcoords"] = true; } else { - parameters_arg += "export_texcoords=False,"; + parameters_map["export_texcoords"] = false; } if (p_options.has(SNAME("blender/meshes/normals")) && p_options[SNAME("blender/meshes/normals")]) { - parameters_arg += "export_normals=True,"; + parameters_map["export_normals"] = true; } else { - parameters_arg += "export_normals=False,"; + parameters_map["export_normals"] = false; } if (p_options.has(SNAME("blender/meshes/tangents")) && p_options[SNAME("blender/meshes/tangents")]) { - parameters_arg += "export_tangents=True,"; + parameters_map["export_tangents"] = true; } else { - parameters_arg += "export_tangents=False,"; + parameters_map["export_tangents"] = false; } if (p_options.has(SNAME("blender/animation/group_tracks")) && p_options[SNAME("blender/animation/group_tracks")]) { - parameters_arg += "export_nla_strips=True,"; + parameters_map["export_nla_strips"] = true; } else { - parameters_arg += "export_nla_strips=False,"; + parameters_map["export_nla_strips"] = false; } if (p_options.has(SNAME("blender/animation/limit_playback")) && p_options[SNAME("blender/animation/limit_playback")]) { - parameters_arg += "export_frame_range=True,"; + parameters_map["export_frame_range"] = true; } else { - parameters_arg += "export_frame_range=False,"; + parameters_map["export_frame_range"] = false; } if (p_options.has(SNAME("blender/animation/always_sample")) && p_options[SNAME("blender/animation/always_sample")]) { - parameters_arg += "export_force_sampling=True,"; + parameters_map["export_force_sampling"] = true; } else { - parameters_arg += "export_force_sampling=False,"; + parameters_map["export_force_sampling"] = false; } if (p_options.has(SNAME("blender/meshes/export_bones_deforming_mesh_only")) && p_options[SNAME("blender/meshes/export_bones_deforming_mesh_only")]) { - parameters_arg += "export_def_bones=True,"; + parameters_map["export_def_bones"] = true; } else { - parameters_arg += "export_def_bones=False,"; + parameters_map["export_def_bones"] = false; } if (p_options.has(SNAME("blender/nodes/modifiers")) && p_options[SNAME("blender/nodes/modifiers")]) { - parameters_arg += "export_apply=True"; + parameters_map["export_apply"] = true; } else { - parameters_arg += "export_apply=False"; + parameters_map["export_apply"] = false; } - String unpack_all; if (p_options.has(SNAME("blender/materials/unpack_enabled")) && p_options[SNAME("blender/materials/unpack_enabled")]) { - unpack_all = "bpy.ops.file.unpack_all(method='USE_LOCAL');"; + request_options["unpack_all"] = true; + } else { + request_options["unpack_all"] = false; } - // Prepare Blender export script. - - String common_args = vformat("filepath='%s',", sink_global) + - "export_format='GLTF_SEPARATE'," - "export_yup=True," + - parameters_arg; - String export_script = - String("import bpy, sys;") + - "print('Blender 3.0 or higher is required.', file=sys.stderr) if bpy.app.version < (3, 0, 0) else None;" + - vformat("bpy.ops.wm.open_mainfile(filepath='%s');", source_global) + - unpack_all + - vformat("bpy.ops.export_scene.gltf(export_keep_originals=True,%s);", common_args); - print_verbose(export_script); - - // Run script with configured Blender binary. + request_options["path"] = source_global; + request_options["gltf_options"] = parameters_map; - String blender_path = EDITOR_GET("filesystem/import/blender/blender3_path"); - -#ifdef WINDOWS_ENABLED - blender_path = blender_path.path_join("blender.exe"); -#else - blender_path = blender_path.path_join("blender"); -#endif - - List<String> args; - args.push_back("--background"); - args.push_back("--python-expr"); - args.push_back(export_script); - - String standard_out; - int ret; - OS::get_singleton()->execute(blender_path, args, &standard_out, &ret, true); - print_verbose(blender_path); - print_verbose(standard_out); - - if (ret != 0) { + // Run Blender and export glTF. + Error err = EditorImportBlendRunner::get_singleton()->do_import(request_options); + if (err != OK) { if (r_err) { *r_err = ERR_SCRIPT_FAILED; } - ERR_PRINT(vformat("Blend export to glTF failed with error: %d.", ret)); return nullptr; } @@ -226,7 +207,7 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_ if (p_options.has(SNAME("blender/materials/unpack_enabled")) && p_options[SNAME("blender/materials/unpack_enabled")]) { base_dir = sink.get_base_dir(); } - Error err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, base_dir); + err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, base_dir); if (err != OK) { if (r_err) { *r_err = FAILED; diff --git a/modules/gltf/editor/editor_scene_importer_gltf.cpp b/modules/gltf/editor/editor_scene_importer_gltf.cpp index 67bbf8dd15..012a144d52 100644 --- a/modules/gltf/editor/editor_scene_importer_gltf.cpp +++ b/modules/gltf/editor/editor_scene_importer_gltf.cpp @@ -51,8 +51,8 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t doc.instantiate(); Ref<GLTFState> state; state.instantiate(); - if (p_options.has("meshes/handle_gltf_embedded_images")) { - int32_t enum_option = p_options["meshes/handle_gltf_embedded_images"]; + if (p_options.has("gltf/embedded_image_handling")) { + int32_t enum_option = p_options["gltf/embedded_image_handling"]; state->set_handle_binary_image(enum_option); } Error err = doc->append_from_file(p_path, state, p_flags); @@ -87,7 +87,7 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t void EditorSceneFormatImporterGLTF::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) { - r_options->push_back(ResourceImporterScene::ImportOption(PropertyInfo(Variant::INT, "meshes/handle_gltf_embedded_images", PROPERTY_HINT_ENUM, "Discard All Textures,Extract Textures,Embed As Basis Universal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), GLTFState::HANDLE_BINARY_EXTRACT_TEXTURES)); + r_options->push_back(ResourceImporterScene::ImportOption(PropertyInfo(Variant::INT, "gltf/embedded_image_handling", PROPERTY_HINT_ENUM, "Discard All Textures,Extract Textures,Embed As Basis Universal,Embed as Uncompressed", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), GLTFState::HANDLE_BINARY_EXTRACT_TEXTURES)); } #endif // TOOLS_ENABLED diff --git a/modules/gltf/extensions/gltf_document_extension.cpp b/modules/gltf/extensions/gltf_document_extension.cpp index 496a8f6cb8..bedb42eb32 100644 --- a/modules/gltf/extensions/gltf_document_extension.cpp +++ b/modules/gltf/extensions/gltf_document_extension.cpp @@ -49,9 +49,9 @@ void GLTFDocumentExtension::_bind_methods() { // Import process. Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) { ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); - int err = OK; + Error err = OK; GDVIRTUAL_CALL(_import_preflight, p_state, p_extensions, err); - return Error(err); + return err; } Vector<String> GLTFDocumentExtension::get_supported_extensions() { @@ -63,9 +63,9 @@ Vector<String> GLTFDocumentExtension::get_supported_extensions() { Error GLTFDocumentExtension::parse_node_extensions(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &p_extensions) { ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER); - int err = OK; + Error err = OK; GDVIRTUAL_CALL(_parse_node_extensions, p_state, p_gltf_node, p_extensions, err); - return Error(err); + return err; } Node3D *GLTFDocumentExtension::generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) { @@ -79,34 +79,34 @@ Node3D *GLTFDocumentExtension::generate_scene_node(Ref<GLTFState> p_state, Ref<G Error GLTFDocumentExtension::import_post_parse(Ref<GLTFState> p_state) { ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); - int err = OK; + Error err = OK; GDVIRTUAL_CALL(_import_post_parse, p_state, err); - return Error(err); + return err; } Error GLTFDocumentExtension::import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) { ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER); ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER); - int err = OK; + Error err = OK; GDVIRTUAL_CALL(_import_node, p_state, p_gltf_node, r_dict, p_node, err); - return Error(err); + return err; } Error GLTFDocumentExtension::import_post(Ref<GLTFState> p_state, Node *p_root) { ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER); ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); - int err = OK; + Error err = OK; GDVIRTUAL_CALL(_import_post, p_state, p_root, err); - return Error(err); + return err; } // Export process. Error GLTFDocumentExtension::export_preflight(Ref<GLTFState> p_state, Node *p_root) { ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER); - int err = OK; + Error err = OK; GDVIRTUAL_CALL(_export_preflight, p_state, p_root, err); - return Error(err); + return err; } void GLTFDocumentExtension::convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_node) { @@ -120,14 +120,14 @@ Error GLTFDocumentExtension::export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); ERR_FAIL_NULL_V(p_gltf_node, ERR_INVALID_PARAMETER); ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER); - int err = OK; + Error err = OK; GDVIRTUAL_CALL(_export_node, p_state, p_gltf_node, r_dict, p_node, err); - return Error(err); + return err; } Error GLTFDocumentExtension::export_post(Ref<GLTFState> p_state) { ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER); - int err = OK; + Error err = OK; GDVIRTUAL_CALL(_export_post, p_state, err); - return Error(err); + return err; } diff --git a/modules/gltf/extensions/gltf_document_extension.h b/modules/gltf/extensions/gltf_document_extension.h index 97f5045a1c..3531f81f6f 100644 --- a/modules/gltf/extensions/gltf_document_extension.h +++ b/modules/gltf/extensions/gltf_document_extension.h @@ -55,18 +55,18 @@ public: virtual Error export_post(Ref<GLTFState> p_state); // Import process. - GDVIRTUAL2R(int, _import_preflight, Ref<GLTFState>, Vector<String>); + GDVIRTUAL2R(Error, _import_preflight, Ref<GLTFState>, Vector<String>); GDVIRTUAL0R(Vector<String>, _get_supported_extensions); - GDVIRTUAL3R(int, _parse_node_extensions, Ref<GLTFState>, Ref<GLTFNode>, Dictionary); + GDVIRTUAL3R(Error, _parse_node_extensions, Ref<GLTFState>, Ref<GLTFNode>, Dictionary); GDVIRTUAL3R(Node3D *, _generate_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *); - GDVIRTUAL1R(int, _import_post_parse, Ref<GLTFState>); - GDVIRTUAL4R(int, _import_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *); - GDVIRTUAL2R(int, _import_post, Ref<GLTFState>, Node *); + GDVIRTUAL1R(Error, _import_post_parse, Ref<GLTFState>); + GDVIRTUAL4R(Error, _import_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *); + GDVIRTUAL2R(Error, _import_post, Ref<GLTFState>, Node *); // Export process. - GDVIRTUAL2R(int, _export_preflight, Ref<GLTFState>, Node *); + GDVIRTUAL2R(Error, _export_preflight, Ref<GLTFState>, Node *); GDVIRTUAL3(_convert_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *); - GDVIRTUAL4R(int, _export_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *); - GDVIRTUAL1R(int, _export_post, Ref<GLTFState>); + GDVIRTUAL4R(Error, _export_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *); + GDVIRTUAL1R(Error, _export_post, Ref<GLTFState>); }; #endif // GLTF_DOCUMENT_EXTENSION_H diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 0b519bd6a3..1a09b5bdcc 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -32,6 +32,7 @@ #include "extensions/gltf_spec_gloss.h" +#include "core/config/project_settings.h" #include "core/crypto/crypto_core.h" #include "core/io/config_file.h" #include "core/io/dir_access.h" @@ -3065,6 +3066,7 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_p // Ref: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#images const Array &images = p_state->json["images"]; + HashSet<String> used_names; for (int i = 0; i < images.size(); i++) { const Dictionary &d = images[i]; @@ -3092,11 +3094,21 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_p int data_size = 0; String image_name; + if (d.has("name")) { + image_name = d["name"]; + image_name = image_name.get_file().get_basename().validate_filename(); + } + if (image_name.is_empty()) { + image_name = itos(i); + } + while (used_names.has(image_name)) { + image_name += "_" + itos(i); + } + used_names.insert(image_name); if (d.has("uri")) { // Handles the first two bullet points from the spec (embedded data, or external file). String uri = d["uri"]; - image_name = uri; if (uri.begins_with("data:")) { // Embedded data using base64. // Validate data MIME types and throw a warning if it's one we don't know/support. @@ -3158,7 +3170,6 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_p vformat("glTF: Image index '%d' specifies 'bufferView' but no 'mimeType', which is invalid.", i)); const GLTFBufferViewIndex bvi = d["bufferView"]; - image_name = itos(bvi); ERR_FAIL_INDEX_V(bvi, p_state->buffer_views.size(), ERR_PARAMETER_RANGE_ERROR); @@ -3206,13 +3217,12 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_p p_state->source_images.push_back(Ref<Image>()); continue; } + img->set_name(image_name); if (GLTFState::GLTFHandleBinary(p_state->handle_binary_image) == GLTFState::GLTFHandleBinary::HANDLE_BINARY_DISCARD_TEXTURES) { p_state->images.push_back(Ref<Texture2D>()); p_state->source_images.push_back(Ref<Image>()); - continue; - } else if (GLTFState::GLTFHandleBinary(p_state->handle_binary_image) == GLTFState::GLTFHandleBinary::HANDLE_BINARY_EXTRACT_TEXTURES) { - String extracted_image_name = image_name.get_file().get_basename().validate_filename(); - img->set_name(extracted_image_name); +#ifdef TOOLS_ENABLED + } else if (Engine::get_singleton()->is_editor_hint() && GLTFState::GLTFHandleBinary(p_state->handle_binary_image) == GLTFState::GLTFHandleBinary::HANDLE_BINARY_EXTRACT_TEXTURES) { if (p_state->base_path.is_empty()) { p_state->images.push_back(Ref<Texture2D>()); p_state->source_images.push_back(Ref<Image>()); @@ -3221,26 +3231,56 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_p p_state->images.push_back(Ref<Texture2D>()); p_state->source_images.push_back(Ref<Image>()); } else { + Error err = OK; + bool must_import = false; String file_path = p_state->get_base_path() + "/" + p_state->filename.get_basename() + "_" + img->get_name() + ".png"; - Ref<ConfigFile> config; - config.instantiate(); - if (FileAccess::exists(file_path + ".import")) { - config->load(file_path + ".import"); + if (!FileAccess::exists(file_path + ".import")) { + Ref<ConfigFile> config; + config.instantiate(); + config->set_value("remap", "importer", "texture"); + config->set_value("remap", "type", "Texture2D"); + // Currently, it will likely use project defaults of Detect 3D, so textures will be reimported again. + if (!config->has_section_key("params", "mipmaps/generate")) { + config->set_value("params", "mipmaps/generate", true); + } + + if (ProjectSettings::get_singleton()->has_setting("importer_defaults/texture")) { + //use defaults if exist + Dictionary importer_defaults = GLOBAL_GET("importer_defaults/texture"); + List<Variant> importer_def_keys; + importer_defaults.get_key_list(&importer_def_keys); + for (const Variant &key : importer_def_keys) { + if (!config->has_section_key("params", (String)key)) { + config->set_value("params", (String)key, importer_defaults[key]); + } + } + } + err = config->save(file_path + ".import"); + ERR_FAIL_COND_V(err != OK, err); + must_import = true; } - config->set_value("remap", "importer", "texture"); - config->set_value("remap", "type", "Texture2D"); - if (!config->has_section_key("params", "compress/mode")) { - config->set_value("remap", "compress/mode", 2); //user may want another compression, so leave it bes + Vector<uint8_t> png_buffer = img->save_png_to_buffer(); + if (ResourceLoader::exists(file_path)) { + Ref<FileAccess> file = FileAccess::open(file_path, FileAccess::READ, &err); + if (err == OK && file.is_valid()) { + Vector<uint8_t> orig_png_buffer = file->get_buffer(file->get_length()); + if (png_buffer != orig_png_buffer) { + must_import = true; + } + } + } else { + must_import = true; } - if (!config->has_section_key("params", "mipmaps/generate")) { - config->set_value("params", "mipmaps/generate", true); + if (must_import) { + Ref<FileAccess> file = FileAccess::open(file_path, FileAccess::WRITE, &err); + ERR_FAIL_COND_V(err != OK, err); + ERR_FAIL_COND_V(file.is_null(), FAILED); + file->store_buffer(png_buffer); + file->flush(); + file.unref(); + // ResourceLoader::import will crash if not is_editor_hint(), so this case is protected above and will fall through to uncompressed. + ResourceLoader::import(file_path); } - Error err = OK; - err = config->save(file_path + ".import"); - ERR_FAIL_COND_V(err != OK, err); - img->save_png(file_path); - ERR_FAIL_COND_V(err != OK, err); - ResourceLoader::import(file_path); Ref<Texture2D> saved_image = ResourceLoader::load(file_path, "Texture2D"); if (saved_image.is_valid()) { p_state->images.push_back(saved_image); @@ -3252,7 +3292,7 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_p p_state->source_images.push_back(Ref<Image>()); } } - continue; +#endif } else if (GLTFState::GLTFHandleBinary(p_state->handle_binary_image) == GLTFState::GLTFHandleBinary::HANDLE_BINARY_EMBED_AS_BASISU) { Ref<PortableCompressedTexture2D> tex; tex.instantiate(); @@ -3262,11 +3302,15 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> p_state, const String &p_base_p tex->create_from_image(img, PortableCompressedTexture2D::COMPRESSION_MODE_BASIS_UNIVERSAL); p_state->images.push_back(tex); p_state->source_images.push_back(img); - continue; + } else { + // This handles two cases: if editor hint and HANDLE_BINARY_EXTRACT_TEXTURES; or if HANDLE_BINARY_EMBED_AS_UNCOMPRESSED + Ref<ImageTexture> tex; + tex.instantiate(); + tex->set_name(img->get_name()); + tex->set_image(img); + p_state->images.push_back(tex); + p_state->source_images.push_back(img); } - - p_state->images.push_back(Ref<Texture2D>()); - p_state->source_images.push_back(Ref<Image>()); } print_verbose("glTF: Total images: " + itos(p_state->images.size())); diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index b67484fc8e..b7b7113a97 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -120,11 +120,12 @@ void GLTFState::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "skeleton_to_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_skeleton_to_node", "get_skeleton_to_node"); // RBMap<GLTFSkeletonIndex, ADD_PROPERTY(PropertyInfo(Variant::BOOL, "create_animations"), "set_create_animations", "get_create_animations"); // bool ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "animations", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_animations", "get_animations"); // Vector<Ref<GLTFAnimation>> - ADD_PROPERTY(PropertyInfo(Variant::INT, "handle_binary_image", PROPERTY_HINT_ENUM, "Discard All Textures,Extract Textures,Embed As Basis Universal", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_handle_binary_image", "get_handle_binary_image"); // enum + ADD_PROPERTY(PropertyInfo(Variant::INT, "handle_binary_image", PROPERTY_HINT_ENUM, "Discard All Textures,Extract Textures,Embed As Basis Universal,Embed as Uncompressed", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_EDITOR), "set_handle_binary_image", "get_handle_binary_image"); // enum BIND_CONSTANT(HANDLE_BINARY_DISCARD_TEXTURES); BIND_CONSTANT(HANDLE_BINARY_EXTRACT_TEXTURES); BIND_CONSTANT(HANDLE_BINARY_EMBED_AS_BASISU); + BIND_CONSTANT(HANDLE_BINARY_EMBED_AS_UNCOMPRESSED); } void GLTFState::add_used_extension(const String &p_extension_name, bool p_required) { diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index 52d7949d03..b6979ca48e 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -108,6 +108,7 @@ public: HANDLE_BINARY_DISCARD_TEXTURES = 0, HANDLE_BINARY_EXTRACT_TEXTURES, HANDLE_BINARY_EMBED_AS_BASISU, + HANDLE_BINARY_EMBED_AS_UNCOMPRESSED, // if this value changes from 3, ResourceImporterScene::pre_import must be changed as well. }; int32_t get_handle_binary_image() { return handle_binary_image; diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index f80e12bbae..78589090db 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -36,6 +36,7 @@ #ifdef TOOLS_ENABLED #include "core/config/project_settings.h" +#include "editor/editor_import_blend_runner.h" #include "editor/editor_node.h" #include "editor/editor_scene_exporter_gltf_plugin.h" #include "editor/editor_scene_importer_blend.h" @@ -52,6 +53,14 @@ static void _editor_init() { bool blend_enabled = GLOBAL_GET("filesystem/import/blender/enabled"); // Defined here because EditorSettings doesn't exist in `register_gltf_types` yet. + EDITOR_DEF_RST("filesystem/import/blender/rpc_port", 6011); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, + "filesystem/import/blender/rpc_port", PROPERTY_HINT_RANGE, "0,65535,1")); + + EDITOR_DEF_RST("filesystem/import/blender/rpc_server_uptime", 5); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::FLOAT, + "filesystem/import/blender/rpc_server_uptime", PROPERTY_HINT_RANGE, "0,300,1,or_greater,suffix:s")); + String blender3_path = EDITOR_DEF_RST("filesystem/import/blender/blender3_path", ""); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "filesystem/import/blender/blender3_path", PROPERTY_HINT_GLOBAL_DIR)); @@ -71,6 +80,8 @@ static void _editor_init() { EditorFileSystem::get_singleton()->add_import_format_support_query(blend_import_query); } } + memnew(EditorImportBlendRunner); + EditorNode::get_singleton()->add_child(EditorImportBlendRunner::get_singleton()); // FBX to glTF importer. diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs index 8463403096..4610761bdb 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs @@ -7,7 +7,7 @@ namespace Godot /// <summary> /// Instantiates the scene's node hierarchy, erroring on failure. /// Triggers child scene instantiation(s). Triggers a - /// <see cref="Node.NotificationInstanced"/> notification on the root node. + /// <see cref="Node.NotificationSceneInstantiated"/> notification on the root node. /// </summary> /// <seealso cref="InstantiateOrNull{T}(GenEditState)"/> /// <exception cref="InvalidCastException"> @@ -23,7 +23,7 @@ namespace Godot /// <summary> /// Instantiates the scene's node hierarchy, returning <see langword="null"/> on failure. /// Triggers child scene instantiation(s). Triggers a - /// <see cref="Node.NotificationInstanced"/> notification on the root node. + /// <see cref="Node.NotificationSceneInstantiated"/> notification on the root node. /// </summary> /// <seealso cref="Instantiate{T}(GenEditState)"/> /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rid.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rid.cs index 150eb98fc7..350626389b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rid.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rid.cs @@ -6,13 +6,17 @@ using Godot.NativeInterop; namespace Godot { /// <summary> - /// The Rid type is used to access the unique integer ID of a resource. - /// They are opaque, which means they do not grant access to the associated - /// resource by themselves. They are used by and with the low-level Server - /// classes such as <see cref="RenderingServer"/>. + /// The RID type is used to access a low-level resource by its unique ID. + /// RIDs are opaque, which means they do not grant access to the resource + /// by themselves. They are used by the low-level server classes, such as + /// <see cref="DisplayServer"/>, <see cref="RenderingServer"/>, + /// <see cref="TextServer"/>, etc. + /// + /// A low-level resource may correspond to a high-level <see cref="Resource"/>, + /// such as <see cref="Texture"/> or <see cref="Mesh"/> /// </summary> [StructLayout(LayoutKind.Sequential)] - public readonly struct Rid + public readonly struct Rid : IEquatable<Rid> { private readonly ulong _id; // Default is 0 @@ -28,15 +32,73 @@ namespace Godot => _id = from is Resource res ? res.GetRid()._id : default; /// <summary> - /// Returns the ID of the referenced resource. + /// Returns the ID of the referenced low-level resource. /// </summary> /// <returns>The ID of the referenced resource.</returns> public ulong Id => _id; /// <summary> + /// Returns <see langword="true"/> if the <see cref="Rid"/> is not <c>0</c>. + /// </summary> + /// <returns>Whether or not the ID is valid.</returns> + public bool IsValid => _id != 0; + + /// <summary> + /// Returns <see langword="true"/> if both <see cref="Rid"/>s are equal, + /// which means they both refer to the same low-level resource. + /// </summary> + /// <param name="left">The left RID.</param> + /// <param name="right">The right RID.</param> + /// <returns>Whether or not the RIDs are equal.</returns> + public static bool operator ==(Rid left, Rid right) + { + return left.Equals(right); + } + + /// <summary> + /// Returns <see langword="true"/> if the <see cref="Rid"/>s are not equal. + /// </summary> + /// <param name="left">The left RID.</param> + /// <param name="right">The right RID.</param> + /// <returns>Whether or not the RIDs are equal.</returns> + public static bool operator !=(Rid left, Rid right) + { + return !left.Equals(right); + } + + /// <summary> + /// Returns <see langword="true"/> if this RID and <paramref name="obj"/> are equal. + /// </summary> + /// <param name="obj">The other object to compare.</param> + /// <returns>Whether or not the color and the other object are equal.</returns> + public override readonly bool Equals(object obj) + { + return obj is Rid other && Equals(other); + } + + /// <summary> + /// Returns <see langword="true"/> if the RIDs are equal. + /// </summary> + /// <param name="other">The other RID.</param> + /// <returns>Whether or not the RIDs are equal.</returns> + public readonly bool Equals(Rid other) + { + return _id == other.Id; + } + + /// <summary> + /// Serves as the hash function for <see cref="Rid"/>. + /// </summary> + /// <returns>A hash code for this RID.</returns> + public override readonly int GetHashCode() + { + return HashCode.Combine(_id); + } + + /// <summary> /// Converts this <see cref="Rid"/> to a string. /// </summary> /// <returns>A string representation of this Rid.</returns> - public override string ToString() => $"Rid({Id})"; + public override string ToString() => $"RID({Id})"; } } diff --git a/modules/openxr/doc_classes/OpenXRInterface.xml b/modules/openxr/doc_classes/OpenXRInterface.xml index 7251a4a9bd..f3cc469c9d 100644 --- a/modules/openxr/doc_classes/OpenXRInterface.xml +++ b/modules/openxr/doc_classes/OpenXRInterface.xml @@ -11,12 +11,33 @@ <link title="Setting up XR">$DOCS_URL/tutorials/xr/setting_up_xr.html</link> </tutorials> <methods> + <method name="get_action_sets" qualifiers="const"> + <return type="Array" /> + <description> + Returns a list of action sets registered with Godot (loaded from the action map at runtime). + </description> + </method> <method name="get_available_display_refresh_rates" qualifiers="const"> <return type="Array" /> <description> Returns display refresh rates supported by the current HMD. Only returned if this feature is supported by the OpenXR runtime and after the interface has been initialized. </description> </method> + <method name="is_action_set_active" qualifiers="const"> + <return type="bool" /> + <param index="0" name="name" type="String" /> + <description> + Returns [code]true[/code] if the given action set is active. + </description> + </method> + <method name="set_action_set_active"> + <return type="void" /> + <param index="0" name="name" type="String" /> + <param index="1" name="active" type="bool" /> + <description> + Sets the given action set as active or inactive. + </description> + </method> </methods> <members> <member name="display_refresh_rate" type="float" setter="set_display_refresh_rate" getter="get_display_refresh_rate" default="0.0"> diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index f9afdf2d4a..702e56b410 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -47,6 +47,10 @@ void OpenXRInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("set_display_refresh_rate", "refresh_rate"), &OpenXRInterface::set_display_refresh_rate); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "display_refresh_rate"), "set_display_refresh_rate", "get_display_refresh_rate"); + ClassDB::bind_method(D_METHOD("is_action_set_active", "name"), &OpenXRInterface::is_action_set_active); + ClassDB::bind_method(D_METHOD("set_action_set_active", "name", "active"), &OpenXRInterface::set_action_set_active); + ClassDB::bind_method(D_METHOD("get_action_sets"), &OpenXRInterface::get_action_sets); + ClassDB::bind_method(D_METHOD("get_available_display_refresh_rates"), &OpenXRInterface::get_available_display_refresh_rates); } @@ -621,6 +625,38 @@ Array OpenXRInterface::get_available_display_refresh_rates() const { } } +bool OpenXRInterface::is_action_set_active(const String &p_action_set) const { + for (ActionSet *action_set : action_sets) { + if (action_set->action_set_name == p_action_set) { + return action_set->is_active; + } + } + + WARN_PRINT("OpenXR: Unknown action set " + p_action_set); + return false; +} + +void OpenXRInterface::set_action_set_active(const String &p_action_set, bool p_active) { + for (ActionSet *action_set : action_sets) { + if (action_set->action_set_name == p_action_set) { + action_set->is_active = p_active; + return; + } + } + + WARN_PRINT("OpenXR: Unknown action set " + p_action_set); +} + +Array OpenXRInterface::get_action_sets() const { + Array arr; + + for (ActionSet *action_set : action_sets) { + arr.push_back(action_set->action_set_name); + } + + return arr; +} + Size2 OpenXRInterface::get_render_target_size() { if (openxr_api == nullptr) { return Size2(); diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h index 2b43369523..cce329d8e6 100644 --- a/modules/openxr/openxr_interface.h +++ b/modules/openxr/openxr_interface.h @@ -123,6 +123,10 @@ public: void set_display_refresh_rate(float p_refresh_rate); Array get_available_display_refresh_rates() const; + bool is_action_set_active(const String &p_action_set) const; + void set_action_set_active(const String &p_action_set, bool p_active); + Array get_action_sets() const; + virtual Size2 get_render_target_size() override; virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; diff --git a/modules/theora/doc_classes/VideoStreamTheora.xml b/modules/theora/doc_classes/VideoStreamTheora.xml index e07af8f169..3ec762a880 100644 --- a/modules/theora/doc_classes/VideoStreamTheora.xml +++ b/modules/theora/doc_classes/VideoStreamTheora.xml @@ -9,19 +9,4 @@ </description> <tutorials> </tutorials> - <methods> - <method name="get_file"> - <return type="String" /> - <description> - Returns the Ogg Theora video file handled by this [VideoStreamTheora]. - </description> - </method> - <method name="set_file"> - <return type="void" /> - <param index="0" name="file" type="String" /> - <description> - Sets the Ogg Theora video file that this [VideoStreamTheora] resource handles. The [code]file[/code] name should have the [code].ogv[/code] extension. - </description> - </method> - </methods> </class> diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index c600924a3e..b38f7225a2 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -574,25 +574,10 @@ bool VideoStreamPlaybackTheora::is_paused() const { return paused; } -void VideoStreamPlaybackTheora::set_loop(bool p_enable) { -} - -bool VideoStreamPlaybackTheora::has_loop() const { - return false; -} - double VideoStreamPlaybackTheora::get_length() const { return 0; } -String VideoStreamPlaybackTheora::get_stream_name() const { - return ""; -} - -int VideoStreamPlaybackTheora::get_loop_count() const { - return 0; -} - double VideoStreamPlaybackTheora::get_playback_position() const { return get_time(); } @@ -601,11 +586,6 @@ void VideoStreamPlaybackTheora::seek(double p_time) { WARN_PRINT_ONCE("Seeking in Theora videos is not implemented yet (it's only supported for GDExtension-provided video streams)."); } -void VideoStreamPlaybackTheora::set_mix_callback(AudioMixCallback p_callback, void *p_userdata) { - mix_callback = p_callback; - mix_udata = p_userdata; -} - int VideoStreamPlaybackTheora::get_channels() const { return vi.channels; } @@ -657,16 +637,9 @@ VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() { memdelete(thread_sem); #endif clear(); -} - -void VideoStreamTheora::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_file", "file"), &VideoStreamTheora::set_file); - ClassDB::bind_method(D_METHOD("get_file"), &VideoStreamTheora::get_file); - - ADD_PROPERTY(PropertyInfo(Variant::STRING, "file", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_file", "get_file"); -} +}; -//////////// +void VideoStreamTheora::_bind_methods() {} Ref<Resource> ResourceFormatLoaderTheora::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) { Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h index f047440df7..32adc28a88 100644 --- a/modules/theora/video_stream_theora.h +++ b/modules/theora/video_stream_theora.h @@ -99,8 +99,6 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback { Ref<ImageTexture> texture; - AudioMixCallback mix_callback = nullptr; - void *mix_udata = nullptr; bool paused = false; #ifdef THEORA_USE_THREAD_STREAMING @@ -133,15 +131,8 @@ public: virtual void set_paused(bool p_paused) override; virtual bool is_paused() const override; - virtual void set_loop(bool p_enable) override; - virtual bool has_loop() const override; - virtual double get_length() const override; - virtual String get_stream_name() const; - - virtual int get_loop_count() const; - virtual double get_playback_position() const override; virtual void seek(double p_time) override; @@ -150,7 +141,6 @@ public: virtual Ref<Texture2D> get_texture() const override; virtual void update(double p_delta) override; - virtual void set_mix_callback(AudioMixCallback p_callback, void *p_userdata) override; virtual int get_channels() const override; virtual int get_mix_rate() const override; @@ -163,9 +153,6 @@ public: class VideoStreamTheora : public VideoStream { GDCLASS(VideoStreamTheora, VideoStream); - String file; - int audio_track; - protected: static void _bind_methods(); @@ -177,8 +164,6 @@ public: return pb; } - void set_file(const String &p_file) { file = p_file; } - String get_file() { return file; } void set_audio_track(int p_track) override { audio_track = p_track; } VideoStreamTheora() { audio_track = 0; } diff --git a/modules/webrtc/webrtc_multiplayer_peer.cpp b/modules/webrtc/webrtc_multiplayer_peer.cpp index 36d0b41889..9224760c5b 100644 --- a/modules/webrtc/webrtc_multiplayer_peer.cpp +++ b/modules/webrtc/webrtc_multiplayer_peer.cpp @@ -128,7 +128,6 @@ void WebRTCMultiplayerPeer::poll() { // Server connected. connection_status = CONNECTION_CONNECTED; emit_signal(SNAME("peer_connected"), TARGET_PEER_SERVER); - emit_signal(SNAME("connection_succeeded")); } else { emit_signal(SNAME("peer_connected"), E); } diff --git a/modules/websocket/websocket_multiplayer_peer.cpp b/modules/websocket/websocket_multiplayer_peer.cpp index 389d8c56ad..c12fc5e834 100644 --- a/modules/websocket/websocket_multiplayer_peer.cpp +++ b/modules/websocket/websocket_multiplayer_peer.cpp @@ -237,7 +237,6 @@ void WebSocketMultiplayerPeer::_poll_client() { } connection_status = CONNECTION_CONNECTED; emit_signal("peer_connected", 1); - emit_signal("connection_succeeded"); } else { return; // Still waiting for an ID. } diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 9ebb8aa102..0902be9595 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -1027,6 +1027,10 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p encode_uint32(is_resizeable, &p_manifest.write[iofs + 16]); } + if (tname == "provider" && attrname == "authorities") { + string_table.write[attr_value] = get_package_name(package_name) + String(".fileprovider"); + } + if (tname == "supports-screens") { if (attrname == "smallScreens") { encode_uint32(screen_support_small ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml index 1f77e2fc34..f03a1dd47a 100644 --- a/platform/android/java/lib/AndroidManifest.xml +++ b/platform/android/java/lib/AndroidManifest.xml @@ -20,6 +20,16 @@ android:exported="false" /> + <provider + android:name="androidx.core.content.FileProvider" + android:authorities="${applicationId}.fileprovider" + android:exported="false" + android:grantUriPermissions="true"> + <meta-data + android:name="android.support.FILE_PROVIDER_PATHS" + android:resource="@xml/godot_provider_paths" /> + </provider> + </application> </manifest> diff --git a/platform/android/java/lib/res/xml/godot_provider_paths.xml b/platform/android/java/lib/res/xml/godot_provider_paths.xml new file mode 100644 index 0000000000..1255f576bf --- /dev/null +++ b/platform/android/java/lib/res/xml/godot_provider_paths.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<paths xmlns:android="http://schemas.android.com/apk/res/android"> + + <external-path + name="public" + path="." /> + + <external-files-path + name="app" + path="." /> +</paths> diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java index 41d06a6458..edcd9c4d1f 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -49,6 +49,9 @@ import android.view.Display; import android.view.DisplayCutout; import android.view.WindowInsets; +import androidx.core.content.FileProvider; + +import java.io.File; import java.util.List; import java.util.Locale; @@ -84,29 +87,42 @@ public class GodotIO { // MISCELLANEOUS OS IO ///////////////////////// - public int openURI(String p_uri) { + public int openURI(String uriString) { try { - String path = p_uri; - String type = ""; - if (path.startsWith("/")) { - //absolute path to filesystem, prepend file:// - path = "file://" + path; - if (p_uri.endsWith(".png") || p_uri.endsWith(".jpg") || p_uri.endsWith(".gif") || p_uri.endsWith(".webp")) { - type = "image/*"; + Uri dataUri; + String dataType = ""; + boolean grantReadUriPermission = false; + + if (uriString.startsWith("/") || uriString.startsWith("file://")) { + String filePath = uriString; + // File uris needs to be provided via the FileProvider + grantReadUriPermission = true; + if (filePath.startsWith("file://")) { + filePath = filePath.replace("file://", ""); } + + File targetFile = new File(filePath); + dataUri = FileProvider.getUriForFile(activity, activity.getPackageName() + ".fileprovider", targetFile); + dataType = activity.getContentResolver().getType(dataUri); + } else { + dataUri = Uri.parse(uriString); } Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); - if (!type.equals("")) { - intent.setDataAndType(Uri.parse(path), type); + if (TextUtils.isEmpty(dataType)) { + intent.setData(dataUri); } else { - intent.setData(Uri.parse(path)); + intent.setDataAndType(dataUri, dataType); + } + if (grantReadUriPermission) { + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } activity.startActivity(intent); return 0; } catch (ActivityNotFoundException e) { + Log.e(TAG, "Unable to open uri " + uriString, e); return 1; } } diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index c09da2f7b3..8377e81a53 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -3672,8 +3672,23 @@ Rect2i DisplayServerX11::window_get_popup_safe_rect(WindowID p_window) const { void DisplayServerX11::popup_open(WindowID p_window) { _THREAD_SAFE_METHOD_ + bool has_popup_ancestor = false; + WindowID transient_root = p_window; + while (true) { + WindowID parent = windows[transient_root].transient_parent; + if (parent == INVALID_WINDOW_ID) { + break; + } else { + transient_root = parent; + if (windows[parent].is_popup) { + has_popup_ancestor = true; + break; + } + } + } + WindowData &wd = windows[p_window]; - if (wd.is_popup) { + if (wd.is_popup || has_popup_ancestor) { // Find current popup parent, or root popup if new window is not transient. List<WindowID>::Element *C = nullptr; List<WindowID>::Element *E = popup_list.back(); @@ -4897,7 +4912,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V // handling decorations and placement. // On the other hand, focus changes need to be handled manually when this is set. // - save_under is a hint for the WM to keep the content of windows behind to avoid repaint. - if (wd.is_popup || wd.no_focus) { + if (wd.no_focus) { windowAttributes.override_redirect = True; windowAttributes.save_under = True; valuemask |= CWOverrideRedirect | CWSaveUnder; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 2832495693..b1880c2fb6 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -3681,8 +3681,23 @@ Rect2i DisplayServerMacOS::window_get_popup_safe_rect(WindowID p_window) const { void DisplayServerMacOS::popup_open(WindowID p_window) { _THREAD_SAFE_METHOD_ + bool has_popup_ancestor = false; + WindowID transient_root = p_window; + while (true) { + WindowID parent = windows[transient_root].transient_parent; + if (parent == INVALID_WINDOW_ID) { + break; + } else { + transient_root = parent; + if (windows[parent].is_popup) { + has_popup_ancestor = true; + break; + } + } + } + WindowData &wd = windows[p_window]; - if (wd.is_popup) { + if (wd.is_popup || has_popup_ancestor) { bool was_empty = popup_list.is_empty(); // Find current popup parent, or root popup if new window is not transient. List<WindowID>::Element *C = nullptr; diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index ebd0733c55..777d05584c 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -991,15 +991,6 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - wsize.height / 3); window_set_position(wpos, p_window); } - - // Don't let the mouse leave the window when resizing to a smaller resolution. - if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { - RECT crect; - GetClientRect(wd.hWnd, &crect); - ClientToScreen(wd.hWnd, (POINT *)&crect.left); - ClientToScreen(wd.hWnd, (POINT *)&crect.right); - ClipCursor(&crect); - } } Point2i DisplayServerWindows::window_get_position(WindowID p_window) const { @@ -1077,15 +1068,6 @@ void DisplayServerWindows::window_set_position(const Point2i &p_position, Window AdjustWindowRectEx(&rc, style, false, exStyle); MoveWindow(wd.hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); - // Don't let the mouse leave the window when moved. - if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { - RECT rect; - GetClientRect(wd.hWnd, &rect); - ClientToScreen(wd.hWnd, (POINT *)&rect.left); - ClientToScreen(wd.hWnd, (POINT *)&rect.right); - ClipCursor(&rect); - } - wd.last_pos = p_position; _update_real_mouse_position(p_window); } @@ -1227,15 +1209,6 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo } MoveWindow(wd.hWnd, rect.left, rect.top, w, h, TRUE); - - // Don't let the mouse leave the window when resizing to a smaller resolution. - if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { - RECT crect; - GetClientRect(wd.hWnd, &crect); - ClientToScreen(wd.hWnd, (POINT *)&crect.left); - ClientToScreen(wd.hWnd, (POINT *)&crect.right); - ClipCursor(&crect); - } } Size2i DisplayServerWindows::window_get_size(WindowID p_window) const { @@ -1423,15 +1396,6 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window) SystemParametersInfoA(SPI_SETMOUSETRAILS, 0, 0, 0); } } - - // Don't let the mouse leave the window when resizing to a smaller resolution. - if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { - RECT crect; - GetClientRect(wd.hWnd, &crect); - ClientToScreen(wd.hWnd, (POINT *)&crect.left); - ClientToScreen(wd.hWnd, (POINT *)&crect.right); - ClipCursor(&crect); - } } DisplayServer::WindowMode DisplayServerWindows::window_get_mode(WindowID p_window) const { @@ -2396,8 +2360,23 @@ Rect2i DisplayServerWindows::window_get_popup_safe_rect(WindowID p_window) const void DisplayServerWindows::popup_open(WindowID p_window) { _THREAD_SAFE_METHOD_ - const WindowData &wd = windows[p_window]; - if (wd.is_popup) { + bool has_popup_ancestor = false; + WindowID transient_root = p_window; + while (true) { + WindowID parent = windows[transient_root].transient_parent; + if (parent == INVALID_WINDOW_ID) { + break; + } else { + transient_root = parent; + if (windows[parent].is_popup) { + has_popup_ancestor = true; + break; + } + } + } + + WindowData &wd = windows[p_window]; + if (wd.is_popup || has_popup_ancestor) { // Find current popup parent, or root popup if new window is not transient. List<WindowID>::Element *C = nullptr; List<WindowID>::Element *E = popup_list.back(); @@ -3381,6 +3360,15 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA Callable::CallError ce; window.rect_changed_callback.callp(args, 1, ret, ce); } + + // Update cursor clip region after window rect has changed. + if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { + RECT crect; + GetClientRect(window.hWnd, &crect); + ClientToScreen(window.hWnd, (POINT *)&crect.left); + ClientToScreen(window.hWnd, (POINT *)&crect.right); + ClipCursor(&crect); + } } // Return here to prevent WM_MOVE and WM_SIZE from being sent diff --git a/platform/windows/gl_manager_windows.h b/platform/windows/gl_manager_windows.h index b97d0f667c..361c559a5a 100644 --- a/platform/windows/gl_manager_windows.h +++ b/platform/windows/gl_manager_windows.h @@ -74,7 +74,6 @@ private: GLWindow *_current_window = nullptr; PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr; - PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = nullptr; // funcs void _internal_set_current_window(GLWindow *p_win); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 08299d9b98..d384049fb5 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -830,7 +830,7 @@ class FallbackTextAnalysisSource : public IDWriteTextAnalysisSource { IDWriteNumberSubstitution *n_sub = nullptr; public: - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface) { + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface) override { if (IID_IUnknown == riid) { AddRef(); *ppvInterface = (IUnknown *)this; @@ -844,11 +844,11 @@ public: return S_OK; } - ULONG STDMETHODCALLTYPE AddRef() { + ULONG STDMETHODCALLTYPE AddRef() override { return InterlockedIncrement(&_cRef); } - ULONG STDMETHODCALLTYPE Release() { + ULONG STDMETHODCALLTYPE Release() override { ULONG ulRef = InterlockedDecrement(&_cRef); if (0 == ulRef) { delete this; diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 2dcf7c3a11..a37fabf21f 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -51,13 +51,13 @@ bool Area2D::is_gravity_a_point() const { return gravity_is_point; } -void Area2D::set_gravity_point_distance_scale(real_t p_scale) { - gravity_distance_scale = p_scale; - PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale); +void Area2D::set_gravity_point_unit_distance(real_t p_scale) { + gravity_point_unit_distance = p_scale; + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE, p_scale); } -real_t Area2D::get_gravity_point_distance_scale() const { - return gravity_distance_scale; +real_t Area2D::get_gravity_point_unit_distance() const { + return gravity_point_unit_distance; } void Area2D::set_gravity_point_center(const Vector2 &p_center) { @@ -557,8 +557,8 @@ void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_gravity_is_point", "enable"), &Area2D::set_gravity_is_point); ClassDB::bind_method(D_METHOD("is_gravity_a_point"), &Area2D::is_gravity_a_point); - ClassDB::bind_method(D_METHOD("set_gravity_point_distance_scale", "distance_scale"), &Area2D::set_gravity_point_distance_scale); - ClassDB::bind_method(D_METHOD("get_gravity_point_distance_scale"), &Area2D::get_gravity_point_distance_scale); + ClassDB::bind_method(D_METHOD("set_gravity_point_unit_distance", "distance_scale"), &Area2D::set_gravity_point_unit_distance); + ClassDB::bind_method(D_METHOD("get_gravity_point_unit_distance"), &Area2D::get_gravity_point_unit_distance); ClassDB::bind_method(D_METHOD("set_gravity_point_center", "center"), &Area2D::set_gravity_point_center); ClassDB::bind_method(D_METHOD("get_gravity_point_center"), &Area2D::get_gravity_point_center); @@ -622,7 +622,7 @@ void Area2D::_bind_methods() { ADD_GROUP("Gravity", "gravity_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_space_override_mode", "get_gravity_space_override_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_is_point", "is_gravity_a_point"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_point_distance_scale", "get_gravity_point_distance_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_unit_distance", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp,suffix:px"), "set_gravity_point_unit_distance", "get_gravity_point_unit_distance"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_point_center", PROPERTY_HINT_NONE, "suffix:px"), "set_gravity_point_center", "get_gravity_point_center"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity_direction"), "set_gravity_direction", "get_gravity_direction"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, U"-4096,4096,0.001,or_less,or_greater,suffix:px/s\u00B2"), "set_gravity", "get_gravity"); diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index aaf7ea28f8..8f4bbe3219 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -51,7 +51,7 @@ private: Vector2 gravity_vec; real_t gravity = 0.0; bool gravity_is_point = false; - real_t gravity_distance_scale = 0.0; + real_t gravity_point_unit_distance = 0.0; SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED; SpaceOverride angular_damp_space_override = SPACE_OVERRIDE_DISABLED; @@ -144,8 +144,8 @@ public: void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; - void set_gravity_point_distance_scale(real_t p_scale); - real_t get_gravity_point_distance_scale() const; + void set_gravity_point_unit_distance(real_t p_scale); + real_t get_gravity_point_unit_distance() const; void set_gravity_point_center(const Vector2 &p_center); const Vector2 &get_gravity_point_center() const; diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 71b8fdb539..49c5501e77 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -50,7 +50,7 @@ void Camera2D::_update_scroll() { return; } - if (current) { + if (is_current()) { ERR_FAIL_COND(custom_viewport && !ObjectDB::get_instance(custom_viewport_id)); Transform2D xform = get_camera_transform(); @@ -241,10 +241,6 @@ void Camera2D::_notification(int p_what) { viewport = get_viewport(); } - if (is_current()) { - viewport->_camera_2d_set(this); - } - canvas = get_canvas(); RID vp = viewport->get_viewport_rid(); @@ -254,6 +250,10 @@ void Camera2D::_notification(int p_what) { add_to_group(group_name); add_to_group(canvas_group_name); + if (enabled && !viewport->get_camera_2d()) { + make_current(); + } + _update_process_callback(); first = true; _update_scroll(); @@ -261,11 +261,7 @@ void Camera2D::_notification(int p_what) { case NOTIFICATION_EXIT_TREE: { if (is_current()) { - if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) { - viewport->set_canvas_transform(Transform2D()); - clear_current(); - current = true; - } + clear_current(); } remove_from_group(group_name); remove_from_group(canvas_group_name); @@ -397,19 +393,31 @@ void Camera2D::set_process_callback(Camera2DProcessCallback p_mode) { _update_process_callback(); } +void Camera2D::set_enabled(bool p_enabled) { + enabled = p_enabled; + + if (enabled && is_inside_tree() && !viewport->get_camera_2d()) { + make_current(); + } else if (!enabled && is_current()) { + clear_current(); + } +} + +bool Camera2D::is_enabled() const { + return enabled; +} + Camera2D::Camera2DProcessCallback Camera2D::get_process_callback() const { return process_callback; } void Camera2D::_make_current(Object *p_which) { if (p_which == this) { - current = true; if (is_inside_tree()) { get_viewport()->_camera_2d_set(this); queue_redraw(); } } else { - current = false; if (is_inside_tree()) { if (get_viewport()->get_camera_2d() == this) { get_viewport()->_camera_2d_set(nullptr); @@ -419,43 +427,32 @@ void Camera2D::_make_current(Object *p_which) { } } -void Camera2D::set_current(bool p_current) { - if (p_current) { - make_current(); - } else { - if (current) { - clear_current(); - } - } -} - void Camera2D::_update_process_internal_for_smoothing() { bool is_not_in_scene_or_editor = !(is_inside_tree() && Engine::get_singleton()->is_editor_hint()); bool is_any_smoothing_valid = position_smoothing_speed > 0 || rotation_smoothing_speed > 0; - bool enabled = is_any_smoothing_valid && is_not_in_scene_or_editor; - set_process_internal(enabled); -} - -bool Camera2D::is_current() const { - return current; + bool enable = is_any_smoothing_valid && is_not_in_scene_or_editor; + set_process_internal(enable); } void Camera2D::make_current() { - if (is_inside_tree()) { - get_tree()->call_group(group_name, "_make_current", this); - } else { - current = true; - } + ERR_FAIL_COND(!enabled || !is_inside_tree()); + get_tree()->call_group(group_name, "_make_current", this); _update_scroll(); } void Camera2D::clear_current() { - if (is_inside_tree()) { - get_tree()->call_group(group_name, "_make_current", (Object *)nullptr); - } else { - current = false; + ERR_FAIL_COND(!is_current()); + if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) { + viewport->assign_next_enabled_camera_2d(group_name); + } +} + +bool Camera2D::is_current() const { + if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) { + return viewport->get_camera_2d() == this; } + return false; } void Camera2D::set_limit(Side p_side, int p_limit) { @@ -715,7 +712,10 @@ void Camera2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_process_callback", "mode"), &Camera2D::set_process_callback); ClassDB::bind_method(D_METHOD("get_process_callback"), &Camera2D::get_process_callback); - ClassDB::bind_method(D_METHOD("set_current", "current"), &Camera2D::set_current); + ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &Camera2D::set_enabled); + ClassDB::bind_method(D_METHOD("is_enabled"), &Camera2D::is_enabled); + + ClassDB::bind_method(D_METHOD("make_current"), &Camera2D::make_current); ClassDB::bind_method(D_METHOD("is_current"), &Camera2D::is_current); ClassDB::bind_method(D_METHOD("_make_current"), &Camera2D::_make_current); @@ -779,7 +779,7 @@ void Camera2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset"); ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_mode", PROPERTY_HINT_ENUM, "Fixed TopLeft,Drag Center"), "set_anchor_mode", "get_anchor_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_rotation"), "set_ignore_rotation", "is_ignoring_rotation"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom", PROPERTY_HINT_LINK), "set_zoom", "get_zoom"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", PROPERTY_USAGE_NONE), "set_custom_viewport", "get_custom_viewport"); ADD_PROPERTY(PropertyInfo(Variant::INT, "process_callback", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_callback", "get_process_callback"); diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h index 304b4ceaa6..7a77266db8 100644 --- a/scene/2d/camera_2d.h +++ b/scene/2d/camera_2d.h @@ -64,7 +64,7 @@ protected: Vector2 zoom_scale = Vector2(1, 1); AnchorMode anchor_mode = ANCHOR_MODE_DRAG_CENTER; bool ignore_rotation = true; - bool current = false; + bool enabled = true; real_t position_smoothing_speed = 5.0; bool follow_smoothing_enabled = false; @@ -88,7 +88,6 @@ protected: void _update_scroll(); void _make_current(Object *p_which); - void set_current(bool p_current); void _set_old_smoothing(real_t p_enable); @@ -155,6 +154,9 @@ public: void set_process_callback(Camera2DProcessCallback p_mode); Camera2DProcessCallback get_process_callback() const; + void set_enabled(bool p_enabled); + bool is_enabled() const; + void make_current(); void clear_current(); bool is_current() const; diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index e73b6e7e23..380a684c9b 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -108,6 +108,26 @@ void NavigationAgent2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10,0.01,suffix:s"), "set_time_horizon", "get_time_horizon"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:px/s"), "set_max_speed", "get_max_speed"); +#ifdef DEBUG_ENABLED + ClassDB::bind_method(D_METHOD("set_debug_enabled", "enabled"), &NavigationAgent2D::set_debug_enabled); + ClassDB::bind_method(D_METHOD("get_debug_enabled"), &NavigationAgent2D::get_debug_enabled); + ClassDB::bind_method(D_METHOD("set_debug_use_custom", "enabled"), &NavigationAgent2D::set_debug_use_custom); + ClassDB::bind_method(D_METHOD("get_debug_use_custom"), &NavigationAgent2D::get_debug_use_custom); + ClassDB::bind_method(D_METHOD("set_debug_path_custom_color", "color"), &NavigationAgent2D::set_debug_path_custom_color); + ClassDB::bind_method(D_METHOD("get_debug_path_custom_color"), &NavigationAgent2D::get_debug_path_custom_color); + ClassDB::bind_method(D_METHOD("set_debug_path_custom_point_size", "point_size"), &NavigationAgent2D::set_debug_path_custom_point_size); + ClassDB::bind_method(D_METHOD("get_debug_path_custom_point_size"), &NavigationAgent2D::get_debug_path_custom_point_size); + ClassDB::bind_method(D_METHOD("set_debug_path_custom_line_width", "line_width"), &NavigationAgent2D::set_debug_path_custom_line_width); + ClassDB::bind_method(D_METHOD("get_debug_path_custom_line_width"), &NavigationAgent2D::get_debug_path_custom_line_width); + + ADD_GROUP("Debug", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_enabled"), "set_debug_enabled", "get_debug_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_use_custom"), "set_debug_use_custom", "get_debug_use_custom"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_path_custom_color"), "set_debug_path_custom_color", "get_debug_path_custom_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "debug_path_custom_point_size", PROPERTY_HINT_RANGE, "1,50,1,suffix:px"), "set_debug_path_custom_point_size", "get_debug_path_custom_point_size"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "debug_path_custom_line_width", PROPERTY_HINT_RANGE, "1,50,1,suffix:px"), "set_debug_path_custom_line_width", "get_debug_path_custom_line_width"); +#endif // DEBUG_ENABLED + ADD_SIGNAL(MethodInfo("path_changed")); ADD_SIGNAL(MethodInfo("target_reached")); ADD_SIGNAL(MethodInfo("waypoint_reached", PropertyInfo(Variant::DICTIONARY, "details"))); @@ -123,6 +143,12 @@ void NavigationAgent2D::_notification(int p_what) { // cannot use READY as ready does not get called if Node is readded to SceneTree set_agent_parent(get_parent()); set_physics_process_internal(true); + +#ifdef DEBUG_ENABLED + if (NavigationServer2D::get_singleton()->get_debug_enabled()) { + debug_path_dirty = true; + } +#endif // DEBUG_ENABLED } break; case NOTIFICATION_PARENTED: { @@ -165,6 +191,12 @@ void NavigationAgent2D::_notification(int p_what) { case NOTIFICATION_EXIT_TREE: { agent_parent = nullptr; set_physics_process_internal(false); + +#ifdef DEBUG_ENABLED + if (debug_path_instance.is_valid()) { + RenderingServer::get_singleton()->canvas_item_set_visible(debug_path_instance, false); + } +#endif // DEBUG_ENABLED } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { @@ -176,6 +208,12 @@ void NavigationAgent2D::_notification(int p_what) { } _check_distance_to_target(); } + +#ifdef DEBUG_ENABLED + if (debug_path_dirty) { + _update_debug_path(); + } +#endif // DEBUG_ENABLED } break; } } @@ -194,12 +232,25 @@ NavigationAgent2D::NavigationAgent2D() { navigation_result = Ref<NavigationPathQueryResult2D>(); navigation_result.instantiate(); + +#ifdef DEBUG_ENABLED + NavigationServer2D::get_singleton()->connect(SNAME("navigation_debug_changed"), callable_mp(this, &NavigationAgent2D::_navigation_debug_changed)); +#endif // DEBUG_ENABLED } NavigationAgent2D::~NavigationAgent2D() { ERR_FAIL_NULL(NavigationServer2D::get_singleton()); NavigationServer2D::get_singleton()->free(agent); agent = RID(); // Pointless + +#ifdef DEBUG_ENABLED + NavigationServer2D::get_singleton()->disconnect(SNAME("navigation_debug_changed"), callable_mp(this, &NavigationAgent2D::_navigation_debug_changed)); + + ERR_FAIL_NULL(RenderingServer::get_singleton()); + if (debug_path_instance.is_valid()) { + RenderingServer::get_singleton()->free(debug_path_instance); + } +#endif // DEBUG_ENABLED } void NavigationAgent2D::set_avoidance_enabled(bool p_enabled) { @@ -463,6 +514,9 @@ void NavigationAgent2D::update_navigation() { } NavigationServer2D::get_singleton()->query_path(navigation_query, navigation_result); +#ifdef DEBUG_ENABLED + debug_path_dirty = true; +#endif // DEBUG_ENABLED navigation_finished = false; navigation_path_index = 0; emit_signal(SNAME("path_changed")); @@ -549,3 +603,111 @@ void NavigationAgent2D::_check_distance_to_target() { } } } + +////////DEBUG//////////////////////////////////////////////////////////// + +#ifdef DEBUG_ENABLED +void NavigationAgent2D::set_debug_enabled(bool p_enabled) { + debug_enabled = p_enabled; + debug_path_dirty = true; +} + +bool NavigationAgent2D::get_debug_enabled() const { + return debug_enabled; +} + +void NavigationAgent2D::set_debug_use_custom(bool p_enabled) { + debug_use_custom = p_enabled; + debug_path_dirty = true; +} + +bool NavigationAgent2D::get_debug_use_custom() const { + return debug_use_custom; +} + +void NavigationAgent2D::set_debug_path_custom_color(Color p_color) { + debug_path_custom_color = p_color; + debug_path_dirty = true; +} + +Color NavigationAgent2D::get_debug_path_custom_color() const { + return debug_path_custom_color; +} + +void NavigationAgent2D::set_debug_path_custom_point_size(float p_point_size) { + debug_path_custom_point_size = MAX(0.1, p_point_size); + debug_path_dirty = true; +} + +float NavigationAgent2D::get_debug_path_custom_point_size() const { + return debug_path_custom_point_size; +} + +void NavigationAgent2D::set_debug_path_custom_line_width(float p_line_width) { + debug_path_custom_line_width = p_line_width; + debug_path_dirty = true; +} + +float NavigationAgent2D::get_debug_path_custom_line_width() const { + return debug_path_custom_line_width; +} + +void NavigationAgent2D::_navigation_debug_changed() { + debug_path_dirty = true; +} + +void NavigationAgent2D::_update_debug_path() { + if (!debug_path_dirty) { + return; + } + debug_path_dirty = false; + + if (!debug_path_instance.is_valid()) { + debug_path_instance = RenderingServer::get_singleton()->canvas_item_create(); + } + + RenderingServer::get_singleton()->canvas_item_clear(debug_path_instance); + + if (!(debug_enabled && NavigationServer2D::get_singleton()->get_debug_navigation_enable_agent_paths())) { + return; + } + + if (!(agent_parent && agent_parent->is_inside_tree())) { + return; + } + + RenderingServer::get_singleton()->canvas_item_set_parent(debug_path_instance, agent_parent->get_canvas()); + RenderingServer::get_singleton()->canvas_item_set_visible(debug_path_instance, agent_parent->is_visible_in_tree()); + + const Vector<Vector2> &navigation_path = navigation_result->get_path(); + + if (navigation_path.size() <= 1) { + return; + } + + Color debug_path_color = NavigationServer2D::get_singleton()->get_debug_navigation_agent_path_color(); + if (debug_use_custom) { + debug_path_color = debug_path_custom_color; + } + + Vector<Color> debug_path_colors; + debug_path_colors.resize(navigation_path.size()); + debug_path_colors.fill(debug_path_color); + + RenderingServer::get_singleton()->canvas_item_add_polyline(debug_path_instance, navigation_path, debug_path_colors, debug_path_custom_line_width, false); + + float point_size = NavigationServer2D::get_singleton()->get_debug_navigation_agent_path_point_size(); + float half_point_size = point_size * 0.5; + + if (debug_use_custom) { + point_size = debug_path_custom_point_size; + half_point_size = debug_path_custom_point_size * 0.5; + } + + for (int i = 0; i < navigation_path.size(); i++) { + const Vector2 &vert = navigation_path[i]; + Rect2 path_point_rect = Rect2(vert.x - half_point_size, vert.y - half_point_size, point_size, point_size); + RenderingServer::get_singleton()->canvas_item_add_rect(debug_path_instance, path_point_rect, debug_path_color); + } +} +#endif // DEBUG_ENABLED diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h index 9787bb1bdb..8f4a373327 100644 --- a/scene/2d/navigation_agent_2d.h +++ b/scene/2d/navigation_agent_2d.h @@ -74,6 +74,20 @@ class NavigationAgent2D : public Node { // No initialized on purpose uint32_t update_frame_id = 0; +#ifdef DEBUG_ENABLED + bool debug_enabled = false; + bool debug_path_dirty = true; + RID debug_path_instance; + float debug_path_custom_point_size = 4.0; + float debug_path_custom_line_width = 1.0; + bool debug_use_custom = false; + Color debug_path_custom_color = Color(1.0, 1.0, 1.0, 1.0); + +private: + void _navigation_debug_changed(); + void _update_debug_path(); +#endif // DEBUG_ENABLED + protected: static void _bind_methods(); void _notification(int p_what); @@ -169,6 +183,23 @@ public: PackedStringArray get_configuration_warnings() const override; +#ifdef DEBUG_ENABLED + void set_debug_enabled(bool p_enabled); + bool get_debug_enabled() const; + + void set_debug_use_custom(bool p_enabled); + bool get_debug_use_custom() const; + + void set_debug_path_custom_color(Color p_color); + Color get_debug_path_custom_color() const; + + void set_debug_path_custom_point_size(float p_point_size); + float get_debug_path_custom_point_size() const; + + void set_debug_path_custom_line_width(float p_line_width); + float get_debug_path_custom_line_width() const; +#endif // DEBUG_ENABLED + private: void update_navigation(); void _request_repath(); diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index 72f186c676..5901e38bb4 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -51,13 +51,13 @@ bool Area3D::is_gravity_a_point() const { return gravity_is_point; } -void Area3D::set_gravity_point_distance_scale(real_t p_scale) { - gravity_distance_scale = p_scale; - PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale); +void Area3D::set_gravity_point_unit_distance(real_t p_scale) { + gravity_point_unit_distance = p_scale; + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE, p_scale); } -real_t Area3D::get_gravity_point_distance_scale() const { - return gravity_distance_scale; +real_t Area3D::get_gravity_point_unit_distance() const { + return gravity_point_unit_distance; } void Area3D::set_gravity_point_center(const Vector3 &p_center) { @@ -655,8 +655,8 @@ void Area3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_gravity_is_point", "enable"), &Area3D::set_gravity_is_point); ClassDB::bind_method(D_METHOD("is_gravity_a_point"), &Area3D::is_gravity_a_point); - ClassDB::bind_method(D_METHOD("set_gravity_point_distance_scale", "distance_scale"), &Area3D::set_gravity_point_distance_scale); - ClassDB::bind_method(D_METHOD("get_gravity_point_distance_scale"), &Area3D::get_gravity_point_distance_scale); + ClassDB::bind_method(D_METHOD("set_gravity_point_unit_distance", "distance_scale"), &Area3D::set_gravity_point_unit_distance); + ClassDB::bind_method(D_METHOD("get_gravity_point_unit_distance"), &Area3D::get_gravity_point_unit_distance); ClassDB::bind_method(D_METHOD("set_gravity_point_center", "center"), &Area3D::set_gravity_point_center); ClassDB::bind_method(D_METHOD("get_gravity_point_center"), &Area3D::get_gravity_point_center); @@ -741,7 +741,7 @@ void Area3D::_bind_methods() { ADD_GROUP("Gravity", "gravity_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gravity_space_override", PROPERTY_HINT_ENUM, "Disabled,Combine,Combine-Replace,Replace,Replace-Combine", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_space_override_mode", "get_gravity_space_override_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gravity_point", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_gravity_is_point", "is_gravity_a_point"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_distance_scale", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp"), "set_gravity_point_distance_scale", "get_gravity_point_distance_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_point_unit_distance", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,exp,suffix:m"), "set_gravity_point_unit_distance", "get_gravity_point_unit_distance"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_point_center", PROPERTY_HINT_NONE, "suffix:m"), "set_gravity_point_center", "get_gravity_point_center"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_direction"), "set_gravity_direction", "get_gravity_direction"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, U"-32,32,0.001,or_less,or_greater,suffix:m/s\u00B2"), "set_gravity", "get_gravity"); diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h index 91b91f741a..607e0d2af8 100644 --- a/scene/3d/area_3d.h +++ b/scene/3d/area_3d.h @@ -51,7 +51,7 @@ private: Vector3 gravity_vec; real_t gravity = 0.0; bool gravity_is_point = false; - real_t gravity_distance_scale = 0.0; + real_t gravity_point_unit_distance = 0.0; SpaceOverride linear_damp_space_override = SPACE_OVERRIDE_DISABLED; SpaceOverride angular_damp_space_override = SPACE_OVERRIDE_DISABLED; @@ -155,8 +155,8 @@ public: void set_gravity_is_point(bool p_enabled); bool is_gravity_a_point() const; - void set_gravity_point_distance_scale(real_t p_scale); - real_t get_gravity_point_distance_scale() const; + void set_gravity_point_unit_distance(real_t p_scale); + real_t get_gravity_point_unit_distance() const; void set_gravity_point_center(const Vector3 &p_center); const Vector3 &get_gravity_point_center() const; diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp index fe7f6837f0..ba5ff02862 100644 --- a/scene/3d/bone_attachment_3d.cpp +++ b/scene/3d/bone_attachment_3d.cpp @@ -81,11 +81,6 @@ bool BoneAttachment3D::_get(const StringName &p_path, Variant &r_ret) const { } void BoneAttachment3D::_get_property_list(List<PropertyInfo> *p_list) const { - p_list->push_back(PropertyInfo(Variant::BOOL, "override_pose", PROPERTY_HINT_NONE, "")); - if (override_pose) { - p_list->push_back(PropertyInfo(Variant::INT, "override_mode", PROPERTY_HINT_ENUM, "Global Pose Override,Local Pose Override,Custom Pose")); - } - p_list->push_back(PropertyInfo(Variant::BOOL, "use_external_skeleton", PROPERTY_HINT_NONE, "")); if (use_external_skeleton) { p_list->push_back(PropertyInfo(Variant::NODE_PATH, "external_skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton3D")); diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp index fbcb1c8f2c..e122adcc8c 100644 --- a/scene/3d/decal.cpp +++ b/scene/3d/decal.cpp @@ -30,14 +30,14 @@ #include "decal.h" -void Decal::set_extents(const Vector3 &p_extents) { - extents = p_extents; - RS::get_singleton()->decal_set_extents(decal, p_extents); +void Decal::set_size(const Vector3 &p_size) { + size = p_size; + RS::get_singleton()->decal_set_size(decal, p_size); update_gizmos(); } -Vector3 Decal::get_extents() const { - return extents; +Vector3 Decal::get_size() const { + return size; } void Decal::set_texture(DecalTexture p_type, const Ref<Texture2D> &p_texture) { @@ -147,8 +147,8 @@ uint32_t Decal::get_cull_mask() const { AABB Decal::get_aabb() const { AABB aabb; - aabb.position = -extents; - aabb.size = extents * 2.0; + aabb.position = -size / 2; + aabb.size = size; return aabb; } @@ -181,8 +181,8 @@ PackedStringArray Decal::get_configuration_warnings() const { } void Decal::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &Decal::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &Decal::get_extents); + ClassDB::bind_method(D_METHOD("set_size", "size"), &Decal::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &Decal::get_size); ClassDB::bind_method(D_METHOD("set_texture", "type", "texture"), &Decal::set_texture); ClassDB::bind_method(D_METHOD("get_texture", "type"), &Decal::get_texture); @@ -217,7 +217,7 @@ void Decal::_bind_methods() { ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &Decal::set_cull_mask); ClassDB::bind_method(D_METHOD("get_cull_mask"), &Decal::get_cull_mask); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,suffix:m"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_RANGE, "0,1024,0.001,or_greater,suffix:m"), "set_size", "get_size"); ADD_GROUP("Textures", "texture_"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "texture_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ALBEDO); @@ -252,6 +252,24 @@ void Decal::_bind_methods() { BIND_ENUM_CONSTANT(TEXTURE_MAX); } +#ifndef DISABLE_DEPRECATED +bool Decal::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "extents") { // Compatibility with Godot 3.x. + set_size((Vector3)p_value * 2); + return true; + } + return false; +} + +bool Decal::_get(const StringName &p_name, Variant &r_property) const { + if (p_name == "extents") { // Compatibility with Godot 3.x. + r_property = size / 2; + return true; + } + return false; +} +#endif // DISABLE_DEPRECATED + Decal::Decal() { decal = RenderingServer::get_singleton()->decal_create(); RS::get_singleton()->instance_set_base(get_instance(), decal); diff --git a/scene/3d/decal.h b/scene/3d/decal.h index 5797a2f645..171b52815a 100644 --- a/scene/3d/decal.h +++ b/scene/3d/decal.h @@ -47,7 +47,7 @@ public: private: RID decal; - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(2, 2, 2); Ref<Texture2D> textures[TEXTURE_MAX]; real_t emission_energy = 1.0; real_t albedo_mix = 1.0; @@ -63,12 +63,16 @@ private: protected: static void _bind_methods(); void _validate_property(PropertyInfo &p_property) const; +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_property) const; +#endif // DISABLE_DEPRECATED public: virtual PackedStringArray get_configuration_warnings() const override; - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; + void set_size(const Vector3 &p_size); + Vector3 get_size() const; void set_texture(DecalTexture p_type, const Ref<Texture2D> &p_texture); Ref<Texture2D> get_texture(DecalTexture p_type) const; diff --git a/scene/3d/fog_volume.cpp b/scene/3d/fog_volume.cpp index 30dfb45836..9b0a7bb302 100644 --- a/scene/3d/fog_volume.cpp +++ b/scene/3d/fog_volume.cpp @@ -34,36 +34,54 @@ /////////////////////////// void FogVolume::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &FogVolume::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &FogVolume::get_extents); + ClassDB::bind_method(D_METHOD("set_size", "size"), &FogVolume::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &FogVolume::get_size); ClassDB::bind_method(D_METHOD("set_shape", "shape"), &FogVolume::set_shape); ClassDB::bind_method(D_METHOD("get_shape"), &FogVolume::get_shape); ClassDB::bind_method(D_METHOD("set_material", "material"), &FogVolume::set_material); ClassDB::bind_method(D_METHOD("get_material"), &FogVolume::get_material); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "shape", PROPERTY_HINT_ENUM, "Ellipsoid (Local),Cone (Local),Cylinder (Local),Box (Local),World (Global)"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "FogMaterial,ShaderMaterial"), "set_material", "get_material"); } void FogVolume::_validate_property(PropertyInfo &p_property) const { - if (p_property.name == "extents" && shape == RS::FOG_VOLUME_SHAPE_WORLD) { + if (p_property.name == "size" && shape == RS::FOG_VOLUME_SHAPE_WORLD) { p_property.usage = PROPERTY_USAGE_NONE; return; } } -void FogVolume::set_extents(const Vector3 &p_extents) { - extents = p_extents; - extents.x = MAX(0.0, extents.x); - extents.y = MAX(0.0, extents.y); - extents.z = MAX(0.0, extents.z); - RS::get_singleton()->fog_volume_set_extents(_get_volume(), extents); +#ifndef DISABLE_DEPRECATED +bool FogVolume::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "extents") { // Compatibility with Godot 3.x. + set_size((Vector3)p_value * 2); + return true; + } + return false; +} + +bool FogVolume::_get(const StringName &p_name, Variant &r_property) const { + if (p_name == "extents") { // Compatibility with Godot 3.x. + r_property = size / 2; + return true; + } + return false; +} +#endif // DISABLE_DEPRECATED + +void FogVolume::set_size(const Vector3 &p_size) { + size = p_size; + size.x = MAX(0.0, size.x); + size.y = MAX(0.0, size.y); + size.z = MAX(0.0, size.z); + RS::get_singleton()->fog_volume_set_size(_get_volume(), size); update_gizmos(); } -Vector3 FogVolume::get_extents() const { - return extents; +Vector3 FogVolume::get_size() const { + return size; } void FogVolume::set_shape(RS::FogVolumeShape p_type) { @@ -94,7 +112,7 @@ Ref<Material> FogVolume::get_material() const { AABB FogVolume::get_aabb() const { if (shape != RS::FOG_VOLUME_SHAPE_WORLD) { - return AABB(-extents, extents * 2); + return AABB(-size / 2, size); } return AABB(); } diff --git a/scene/3d/fog_volume.h b/scene/3d/fog_volume.h index fa02834762..f7e861e3d0 100644 --- a/scene/3d/fog_volume.h +++ b/scene/3d/fog_volume.h @@ -40,7 +40,7 @@ class FogVolume : public VisualInstance3D { GDCLASS(FogVolume, VisualInstance3D); - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(2, 2, 2); Ref<Material> material; RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX; @@ -50,10 +50,14 @@ protected: _FORCE_INLINE_ RID _get_volume() { return volume; } static void _bind_methods(); void _validate_property(PropertyInfo &p_property) const; +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_property) const; +#endif // DISABLE_DEPRECATED public: - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; + void set_size(const Vector3 &p_size); + Vector3 get_size() const; void set_shape(RS::FogVolumeShape p_type); RS::FogVolumeShape get_shape() const; diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp index d1f2dfb25f..137d578291 100644 --- a/scene/3d/gpu_particles_collision_3d.cpp +++ b/scene/3d/gpu_particles_collision_3d.cpp @@ -95,24 +95,42 @@ GPUParticlesCollisionSphere3D::~GPUParticlesCollisionSphere3D() { /////////////////////////// void GPUParticlesCollisionBox3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionBox3D::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionBox3D::get_extents); + ClassDB::bind_method(D_METHOD("set_size", "size"), &GPUParticlesCollisionBox3D::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &GPUParticlesCollisionBox3D::get_size); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_size", "get_size"); } -void GPUParticlesCollisionBox3D::set_extents(const Vector3 &p_extents) { - extents = p_extents; - RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); +#ifndef DISABLE_DEPRECATED +bool GPUParticlesCollisionBox3D::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "extents") { // Compatibility with Godot 3.x. + set_size((Vector3)p_value * 2); + return true; + } + return false; +} + +bool GPUParticlesCollisionBox3D::_get(const StringName &p_name, Variant &r_property) const { + if (p_name == "extents") { // Compatibility with Godot 3.x. + r_property = size / 2; + return true; + } + return false; +} +#endif // DISABLE_DEPRECATED + +void GPUParticlesCollisionBox3D::set_size(const Vector3 &p_size) { + size = p_size; + RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), size / 2); update_gizmos(); } -Vector3 GPUParticlesCollisionBox3D::get_extents() const { - return extents; +Vector3 GPUParticlesCollisionBox3D::get_size() const { + return size; } AABB GPUParticlesCollisionBox3D::get_aabb() const { - return AABB(-extents, extents * 2); + return AABB(-size / 2, size); } GPUParticlesCollisionBox3D::GPUParticlesCollisionBox3D() : @@ -359,7 +377,7 @@ Vector3i GPUParticlesCollisionSDF3D::get_estimated_cell_size() const { static const int subdivs[RESOLUTION_MAX] = { 16, 32, 64, 128, 256, 512 }; int subdiv = subdivs[get_resolution()]; - AABB aabb(-extents, extents * 2); + AABB aabb(-size / 2, size); float cell_size = aabb.get_longest_axis_size() / float(subdiv); @@ -374,7 +392,7 @@ Ref<Image> GPUParticlesCollisionSDF3D::bake() { static const int subdivs[RESOLUTION_MAX] = { 16, 32, 64, 128, 256, 512 }; int subdiv = subdivs[get_resolution()]; - AABB aabb(-extents, extents * 2); + AABB aabb(-size / 2, size); float cell_size = aabb.get_longest_axis_size() / float(subdiv); @@ -515,8 +533,8 @@ PackedStringArray GPUParticlesCollisionSDF3D::get_configuration_warnings() const } void GPUParticlesCollisionSDF3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionSDF3D::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionSDF3D::get_extents); + ClassDB::bind_method(D_METHOD("set_size", "size"), &GPUParticlesCollisionSDF3D::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &GPUParticlesCollisionSDF3D::get_size); ClassDB::bind_method(D_METHOD("set_resolution", "resolution"), &GPUParticlesCollisionSDF3D::set_resolution); ClassDB::bind_method(D_METHOD("get_resolution"), &GPUParticlesCollisionSDF3D::get_resolution); @@ -532,7 +550,7 @@ void GPUParticlesCollisionSDF3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bake_mask_value", "layer_number", "value"), &GPUParticlesCollisionSDF3D::set_bake_mask_value); ClassDB::bind_method(D_METHOD("get_bake_mask_value", "layer_number"), &GPUParticlesCollisionSDF3D::get_bake_mask_value); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "16,32,64,128,256,512"), "set_resolution", "get_resolution"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "thickness", PROPERTY_HINT_RANGE, "0.0,2.0,0.01,suffix:m"), "set_thickness", "get_thickness"); ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_bake_mask", "get_bake_mask"); @@ -547,6 +565,24 @@ void GPUParticlesCollisionSDF3D::_bind_methods() { BIND_ENUM_CONSTANT(RESOLUTION_MAX); } +#ifndef DISABLE_DEPRECATED +bool GPUParticlesCollisionSDF3D::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "extents") { // Compatibility with Godot 3.x. + set_size((Vector3)p_value * 2); + return true; + } + return false; +} + +bool GPUParticlesCollisionSDF3D::_get(const StringName &p_name, Variant &r_property) const { + if (p_name == "extents") { // Compatibility with Godot 3.x. + r_property = size / 2; + return true; + } + return false; +} +#endif // DISABLE_DEPRECATED + void GPUParticlesCollisionSDF3D::set_thickness(float p_thickness) { thickness = p_thickness; } @@ -555,14 +591,14 @@ float GPUParticlesCollisionSDF3D::get_thickness() const { return thickness; } -void GPUParticlesCollisionSDF3D::set_extents(const Vector3 &p_extents) { - extents = p_extents; - RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); +void GPUParticlesCollisionSDF3D::set_size(const Vector3 &p_size) { + size = p_size; + RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), size / 2); update_gizmos(); } -Vector3 GPUParticlesCollisionSDF3D::get_extents() const { - return extents; +Vector3 GPUParticlesCollisionSDF3D::get_size() const { + return size; } void GPUParticlesCollisionSDF3D::set_resolution(Resolution p_resolution) { @@ -610,7 +646,7 @@ Ref<Texture3D> GPUParticlesCollisionSDF3D::get_texture() const { } AABB GPUParticlesCollisionSDF3D::get_aabb() const { - return AABB(-extents, extents * 2); + return AABB(-size / 2, size); } GPUParticlesCollisionSDF3D::BakeBeginFunc GPUParticlesCollisionSDF3D::bake_begin_function = nullptr; @@ -675,8 +711,8 @@ void GPUParticlesCollisionHeightField3D::_notification(int p_what) { } void GPUParticlesCollisionHeightField3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionHeightField3D::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionHeightField3D::get_extents); + ClassDB::bind_method(D_METHOD("set_size", "size"), &GPUParticlesCollisionHeightField3D::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &GPUParticlesCollisionHeightField3D::get_size); ClassDB::bind_method(D_METHOD("set_resolution", "resolution"), &GPUParticlesCollisionHeightField3D::set_resolution); ClassDB::bind_method(D_METHOD("get_resolution"), &GPUParticlesCollisionHeightField3D::get_resolution); @@ -687,7 +723,7 @@ void GPUParticlesCollisionHeightField3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_follow_camera_enabled", "enabled"), &GPUParticlesCollisionHeightField3D::set_follow_camera_enabled); ClassDB::bind_method(D_METHOD("is_follow_camera_enabled"), &GPUParticlesCollisionHeightField3D::is_follow_camera_enabled); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "256 (Fastest),512 (Fast),1024 (Average),2048 (Slow),4096 (Slower),8192 (Slowest)"), "set_resolution", "get_resolution"); ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "When Moved (Fast),Always (Slow)"), "set_update_mode", "get_update_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_camera_enabled"), "set_follow_camera_enabled", "is_follow_camera_enabled"); @@ -704,15 +740,33 @@ void GPUParticlesCollisionHeightField3D::_bind_methods() { BIND_ENUM_CONSTANT(UPDATE_MODE_ALWAYS); } -void GPUParticlesCollisionHeightField3D::set_extents(const Vector3 &p_extents) { - extents = p_extents; - RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); +#ifndef DISABLE_DEPRECATED +bool GPUParticlesCollisionHeightField3D::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "extents") { // Compatibility with Godot 3.x. + set_size((Vector3)p_value * 2); + return true; + } + return false; +} + +bool GPUParticlesCollisionHeightField3D::_get(const StringName &p_name, Variant &r_property) const { + if (p_name == "extents") { // Compatibility with Godot 3.x. + r_property = size / 2; + return true; + } + return false; +} +#endif // DISABLE_DEPRECATED + +void GPUParticlesCollisionHeightField3D::set_size(const Vector3 &p_size) { + size = p_size; + RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), size / 2); update_gizmos(); RS::get_singleton()->particles_collision_height_field_update(_get_collision()); } -Vector3 GPUParticlesCollisionHeightField3D::get_extents() const { - return extents; +Vector3 GPUParticlesCollisionHeightField3D::get_size() const { + return size; } void GPUParticlesCollisionHeightField3D::set_resolution(Resolution p_resolution) { @@ -745,7 +799,7 @@ bool GPUParticlesCollisionHeightField3D::is_follow_camera_enabled() const { } AABB GPUParticlesCollisionHeightField3D::get_aabb() const { - return AABB(-extents, extents * 2); + return AABB(-size / 2, size); } GPUParticlesCollisionHeightField3D::GPUParticlesCollisionHeightField3D() : @@ -857,24 +911,42 @@ GPUParticlesAttractorSphere3D::~GPUParticlesAttractorSphere3D() { /////////////////////////// void GPUParticlesAttractorBox3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesAttractorBox3D::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesAttractorBox3D::get_extents); + ClassDB::bind_method(D_METHOD("set_size", "size"), &GPUParticlesAttractorBox3D::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &GPUParticlesAttractorBox3D::get_size); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_size", "get_size"); +} - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents"); +#ifndef DISABLE_DEPRECATED +bool GPUParticlesAttractorBox3D::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "extents") { // Compatibility with Godot 3.x. + set_size((Vector3)p_value * 2); + return true; + } + return false; } -void GPUParticlesAttractorBox3D::set_extents(const Vector3 &p_extents) { - extents = p_extents; - RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); +bool GPUParticlesAttractorBox3D::_get(const StringName &p_name, Variant &r_property) const { + if (p_name == "extents") { // Compatibility with Godot 3.x. + r_property = size / 2; + return true; + } + return false; +} +#endif // DISABLE_DEPRECATED + +void GPUParticlesAttractorBox3D::set_size(const Vector3 &p_size) { + size = p_size; + RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), size / 2); update_gizmos(); } -Vector3 GPUParticlesAttractorBox3D::get_extents() const { - return extents; +Vector3 GPUParticlesAttractorBox3D::get_size() const { + return size; } AABB GPUParticlesAttractorBox3D::get_aabb() const { - return AABB(-extents, extents * 2); + return AABB(-size / 2, size); } GPUParticlesAttractorBox3D::GPUParticlesAttractorBox3D() : @@ -887,24 +959,42 @@ GPUParticlesAttractorBox3D::~GPUParticlesAttractorBox3D() { /////////////////////////// void GPUParticlesAttractorVectorField3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesAttractorVectorField3D::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesAttractorVectorField3D::get_extents); + ClassDB::bind_method(D_METHOD("set_size", "size"), &GPUParticlesAttractorVectorField3D::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &GPUParticlesAttractorVectorField3D::get_size); ClassDB::bind_method(D_METHOD("set_texture", "texture"), &GPUParticlesAttractorVectorField3D::set_texture); ClassDB::bind_method(D_METHOD("get_texture"), &GPUParticlesAttractorVectorField3D::get_texture); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture"); } -void GPUParticlesAttractorVectorField3D::set_extents(const Vector3 &p_extents) { - extents = p_extents; - RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); +#ifndef DISABLE_DEPRECATED +bool GPUParticlesAttractorVectorField3D::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "extents") { // Compatibility with Godot 3.x. + set_size((Vector3)p_value * 2); + return true; + } + return false; +} + +bool GPUParticlesAttractorVectorField3D::_get(const StringName &p_name, Variant &r_property) const { + if (p_name == "extents") { // Compatibility with Godot 3.x. + r_property = size / 2; + return true; + } + return false; +} +#endif // DISABLE_DEPRECATED + +void GPUParticlesAttractorVectorField3D::set_size(const Vector3 &p_size) { + size = p_size; + RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), size / 2); update_gizmos(); } -Vector3 GPUParticlesAttractorVectorField3D::get_extents() const { - return extents; +Vector3 GPUParticlesAttractorVectorField3D::get_size() const { + return size; } void GPUParticlesAttractorVectorField3D::set_texture(const Ref<Texture3D> &p_texture) { @@ -918,7 +1008,7 @@ Ref<Texture3D> GPUParticlesAttractorVectorField3D::get_texture() const { } AABB GPUParticlesAttractorVectorField3D::get_aabb() const { - return AABB(-extents, extents * 2); + return AABB(-size / 2, size); } GPUParticlesAttractorVectorField3D::GPUParticlesAttractorVectorField3D() : diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h index 3c569ac73d..1649320069 100644 --- a/scene/3d/gpu_particles_collision_3d.h +++ b/scene/3d/gpu_particles_collision_3d.h @@ -74,14 +74,18 @@ public: class GPUParticlesCollisionBox3D : public GPUParticlesCollision3D { GDCLASS(GPUParticlesCollisionBox3D, GPUParticlesCollision3D); - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(2, 2, 2); protected: static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_property) const; +#endif // DISABLE_DEPRECATED public: - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; + void set_size(const Vector3 &p_size); + Vector3 get_size() const; virtual AABB get_aabb() const override; @@ -108,7 +112,7 @@ public: typedef void (*BakeEndFunc)(); private: - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(2, 2, 2); Resolution resolution = RESOLUTION_64; uint32_t bake_mask = 0xFFFFFFFF; Ref<Texture3D> texture; @@ -160,6 +164,10 @@ private: protected: static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_property) const; +#endif // DISABLE_DEPRECATED public: virtual PackedStringArray get_configuration_warnings() const override; @@ -167,8 +175,8 @@ public: void set_thickness(float p_thickness); float get_thickness() const; - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; + void set_size(const Vector3 &p_size); + Vector3 get_size() const; void set_resolution(Resolution p_resolution); Resolution get_resolution() const; @@ -217,7 +225,7 @@ public: }; private: - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(2, 2, 2); Resolution resolution = RESOLUTION_1024; bool follow_camera_mode = false; @@ -226,10 +234,14 @@ private: protected: void _notification(int p_what); static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_property) const; +#endif // DISABLE_DEPRECATED public: - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; + void set_size(const Vector3 &p_size); + Vector3 get_size() const; void set_resolution(Resolution p_resolution); Resolution get_resolution() const; @@ -301,14 +313,18 @@ public: class GPUParticlesAttractorBox3D : public GPUParticlesAttractor3D { GDCLASS(GPUParticlesAttractorBox3D, GPUParticlesAttractor3D); - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(2, 2, 2); protected: static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_property) const; +#endif // DISABLE_DEPRECATED public: - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; + void set_size(const Vector3 &p_size); + Vector3 get_size() const; virtual AABB get_aabb() const override; @@ -319,15 +335,19 @@ public: class GPUParticlesAttractorVectorField3D : public GPUParticlesAttractor3D { GDCLASS(GPUParticlesAttractorVectorField3D, GPUParticlesAttractor3D); - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(2, 2, 2); Ref<Texture3D> texture; protected: static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_property) const; +#endif // DISABLE_DEPRECATED public: - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; + void set_size(const Vector3 &p_size); + Vector3 get_size() const; void set_texture(const Ref<Texture3D> &p_texture); Ref<Texture3D> get_texture() const; diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 6a9b8c9ac4..b39ca43d2e 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -112,6 +112,12 @@ void Label3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_alpha_hash_scale", "threshold"), &Label3D::set_alpha_hash_scale); ClassDB::bind_method(D_METHOD("get_alpha_hash_scale"), &Label3D::get_alpha_hash_scale); + ClassDB::bind_method(D_METHOD("set_alpha_antialiasing", "alpha_aa"), &Label3D::set_alpha_antialiasing); + ClassDB::bind_method(D_METHOD("get_alpha_antialiasing"), &Label3D::get_alpha_antialiasing); + + ClassDB::bind_method(D_METHOD("set_alpha_antialiasing_edge", "edge"), &Label3D::set_alpha_antialiasing_edge); + ClassDB::bind_method(D_METHOD("get_alpha_antialiasing_edge"), &Label3D::get_alpha_antialiasing_edge); + ClassDB::bind_method(D_METHOD("set_texture_filter", "mode"), &Label3D::set_texture_filter); ClassDB::bind_method(D_METHOD("get_texture_filter"), &Label3D::get_texture_filter); @@ -133,6 +139,8 @@ void Label3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_cut", PROPERTY_HINT_ENUM, "Disabled,Discard,Opaque Pre-Pass,Alpha Hash"), "set_alpha_cut_mode", "get_alpha_cut_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_hash_scale", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_alpha_hash_scale", "get_alpha_hash_scale"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_antialiasing_mode", PROPERTY_HINT_ENUM, "Disabled,Alpha Edge Blend,Alpha Edge Clip"), "set_alpha_antialiasing", "get_alpha_antialiasing"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_antialiasing_edge", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_antialiasing_edge", "get_alpha_antialiasing_edge"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "render_priority", PROPERTY_HINT_RANGE, itos(RS::MATERIAL_RENDER_PRIORITY_MIN) + "," + itos(RS::MATERIAL_RENDER_PRIORITY_MAX) + ",1"), "set_render_priority", "get_render_priority"); ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_render_priority", PROPERTY_HINT_RANGE, itos(RS::MATERIAL_RENDER_PRIORITY_MIN) + "," + itos(RS::MATERIAL_RENDER_PRIORITY_MAX) + ",1"), "set_outline_render_priority", "get_outline_render_priority"); @@ -356,6 +364,7 @@ void Label3D::_generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset, RS::get_singleton()->material_set_param(surf.material, "uv2_scale", Vector3(1, 1, 1)); RS::get_singleton()->material_set_param(surf.material, "alpha_scissor_threshold", alpha_scissor_threshold); RS::get_singleton()->material_set_param(surf.material, "alpha_hash_scale", alpha_hash_scale); + RS::get_singleton()->material_set_param(surf.material, "alpha_antialiasing_edge", alpha_antialiasing_edge); if (msdf) { RS::get_singleton()->material_set_param(surf.material, "msdf_pixel_range", TS->font_get_msdf_pixel_range(p_glyph.font_rid)); RS::get_singleton()->material_set_param(surf.material, "msdf_outline_size", p_outline_size); @@ -371,7 +380,7 @@ void Label3D::_generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset, } RID shader_rid; - StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), mat_transparency, get_draw_flag(FLAG_DOUBLE_SIDED), get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, msdf, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), texture_filter, &shader_rid); + StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), mat_transparency, get_draw_flag(FLAG_DOUBLE_SIDED), get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, msdf, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), texture_filter, alpha_antialiasing_mode, &shader_rid); RS::get_singleton()->material_set_shader(surf.material, shader_rid); RS::get_singleton()->material_set_param(surf.material, "texture_albedo", tex); @@ -966,6 +975,28 @@ float Label3D::get_alpha_scissor_threshold() const { return alpha_scissor_threshold; } +void Label3D::set_alpha_antialiasing(BaseMaterial3D::AlphaAntiAliasing p_alpha_aa) { + if (alpha_antialiasing_mode != p_alpha_aa) { + alpha_antialiasing_mode = p_alpha_aa; + _queue_update(); + } +} + +BaseMaterial3D::AlphaAntiAliasing Label3D::get_alpha_antialiasing() const { + return alpha_antialiasing_mode; +} + +void Label3D::set_alpha_antialiasing_edge(float p_edge) { + if (alpha_antialiasing_edge != p_edge) { + alpha_antialiasing_edge = p_edge; + _queue_update(); + } +} + +float Label3D::get_alpha_antialiasing_edge() const { + return alpha_antialiasing_edge; +} + Label3D::Label3D() { for (int i = 0; i < FLAG_MAX; i++) { flags[i] = (i == FLAG_DOUBLE_SIDED); diff --git a/scene/3d/label_3d.h b/scene/3d/label_3d.h index 576735840a..912f485354 100644 --- a/scene/3d/label_3d.h +++ b/scene/3d/label_3d.h @@ -62,6 +62,8 @@ private: AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED; float alpha_scissor_threshold = 0.5; float alpha_hash_scale = 1.0; + StandardMaterial3D::AlphaAntiAliasing alpha_antialiasing_mode = StandardMaterial3D::ALPHA_ANTIALIASING_OFF; + float alpha_antialiasing_edge = 0.0f; AABB aabb; @@ -234,6 +236,12 @@ public: void set_alpha_hash_scale(float p_hash_scale); float get_alpha_hash_scale() const; + void set_alpha_antialiasing(BaseMaterial3D::AlphaAntiAliasing p_alpha_aa); + BaseMaterial3D::AlphaAntiAliasing get_alpha_antialiasing() const; + + void set_alpha_antialiasing_edge(float p_edge); + float get_alpha_antialiasing_edge() const; + void set_billboard_mode(StandardMaterial3D::BillboardMode p_mode); StandardMaterial3D::BillboardMode get_billboard_mode() const; diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 4aa6e61ec5..5db8611d72 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -120,6 +120,23 @@ void NavigationAgent3D::_bind_methods() { ADD_SIGNAL(MethodInfo("link_reached", PropertyInfo(Variant::DICTIONARY, "details"))); ADD_SIGNAL(MethodInfo("navigation_finished")); ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR3, "safe_velocity"))); + +#ifdef DEBUG_ENABLED + ClassDB::bind_method(D_METHOD("set_debug_enabled", "enabled"), &NavigationAgent3D::set_debug_enabled); + ClassDB::bind_method(D_METHOD("get_debug_enabled"), &NavigationAgent3D::get_debug_enabled); + ClassDB::bind_method(D_METHOD("set_debug_use_custom", "enabled"), &NavigationAgent3D::set_debug_use_custom); + ClassDB::bind_method(D_METHOD("get_debug_use_custom"), &NavigationAgent3D::get_debug_use_custom); + ClassDB::bind_method(D_METHOD("set_debug_path_custom_color", "color"), &NavigationAgent3D::set_debug_path_custom_color); + ClassDB::bind_method(D_METHOD("get_debug_path_custom_color"), &NavigationAgent3D::get_debug_path_custom_color); + ClassDB::bind_method(D_METHOD("set_debug_path_custom_point_size", "point_size"), &NavigationAgent3D::set_debug_path_custom_point_size); + ClassDB::bind_method(D_METHOD("get_debug_path_custom_point_size"), &NavigationAgent3D::get_debug_path_custom_point_size); + + ADD_GROUP("Debug", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_enabled"), "set_debug_enabled", "get_debug_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_use_custom"), "set_debug_use_custom", "get_debug_use_custom"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_path_custom_color"), "set_debug_path_custom_color", "get_debug_path_custom_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "debug_path_custom_point_size", PROPERTY_HINT_RANGE, "1,50,1,suffix:px"), "set_debug_path_custom_point_size", "get_debug_path_custom_point_size"); +#endif // DEBUG_ENABLED } void NavigationAgent3D::_notification(int p_what) { @@ -129,6 +146,12 @@ void NavigationAgent3D::_notification(int p_what) { // cannot use READY as ready does not get called if Node is readded to SceneTree set_agent_parent(get_parent()); set_physics_process_internal(true); + +#ifdef DEBUG_ENABLED + if (NavigationServer3D::get_singleton()->get_debug_enabled()) { + debug_path_dirty = true; + } +#endif // DEBUG_ENABLED } break; case NOTIFICATION_PARENTED: { @@ -151,6 +174,12 @@ void NavigationAgent3D::_notification(int p_what) { case NOTIFICATION_EXIT_TREE: { set_agent_parent(nullptr); set_physics_process_internal(false); + +#ifdef DEBUG_ENABLED + if (debug_path_instance.is_valid()) { + RS::get_singleton()->instance_set_visible(debug_path_instance, false); + } +#endif // DEBUG_ENABLED } break; case NOTIFICATION_PAUSED: { @@ -182,6 +211,11 @@ void NavigationAgent3D::_notification(int p_what) { } _check_distance_to_target(); } +#ifdef DEBUG_ENABLED + if (debug_path_dirty) { + _update_debug_path(); + } +#endif // DEBUG_ENABLED } break; } } @@ -201,12 +235,28 @@ NavigationAgent3D::NavigationAgent3D() { navigation_result = Ref<NavigationPathQueryResult3D>(); navigation_result.instantiate(); + +#ifdef DEBUG_ENABLED + NavigationServer3D::get_singleton()->connect(SNAME("navigation_debug_changed"), callable_mp(this, &NavigationAgent3D::_navigation_debug_changed)); +#endif // DEBUG_ENABLED } NavigationAgent3D::~NavigationAgent3D() { ERR_FAIL_NULL(NavigationServer3D::get_singleton()); NavigationServer3D::get_singleton()->free(agent); agent = RID(); // Pointless + +#ifdef DEBUG_ENABLED + NavigationServer3D::get_singleton()->disconnect(SNAME("navigation_debug_changed"), callable_mp(this, &NavigationAgent3D::_navigation_debug_changed)); + + ERR_FAIL_NULL(RenderingServer::get_singleton()); + if (debug_path_instance.is_valid()) { + RenderingServer::get_singleton()->free(debug_path_instance); + } + if (debug_path_mesh.is_valid()) { + RenderingServer::get_singleton()->free(debug_path_mesh->get_rid()); + } +#endif // DEBUG_ENABLED } void NavigationAgent3D::set_avoidance_enabled(bool p_enabled) { @@ -480,6 +530,9 @@ void NavigationAgent3D::update_navigation() { } NavigationServer3D::get_singleton()->query_path(navigation_query, navigation_result); +#ifdef DEBUG_ENABLED + debug_path_dirty = true; +#endif // DEBUG_ENABLED navigation_finished = false; navigation_path_index = 0; emit_signal(SNAME("path_changed")); @@ -566,3 +619,130 @@ void NavigationAgent3D::_check_distance_to_target() { } } } + +////////DEBUG//////////////////////////////////////////////////////////// + +#ifdef DEBUG_ENABLED +void NavigationAgent3D::set_debug_enabled(bool p_enabled) { + debug_enabled = p_enabled; + debug_path_dirty = true; +} + +bool NavigationAgent3D::get_debug_enabled() const { + return debug_enabled; +} + +void NavigationAgent3D::set_debug_use_custom(bool p_enabled) { + debug_use_custom = p_enabled; + debug_path_dirty = true; +} + +bool NavigationAgent3D::get_debug_use_custom() const { + return debug_use_custom; +} + +void NavigationAgent3D::set_debug_path_custom_color(Color p_color) { + debug_path_custom_color = p_color; + debug_path_dirty = true; +} + +Color NavigationAgent3D::get_debug_path_custom_color() const { + return debug_path_custom_color; +} + +void NavigationAgent3D::set_debug_path_custom_point_size(float p_point_size) { + debug_path_custom_point_size = p_point_size; + debug_path_dirty = true; +} + +float NavigationAgent3D::get_debug_path_custom_point_size() const { + return debug_path_custom_point_size; +} + +void NavigationAgent3D::_navigation_debug_changed() { + debug_path_dirty = true; +} + +void NavigationAgent3D::_update_debug_path() { + if (!debug_path_dirty) { + return; + } + debug_path_dirty = false; + + if (!debug_path_instance.is_valid()) { + debug_path_instance = RenderingServer::get_singleton()->instance_create(); + } + + if (!debug_path_mesh.is_valid()) { + debug_path_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + } + + debug_path_mesh->clear_surfaces(); + + if (!(debug_enabled && NavigationServer3D::get_singleton()->get_debug_navigation_enable_agent_paths())) { + return; + } + + if (!(agent_parent && agent_parent->is_inside_tree())) { + return; + } + + const Vector<Vector3> &navigation_path = navigation_result->get_path(); + + if (navigation_path.size() <= 1) { + return; + } + + Vector<Vector3> debug_path_lines_vertex_array; + + for (int i = 0; i < navigation_path.size() - 1; i++) { + debug_path_lines_vertex_array.push_back(navigation_path[i]); + debug_path_lines_vertex_array.push_back(navigation_path[i + 1]); + } + + Array debug_path_lines_mesh_array; + debug_path_lines_mesh_array.resize(Mesh::ARRAY_MAX); + debug_path_lines_mesh_array[Mesh::ARRAY_VERTEX] = debug_path_lines_vertex_array; + + debug_path_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, debug_path_lines_mesh_array); + + Ref<StandardMaterial3D> debug_agent_path_line_material = NavigationServer3D::get_singleton()->get_debug_navigation_agent_path_line_material(); + if (debug_use_custom) { + if (!debug_agent_path_line_custom_material.is_valid()) { + debug_agent_path_line_custom_material = debug_agent_path_line_material->duplicate(); + } + debug_agent_path_line_custom_material->set_albedo(debug_path_custom_color); + debug_path_mesh->surface_set_material(0, debug_agent_path_line_custom_material); + } else { + debug_path_mesh->surface_set_material(0, debug_agent_path_line_material); + } + + Vector<Vector3> debug_path_points_vertex_array; + + for (int i = 0; i < navigation_path.size(); i++) { + debug_path_points_vertex_array.push_back(navigation_path[i]); + } + + Array debug_path_points_mesh_array; + debug_path_points_mesh_array.resize(Mesh::ARRAY_MAX); + debug_path_points_mesh_array[Mesh::ARRAY_VERTEX] = debug_path_lines_vertex_array; + + debug_path_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_POINTS, debug_path_points_mesh_array); + + Ref<StandardMaterial3D> debug_agent_path_point_material = NavigationServer3D::get_singleton()->get_debug_navigation_agent_path_point_material(); + if (debug_use_custom) { + if (!debug_agent_path_point_custom_material.is_valid()) { + debug_agent_path_point_custom_material = debug_agent_path_point_material->duplicate(); + } + debug_agent_path_point_custom_material->set_albedo(debug_path_custom_color); + debug_agent_path_point_custom_material->set_point_size(debug_path_custom_point_size); + debug_path_mesh->surface_set_material(1, debug_agent_path_point_custom_material); + } else { + debug_path_mesh->surface_set_material(1, debug_agent_path_point_material); + } + + RS::get_singleton()->instance_set_base(debug_path_instance, debug_path_mesh->get_rid()); + RS::get_singleton()->instance_set_scenario(debug_path_instance, agent_parent->get_world_3d()->get_scenario()); + RS::get_singleton()->instance_set_visible(debug_path_instance, agent_parent->is_visible_in_tree()); +} +#endif // DEBUG_ENABLED diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h index 12f83ce6a8..98bf395d7c 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -76,6 +76,22 @@ class NavigationAgent3D : public Node { // No initialized on purpose uint32_t update_frame_id = 0; +#ifdef DEBUG_ENABLED + bool debug_enabled = false; + bool debug_path_dirty = true; + RID debug_path_instance; + Ref<ArrayMesh> debug_path_mesh; + float debug_path_custom_point_size = 4.0; + bool debug_use_custom = false; + Color debug_path_custom_color = Color(1.0, 1.0, 1.0, 1.0); + Ref<StandardMaterial3D> debug_agent_path_line_custom_material; + Ref<StandardMaterial3D> debug_agent_path_point_custom_material; + +private: + void _navigation_debug_changed(); + void _update_debug_path(); +#endif // DEBUG_ENABLED + protected: static void _bind_methods(); void _notification(int p_what); @@ -181,6 +197,20 @@ public: PackedStringArray get_configuration_warnings() const override; +#ifdef DEBUG_ENABLED + void set_debug_enabled(bool p_enabled); + bool get_debug_enabled() const; + + void set_debug_use_custom(bool p_enabled); + bool get_debug_use_custom() const; + + void set_debug_path_custom_color(Color p_color); + Color get_debug_path_custom_color() const; + + void set_debug_path_custom_point_size(float p_point_size); + float get_debug_path_custom_point_size() const; +#endif // DEBUG_ENABLED + private: void update_navigation(); void _request_repath(); diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp index 632b27953f..594580a205 100644 --- a/scene/3d/occluder_instance_3d.cpp +++ b/scene/3d/occluder_instance_3d.cpp @@ -542,13 +542,14 @@ void OccluderInstance3D::_bake_surface(const Transform3D &p_transform, Array p_s float error = -1.0f; int target_index_count = MIN(indices.size(), 36); + const int simplify_options = SurfaceTool::SIMPLIFY_LOCK_BORDER; + uint32_t index_count = SurfaceTool::simplify_func( (unsigned int *)indices.ptrw(), (unsigned int *)indices.ptr(), indices.size(), vertices_f32.ptr(), vertices.size(), sizeof(float) * 3, - target_index_count, target_error, &error); - + target_index_count, target_error, simplify_options, &error); indices.resize(index_count); } diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index f4ab09cd9b..c8cfcf7d7a 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -333,6 +333,11 @@ void AnimatableBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) { } void AnimatableBody3D::_notification(int p_what) { +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + return; + } +#endif switch (p_what) { case NOTIFICATION_ENTER_TREE: { last_valid_transform = get_global_transform(); diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index 606f6140cb..62202c0b1b 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -85,38 +85,40 @@ float ReflectionProbe::get_mesh_lod_threshold() const { return mesh_lod_threshold; } -void ReflectionProbe::set_extents(const Vector3 &p_extents) { - extents = p_extents; +void ReflectionProbe::set_size(const Vector3 &p_size) { + size = p_size; for (int i = 0; i < 3; i++) { - if (extents[i] < 0.01) { - extents[i] = 0.01; + float half_size = size[i] / 2; + if (half_size < 0.01) { + half_size = 0.01; } - if (extents[i] - 0.01 < ABS(origin_offset[i])) { - origin_offset[i] = SIGN(origin_offset[i]) * (extents[i] - 0.01); + if (half_size - 0.01 < ABS(origin_offset[i])) { + origin_offset[i] = SIGN(origin_offset[i]) * (half_size - 0.01); } } - RS::get_singleton()->reflection_probe_set_extents(probe, extents); + RS::get_singleton()->reflection_probe_set_size(probe, size); RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset); update_gizmos(); } -Vector3 ReflectionProbe::get_extents() const { - return extents; +Vector3 ReflectionProbe::get_size() const { + return size; } -void ReflectionProbe::set_origin_offset(const Vector3 &p_extents) { - origin_offset = p_extents; +void ReflectionProbe::set_origin_offset(const Vector3 &p_offset) { + origin_offset = p_offset; for (int i = 0; i < 3; i++) { - if (extents[i] - 0.01 < ABS(origin_offset[i])) { - origin_offset[i] = SIGN(origin_offset[i]) * (extents[i] - 0.01); + float half_size = size[i] / 2; + if (half_size - 0.01 < ABS(origin_offset[i])) { + origin_offset[i] = SIGN(origin_offset[i]) * (half_size - 0.01); } } - RS::get_singleton()->reflection_probe_set_extents(probe, extents); + RS::get_singleton()->reflection_probe_set_size(probe, size); RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset); update_gizmos(); @@ -174,7 +176,7 @@ ReflectionProbe::UpdateMode ReflectionProbe::get_update_mode() const { AABB ReflectionProbe::get_aabb() const { AABB aabb; aabb.position = -origin_offset; - aabb.size = origin_offset + extents; + aabb.size = origin_offset + size / 2; return aabb; } @@ -205,8 +207,8 @@ void ReflectionProbe::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mesh_lod_threshold", "ratio"), &ReflectionProbe::set_mesh_lod_threshold); ClassDB::bind_method(D_METHOD("get_mesh_lod_threshold"), &ReflectionProbe::get_mesh_lod_threshold); - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &ReflectionProbe::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &ReflectionProbe::get_extents); + ClassDB::bind_method(D_METHOD("set_size", "size"), &ReflectionProbe::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &ReflectionProbe::get_size); ClassDB::bind_method(D_METHOD("set_origin_offset", "origin_offset"), &ReflectionProbe::set_origin_offset); ClassDB::bind_method(D_METHOD("get_origin_offset"), &ReflectionProbe::get_origin_offset); @@ -229,7 +231,7 @@ void ReflectionProbe::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Once (Fast),Always (Slow)"), "set_update_mode", "get_update_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "intensity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_intensity", "get_intensity"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "0,16384,0.1,or_greater,exp,suffix:m"), "set_max_distance", "get_max_distance"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_NONE, "suffix:m"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "origin_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_origin_offset", "get_origin_offset"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "box_projection"), "set_enable_box_projection", "is_box_projection_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_as_interior", "is_set_as_interior"); @@ -250,6 +252,24 @@ void ReflectionProbe::_bind_methods() { BIND_ENUM_CONSTANT(AMBIENT_COLOR); } +#ifndef DISABLE_DEPRECATED +bool ReflectionProbe::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "extents") { // Compatibility with Godot 3.x. + set_size((Vector3)p_value * 2); + return true; + } + return false; +} + +bool ReflectionProbe::_get(const StringName &p_name, Variant &r_property) const { + if (p_name == "extents") { // Compatibility with Godot 3.x. + r_property = size / 2; + return true; + } + return false; +} +#endif // DISABLE_DEPRECATED + ReflectionProbe::ReflectionProbe() { probe = RenderingServer::get_singleton()->reflection_probe_create(); RS::get_singleton()->instance_set_base(get_instance(), probe); diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h index cb417c3eea..738277ad39 100644 --- a/scene/3d/reflection_probe.h +++ b/scene/3d/reflection_probe.h @@ -52,7 +52,7 @@ private: RID probe; float intensity = 1.0; float max_distance = 0.0; - Vector3 extents = Vector3(10, 10, 10); + Vector3 size = Vector3(20, 20, 20); Vector3 origin_offset = Vector3(0, 0, 0); bool box_projection = false; bool enable_shadows = false; @@ -68,6 +68,10 @@ private: protected: static void _bind_methods(); void _validate_property(PropertyInfo &p_property) const; +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_property) const; +#endif // DISABLE_DEPRECATED public: void set_intensity(float p_intensity); @@ -91,10 +95,10 @@ public: void set_mesh_lod_threshold(float p_pixels); float get_mesh_lod_threshold() const; - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; + void set_size(const Vector3 &p_size); + Vector3 get_size() const; - void set_origin_offset(const Vector3 &p_extents); + void set_origin_offset(const Vector3 &p_offset); Vector3 get_origin_offset() const; void set_as_interior(bool p_enable); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 041ca7707b..59e4a0b718 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -247,6 +247,7 @@ void SpriteBase3D::draw_texture_rect(Ref<Texture2D> p_texture, Rect2 p_dst_rect, RS::get_singleton()->material_set_param(get_material(), "alpha_scissor_threshold", alpha_scissor_threshold); RS::get_singleton()->material_set_param(get_material(), "alpha_hash_scale", alpha_hash_scale); + RS::get_singleton()->material_set_param(get_material(), "alpha_antialiasing_edge", alpha_antialiasing_edge); BaseMaterial3D::Transparency mat_transparency = BaseMaterial3D::Transparency::TRANSPARENCY_DISABLED; if (get_draw_flag(FLAG_TRANSPARENT)) { @@ -262,7 +263,7 @@ void SpriteBase3D::draw_texture_rect(Ref<Texture2D> p_texture, Rect2 p_dst_rect, } RID shader_rid; - StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), mat_transparency, get_draw_flag(FLAG_DOUBLE_SIDED), get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, false, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), get_texture_filter(), &shader_rid); + StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), mat_transparency, get_draw_flag(FLAG_DOUBLE_SIDED), get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, false, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), get_texture_filter(), alpha_antialiasing_mode, &shader_rid); if (last_shader != shader_rid) { RS::get_singleton()->material_set_shader(get_material(), shader_rid); @@ -481,6 +482,28 @@ float SpriteBase3D::get_alpha_scissor_threshold() const { return alpha_scissor_threshold; } +void SpriteBase3D::set_alpha_antialiasing(BaseMaterial3D::AlphaAntiAliasing p_alpha_aa) { + if (alpha_antialiasing_mode != p_alpha_aa) { + alpha_antialiasing_mode = p_alpha_aa; + _queue_redraw(); + } +} + +BaseMaterial3D::AlphaAntiAliasing SpriteBase3D::get_alpha_antialiasing() const { + return alpha_antialiasing_mode; +} + +void SpriteBase3D::set_alpha_antialiasing_edge(float p_edge) { + if (alpha_antialiasing_edge != p_edge) { + alpha_antialiasing_edge = p_edge; + _queue_redraw(); + } +} + +float SpriteBase3D::get_alpha_antialiasing_edge() const { + return alpha_antialiasing_edge; +} + void SpriteBase3D::set_billboard_mode(StandardMaterial3D::BillboardMode p_mode) { ERR_FAIL_INDEX(p_mode, 3); // Cannot use BILLBOARD_PARTICLES. billboard_mode = p_mode; @@ -539,6 +562,12 @@ void SpriteBase3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_alpha_hash_scale", "threshold"), &SpriteBase3D::set_alpha_hash_scale); ClassDB::bind_method(D_METHOD("get_alpha_hash_scale"), &SpriteBase3D::get_alpha_hash_scale); + ClassDB::bind_method(D_METHOD("set_alpha_antialiasing", "alpha_aa"), &SpriteBase3D::set_alpha_antialiasing); + ClassDB::bind_method(D_METHOD("get_alpha_antialiasing"), &SpriteBase3D::get_alpha_antialiasing); + + ClassDB::bind_method(D_METHOD("set_alpha_antialiasing_edge", "edge"), &SpriteBase3D::set_alpha_antialiasing_edge); + ClassDB::bind_method(D_METHOD("get_alpha_antialiasing_edge"), &SpriteBase3D::get_alpha_antialiasing_edge); + ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &SpriteBase3D::set_billboard_mode); ClassDB::bind_method(D_METHOD("get_billboard_mode"), &SpriteBase3D::get_billboard_mode); @@ -567,6 +596,8 @@ void SpriteBase3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_cut", PROPERTY_HINT_ENUM, "Disabled,Discard,Opaque Pre-Pass,Alpha Hash"), "set_alpha_cut_mode", "get_alpha_cut_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_hash_scale", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_alpha_hash_scale", "get_alpha_hash_scale"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_antialiasing_mode", PROPERTY_HINT_ENUM, "Disabled,Alpha Edge Blend,Alpha Edge Clip"), "set_alpha_antialiasing", "get_alpha_antialiasing"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_antialiasing_edge", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_antialiasing_edge", "get_alpha_antialiasing_edge"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "render_priority", PROPERTY_HINT_RANGE, itos(RS::MATERIAL_RENDER_PRIORITY_MIN) + "," + itos(RS::MATERIAL_RENDER_PRIORITY_MAX) + ",1"), "set_render_priority", "get_render_priority"); diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 873c321878..1eb1211951 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -89,6 +89,8 @@ private: AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED; float alpha_scissor_threshold = 0.5; float alpha_hash_scale = 1.0; + StandardMaterial3D::AlphaAntiAliasing alpha_antialiasing_mode = StandardMaterial3D::ALPHA_ANTIALIASING_OFF; + float alpha_antialiasing_edge = 0.0f; StandardMaterial3D::BillboardMode billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED; StandardMaterial3D::TextureFilter texture_filter = StandardMaterial3D::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS; bool pending_update = false; @@ -153,6 +155,12 @@ public: void set_alpha_hash_scale(float p_hash_scale); float get_alpha_hash_scale() const; + void set_alpha_antialiasing(BaseMaterial3D::AlphaAntiAliasing p_alpha_aa); + BaseMaterial3D::AlphaAntiAliasing get_alpha_antialiasing() const; + + void set_alpha_antialiasing_edge(float p_edge); + float get_alpha_antialiasing_edge() const; + void set_billboard_mode(StandardMaterial3D::BillboardMode p_mode); StandardMaterial3D::BillboardMode get_billboard_mode() const; diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp index 41dc27352f..36a877246e 100644 --- a/scene/3d/voxel_gi.cpp +++ b/scene/3d/voxel_gi.cpp @@ -237,6 +237,24 @@ void VoxelGIData::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior"); } +#ifndef DISABLE_DEPRECATED +bool VoxelGI::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "extents") { // Compatibility with Godot 3.x. + set_size((Vector3)p_value * 2); + return true; + } + return false; +} + +bool VoxelGI::_get(const StringName &p_name, Variant &r_property) const { + if (p_name == "extents") { // Compatibility with Godot 3.x. + r_property = size / 2; + return true; + } + return false; +} +#endif // DISABLE_DEPRECATED + VoxelGIData::VoxelGIData() { probe = RS::get_singleton()->voxel_gi_create(); } @@ -273,14 +291,14 @@ VoxelGI::Subdiv VoxelGI::get_subdiv() const { return subdiv; } -void VoxelGI::set_extents(const Vector3 &p_extents) { - // Prevent very small extents as these break baking if other extents are set very high. - extents = Vector3(MAX(1.0, p_extents.x), MAX(1.0, p_extents.y), MAX(1.0, p_extents.z)); +void VoxelGI::set_size(const Vector3 &p_size) { + // Prevent very small size dimensions as these breaks baking if other size dimensions are set very high. + size = Vector3(MAX(1.0, p_size.x), MAX(1.0, p_size.y), MAX(1.0, p_size.z)); update_gizmos(); } -Vector3 VoxelGI::get_extents() const { - return extents; +Vector3 VoxelGI::get_size() const { + return size; } void VoxelGI::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) { @@ -300,7 +318,7 @@ void VoxelGI::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) { Transform3D xf = get_global_transform().affine_inverse() * mi->get_global_transform(); - if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { + if (AABB(-size / 2, size).intersects(xf.xform(aabb))) { PlotMesh pm; pm.local_xform = xf; pm.mesh = mesh; @@ -328,7 +346,7 @@ void VoxelGI::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) { Transform3D xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf); - if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { + if (AABB(-size / 2, size).intersects(xf.xform(aabb))) { PlotMesh pm; pm.local_xform = xf; pm.mesh = mesh; @@ -352,7 +370,7 @@ Vector3i VoxelGI::get_estimated_cell_size() const { static const int subdiv_value[SUBDIV_MAX] = { 6, 7, 8, 9 }; int cell_subdiv = subdiv_value[subdiv]; int axis_cell_size[3]; - AABB bounds = AABB(-extents, extents * 2.0); + AABB bounds = AABB(-size / 2, size); int longest_axis = bounds.get_longest_axis_index(); axis_cell_size[longest_axis] = 1 << cell_subdiv; @@ -390,7 +408,7 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) { Voxelizer baker; - baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0), exposure_normalization); + baker.begin_bake(subdiv_value[subdiv], AABB(-size / 2, size), exposure_normalization); List<PlotMesh> mesh_list; @@ -448,7 +466,7 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) { RS::get_singleton()->voxel_gi_set_baked_exposure_normalization(probe_data_new->get_rid(), exposure_normalization); - probe_data_new->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_voxel_gi_octree_size(), baker.get_voxel_gi_octree_cells(), baker.get_voxel_gi_data_cells(), df, baker.get_voxel_gi_level_cell_count()); + probe_data_new->allocate(baker.get_to_cell_space_xform(), AABB(-size / 2, size), baker.get_voxel_gi_octree_size(), baker.get_voxel_gi_octree_cells(), baker.get_voxel_gi_data_cells(), df, baker.get_voxel_gi_level_cell_count()); set_probe_data(probe_data_new); #ifdef TOOLS_ENABLED @@ -468,7 +486,7 @@ void VoxelGI::_debug_bake() { } AABB VoxelGI::get_aabb() const { - return AABB(-extents, extents * 2); + return AABB(-size / 2, size); } PackedStringArray VoxelGI::get_configuration_warnings() const { @@ -489,8 +507,8 @@ void VoxelGI::_bind_methods() { ClassDB::bind_method(D_METHOD("set_subdiv", "subdiv"), &VoxelGI::set_subdiv); ClassDB::bind_method(D_METHOD("get_subdiv"), &VoxelGI::get_subdiv); - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &VoxelGI::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &VoxelGI::get_extents); + ClassDB::bind_method(D_METHOD("set_size", "size"), &VoxelGI::set_size); + ClassDB::bind_method(D_METHOD("get_size"), &VoxelGI::get_size); ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &VoxelGI::set_camera_attributes); ClassDB::bind_method(D_METHOD("get_camera_attributes"), &VoxelGI::get_camera_attributes); @@ -500,7 +518,7 @@ void VoxelGI::_bind_methods() { ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_NONE, "suffix:m"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "VoxelGIData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ALWAYS_DUPLICATE), "set_probe_data", "get_probe_data"); diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h index ae348daf9e..d276186dd1 100644 --- a/scene/3d/voxel_gi.h +++ b/scene/3d/voxel_gi.h @@ -118,7 +118,7 @@ private: RID voxel_gi; Subdiv subdiv = SUBDIV_128; - Vector3 extents = Vector3(10, 10, 10); + Vector3 size = Vector3(20, 20, 20); Ref<CameraAttributes> camera_attributes; struct PlotMesh { @@ -133,6 +133,10 @@ private: protected: static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_property) const; +#endif // DISABLE_DEPRECATED public: static BakeBeginFunc bake_begin_function; @@ -145,8 +149,8 @@ public: void set_subdiv(Subdiv p_subdiv); Subdiv get_subdiv() const; - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; + void set_size(const Vector3 &p_size); + Vector3 get_size() const; void set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes); Ref<CameraAttributes> get_camera_attributes() const; diff --git a/scene/animation/animation_blend_space_1d.cpp b/scene/animation/animation_blend_space_1d.cpp index a2028b8de8..d28a6fcc04 100644 --- a/scene/animation/animation_blend_space_1d.cpp +++ b/scene/animation/animation_blend_space_1d.cpp @@ -30,12 +30,20 @@ #include "animation_blend_space_1d.h" +#include "animation_blend_tree.h" + void AnimationNodeBlendSpace1D::get_parameter_list(List<PropertyInfo> *r_list) const { r_list->push_back(PropertyInfo(Variant::FLOAT, blend_position)); + r_list->push_back(PropertyInfo(Variant::INT, closest, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE)); + r_list->push_back(PropertyInfo(Variant::FLOAT, length_internal, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE)); } Variant AnimationNodeBlendSpace1D::get_parameter_default_value(const StringName &p_parameter) const { - return 0; + if (p_parameter == closest) { + return -1; + } else { + return 0; + } } Ref<AnimationNode> AnimationNodeBlendSpace1D::get_child_by_name(const StringName &p_name) { @@ -77,6 +85,9 @@ void AnimationNodeBlendSpace1D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_value_label", "text"), &AnimationNodeBlendSpace1D::set_value_label); ClassDB::bind_method(D_METHOD("get_value_label"), &AnimationNodeBlendSpace1D::get_value_label); + ClassDB::bind_method(D_METHOD("set_blend_mode", "mode"), &AnimationNodeBlendSpace1D::set_blend_mode); + ClassDB::bind_method(D_METHOD("get_blend_mode"), &AnimationNodeBlendSpace1D::get_blend_mode); + ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeBlendSpace1D::set_use_sync); ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeBlendSpace1D::is_using_sync); @@ -91,7 +102,12 @@ void AnimationNodeBlendSpace1D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_space", "get_max_space"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "snap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_snap", "get_snap"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "value_label", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_value_label", "get_value_label"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Interpolated,Discrete,Carry", PROPERTY_USAGE_NO_EDITOR), "set_blend_mode", "get_blend_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_use_sync", "is_using_sync"); + + BIND_ENUM_CONSTANT(BLEND_MODE_INTERPOLATED); + BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE); + BIND_ENUM_CONSTANT(BLEND_MODE_DISCRETE_CARRY); } void AnimationNodeBlendSpace1D::get_child_nodes(List<ChildNode> *r_child_nodes) { @@ -214,6 +230,14 @@ String AnimationNodeBlendSpace1D::get_value_label() const { return value_label; } +void AnimationNodeBlendSpace1D::set_blend_mode(BlendMode p_blend_mode) { + blend_mode = p_blend_mode; +} + +AnimationNodeBlendSpace1D::BlendMode AnimationNodeBlendSpace1D::get_blend_mode() const { + return blend_mode; +} + void AnimationNodeBlendSpace1D::set_use_sync(bool p_sync) { sync = p_sync; } @@ -241,79 +265,125 @@ double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek, bool p_is_ } double blend_pos = get_parameter(blend_position); + int cur_closest = get_parameter(closest); + double cur_length_internal = get_parameter(length_internal); + double max_time_remaining = 0.0; - float weights[MAX_BLEND_POINTS] = {}; + if (blend_mode == BLEND_MODE_INTERPOLATED) { + float weights[MAX_BLEND_POINTS] = {}; + + int point_lower = -1; + float pos_lower = 0.0; + int point_higher = -1; + float pos_higher = 0.0; + + // find the closest two points to blend between + for (int i = 0; i < blend_points_used; i++) { + float pos = blend_points[i].position; + + if (pos <= blend_pos) { + if (point_lower == -1) { + point_lower = i; + pos_lower = pos; + } else if ((blend_pos - pos) < (blend_pos - pos_lower)) { + point_lower = i; + pos_lower = pos; + } + } else { + if (point_higher == -1) { + point_higher = i; + pos_higher = pos; + } else if ((pos - blend_pos) < (pos_higher - blend_pos)) { + point_higher = i; + pos_higher = pos; + } + } + } - int point_lower = -1; - float pos_lower = 0.0; - int point_higher = -1; - float pos_higher = 0.0; + // fill in weights - // find the closest two points to blend between - for (int i = 0; i < blend_points_used; i++) { - float pos = blend_points[i].position; - - if (pos <= blend_pos) { - if (point_lower == -1) { - point_lower = i; - pos_lower = pos; - } else if ((blend_pos - pos) < (blend_pos - pos_lower)) { - point_lower = i; - pos_lower = pos; - } + if (point_lower == -1 && point_higher != -1) { + // we are on the left side, no other point to the left + // we just play the next point. + + weights[point_higher] = 1.0; + } else if (point_higher == -1) { + // we are on the right side, no other point to the right + // we just play the previous point + + weights[point_lower] = 1.0; } else { - if (point_higher == -1) { - point_higher = i; - pos_higher = pos; - } else if ((pos - blend_pos) < (pos_higher - blend_pos)) { - point_higher = i; - pos_higher = pos; - } - } - } + // we are between two points. + // figure out weights, then blend the animations - // fill in weights + float distance_between_points = pos_higher - pos_lower; - if (point_lower == -1 && point_higher != -1) { - // we are on the left side, no other point to the left - // we just play the next point. + float current_pos_inbetween = blend_pos - pos_lower; - weights[point_higher] = 1.0; - } else if (point_higher == -1) { - // we are on the right side, no other point to the right - // we just play the previous point + float blend_percentage = current_pos_inbetween / distance_between_points; - weights[point_lower] = 1.0; - } else { - // we are between two points. - // figure out weights, then blend the animations + float blend_lower = 1.0 - blend_percentage; + float blend_higher = blend_percentage; - float distance_between_points = pos_higher - pos_lower; + weights[point_lower] = blend_lower; + weights[point_higher] = blend_higher; + } - float current_pos_inbetween = blend_pos - pos_lower; + // actually blend the animations now - float blend_percentage = current_pos_inbetween / distance_between_points; + for (int i = 0; i < blend_points_used; i++) { + if (i == point_lower || i == point_higher) { + double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, weights[i], FILTER_IGNORE, true); + max_time_remaining = MAX(max_time_remaining, remaining); + } else if (sync) { + blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true); + } + } + } else { + int new_closest = -1; + double new_closest_dist = 1e20; + + for (int i = 0; i < blend_points_used; i++) { + double d = abs(blend_points[i].position - blend_pos); + if (d < new_closest_dist) { + new_closest = i; + new_closest_dist = d; + } + } - float blend_lower = 1.0 - blend_percentage; - float blend_higher = blend_percentage; + if (new_closest != cur_closest && new_closest != -1) { + double from = 0.0; + if (blend_mode == BLEND_MODE_DISCRETE_CARRY && cur_closest != -1) { + //for ping-pong loop + Ref<AnimationNodeAnimation> na_c = static_cast<Ref<AnimationNodeAnimation>>(blend_points[cur_closest].node); + Ref<AnimationNodeAnimation> na_n = static_cast<Ref<AnimationNodeAnimation>>(blend_points[new_closest].node); + if (!na_c.is_null() && !na_n.is_null()) { + na_n->set_backward(na_c->is_backward()); + } + //see how much animation remains + from = cur_length_internal - blend_node(blend_points[cur_closest].name, blend_points[cur_closest].node, p_time, false, p_is_external_seeking, 0.0, FILTER_IGNORE, true); + } - weights[point_lower] = blend_lower; - weights[point_higher] = blend_higher; - } + max_time_remaining = blend_node(blend_points[new_closest].name, blend_points[new_closest].node, from, true, p_is_external_seeking, 1.0, FILTER_IGNORE, true); + cur_length_internal = from + max_time_remaining; - // actually blend the animations now + cur_closest = new_closest; - double max_time_remaining = 0.0; + } else { + max_time_remaining = blend_node(blend_points[cur_closest].name, blend_points[cur_closest].node, p_time, p_seek, p_is_external_seeking, 1.0, FILTER_IGNORE, true); + } - for (int i = 0; i < blend_points_used; i++) { - if (i == point_lower || i == point_higher) { - double remaining = blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, weights[i], FILTER_IGNORE, true); - max_time_remaining = MAX(max_time_remaining, remaining); - } else if (sync) { - blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true); + if (sync) { + for (int i = 0; i < blend_points_used; i++) { + if (i != cur_closest) { + blend_node(blend_points[i].name, blend_points[i].node, p_time, p_seek, p_is_external_seeking, 0, FILTER_IGNORE, true); + } + } } } + set_parameter(this->closest, cur_closest); + set_parameter(this->length_internal, cur_length_internal); return max_time_remaining; } diff --git a/scene/animation/animation_blend_space_1d.h b/scene/animation/animation_blend_space_1d.h index af93783c0d..a1e9a7a764 100644 --- a/scene/animation/animation_blend_space_1d.h +++ b/scene/animation/animation_blend_space_1d.h @@ -36,6 +36,14 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode { GDCLASS(AnimationNodeBlendSpace1D, AnimationRootNode); +public: + enum BlendMode { + BLEND_MODE_INTERPOLATED, + BLEND_MODE_DISCRETE, + BLEND_MODE_DISCRETE_CARRY, + }; + +protected: enum { MAX_BLEND_POINTS = 64 }; @@ -61,6 +69,10 @@ class AnimationNodeBlendSpace1D : public AnimationRootNode { void _tree_changed(); StringName blend_position = "blend_position"; + StringName closest = "closest"; + StringName length_internal = "length_internal"; + + BlendMode blend_mode = BLEND_MODE_INTERPOLATED; protected: bool sync = false; @@ -95,6 +107,9 @@ public: void set_value_label(const String &p_label); String get_value_label() const; + void set_blend_mode(BlendMode p_blend_mode); + BlendMode get_blend_mode() const; + void set_use_sync(bool p_sync); bool is_using_sync() const; @@ -107,4 +122,6 @@ public: ~AnimationNodeBlendSpace1D(); }; +VARIANT_ENUM_CAST(AnimationNodeBlendSpace1D::BlendMode) + #endif // ANIMATION_BLEND_SPACE_1D_H diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 45f4f690b9..797999625b 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -800,6 +800,14 @@ Ref<Curve> AnimationNodeTransition::get_xfade_curve() const { return xfade_curve; } +void AnimationNodeTransition::set_allow_transition_to_self(bool p_enable) { + allow_transition_to_self = p_enable; +} + +bool AnimationNodeTransition::is_allow_transition_to_self() const { + return allow_transition_to_self; +} + double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_is_external_seeking) { String cur_transition_request = get_parameter(transition_request); int cur_current_index = get_parameter(current_index); @@ -815,20 +823,22 @@ double AnimationNodeTransition::process(double p_time, bool p_seek, bool p_is_ex int new_idx = find_input(cur_transition_request); if (new_idx >= 0) { if (cur_current_index == new_idx) { - // Transition to same state. - restart = input_data[cur_current_index].reset; - cur_prev_xfading = 0; - set_parameter(prev_xfading, 0); - cur_prev_index = -1; - set_parameter(prev_index, -1); + if (allow_transition_to_self) { + // Transition to same state. + restart = input_data[cur_current_index].reset; + cur_prev_xfading = 0; + set_parameter(prev_xfading, 0); + cur_prev_index = -1; + set_parameter(prev_index, -1); + } } else { switched = true; cur_prev_index = cur_current_index; set_parameter(prev_index, cur_current_index); + cur_current_index = new_idx; + set_parameter(current_index, cur_current_index); + set_parameter(current_state, cur_transition_request); } - cur_current_index = new_idx; - set_parameter(current_index, cur_current_index); - set_parameter(current_state, cur_transition_request); } else { ERR_PRINT("No such input: '" + cur_transition_request + "'"); } @@ -932,8 +942,12 @@ void AnimationNodeTransition::_bind_methods() { ClassDB::bind_method(D_METHOD("set_xfade_curve", "curve"), &AnimationNodeTransition::set_xfade_curve); ClassDB::bind_method(D_METHOD("get_xfade_curve"), &AnimationNodeTransition::get_xfade_curve); + ClassDB::bind_method(D_METHOD("set_allow_transition_to_self", "enable"), &AnimationNodeTransition::set_allow_transition_to_self); + ClassDB::bind_method(D_METHOD("is_allow_transition_to_self"), &AnimationNodeTransition::is_allow_transition_to_self); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,120,0.01,suffix:s"), "set_xfade_time", "get_xfade_time"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "xfade_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_xfade_curve", "get_xfade_curve"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_transition_to_self"), "set_allow_transition_to_self", "is_allow_transition_to_self"); ADD_PROPERTY(PropertyInfo(Variant::INT, "input_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED, "Inputs,input_"), "set_input_count", "get_input_count"); } diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index 3c27edbf70..20f8e9b190 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -294,6 +294,7 @@ class AnimationNodeTransition : public AnimationNodeSync { double xfade_time = 0.0; Ref<Curve> xfade_curve; + bool allow_transition_to_self = false; protected: bool _get(const StringName &p_path, Variant &r_ret) const; @@ -325,6 +326,9 @@ public: void set_xfade_curve(const Ref<Curve> &p_curve); Ref<Curve> get_xfade_curve() const; + void set_allow_transition_to_self(bool p_enable); + bool is_allow_transition_to_self() const; + double process(double p_time, bool p_seek, bool p_is_external_seeking) override; AnimationNodeTransition(); diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 7fb831b3b2..ec28a5cca1 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -252,7 +252,7 @@ bool AnimationNodeStateMachinePlayback::_travel(AnimationNodeStateMachine *p_sta path.clear(); //a new one will be needed if (current == p_travel) { - return false; // Will teleport oneself (restart). + return !p_state_machine->is_allow_transition_to_self(); } Vector2 current_pos = p_state_machine->states[current].position; @@ -813,6 +813,14 @@ void AnimationNodeStateMachine::replace_node(const StringName &p_name, Ref<Anima p_node->connect("tree_changed", callable_mp(this, &AnimationNodeStateMachine::_tree_changed), CONNECT_REFERENCE_COUNTED); } +void AnimationNodeStateMachine::set_allow_transition_to_self(bool p_enable) { + allow_transition_to_self = p_enable; +} + +bool AnimationNodeStateMachine::is_allow_transition_to_self() const { + return allow_transition_to_self; +} + bool AnimationNodeStateMachine::can_edit_node(const StringName &p_name) const { if (states.has(p_name)) { return !(states[p_name].node->is_class("AnimationNodeStartState") || states[p_name].node->is_class("AnimationNodeEndState")); @@ -1383,6 +1391,11 @@ void AnimationNodeStateMachine::_bind_methods() { ClassDB::bind_method(D_METHOD("set_graph_offset", "offset"), &AnimationNodeStateMachine::set_graph_offset); ClassDB::bind_method(D_METHOD("get_graph_offset"), &AnimationNodeStateMachine::get_graph_offset); + + ClassDB::bind_method(D_METHOD("set_allow_transition_to_self", "enable"), &AnimationNodeStateMachine::set_allow_transition_to_self); + ClassDB::bind_method(D_METHOD("is_allow_transition_to_self"), &AnimationNodeStateMachine::is_allow_transition_to_self); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_transition_to_self"), "set_allow_transition_to_self", "is_allow_transition_to_self"); } AnimationNodeStateMachine::AnimationNodeStateMachine() { diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h index cf4d850aa6..5c2a4d6264 100644 --- a/scene/animation/animation_node_state_machine.h +++ b/scene/animation/animation_node_state_machine.h @@ -188,6 +188,7 @@ private: }; HashMap<StringName, State> states; + bool allow_transition_to_self = false; struct Transition { StringName from; @@ -254,6 +255,9 @@ public: void remove_transition_by_index(const int p_transition); void remove_transition(const StringName &p_from, const StringName &p_to); + void set_allow_transition_to_self(bool p_enable); + bool is_allow_transition_to_self() const; + bool can_edit_node(const StringName &p_name) const; AnimationNodeStateMachine *get_prev_state_machine() const; diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 1c1f94c986..fa72bbc593 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -1861,6 +1861,8 @@ void AnimationTree::_setup_animation_player() { return; } + cache_valid = false; + AnimationPlayer *new_player = nullptr; if (!animation_player.is_empty()) { new_player = Object::cast_to<AnimationPlayer>(get_node_or_null(animation_player)); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index f7c056316d..6f5e2cf058 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -692,6 +692,12 @@ Transform2D Control::get_transform() const { return xform; } +void Control::_toplevel_changed_on_parent() { + // Update root control status. + _notification(NOTIFICATION_EXIT_CANVAS); + _notification(NOTIFICATION_ENTER_CANVAS); +} + /// Anchors and offsets. void Control::_set_anchor(Side p_side, real_t p_anchor) { diff --git a/scene/gui/control.h b/scene/gui/control.h index a93a88e5b4..5977f4dbea 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -292,6 +292,9 @@ private: void _update_minimum_size(); void _size_changed(); + void _toplevel_changed() override{}; // Controls don't need to do anything, only other CanvasItems. + void _toplevel_changed_on_parent() override; + void _clear_size_warning(); // Input events. diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index dc23bcb14a..fe2eed6755 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -264,10 +264,6 @@ void GraphEdit::_scroll_moved(double) { top_layer->queue_redraw(); minimap->queue_redraw(); queue_redraw(); - - if (!setting_scroll_ofs) { //in godot, signals on change value are avoided as a convention - emit_signal(SNAME("scroll_offset_changed"), get_scroll_ofs()); - } } void GraphEdit::_update_scroll_offset() { @@ -290,6 +286,10 @@ void GraphEdit::_update_scroll_offset() { connections_layer->set_position(-Point2(h_scroll->get_value(), v_scroll->get_value())); set_block_minimum_size_adjust(false); awaiting_scroll_offset_update = false; + + if (!setting_scroll_ofs) { //in godot, signals on change value are avoided as a convention + emit_signal(SNAME("scroll_offset_changed"), get_scroll_ofs()); + } } void GraphEdit::_update_scroll() { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index ddc11d97b9..0eeac2f285 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -840,6 +840,9 @@ void PopupMenu::_notification(int p_what) { float pm_delay = pm->get_submenu_popup_delay(); set_submenu_popup_delay(pm_delay); } + if (!is_embedded()) { + set_flag(FLAG_NO_FOCUS, true); + } } break; case NOTIFICATION_THEME_CHANGED: diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp index 7c1d2f95a9..f10e1c2cd1 100644 --- a/scene/gui/subviewport_container.cpp +++ b/scene/gui/subviewport_container.cpp @@ -85,7 +85,7 @@ void SubViewportContainer::set_stretch_shrink(int p_shrink) { continue; } - c->set_size(get_size() / shrink); + c->set_size_force(get_size() / shrink); } queue_redraw(); @@ -116,7 +116,7 @@ void SubViewportContainer::_notification(int p_what) { continue; } - c->set_size(get_size() / shrink); + c->set_size_force(get_size() / shrink); } } break; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index d9e6157489..0f39715851 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -5256,7 +5256,6 @@ void Tree::_bind_methods() { ADD_SIGNAL(MethodInfo("empty_clicked", PropertyInfo(Variant::VECTOR2, "position"), PropertyInfo(Variant::INT, "mouse_button_index"))); ADD_SIGNAL(MethodInfo("item_edited")); ADD_SIGNAL(MethodInfo("custom_item_clicked", PropertyInfo(Variant::INT, "mouse_button_index"))); - ADD_SIGNAL(MethodInfo("item_custom_button_pressed")); ADD_SIGNAL(MethodInfo("item_icon_double_clicked")); ADD_SIGNAL(MethodInfo("item_collapsed", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"))); ADD_SIGNAL(MethodInfo("check_propagated_to_item", PropertyInfo(Variant::OBJECT, "item", PROPERTY_HINT_RESOURCE_TYPE, "TreeItem"), PropertyInfo(Variant::INT, "column"))); diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp index 6eb25bf852..1f3bbff779 100644 --- a/scene/gui/video_stream_player.cpp +++ b/scene/gui/video_stream_player.cpp @@ -236,7 +236,6 @@ void VideoStreamPlayer::set_stream(const Ref<VideoStream> &p_stream) { AudioServer::get_singleton()->unlock(); if (!playback.is_null()) { - playback->set_loop(loops); playback->set_paused(paused); texture = playback->get_texture(); @@ -344,6 +343,12 @@ int VideoStreamPlayer::get_buffering_msec() const { void VideoStreamPlayer::set_audio_track(int p_track) { audio_track = p_track; + if (stream.is_valid()) { + stream->set_audio_track(audio_track); + } + if (playback.is_valid()) { + playback->set_audio_track(audio_track); + } } int VideoStreamPlayer::get_audio_track() const { diff --git a/scene/gui/video_stream_player.h b/scene/gui/video_stream_player.h index 09ef272a9a..1fd599a9e1 100644 --- a/scene/gui/video_stream_player.h +++ b/scene/gui/video_stream_player.h @@ -65,7 +65,6 @@ class VideoStreamPlayer : public Control { float volume = 1.0; double last_audio_time = 0.0; bool expand = false; - bool loops = false; int buffering_ms = 500; int audio_track = 0; int bus_index = 0; diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 35176f0edd..541c7a0587 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -400,11 +400,28 @@ void CanvasItem::set_as_top_level(bool p_top_level) { _exit_canvas(); top_level = p_top_level; + _toplevel_changed(); _enter_canvas(); _notify_transform(); } +void CanvasItem::_toplevel_changed() { + // Inform children that toplevel status has changed on a parent. + int children = get_child_count(); + for (int i = 0; i < children; i++) { + CanvasItem *child = Object::cast_to<CanvasItem>(get_child(i)); + if (child) { + child->_toplevel_changed_on_parent(); + } + } +} + +void CanvasItem::_toplevel_changed_on_parent() { + // Inform children that toplevel status has changed on a parent. + _toplevel_changed(); +} + bool CanvasItem::is_set_as_top_level() const { return top_level; } diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index 1c84ea338a..1ddfaa288c 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -125,6 +125,9 @@ private: void _propagate_visibility_changed(bool p_parent_visible_in_tree); void _handle_visibility_change(bool p_visible); + virtual void _toplevel_changed(); + virtual void _toplevel_changed_on_parent(); + void _redraw_callback(); void _enter_canvas(); diff --git a/scene/main/multiplayer_api.cpp b/scene/main/multiplayer_api.cpp index c54e61580f..950eb2809c 100644 --- a/scene/main/multiplayer_api.cpp +++ b/scene/main/multiplayer_api.cpp @@ -329,9 +329,9 @@ void MultiplayerAPI::_bind_methods() { /// MultiplayerAPIExtension Error MultiplayerAPIExtension::poll() { - int err = OK; + Error err = OK; GDVIRTUAL_CALL(_poll, err); - return (Error)err; + return err; } void MultiplayerAPIExtension::set_multiplayer_peer(const Ref<MultiplayerPeer> &p_peer) { @@ -364,9 +364,9 @@ Error MultiplayerAPIExtension::rpcp(Object *p_obj, int p_peer_id, const StringNa for (int i = 0; i < p_argcount; i++) { args.push_back(*p_arg[i]); } - int ret = FAILED; + Error ret = FAILED; GDVIRTUAL_CALL(_rpc, p_peer_id, p_obj, p_method, args, ret); - return (Error)ret; + return ret; } int MultiplayerAPIExtension::get_remote_sender_id() { @@ -376,15 +376,15 @@ int MultiplayerAPIExtension::get_remote_sender_id() { } Error MultiplayerAPIExtension::object_configuration_add(Object *p_object, Variant p_config) { - int err = ERR_UNAVAILABLE; + Error err = ERR_UNAVAILABLE; GDVIRTUAL_CALL(_object_configuration_add, p_object, p_config, err); - return (Error)err; + return err; } Error MultiplayerAPIExtension::object_configuration_remove(Object *p_object, Variant p_config) { - int err = ERR_UNAVAILABLE; + Error err = ERR_UNAVAILABLE; GDVIRTUAL_CALL(_object_configuration_remove, p_object, p_config, err); - return (Error)err; + return err; } void MultiplayerAPIExtension::_bind_methods() { diff --git a/scene/main/multiplayer_api.h b/scene/main/multiplayer_api.h index 0b107ee50b..a578e6f2f1 100644 --- a/scene/main/multiplayer_api.h +++ b/scene/main/multiplayer_api.h @@ -101,15 +101,15 @@ public: virtual Error object_configuration_remove(Object *p_object, Variant p_config) override; // Extensions - GDVIRTUAL0R(int, _poll); + GDVIRTUAL0R(Error, _poll); GDVIRTUAL1(_set_multiplayer_peer, Ref<MultiplayerPeer>); GDVIRTUAL0R(Ref<MultiplayerPeer>, _get_multiplayer_peer); GDVIRTUAL0RC(int, _get_unique_id); GDVIRTUAL0RC(PackedInt32Array, _get_peer_ids); - GDVIRTUAL4R(int, _rpc, int, Object *, StringName, Array); + GDVIRTUAL4R(Error, _rpc, int, Object *, StringName, Array); GDVIRTUAL0RC(int, _get_remote_sender_id); - GDVIRTUAL2R(int, _object_configuration_add, Object *, Variant); - GDVIRTUAL2R(int, _object_configuration_remove, Object *, Variant); + GDVIRTUAL2R(Error, _object_configuration_add, Object *, Variant); + GDVIRTUAL2R(Error, _object_configuration_remove, Object *, Variant); }; #endif // MULTIPLAYER_API_H diff --git a/scene/main/multiplayer_peer.cpp b/scene/main/multiplayer_peer.cpp index 83555966d7..f3e56a1455 100644 --- a/scene/main/multiplayer_peer.cpp +++ b/scene/main/multiplayer_peer.cpp @@ -163,7 +163,7 @@ Error MultiplayerPeerExtension::put_packet(const uint8_t *p_buffer, int p_buffer if (!GDVIRTUAL_CALL(_put_packet_script, a, err)) { return FAILED; } - return (Error)err; + return err; } WARN_PRINT_ONCE("MultiplayerPeerExtension::_put_packet_native is unimplemented!"); return FAILED; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 48cff5aa8e..c31155bd5c 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -527,6 +527,11 @@ void Viewport::_process_picking() { if (to_screen_rect != Rect2i() && Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED) { return; } + if (!gui.mouse_in_viewport) { + // Clear picking events if mouse has left viewport. + physics_picking_events.clear(); + return; + } _drop_physics_mouseover(true); @@ -791,15 +796,21 @@ void Viewport::update_canvas_items() { _update_canvas_items(this); } -void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated) { - if (size == p_size && size_allocated == p_allocated && stretch_transform == p_stretch_transform && p_size_2d_override == size_2d_override && to_screen_rect == p_to_screen_rect) { +void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override, const Rect2i &p_to_screen_rect, bool p_allocated) { + Transform2D stretch_transform_new = Transform2D(); + if (is_size_2d_override_stretch_enabled() && p_size_2d_override.width > 0 && p_size_2d_override.height > 0) { + Size2 scale = Size2(p_size) / Size2(p_size_2d_override); + stretch_transform_new.scale(scale); + } + + if (size == p_size && size_allocated == p_allocated && stretch_transform == stretch_transform_new && p_size_2d_override == size_2d_override && to_screen_rect == p_to_screen_rect) { return; } size = p_size; size_allocated = p_allocated; size_2d_override = p_size_2d_override; - stretch_transform = p_stretch_transform; + stretch_transform = stretch_transform_new; to_screen_rect = p_to_screen_rect; #ifndef _3D_DISABLED @@ -1045,6 +1056,25 @@ Transform2D Viewport::get_final_transform() const { return _get_input_pre_xform().affine_inverse() * stretch_transform * global_canvas_transform; } +void Viewport::assign_next_enabled_camera_2d(const StringName &p_camera_group) { + List<Node *> camera_list; + get_tree()->get_nodes_in_group(p_camera_group, &camera_list); + + Camera2D *new_camera = nullptr; + for (const Node *E : camera_list) { + const Camera2D *cam = Object::cast_to<Camera2D>(E); + if (cam->is_enabled()) { + new_camera = const_cast<Camera2D *>(cam); + break; + } + } + + _camera_2d_set(new_camera); + if (!camera_2d) { + set_canvas_transform(Transform2D()); + } +} + void Viewport::_update_canvas_items(Node *p_node) { if (p_node != this) { Window *w = Object::cast_to<Window>(p_node); @@ -1110,14 +1140,11 @@ Viewport::PositionalShadowAtlasQuadrantSubdiv Viewport::get_positional_shadow_at } Transform2D Viewport::_get_input_pre_xform() const { - Transform2D pre_xf; - - if (to_screen_rect.size.x != 0 && to_screen_rect.size.y != 0) { - pre_xf.columns[2] = -to_screen_rect.position; - pre_xf.scale(Vector2(size) / to_screen_rect.size); + const Window *this_window = Object::cast_to<Window>(this); + if (this_window) { + return this_window->window_transform.affine_inverse(); } - - return pre_xf; + return Transform2D(); } Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) { @@ -4098,9 +4125,26 @@ Viewport::~Viewport() { ///////////////////////////////// void SubViewport::set_size(const Size2i &p_size) { - _set_size(p_size, _get_size_2d_override(), Rect2i(), _stretch_transform(), true); + _internal_set_size(p_size); +} + +void SubViewport::set_size_force(const Size2i &p_size) { + // Use only for setting the size from the parent SubViewportContainer with enabled stretch mode. + // Don't expose function to scripting. + _internal_set_size(p_size, true); +} +void SubViewport::_internal_set_size(const Size2i &p_size, bool p_force) { SubViewportContainer *c = Object::cast_to<SubViewportContainer>(get_parent()); + if (!p_force && c && c->is_stretch_enabled()) { +#ifdef DEBUG_ENABLED + WARN_PRINT("Can't change the size of a `SubViewport` with a `SubViewportContainer` parent that has `stretch` enabled. Set `SubViewportContainer.stretch` to `false` to allow changing the size manually."); +#endif // DEBUG_ENABLED + return; + } + + _set_size(p_size, _get_size_2d_override(), Rect2i(), true); + if (c) { c->update_minimum_size(); } @@ -4111,7 +4155,7 @@ Size2i SubViewport::get_size() const { } void SubViewport::set_size_2d_override(const Size2i &p_size) { - _set_size(_get_size(), p_size, Rect2i(), _stretch_transform(), true); + _set_size(_get_size(), p_size, Rect2i(), true); } Size2i SubViewport::get_size_2d_override() const { @@ -4124,7 +4168,7 @@ void SubViewport::set_size_2d_override_stretch(bool p_enable) { } size_2d_override_stretch = p_enable; - _set_size(_get_size(), _get_size_2d_override(), Rect2i(), _stretch_transform(), true); + _set_size(_get_size(), _get_size_2d_override(), Rect2i(), true); } bool SubViewport::is_size_2d_override_stretch_enabled() const { @@ -4153,17 +4197,6 @@ DisplayServer::WindowID SubViewport::get_window_id() const { return DisplayServer::INVALID_WINDOW_ID; } -Transform2D SubViewport::_stretch_transform() { - Transform2D transform; - Size2i view_size_2d_override = _get_size_2d_override(); - if (size_2d_override_stretch && view_size_2d_override.width > 0 && view_size_2d_override.height > 0) { - Size2 scale = Size2(_get_size()) / Size2(view_size_2d_override); - transform.scale(scale); - } - - return transform; -} - Transform2D SubViewport::get_screen_transform() const { Transform2D container_transform; SubViewportContainer *c = Object::cast_to<SubViewportContainer>(get_parent()); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index d5d5201e9a..7546838568 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -471,7 +471,7 @@ private: uint64_t event_count = 0; protected: - void _set_size(const Size2i &p_size, const Size2i &p_size_2d_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated); + void _set_size(const Size2i &p_size, const Size2i &p_size_2d_override, const Rect2i &p_to_screen_rect, bool p_allocated); Size2i _get_size() const; Size2i _get_size_2d_override() const; @@ -511,6 +511,7 @@ public: Transform2D get_global_canvas_transform() const; Transform2D get_final_transform() const; + void assign_next_enabled_camera_2d(const StringName &p_camera_group); void gui_set_root_order_dirty(); @@ -648,6 +649,8 @@ public: void set_canvas_cull_mask_bit(uint32_t p_layer, bool p_enable); bool get_canvas_cull_mask_bit(uint32_t p_layer) const; + virtual bool is_size_2d_override_stretch_enabled() const { return true; } + virtual Transform2D get_screen_transform() const; virtual Transform2D get_popup_base_transform() const { return Transform2D(); } @@ -753,21 +756,23 @@ private: ClearMode clear_mode = CLEAR_MODE_ALWAYS; bool size_2d_override_stretch = false; + void _internal_set_size(const Size2i &p_size, bool p_force = false); + protected: static void _bind_methods(); virtual DisplayServer::WindowID get_window_id() const override; - Transform2D _stretch_transform(); void _notification(int p_what); public: void set_size(const Size2i &p_size); Size2i get_size() const; + void set_size_force(const Size2i &p_size); void set_size_2d_override(const Size2i &p_size); Size2i get_size_2d_override() const; void set_size_2d_override_stretch(bool p_enable); - bool is_size_2d_override_stretch_enabled() const; + bool is_size_2d_override_stretch_enabled() const override; void set_update_mode(UpdateMode p_mode); UpdateMode get_update_mode() const; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 869d12b4df..b6f1d3f54b 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -905,16 +905,13 @@ void Window::_update_viewport_size() { Size2i final_size; Size2i final_size_override; Rect2i attach_to_screen_rect(Point2i(), size); - Transform2D stretch_transform_new; float font_oversampling = 1.0; + window_transform = Transform2D(); if (content_scale_mode == CONTENT_SCALE_MODE_DISABLED || content_scale_size.x == 0 || content_scale_size.y == 0) { font_oversampling = content_scale_factor; final_size = size; final_size_override = Size2(size) / content_scale_factor; - - stretch_transform_new = Transform2D(); - stretch_transform_new.scale(Size2(content_scale_factor, content_scale_factor)); } else { //actual screen video mode Size2 video_mode = size; @@ -990,20 +987,24 @@ void Window::_update_viewport_size() { attach_to_screen_rect = Rect2(margin, screen_size); font_oversampling = (screen_size.x / viewport_size.x) * content_scale_factor; - Size2 scale = Vector2(screen_size) / Vector2(final_size_override); - stretch_transform_new.scale(scale); - + window_transform.translate_local(margin); } break; case CONTENT_SCALE_MODE_VIEWPORT: { final_size = (viewport_size / content_scale_factor).floor(); attach_to_screen_rect = Rect2(margin, screen_size); + window_transform.translate_local(margin); + if (final_size.x != 0 && final_size.y != 0) { + Transform2D scale_transform; + scale_transform.scale(Vector2(attach_to_screen_rect.size) / Vector2(final_size)); + window_transform *= scale_transform; + } } break; } } bool allocate = is_inside_tree() && visible && (window_id != DisplayServer::INVALID_WINDOW_ID || embedder != nullptr); - _set_size(final_size, final_size_override, attach_to_screen_rect, stretch_transform_new, allocate); + _set_size(final_size, final_size_override, attach_to_screen_rect, allocate); if (window_id != DisplayServer::INVALID_WINDOW_ID) { RenderingServer::get_singleton()->viewport_attach_to_screen(get_viewport_rid(), attach_to_screen_rect, window_id); @@ -2127,13 +2128,13 @@ Transform2D Window::get_popup_base_transform() const { if (is_embedding_subwindows()) { return Transform2D(); } - Transform2D window_transform; - window_transform.set_origin(get_position()); - window_transform *= Viewport::get_screen_transform(); + Transform2D popup_base_transform; + popup_base_transform.set_origin(get_position()); + popup_base_transform *= Viewport::get_screen_transform(); if (_get_embedder()) { - return _get_embedder()->get_popup_base_transform() * window_transform; + return _get_embedder()->get_popup_base_transform() * popup_base_transform; } - return window_transform; + return popup_base_transform; } void Window::_bind_methods() { @@ -2336,6 +2337,7 @@ void Window::_bind_methods() { ADD_SIGNAL(MethodInfo("visibility_changed")); ADD_SIGNAL(MethodInfo("about_to_popup")); ADD_SIGNAL(MethodInfo("theme_changed")); + ADD_SIGNAL(MethodInfo("dpi_changed")); ADD_SIGNAL(MethodInfo("titlebar_changed")); BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED); diff --git a/scene/main/window.h b/scene/main/window.h index 182caf5f0c..1730de0b33 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -173,6 +173,8 @@ private: Viewport *embedder = nullptr; + Transform2D window_transform; + friend class Viewport; //friend back, can call the methods below void _window_input(const Ref<InputEvent> &p_ev); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 7bebf1cfd3..39fc03f9f1 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -393,6 +393,8 @@ void register_scene_types() { GDREGISTER_CLASS(LineEdit); GDREGISTER_CLASS(VideoStreamPlayer); + GDREGISTER_VIRTUAL_CLASS(VideoStreamPlayback); + GDREGISTER_VIRTUAL_CLASS(VideoStream); #ifndef ADVANCED_GUI_DISABLED GDREGISTER_CLASS(FileDialog); @@ -906,7 +908,6 @@ void register_scene_types() { #ifndef _3D_DISABLED GDREGISTER_CLASS(AudioStreamPlayer3D); #endif - GDREGISTER_ABSTRACT_CLASS(VideoStream); GDREGISTER_CLASS(AudioStreamWAV); GDREGISTER_CLASS(AudioStreamPolyphonic); GDREGISTER_ABSTRACT_CLASS(AudioStreamPlaybackPolyphonic); diff --git a/scene/resources/bone_map.cpp b/scene/resources/bone_map.cpp index c73f8ca0b0..759d189bfa 100644 --- a/scene/resources/bone_map.cpp +++ b/scene/resources/bone_map.cpp @@ -152,7 +152,6 @@ void BoneMap::_validate_bone_map() { } else { bone_map.clear(); } - emit_signal("retarget_option_updated"); } void BoneMap::_bind_methods() { diff --git a/scene/resources/fog_material.cpp b/scene/resources/fog_material.cpp index 4e51bbaa73..aabaa54505 100644 --- a/scene/resources/fog_material.cpp +++ b/scene/resources/fog_material.cpp @@ -159,7 +159,7 @@ uniform sampler3D density_texture: hint_default_white; void fog() { DENSITY = density * clamp(exp2(-height_falloff * (WORLD_POSITION.y - OBJECT_POSITION.y)), 0.0, 1.0); DENSITY *= texture(density_texture, UVW).r; - DENSITY *= pow(clamp(-SDF / min(min(EXTENTS.x, EXTENTS.y), EXTENTS.z), 0.0, 1.0), edge_fade); + DENSITY *= pow(clamp(-2.0 * SDF / min(min(SIZE.x, SIZE.y), SIZE.z), 0.0, 1.0), edge_fade); ALBEDO = albedo.rgb; EMISSION = emission.rgb; } diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index 55b633a40c..672581bbe2 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -452,6 +452,7 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli new_indices.resize(index_count); Vector<float> merged_normals_f32 = vector3_to_float32_array(merged_normals.ptr(), merged_normals.size()); + const int simplify_options = SurfaceTool::SIMPLIFY_LOCK_BORDER; size_t new_index_count = SurfaceTool::simplify_with_attrib_func( (unsigned int *)new_indices.ptrw(), @@ -460,6 +461,7 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli sizeof(float) * 3, // Vertex stride index_target, max_mesh_error, + simplify_options, &mesh_error, merged_normals_f32.ptr(), normal_weights.ptr(), 3); @@ -1058,6 +1060,8 @@ struct EditorSceneFormatImporterMeshLightmapSurface { String name; }; +static const uint32_t custom_shift[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM1_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM2_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM3_SHIFT }; + Error ImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache) { ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED); ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes."); @@ -1178,9 +1182,6 @@ Error ImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, return ERR_CANT_CREATE; } - //remove surfaces - clear(); - //create surfacetools for each surface.. LocalVector<Ref<SurfaceTool>> surfaces_tools; @@ -1190,9 +1191,16 @@ Error ImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, st->begin(Mesh::PRIMITIVE_TRIANGLES); st->set_material(lightmap_surfaces[i].material); st->set_meta("name", lightmap_surfaces[i].name); + + for (int custom_i = 0; custom_i < RS::ARRAY_CUSTOM_COUNT; custom_i++) { + st->set_custom_format(custom_i, (SurfaceTool::CustomFormat)((lightmap_surfaces[i].format >> custom_shift[custom_i]) & RS::ARRAY_FORMAT_CUSTOM_MASK)); + } surfaces_tools.push_back(st); //stay there } + //remove surfaces + clear(); + print_verbose("Mesh: Gen indices: " + itos(gen_index_count)); //go through all indices @@ -1229,6 +1237,11 @@ Error ImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_WEIGHTS) { surfaces_tools[surface]->set_weights(v.weights); } + for (int custom_i = 0; custom_i < RS::ARRAY_CUSTOM_COUNT; custom_i++) { + if ((lightmap_surfaces[surface].format >> custom_shift[custom_i]) & RS::ARRAY_FORMAT_CUSTOM_MASK) { + surfaces_tools[surface]->set_custom(custom_i, v.custom[custom_i]); + } + } Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]); surfaces_tools[surface]->set_uv2(uv2); @@ -1238,10 +1251,11 @@ Error ImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, } //generate surfaces - for (Ref<SurfaceTool> &tool : surfaces_tools) { + for (int i = 0; i < lightmap_surfaces.size(); i++) { + Ref<SurfaceTool> &tool = surfaces_tools[i]; tool->index(); Array arrays = tool->commit_to_arrays(); - add_surface(tool->get_primitive_type(), arrays, Array(), Dictionary(), tool->get_material(), tool->get_meta("name")); + add_surface(tool->get_primitive_type(), arrays, Array(), Dictionary(), tool->get_material(), tool->get_meta("name"), lightmap_surfaces[i].format); } set_lightmap_size_hint(Size2(size_x, size_y)); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index d6393966b1..7e84814ab3 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -2316,7 +2316,7 @@ BaseMaterial3D::TextureChannel BaseMaterial3D::get_refraction_texture_channel() return refraction_texture_channel; } -Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, Transparency p_transparency, bool p_double_sided, bool p_billboard, bool p_billboard_y, bool p_msdf, bool p_no_depth, bool p_fixed_size, TextureFilter p_filter, RID *r_shader_rid) { +Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, Transparency p_transparency, bool p_double_sided, bool p_billboard, bool p_billboard_y, bool p_msdf, bool p_no_depth, bool p_fixed_size, TextureFilter p_filter, AlphaAntiAliasing p_alpha_antialiasing_mode, RID *r_shader_rid) { uint64_t key = 0; key |= ((int8_t)p_shaded & 0x01) << 0; key |= ((int8_t)p_transparency & 0x07) << 1; // Bits 1-3. @@ -2326,7 +2326,8 @@ Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, Transparency p_ key |= ((int8_t)p_msdf & 0x01) << 7; key |= ((int8_t)p_no_depth & 0x01) << 8; key |= ((int8_t)p_fixed_size & 0x01) << 9; - key |= ((int8_t)p_filter & 0x07) << 10; // Bits 10-13. + key |= ((int8_t)p_filter & 0x07) << 10; // Bits 10-12. + key |= ((int8_t)p_alpha_antialiasing_mode & 0x07) << 13; // Bits 13-15. if (materials_for_2d.has(key)) { if (r_shader_rid) { @@ -2346,6 +2347,7 @@ Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, Transparency p_ material->set_flag(FLAG_ALBEDO_TEXTURE_MSDF, p_msdf); material->set_flag(FLAG_DISABLE_DEPTH_TEST, p_no_depth); material->set_flag(FLAG_FIXED_SIZE, p_fixed_size); + material->set_alpha_antialiasing(p_alpha_antialiasing_mode); material->set_texture_filter(p_filter); if (p_billboard || p_billboard_y) { material->set_flag(FLAG_BILLBOARD_KEEP_SCALE, true); diff --git a/scene/resources/material.h b/scene/resources/material.h index 23f3a8824d..5ea9a807d4 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -760,7 +760,7 @@ public: static void finish_shaders(); static void flush_changes(); - static Ref<Material> get_material_for_2d(bool p_shaded, Transparency p_transparency, bool p_double_sided, bool p_billboard = false, bool p_billboard_y = false, bool p_msdf = false, bool p_no_depth = false, bool p_fixed_size = false, TextureFilter p_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RID *r_shader_rid = nullptr); + static Ref<Material> get_material_for_2d(bool p_shaded, Transparency p_transparency, bool p_double_sided, bool p_billboard = false, bool p_billboard_y = false, bool p_msdf = false, bool p_no_depth = false, bool p_fixed_size = false, TextureFilter p_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, AlphaAntiAliasing p_alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF, RID *r_shader_rid = nullptr); virtual RID get_shader_rid() const override; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index e497a628aa..1e9038139e 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -43,7 +43,7 @@ #include "scene/main/missing_node.h" #include "scene/property_utils.h" -#define PACKED_SCENE_VERSION 2 +#define PACKED_SCENE_VERSION 3 #define META_POINTER_PROPERTY_BASE "metadata/_editor_prop_ptr_" bool SceneState::can_instantiate() const { return nodes.size() > 0; @@ -314,7 +314,19 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { //must make a copy, because this res is local to scene } } - } else if (p_edit_state == GEN_EDIT_STATE_INSTANCE) { + } + if (value.get_type() == Variant::ARRAY) { + Array set_array = value; + bool is_get_valid = false; + Variant get_value = node->get(snames[nprops[j].name], &is_get_valid); + if (is_get_valid && get_value.get_type() == Variant::ARRAY) { + Array get_array = get_value; + if (!set_array.is_same_typed(get_array)) { + value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script()); + } + } + } + if (p_edit_state == GEN_EDIT_STATE_INSTANCE && value.get_type() != Variant::OBJECT) { value = value.duplicate(true); // Duplicate arrays and dictionaries for the editor } @@ -1282,6 +1294,9 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { for (int j = 0; j < cd.binds.size(); j++) { cd.binds.write[j] = r[idx++]; } + if (version >= 3) { + cd.unbinds = r[idx++]; + } } } @@ -1368,6 +1383,7 @@ Dictionary SceneState::get_bundled_scene() const { for (int j = 0; j < cd.binds.size(); j++) { rconns.push_back(cd.binds[j]); } + rconns.push_back(cd.unbinds); } d["conns"] = rconns; diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index 0ba177f882..608d15019e 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -636,6 +636,18 @@ Error ResourceLoaderText::load() { } } + if (value.get_type() == Variant::ARRAY) { + Array set_array = value; + bool is_get_valid = false; + Variant get_value = res->get(assign, &is_get_valid); + if (is_get_valid && get_value.get_type() == Variant::ARRAY) { + Array get_array = get_value; + if (!set_array.is_same_typed(get_array)) { + value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script()); + } + } + } + if (set_valid) { res->set(assign, value); } @@ -746,6 +758,18 @@ Error ResourceLoaderText::load() { } } + if (value.get_type() == Variant::ARRAY) { + Array set_array = value; + bool is_get_valid = false; + Variant get_value = resource->get(assign, &is_get_valid); + if (is_get_valid && get_value.get_type() == Variant::ARRAY) { + Array get_array = get_value; + if (!set_array.is_same_typed(get_array)) { + value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script()); + } + } + } + if (set_valid) { resource->set(assign, value); } diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 5a2b917b9a..16cc1c3370 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -1307,7 +1307,8 @@ Vector<int> SurfaceTool::generate_lod(float p_threshold, int p_target_index_coun } float error; - uint32_t index_count = simplify_func((unsigned int *)lod.ptrw(), (unsigned int *)index_array.ptr(), index_array.size(), vertices.ptr(), vertex_array.size(), sizeof(float) * 3, p_target_index_count, p_threshold, &error); + const int simplify_options = SIMPLIFY_LOCK_BORDER; + uint32_t index_count = simplify_func((unsigned int *)lod.ptrw(), (unsigned int *)index_array.ptr(), index_array.size(), vertices.ptr(), vertex_array.size(), sizeof(float) * 3, p_target_index_count, p_threshold, simplify_options, &error); ERR_FAIL_COND_V(index_count == 0, lod); lod.resize(index_count); diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index 00438c4a53..77318bb061 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -74,11 +74,16 @@ public: SKIN_8_WEIGHTS }; + enum { + /* Do not move vertices that are located on the topological border (vertices on triangle edges that don't have a paired triangle). Useful for simplifying portions of the larger mesh. */ + SIMPLIFY_LOCK_BORDER = 1 << 0, // From meshopt_SimplifyLockBorder + }; + typedef void (*OptimizeVertexCacheFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, size_t vertex_count); static OptimizeVertexCacheFunc optimize_vertex_cache_func; - typedef size_t (*SimplifyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float *r_error); + typedef size_t (*SimplifyFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float *r_error); static SimplifyFunc simplify_func; - typedef size_t (*SimplifyWithAttribFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float *result_error, const float *attributes, const float *attribute_weights, size_t attribute_count); + typedef size_t (*SimplifyWithAttribFunc)(unsigned int *destination, const unsigned int *indices, size_t index_count, const float *vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, unsigned int options, float *result_error, const float *attributes, const float *attribute_weights, size_t attribute_count); static SimplifyWithAttribFunc simplify_with_attrib_func; typedef float (*SimplifyScaleFunc)(const float *vertex_positions, size_t vertex_count, size_t vertex_positions_stride); static SimplifyScaleFunc simplify_scale_func; diff --git a/scene/resources/video_stream.cpp b/scene/resources/video_stream.cpp new file mode 100644 index 0000000000..ee1a47c338 --- /dev/null +++ b/scene/resources/video_stream.cpp @@ -0,0 +1,198 @@ +/**************************************************************************/ +/* video_stream.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "video_stream.h" + +#include "core/config/project_settings.h" +#include "servers/audio_server.h" + +// VideoStreamPlayback starts here. + +void VideoStreamPlayback::_bind_methods() { + ClassDB::bind_method(D_METHOD("mix_audio", "num_frames", "buffer", "offset"), &VideoStreamPlayback::mix_audio, DEFVAL(PackedFloat32Array()), DEFVAL(0)); + GDVIRTUAL_BIND(_stop); + GDVIRTUAL_BIND(_play); + GDVIRTUAL_BIND(_is_playing); + GDVIRTUAL_BIND(_set_paused, "paused"); + GDVIRTUAL_BIND(_is_paused); + GDVIRTUAL_BIND(_get_length); + GDVIRTUAL_BIND(_get_playback_position); + GDVIRTUAL_BIND(_seek, "time"); + GDVIRTUAL_BIND(_set_audio_track, "idx"); + GDVIRTUAL_BIND(_get_texture); + GDVIRTUAL_BIND(_update, "delta"); + GDVIRTUAL_BIND(_get_channels); + GDVIRTUAL_BIND(_get_mix_rate); +} + +VideoStreamPlayback::VideoStreamPlayback() { +} + +VideoStreamPlayback::~VideoStreamPlayback() { +} + +void VideoStreamPlayback::stop() { + GDVIRTUAL_CALL(_stop); +} + +void VideoStreamPlayback::play() { + GDVIRTUAL_CALL(_play); +} + +bool VideoStreamPlayback::is_playing() const { + bool ret; + if (GDVIRTUAL_CALL(_is_playing, ret)) { + return ret; + } + return false; +} + +void VideoStreamPlayback::set_paused(bool p_paused) { + GDVIRTUAL_CALL(_is_playing, p_paused); +} + +bool VideoStreamPlayback::is_paused() const { + bool ret; + if (GDVIRTUAL_CALL(_is_paused, ret)) { + return ret; + } + return false; +} + +double VideoStreamPlayback::get_length() const { + double ret; + if (GDVIRTUAL_CALL(_get_length, ret)) { + return ret; + } + return 0; +} + +double VideoStreamPlayback::get_playback_position() const { + double ret; + if (GDVIRTUAL_CALL(_get_playback_position, ret)) { + return ret; + } + return 0; +} + +void VideoStreamPlayback::seek(double p_time) { + GDVIRTUAL_CALL(_seek, p_time); +} + +void VideoStreamPlayback::set_audio_track(int p_idx) { + GDVIRTUAL_CALL(_set_audio_track, p_idx); +} + +Ref<Texture2D> VideoStreamPlayback::get_texture() const { + Ref<Texture2D> ret; + if (GDVIRTUAL_CALL(_get_texture, ret)) { + return ret; + } + return nullptr; +} + +void VideoStreamPlayback::update(double p_delta) { + if (!GDVIRTUAL_CALL(_update, p_delta)) { + ERR_FAIL_MSG("VideoStreamPlayback::update unimplemented"); + } +} + +void VideoStreamPlayback::set_mix_callback(AudioMixCallback p_callback, void *p_userdata) { + mix_callback = p_callback; + mix_udata = p_userdata; +} + +int VideoStreamPlayback::get_channels() const { + int ret; + if (GDVIRTUAL_CALL(_get_channels, ret)) { + _channel_count = ret; + return ret; + } + return 0; +} + +int VideoStreamPlayback::get_mix_rate() const { + int ret; + if (GDVIRTUAL_CALL(_get_mix_rate, ret)) { + return ret; + } + return 0; +} + +int VideoStreamPlayback::mix_audio(int num_frames, PackedFloat32Array buffer, int offset) { + if (num_frames <= 0) { + return 0; + } + if (!mix_callback) { + return -1; + } + ERR_FAIL_INDEX_V(offset, buffer.size(), -1); + ERR_FAIL_INDEX_V((_channel_count < 1 ? 1 : _channel_count) * num_frames - 1, buffer.size() - offset, -1); + return mix_callback(mix_udata, buffer.ptr() + offset, num_frames); +} + +/* --- NOTE VideoStream starts here. ----- */ + +Ref<VideoStreamPlayback> VideoStream::instantiate_playback() { + Ref<VideoStreamPlayback> ret; + if (GDVIRTUAL_CALL(_instantiate_playback, ret)) { + ERR_FAIL_COND_V_MSG(ret.is_null(), nullptr, "Plugin returned null playback"); + ret->set_audio_track(audio_track); + return ret; + } + return nullptr; +} + +void VideoStream::set_file(const String &p_file) { + file = p_file; +} + +String VideoStream::get_file() { + return file; +} + +void VideoStream::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_file", "file"), &VideoStream::set_file); + ClassDB::bind_method(D_METHOD("get_file"), &VideoStream::get_file); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "file"), "set_file", "get_file"); + + GDVIRTUAL_BIND(_instantiate_playback); +} + +VideoStream::VideoStream() { +} + +VideoStream::~VideoStream() { +} + +void VideoStream::set_audio_track(int p_track) { + audio_track = p_track; +} diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h index f83c621d0a..b91a7acf35 100644 --- a/scene/resources/video_stream.h +++ b/scene/resources/video_stream.h @@ -31,6 +31,7 @@ #ifndef VIDEO_STREAM_H #define VIDEO_STREAM_H +#include "core/io/file_access.h" #include "scene/resources/texture.h" class VideoStreamPlayback : public Resource { @@ -39,40 +40,77 @@ class VideoStreamPlayback : public Resource { public: typedef int (*AudioMixCallback)(void *p_udata, const float *p_data, int p_frames); - virtual void stop() = 0; - virtual void play() = 0; +protected: + AudioMixCallback mix_callback = nullptr; + void *mix_udata = nullptr; + mutable int _channel_count = 0; // Used only to assist with bounds checking in mix_audio. + + static void _bind_methods(); + GDVIRTUAL0(_stop); + GDVIRTUAL0(_play); + GDVIRTUAL0RC(bool, _is_playing); + GDVIRTUAL1(_set_paused, bool); + GDVIRTUAL0RC(bool, _is_paused); + GDVIRTUAL0RC(double, _get_length); + GDVIRTUAL0RC(double, _get_playback_position); + GDVIRTUAL1(_seek, double); + GDVIRTUAL1(_set_audio_track, int); + GDVIRTUAL0RC(Ref<Texture2D>, _get_texture); + GDVIRTUAL1(_update, double); + GDVIRTUAL0RC(int, _get_channels); + GDVIRTUAL0RC(int, _get_mix_rate); + + int mix_audio(int num_frames, PackedFloat32Array buffer = {}, int offset = 0); - virtual bool is_playing() const = 0; +public: + VideoStreamPlayback(); + virtual ~VideoStreamPlayback(); - virtual void set_paused(bool p_paused) = 0; - virtual bool is_paused() const = 0; + virtual void stop(); + virtual void play(); - virtual void set_loop(bool p_enable) = 0; - virtual bool has_loop() const = 0; + virtual bool is_playing() const; - virtual double get_length() const = 0; + virtual void set_paused(bool p_paused); + virtual bool is_paused() const; - virtual double get_playback_position() const = 0; - virtual void seek(double p_time) = 0; + virtual double get_length() const; - virtual void set_audio_track(int p_idx) = 0; + virtual double get_playback_position() const; + virtual void seek(double p_time); - virtual Ref<Texture2D> get_texture() const = 0; + virtual void set_audio_track(int p_idx); - virtual void update(double p_delta) = 0; + virtual Ref<Texture2D> get_texture() const; + virtual void update(double p_delta); - virtual void set_mix_callback(AudioMixCallback p_callback, void *p_userdata) = 0; - virtual int get_channels() const = 0; - virtual int get_mix_rate() const = 0; + virtual void set_mix_callback(AudioMixCallback p_callback, void *p_userdata); + virtual int get_channels() const; + virtual int get_mix_rate() const; }; class VideoStream : public Resource { GDCLASS(VideoStream, Resource); - OBJ_SAVE_TYPE(VideoStream); // Saves derived classes with common type so they can be interchanged. + OBJ_SAVE_TYPE(VideoStream); + +protected: + static void + _bind_methods(); + + GDVIRTUAL0R(Ref<VideoStreamPlayback>, _instantiate_playback); + + String file; + int audio_track = 0; public: - virtual void set_audio_track(int p_track) = 0; - virtual Ref<VideoStreamPlayback> instantiate_playback() = 0; + void set_file(const String &p_file); + String get_file(); + + virtual void set_audio_track(int p_track); + virtual Ref<VideoStreamPlayback> instantiate_playback(); + + VideoStream(); + ~VideoStream(); }; #endif // VIDEO_STREAM_H diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index bfcf5cb137..4132972cb3 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -427,7 +427,10 @@ void VisualShaderNodeCustom::update_ports() { if (!GDVIRTUAL_CALL(_get_input_port_name, i, port.name)) { port.name = "in" + itos(i); } - if (!GDVIRTUAL_CALL(_get_input_port_type, i, port.type)) { + PortType port_type; + if (GDVIRTUAL_CALL(_get_input_port_type, i, port_type)) { + port.type = (int)port_type; + } else { port.type = (int)PortType::PORT_TYPE_SCALAR; } @@ -445,7 +448,10 @@ void VisualShaderNodeCustom::update_ports() { if (!GDVIRTUAL_CALL(_get_output_port_name, i, port.name)) { port.name = "out" + itos(i); } - if (!GDVIRTUAL_CALL(_get_output_port_type, i, port.type)) { + PortType port_type; + if (GDVIRTUAL_CALL(_get_output_port_type, i, port_type)) { + port.type = (int)port_type; + } else { port.type = (int)PortType::PORT_TYPE_SCALAR; } @@ -2702,6 +2708,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "eye_offset", "EYE_OFFSET" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_world", "NODE_POSITION_WORLD" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_position_world", "CAMERA_POSITION_WORLD" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_direction_world", "CAMERA_DIRECTION_WORLD" }, @@ -2736,6 +2743,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "eye_offset", "EYE_OFFSET" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_world", "NODE_POSITION_WORLD" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_position_world", "CAMERA_POSITION_WORLD" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_direction_world", "CAMERA_DIRECTION_WORLD" }, @@ -2936,7 +2944,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "world_position", "WORLD_POSITION" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "object_position", "OBJECT_POSITION" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "uvw", "UVW" }, - { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "extents", "EXTENTS" }, + { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "size", "SIZE" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "sdf", "SDF" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 0d53589fa5..fc5e48410b 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -369,12 +369,12 @@ protected: GDVIRTUAL0RC(String, _get_name) GDVIRTUAL0RC(String, _get_description) GDVIRTUAL0RC(String, _get_category) - GDVIRTUAL0RC(int, _get_return_icon_type) + GDVIRTUAL0RC(PortType, _get_return_icon_type) GDVIRTUAL0RC(int, _get_input_port_count) - GDVIRTUAL1RC(int, _get_input_port_type, int) + GDVIRTUAL1RC(PortType, _get_input_port_type, int) GDVIRTUAL1RC(String, _get_input_port_name, int) GDVIRTUAL0RC(int, _get_output_port_count) - GDVIRTUAL1RC(int, _get_output_port_type, int) + GDVIRTUAL1RC(PortType, _get_output_port_type, int) GDVIRTUAL1RC(String, _get_output_port_name, int) GDVIRTUAL4RC(String, _get_code, TypedArray<String>, TypedArray<String>, Shader::Mode, VisualShader::Type) GDVIRTUAL2RC(String, _get_func_code, Shader::Mode, VisualShader::Type) diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 12be0f46a6..0695492e7f 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -6923,15 +6923,34 @@ void VisualShaderNodeSwitch::_bind_methods() { // static } String VisualShaderNodeSwitch::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) const { + bool use_mix = false; + switch (op_type) { + case OP_TYPE_FLOAT: { + use_mix = true; + } break; + case OP_TYPE_VECTOR_2D: { + use_mix = true; + } break; + case OP_TYPE_VECTOR_3D: { + use_mix = true; + } break; + case OP_TYPE_VECTOR_4D: { + use_mix = true; + } break; + default: { + } break; + } + String code; - code += " if(" + p_input_vars[0] + ")\n"; - code += " {\n"; - code += " " + p_output_vars[0] + " = " + p_input_vars[1] + ";\n"; - code += " }\n"; - code += " else\n"; - code += " {\n"; - code += " " + p_output_vars[0] + " = " + p_input_vars[2] + ";\n"; - code += " }\n"; + if (use_mix) { + code += " " + p_output_vars[0] + " = mix(" + p_input_vars[2] + ", " + p_input_vars[1] + ", float(" + p_input_vars[0] + "));\n"; + } else { + code += " if (" + p_input_vars[0] + ") {\n"; + code += " " + p_output_vars[0] + " = " + p_input_vars[1] + ";\n"; + code += " } else {\n"; + code += " " + p_output_vars[0] + " = " + p_input_vars[2] + ";\n"; + code += " }\n"; + } return code; } diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index 2a70139bcb..c7304da358 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -43,6 +43,14 @@ RID World2D::get_canvas() const { } RID World2D::get_space() const { + if (space.is_null()) { + space = PhysicsServer2D::get_singleton()->space_create(); + PhysicsServer2D::get_singleton()->space_set_active(space, true); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_GET("physics/2d/default_gravity")); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_GET("physics/2d/default_gravity_vector")); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_LINEAR_DAMP, GLOBAL_GET("physics/2d/default_linear_damp")); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_GET("physics/2d/default_angular_damp")); + } return space; } @@ -71,19 +79,11 @@ void World2D::_bind_methods() { } PhysicsDirectSpaceState2D *World2D::get_direct_space_state() { - return PhysicsServer2D::get_singleton()->space_get_direct_state(space); + return PhysicsServer2D::get_singleton()->space_get_direct_state(get_space()); } World2D::World2D() { canvas = RenderingServer::get_singleton()->canvas_create(); - - // Create and configure space2D to be more friendly with pixels than meters - space = PhysicsServer2D::get_singleton()->space_create(); - PhysicsServer2D::get_singleton()->space_set_active(space, true); - PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF_BASIC("physics/2d/default_gravity", 980.0)); - PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF_BASIC("physics/2d/default_gravity_vector", Vector2(0, 1))); - PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), 0.1)); - PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), 1.0)); } World2D::~World2D() { @@ -91,7 +91,9 @@ World2D::~World2D() { ERR_FAIL_NULL(PhysicsServer2D::get_singleton()); ERR_FAIL_NULL(NavigationServer2D::get_singleton()); RenderingServer::get_singleton()->free(canvas); - PhysicsServer2D::get_singleton()->free(space); + if (space.is_valid()) { + PhysicsServer2D::get_singleton()->free(space); + } if (navigation_map.is_valid()) { NavigationServer2D::get_singleton()->free(navigation_map); } diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index f02dddd2fe..0b3b9df7dc 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -43,7 +43,7 @@ class World2D : public Resource { GDCLASS(World2D, Resource); RID canvas; - RID space; + mutable RID space; mutable RID navigation_map; HashSet<Viewport *> viewports; diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp index cc4d261c0d..82c056d5ee 100644 --- a/scene/resources/world_3d.cpp +++ b/scene/resources/world_3d.cpp @@ -51,6 +51,14 @@ void World3D::_remove_camera(Camera3D *p_camera) { } RID World3D::get_space() const { + if (space.is_null()) { + space = PhysicsServer3D::get_singleton()->space_create(); + PhysicsServer3D::get_singleton()->space_set_active(space, true); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY, GLOBAL_GET("physics/3d/default_gravity")); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_GET("physics/3d/default_gravity_vector")); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_LINEAR_DAMP, GLOBAL_GET("physics/3d/default_linear_damp")); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_GET("physics/3d/default_angular_damp")); + } return space; } @@ -121,7 +129,7 @@ Ref<CameraAttributes> World3D::get_camera_attributes() const { } PhysicsDirectSpaceState3D *World3D::get_direct_space_state() { - return PhysicsServer3D::get_singleton()->space_get_direct_state(space); + return PhysicsServer3D::get_singleton()->space_get_direct_state(get_space()); } void World3D::_bind_methods() { @@ -145,22 +153,18 @@ void World3D::_bind_methods() { } World3D::World3D() { - space = PhysicsServer3D::get_singleton()->space_create(); scenario = RenderingServer::get_singleton()->scenario_create(); - - PhysicsServer3D::get_singleton()->space_set_active(space, true); - PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY, GLOBAL_DEF_BASIC("physics/3d/default_gravity", 9.8)); - PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF_BASIC("physics/3d/default_gravity_vector", Vector3(0, -1, 0))); - PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/default_linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), 0.1)); - PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), 0.1)); } World3D::~World3D() { - ERR_FAIL_NULL(PhysicsServer3D::get_singleton()); ERR_FAIL_NULL(RenderingServer::get_singleton()); + ERR_FAIL_NULL(PhysicsServer3D::get_singleton()); ERR_FAIL_NULL(NavigationServer3D::get_singleton()); - PhysicsServer3D::get_singleton()->free(space); + RenderingServer::get_singleton()->free(scenario); + if (space.is_valid()) { + PhysicsServer3D::get_singleton()->free(space); + } if (navigation_map.is_valid()) { NavigationServer3D::get_singleton()->free(navigation_map); } diff --git a/scene/resources/world_3d.h b/scene/resources/world_3d.h index ad17daf466..518fff64e2 100644 --- a/scene/resources/world_3d.h +++ b/scene/resources/world_3d.h @@ -45,8 +45,8 @@ class World3D : public Resource { GDCLASS(World3D, Resource); private: - RID space; RID scenario; + mutable RID space; mutable RID navigation_map; Ref<Environment> environment; diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 6b4435a991..8c877e4eed 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -144,7 +144,7 @@ int AudioDriver::get_total_channels_by_speaker_mode(AudioDriver::SpeakerMode p_m ERR_FAIL_V(2); } -PackedStringArray AudioDriver::get_device_list() { +PackedStringArray AudioDriver::get_output_device_list() { PackedStringArray list; list.push_back("Default"); @@ -152,11 +152,11 @@ PackedStringArray AudioDriver::get_device_list() { return list; } -String AudioDriver::get_device() { +String AudioDriver::get_output_device() { return "Default"; } -PackedStringArray AudioDriver::capture_get_device_list() { +PackedStringArray AudioDriver::get_input_device_list() { PackedStringArray list; list.push_back("Default"); @@ -238,7 +238,7 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) { #endif if (channel_count != get_channel_count()) { - // Amount of channels changed due to a device change + // Amount of channels changed due to a output_device change // reinitialize the buses channels and buffers init_channels_and_buffers(); } @@ -1632,28 +1632,28 @@ Ref<AudioBusLayout> AudioServer::generate_bus_layout() const { return state; } -PackedStringArray AudioServer::get_device_list() { - return AudioDriver::get_singleton()->get_device_list(); +PackedStringArray AudioServer::get_output_device_list() { + return AudioDriver::get_singleton()->get_output_device_list(); } -String AudioServer::get_device() { - return AudioDriver::get_singleton()->get_device(); +String AudioServer::get_output_device() { + return AudioDriver::get_singleton()->get_output_device(); } -void AudioServer::set_device(String device) { - AudioDriver::get_singleton()->set_device(device); +void AudioServer::set_output_device(String output_device) { + AudioDriver::get_singleton()->set_output_device(output_device); } -PackedStringArray AudioServer::capture_get_device_list() { - return AudioDriver::get_singleton()->capture_get_device_list(); +PackedStringArray AudioServer::get_input_device_list() { + return AudioDriver::get_singleton()->get_input_device_list(); } -String AudioServer::capture_get_device() { - return AudioDriver::get_singleton()->capture_get_device(); +String AudioServer::get_input_device() { + return AudioDriver::get_singleton()->get_input_device(); } -void AudioServer::capture_set_device(const String &p_name) { - AudioDriver::get_singleton()->capture_set_device(p_name); +void AudioServer::set_input_device(const String &p_name) { + AudioDriver::get_singleton()->set_input_device(p_name); } void AudioServer::set_enable_tagging_used_audio_streams(bool p_enable) { @@ -1711,17 +1711,17 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_speaker_mode"), &AudioServer::get_speaker_mode); ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioServer::get_mix_rate); - ClassDB::bind_method(D_METHOD("get_device_list"), &AudioServer::get_device_list); - ClassDB::bind_method(D_METHOD("get_device"), &AudioServer::get_device); - ClassDB::bind_method(D_METHOD("set_device", "device"), &AudioServer::set_device); + ClassDB::bind_method(D_METHOD("get_output_device_list"), &AudioServer::get_output_device_list); + ClassDB::bind_method(D_METHOD("get_output_device"), &AudioServer::get_output_device); + ClassDB::bind_method(D_METHOD("set_output_device", "output_device"), &AudioServer::set_output_device); ClassDB::bind_method(D_METHOD("get_time_to_next_mix"), &AudioServer::get_time_to_next_mix); ClassDB::bind_method(D_METHOD("get_time_since_last_mix"), &AudioServer::get_time_since_last_mix); ClassDB::bind_method(D_METHOD("get_output_latency"), &AudioServer::get_output_latency); - ClassDB::bind_method(D_METHOD("capture_get_device_list"), &AudioServer::capture_get_device_list); - ClassDB::bind_method(D_METHOD("capture_get_device"), &AudioServer::capture_get_device); - ClassDB::bind_method(D_METHOD("capture_set_device", "name"), &AudioServer::capture_set_device); + ClassDB::bind_method(D_METHOD("get_input_device_list"), &AudioServer::get_input_device_list); + ClassDB::bind_method(D_METHOD("get_input_device"), &AudioServer::get_input_device); + ClassDB::bind_method(D_METHOD("set_input_device", "name"), &AudioServer::set_input_device); ClassDB::bind_method(D_METHOD("set_bus_layout", "bus_layout"), &AudioServer::set_bus_layout); ClassDB::bind_method(D_METHOD("generate_bus_layout"), &AudioServer::generate_bus_layout); @@ -1729,11 +1729,11 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enable_tagging_used_audio_streams", "enable"), &AudioServer::set_enable_tagging_used_audio_streams); ADD_PROPERTY(PropertyInfo(Variant::INT, "bus_count"), "set_bus_count", "get_bus_count"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "device"), "set_device", "get_device"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "capture_device"), "capture_set_device", "capture_get_device"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "output_device"), "set_output_device", "get_output_device"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "input_device"), "set_input_device", "get_input_device"); // The default value may be set to an empty string by the platform-specific audio driver. // Override for class reference generation purposes. - ADD_PROPERTY_DEFAULT("capture_device", "Default"); + ADD_PROPERTY_DEFAULT("input_device", "Default"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_speed_scale"), "set_playback_speed_scale", "get_playback_speed_scale"); ADD_SIGNAL(MethodInfo("bus_layout_changed")); diff --git a/servers/audio_server.h b/servers/audio_server.h index a369efedf7..d3d87a8400 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -94,18 +94,18 @@ public: virtual void start() = 0; virtual int get_mix_rate() const = 0; virtual SpeakerMode get_speaker_mode() const = 0; - virtual PackedStringArray get_device_list(); - virtual String get_device(); - virtual void set_device(String device) {} + virtual PackedStringArray get_output_device_list(); + virtual String get_output_device(); + virtual void set_output_device(String output_device) {} virtual void lock() = 0; virtual void unlock() = 0; virtual void finish() = 0; virtual Error capture_start() { return FAILED; } virtual Error capture_stop() { return FAILED; } - virtual void capture_set_device(const String &p_name) {} - virtual String capture_get_device() { return "Default"; } - virtual PackedStringArray capture_get_device_list(); + virtual void set_input_device(const String &p_name) {} + virtual String get_input_device() { return "Default"; } + virtual PackedStringArray get_input_device_list(); virtual float get_latency() { return 0; } @@ -419,13 +419,13 @@ public: void set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout); Ref<AudioBusLayout> generate_bus_layout() const; - PackedStringArray get_device_list(); - String get_device(); - void set_device(String device); + PackedStringArray get_output_device_list(); + String get_output_device(); + void set_output_device(String output_device); - PackedStringArray capture_get_device_list(); - String capture_get_device(); - void capture_set_device(const String &p_name); + PackedStringArray get_input_device_list(); + String get_input_device(); + void set_input_device(const String &p_name); void set_enable_tagging_used_audio_streams(bool p_enable); diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index 2e4087c1de..85ba8ed431 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -207,6 +207,30 @@ void NavigationServer2D::set_debug_navigation_enable_edge_connections(const bool bool NavigationServer2D::get_debug_navigation_enable_edge_connections() const { return NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_connections(); } + +void NavigationServer2D::set_debug_navigation_agent_path_color(const Color &p_color) { + NavigationServer3D::get_singleton()->set_debug_navigation_agent_path_color(p_color); +} + +Color NavigationServer2D::get_debug_navigation_agent_path_color() const { + return NavigationServer3D::get_singleton()->get_debug_navigation_agent_path_color(); +} + +void NavigationServer2D::set_debug_navigation_enable_agent_paths(const bool p_value) { + NavigationServer3D::get_singleton()->set_debug_navigation_enable_agent_paths(p_value); +} + +bool NavigationServer2D::get_debug_navigation_enable_agent_paths() const { + return NavigationServer3D::get_singleton()->get_debug_navigation_enable_agent_paths(); +} + +void NavigationServer2D::set_debug_navigation_agent_path_point_size(float p_point_size) { + NavigationServer3D::get_singleton()->set_debug_navigation_agent_path_point_size(p_point_size); +} + +float NavigationServer2D::get_debug_navigation_agent_path_point_size() const { + return NavigationServer3D::get_singleton()->get_debug_navigation_agent_path_point_size(); +} #endif // DEBUG_ENABLED void NavigationServer2D::_bind_methods() { @@ -286,14 +310,26 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free); ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map"))); + + ADD_SIGNAL(MethodInfo("navigation_debug_changed")); } NavigationServer2D::NavigationServer2D() { singleton = this; ERR_FAIL_COND_MSG(!NavigationServer3D::get_singleton(), "The Navigation3D singleton should be initialized before the 2D one."); NavigationServer3D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationServer2D::_emit_map_changed)); + +#ifdef DEBUG_ENABLED + NavigationServer3D::get_singleton()->connect(SNAME("navigation_debug_changed"), callable_mp(this, &NavigationServer2D::_emit_navigation_debug_changed_signal)); +#endif // DEBUG_ENABLED } +#ifdef DEBUG_ENABLED +void NavigationServer2D::_emit_navigation_debug_changed_signal() { + emit_signal(SNAME("navigation_debug_changed")); +} +#endif // DEBUG_ENABLED + NavigationServer2D::~NavigationServer2D() { singleton = nullptr; } diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index cd18476182..746389404b 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -254,6 +254,20 @@ public: void set_debug_navigation_enable_edge_connections(const bool p_value); bool get_debug_navigation_enable_edge_connections() const; + + void set_debug_navigation_agent_path_color(const Color &p_color); + Color get_debug_navigation_agent_path_color() const; + + void set_debug_navigation_enable_agent_paths(const bool p_value); + bool get_debug_navigation_enable_agent_paths() const; + + void set_debug_navigation_agent_path_point_size(float p_point_size); + float get_debug_navigation_agent_path_point_size() const; +#endif // DEBUG_ENABLED + +#ifdef DEBUG_ENABLED +private: + void _emit_navigation_debug_changed_signal(); #endif // DEBUG_ENABLED }; diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 8f2cff0e04..70897ae75c 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -159,6 +159,7 @@ NavigationServer3D::NavigationServer3D() { debug_navigation_geometry_face_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_disabled_color", Color(0.5, 0.5, 0.5, 0.4)); debug_navigation_link_connection_color = GLOBAL_DEF("debug/shapes/navigation/link_connection_color", Color(1.0, 0.5, 1.0, 1.0)); debug_navigation_link_connection_disabled_color = GLOBAL_DEF("debug/shapes/navigation/link_connection_disabled_color", Color(0.5, 0.5, 0.5, 1.0)); + debug_navigation_agent_path_color = GLOBAL_DEF("debug/shapes/navigation/agent_path_color", Color(1.0, 0.0, 0.0, 1.0)); debug_navigation_enable_edge_connections = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections", true); debug_navigation_enable_edge_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections_xray", true); @@ -168,6 +169,11 @@ NavigationServer3D::NavigationServer3D() { debug_navigation_enable_link_connections = GLOBAL_DEF("debug/shapes/navigation/enable_link_connections", true); debug_navigation_enable_link_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_link_connections_xray", true); + debug_navigation_enable_agent_paths = GLOBAL_DEF("debug/shapes/navigation/enable_agent_paths", true); + debug_navigation_enable_agent_paths_xray = GLOBAL_DEF("debug/shapes/navigation/enable_agent_paths_xray", true); + + debug_navigation_agent_path_point_size = GLOBAL_DEF("debug/shapes/navigation/agent_path_point_size", 4.0); + if (Engine::get_singleton()->is_editor_hint()) { // enable NavigationServer3D when in Editor or else navigation mesh edge connections are invisible // on runtime tests SceneTree has "Visible Navigation" set and main iteration takes care of this @@ -329,6 +335,42 @@ Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_link_connection return debug_navigation_link_connections_disabled_material; } +Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_agent_path_line_material() { + if (debug_navigation_agent_path_line_material.is_valid()) { + return debug_navigation_agent_path_line_material; + } + + Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + material->set_albedo(debug_navigation_agent_path_color); + if (debug_navigation_enable_agent_paths_xray) { + material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); + } + material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2); + + debug_navigation_agent_path_line_material = material; + return debug_navigation_agent_path_line_material; +} + +Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_agent_path_point_material() { + if (debug_navigation_agent_path_point_material.is_valid()) { + return debug_navigation_agent_path_point_material; + } + + Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + material->set_albedo(debug_navigation_agent_path_color); + material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true); + material->set_point_size(debug_navigation_agent_path_point_size); + if (debug_navigation_enable_agent_paths_xray) { + material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); + } + material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2); + + debug_navigation_agent_path_point_material = material; + return debug_navigation_agent_path_point_material; +} + void NavigationServer3D::set_debug_navigation_edge_connection_color(const Color &p_color) { debug_navigation_edge_connection_color = p_color; if (debug_navigation_edge_connections_material.is_valid()) { @@ -406,6 +448,31 @@ Color NavigationServer3D::get_debug_navigation_link_connection_disabled_color() return debug_navigation_link_connection_disabled_color; } +void NavigationServer3D::set_debug_navigation_agent_path_point_size(float p_point_size) { + debug_navigation_agent_path_point_size = MAX(0.1, p_point_size); + if (debug_navigation_agent_path_point_material.is_valid()) { + debug_navigation_agent_path_point_material->set_point_size(debug_navigation_agent_path_point_size); + } +} + +float NavigationServer3D::get_debug_navigation_agent_path_point_size() const { + return debug_navigation_agent_path_point_size; +} + +void NavigationServer3D::set_debug_navigation_agent_path_color(const Color &p_color) { + debug_navigation_agent_path_color = p_color; + if (debug_navigation_agent_path_line_material.is_valid()) { + debug_navigation_agent_path_line_material->set_albedo(debug_navigation_agent_path_color); + } + if (debug_navigation_agent_path_point_material.is_valid()) { + debug_navigation_agent_path_point_material->set_albedo(debug_navigation_agent_path_color); + } +} + +Color NavigationServer3D::get_debug_navigation_agent_path_color() const { + return debug_navigation_agent_path_color; +} + void NavigationServer3D::set_debug_navigation_enable_edge_connections(const bool p_value) { debug_navigation_enable_edge_connections = p_value; debug_dirty = true; @@ -494,6 +561,37 @@ void NavigationServer3D::set_debug_enabled(bool p_enabled) { bool NavigationServer3D::get_debug_enabled() const { return debug_enabled; } + +void NavigationServer3D::set_debug_navigation_enable_agent_paths(const bool p_value) { + if (debug_navigation_enable_agent_paths != p_value) { + debug_dirty = true; + } + + debug_navigation_enable_agent_paths = p_value; + + if (debug_dirty) { + call_deferred("_emit_navigation_debug_changed_signal"); + } +} + +bool NavigationServer3D::get_debug_navigation_enable_agent_paths() const { + return debug_navigation_enable_agent_paths; +} + +void NavigationServer3D::set_debug_navigation_enable_agent_paths_xray(const bool p_value) { + debug_navigation_enable_agent_paths_xray = p_value; + if (debug_navigation_agent_path_line_material.is_valid()) { + debug_navigation_agent_path_line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_agent_paths_xray); + } + if (debug_navigation_agent_path_point_material.is_valid()) { + debug_navigation_agent_path_point_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_agent_paths_xray); + } +} + +bool NavigationServer3D::get_debug_navigation_enable_agent_paths_xray() const { + return debug_navigation_enable_agent_paths_xray; +} + #endif // DEBUG_ENABLED /////////////////////////////////////////////////////// diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index 9c468d1b10..bc4bdf2a30 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -287,6 +287,9 @@ private: Color debug_navigation_geometry_face_disabled_color = Color(0.5, 0.5, 0.5, 0.4); Color debug_navigation_link_connection_color = Color(1.0, 0.5, 1.0, 1.0); Color debug_navigation_link_connection_disabled_color = Color(0.5, 0.5, 0.5, 1.0); + Color debug_navigation_agent_path_color = Color(1.0, 0.0, 0.0, 1.0); + + float debug_navigation_agent_path_point_size = 4.0; bool debug_navigation_enable_edge_connections = true; bool debug_navigation_enable_edge_connections_xray = true; @@ -295,6 +298,8 @@ private: bool debug_navigation_enable_geometry_face_random_color = true; bool debug_navigation_enable_link_connections = true; bool debug_navigation_enable_link_connections_xray = true; + bool debug_navigation_enable_agent_paths = true; + bool debug_navigation_enable_agent_paths_xray = true; Ref<StandardMaterial3D> debug_navigation_geometry_edge_material; Ref<StandardMaterial3D> debug_navigation_geometry_face_material; @@ -304,6 +309,9 @@ private: Ref<StandardMaterial3D> debug_navigation_link_connections_material; Ref<StandardMaterial3D> debug_navigation_link_connections_disabled_material; + Ref<StandardMaterial3D> debug_navigation_agent_path_line_material; + Ref<StandardMaterial3D> debug_navigation_agent_path_point_material; + public: void set_debug_enabled(bool p_enabled); bool get_debug_enabled() const; @@ -329,6 +337,9 @@ public: void set_debug_navigation_link_connection_disabled_color(const Color &p_color); Color get_debug_navigation_link_connection_disabled_color() const; + void set_debug_navigation_agent_path_color(const Color &p_color); + Color get_debug_navigation_agent_path_color() const; + void set_debug_navigation_enable_edge_connections(const bool p_value); bool get_debug_navigation_enable_edge_connections() const; @@ -350,6 +361,15 @@ public: void set_debug_navigation_enable_link_connections_xray(const bool p_value); bool get_debug_navigation_enable_link_connections_xray() const; + void set_debug_navigation_enable_agent_paths(const bool p_value); + bool get_debug_navigation_enable_agent_paths() const; + + void set_debug_navigation_enable_agent_paths_xray(const bool p_value); + bool get_debug_navigation_enable_agent_paths_xray() const; + + void set_debug_navigation_agent_path_point_size(float p_point_size); + float get_debug_navigation_agent_path_point_size() const; + Ref<StandardMaterial3D> get_debug_navigation_geometry_face_material(); Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_material(); Ref<StandardMaterial3D> get_debug_navigation_geometry_face_disabled_material(); @@ -357,6 +377,9 @@ public: Ref<StandardMaterial3D> get_debug_navigation_edge_connections_material(); Ref<StandardMaterial3D> get_debug_navigation_link_connections_material(); Ref<StandardMaterial3D> get_debug_navigation_link_connections_disabled_material(); + + Ref<StandardMaterial3D> get_debug_navigation_agent_path_line_material(); + Ref<StandardMaterial3D> get_debug_navigation_agent_path_point_material(); #endif // DEBUG_ENABLED }; diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp index 4d93bbfa61..4d2148aa07 100644 --- a/servers/physics_2d/godot_area_2d.cpp +++ b/servers/physics_2d/godot_area_2d.cpp @@ -145,11 +145,8 @@ void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Varian case PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point = p_value; break; - case PhysicsServer2D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: - gravity_distance_scale = p_value; - break; - case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: - point_attenuation = p_value; + case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: + gravity_point_unit_distance = p_value; break; case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: _set_space_override_mode(linear_damping_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value); @@ -179,10 +176,8 @@ Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const { return gravity_vector; case PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; - case PhysicsServer2D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: - return gravity_distance_scale; - case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: - return point_attenuation; + case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: + return gravity_point_unit_distance; case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: return linear_damping_override_mode; case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP: @@ -304,13 +299,13 @@ void GodotArea2D::call_queries() { void GodotArea2D::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const { if (is_gravity_point()) { - const real_t gr_distance_scale = get_gravity_distance_scale(); + const real_t gr_unit_dist = get_gravity_point_unit_distance(); Vector2 v = get_transform().xform(get_gravity_vector()) - p_position; - if (gr_distance_scale > 0) { - const real_t v_length = v.length(); - if (v_length > 0) { - const real_t v_scaled = v_length * gr_distance_scale; - r_gravity = (v.normalized() * (get_gravity() / (v_scaled * v_scaled))); + if (gr_unit_dist > 0) { + const real_t v_length_sq = v.length_squared(); + if (v_length_sq > 0) { + const real_t gravity_strength = get_gravity() * gr_unit_dist * gr_unit_dist / v_length_sq; + r_gravity = v.normalized() * gravity_strength; } else { r_gravity = Vector2(); } diff --git a/servers/physics_2d/godot_area_2d.h b/servers/physics_2d/godot_area_2d.h index 07c89ecb88..234e4eb9a9 100644 --- a/servers/physics_2d/godot_area_2d.h +++ b/servers/physics_2d/godot_area_2d.h @@ -48,8 +48,7 @@ class GodotArea2D : public GodotCollisionObject2D { real_t gravity = 9.80665; Vector2 gravity_vector = Vector2(0, -1); bool gravity_is_point = false; - real_t gravity_distance_scale = 0.0; - real_t point_attenuation = 1.0; + real_t gravity_point_unit_distance = 0.0; real_t linear_damp = 0.1; real_t angular_damp = 1.0; int priority = 0; @@ -125,11 +124,8 @@ public: _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point = p_enable; } _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } - _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale = scale; } - _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; } - - _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation = p_point_attenuation; } - _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; } + _FORCE_INLINE_ void set_gravity_point_unit_distance(real_t scale) { gravity_point_unit_distance = scale; } + _FORCE_INLINE_ real_t get_gravity_point_unit_distance() const { return gravity_point_unit_distance; } _FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp = p_linear_damp; } _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; } diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 0a5a7c93cc..1beb5336f7 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -83,7 +83,7 @@ int GodotPhysicsDirectSpaceState2D::intersect_point(const PointParameters &p_par continue; } - if (p_parameters.canvas_instance_id.is_valid() && col_obj->get_canvas_instance_id() != p_parameters.canvas_instance_id) { + if (col_obj->get_canvas_instance_id() != p_parameters.canvas_instance_id) { continue; } @@ -1216,15 +1216,15 @@ GodotPhysicsDirectSpaceState2D *GodotSpace2D::get_direct_state() { } GodotSpace2D::GodotSpace2D() { - body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0); - body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg_to_rad(8.0)); - body_time_to_sleep = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 0.5); - solver_iterations = GLOBAL_DEF(PropertyInfo(Variant::INT, "physics/2d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"), 16); - contact_recycle_radius = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 1.0); - contact_max_separation = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 1.5); - contact_max_allowed_penetration = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_allowed_penetration", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 0.3); - contact_bias = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/default_contact_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.8); - constraint_bias = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/default_constraint_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.2); + body_linear_velocity_sleep_threshold = GLOBAL_GET("physics/2d/sleep_threshold_linear"); + body_angular_velocity_sleep_threshold = GLOBAL_GET("physics/2d/sleep_threshold_angular"); + body_time_to_sleep = GLOBAL_GET("physics/2d/time_before_sleep"); + solver_iterations = GLOBAL_GET("physics/2d/solver/solver_iterations"); + contact_recycle_radius = GLOBAL_GET("physics/2d/solver/contact_recycle_radius"); + contact_max_separation = GLOBAL_GET("physics/2d/solver/contact_max_separation"); + contact_max_allowed_penetration = GLOBAL_GET("physics/2d/solver/contact_max_allowed_penetration"); + contact_bias = GLOBAL_GET("physics/2d/solver/default_contact_bias"); + constraint_bias = GLOBAL_GET("physics/2d/solver/default_constraint_bias"); broadphase = GodotBroadPhase2D::create_func(); broadphase->set_pair_callback(_broadphase_pair, this); diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp index cd1f3b52b9..5bf16aa688 100644 --- a/servers/physics_3d/godot_area_3d.cpp +++ b/servers/physics_3d/godot_area_3d.cpp @@ -152,11 +152,8 @@ void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Varian case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point = p_value; break; - case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: - gravity_distance_scale = p_value; - break; - case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: - point_attenuation = p_value; + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: + gravity_point_unit_distance = p_value; break; case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: _set_space_override_mode(linear_damping_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value); @@ -200,10 +197,8 @@ Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const { return gravity_vector; case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; - case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: - return gravity_distance_scale; - case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: - return point_attenuation; + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE: + return gravity_point_unit_distance; case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE: return linear_damping_override_mode; case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: @@ -333,13 +328,13 @@ void GodotArea3D::call_queries() { void GodotArea3D::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const { if (is_gravity_point()) { - const real_t gr_distance_scale = get_gravity_distance_scale(); + const real_t gr_unit_dist = get_gravity_point_unit_distance(); Vector3 v = get_transform().xform(get_gravity_vector()) - p_position; - if (gr_distance_scale > 0) { - const real_t v_length = v.length(); - if (v_length > 0) { - const real_t v_scaled = v_length * gr_distance_scale; - r_gravity = (v.normalized() * (get_gravity() / (v_scaled * v_scaled))); + if (gr_unit_dist > 0) { + const real_t v_length_sq = v.length_squared(); + if (v_length_sq > 0) { + const real_t gravity_strength = get_gravity() * gr_unit_dist * gr_unit_dist / v_length_sq; + r_gravity = v.normalized() * gravity_strength; } else { r_gravity = Vector3(); } diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h index 0961da5b7d..f05d0f9019 100644 --- a/servers/physics_3d/godot_area_3d.h +++ b/servers/physics_3d/godot_area_3d.h @@ -49,8 +49,7 @@ class GodotArea3D : public GodotCollisionObject3D { real_t gravity = 9.80665; Vector3 gravity_vector = Vector3(0, -1, 0); bool gravity_is_point = false; - real_t gravity_distance_scale = 0.0; - real_t point_attenuation = 1.0; + real_t gravity_point_unit_distance = 0.0; real_t linear_damp = 0.1; real_t angular_damp = 0.1; real_t wind_force_magnitude = 0.0; @@ -134,11 +133,8 @@ public: _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point = p_enable; } _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } - _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale = scale; } - _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; } - - _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation = p_point_attenuation; } - _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; } + _FORCE_INLINE_ void set_gravity_point_unit_distance(real_t scale) { gravity_point_unit_distance = scale; } + _FORCE_INLINE_ real_t get_gravity_point_unit_distance() const { return gravity_point_unit_distance; } _FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp = p_linear_damp; } _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; } diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp index fb5a67c008..2de1d86de1 100644 --- a/servers/physics_3d/godot_collision_solver_3d.cpp +++ b/servers/physics_3d/godot_collision_solver_3d.cpp @@ -127,11 +127,10 @@ bool GodotCollisionSolver3D::solve_separation_ray(const GodotShape3D *p_shape_A, } if (p_result_callback) { + Vector3 normal = (support_B - support_A).normalized(); if (p_swap_result) { - Vector3 normal = (support_B - support_A).normalized(); - p_result_callback(support_B, 0, support_A, 0, normal, p_userdata); + p_result_callback(support_B, 0, support_A, 0, -normal, p_userdata); } else { - Vector3 normal = (support_A - support_B).normalized(); p_result_callback(support_A, 0, support_B, 0, normal, p_userdata); } } diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index 93572965d2..35f6fa023d 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -1250,14 +1250,14 @@ GodotPhysicsDirectSpaceState3D *GodotSpace3D::get_direct_state() { } GodotSpace3D::GodotSpace3D() { - body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1); - body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg_to_rad(8.0)); - body_time_to_sleep = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 0.5); - solver_iterations = GLOBAL_DEF(PropertyInfo(Variant::INT, "physics/3d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"), 16); - contact_recycle_radius = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.01); - contact_max_separation = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.05); - contact_max_allowed_penetration = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_allowed_penetration", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.01); - contact_bias = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/default_contact_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.8); + body_linear_velocity_sleep_threshold = GLOBAL_GET("physics/3d/sleep_threshold_linear"); + body_angular_velocity_sleep_threshold = GLOBAL_GET("physics/3d/sleep_threshold_angular"); + body_time_to_sleep = GLOBAL_GET("physics/3d/time_before_sleep"); + solver_iterations = GLOBAL_GET("physics/3d/solver/solver_iterations"); + contact_recycle_radius = GLOBAL_GET("physics/3d/solver/contact_recycle_radius"); + contact_max_separation = GLOBAL_GET("physics/3d/solver/contact_max_separation"); + contact_max_allowed_penetration = GLOBAL_GET("physics/3d/solver/contact_max_allowed_penetration"); + contact_bias = GLOBAL_GET("physics/3d/solver/default_contact_bias"); broadphase = GodotBroadPhase3D::create_func(); broadphase->set_pair_callback(_broadphase_pair, this); diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 214de27b35..f9a8d5f156 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -811,8 +811,7 @@ void PhysicsServer2D::_bind_methods() { BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE); BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP); BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE); @@ -880,6 +879,23 @@ void PhysicsServer2D::_bind_methods() { PhysicsServer2D::PhysicsServer2D() { singleton = this; + + // World2D physics space + GLOBAL_DEF_BASIC("physics/2d/default_gravity", 980.0); + GLOBAL_DEF_BASIC("physics/2d/default_gravity_vector", Vector2(0, 1)); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), 0.1); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), 1.0); + + // PhysicsServer2D + GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0); + GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg_to_rad(8.0)); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 0.5); + GLOBAL_DEF(PropertyInfo(Variant::INT, "physics/2d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"), 16); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 1.0); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 1.5); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_allowed_penetration", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 0.3); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/default_contact_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.8); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/default_constraint_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.2); } PhysicsServer2D::~PhysicsServer2D() { diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 836ab5bd76..3e254e610e 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -286,8 +286,7 @@ public: AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, - AREA_PARAM_GRAVITY_DISTANCE_SCALE, - AREA_PARAM_GRAVITY_POINT_ATTENUATION, + AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE, AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, AREA_PARAM_LINEAR_DAMP, AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index f1272a985d..6a163c86d2 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -976,8 +976,7 @@ void PhysicsServer3D::_bind_methods() { BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE); BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE); BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP); BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE); @@ -1048,6 +1047,22 @@ void PhysicsServer3D::_bind_methods() { PhysicsServer3D::PhysicsServer3D() { singleton = this; + + // World3D physics space + GLOBAL_DEF_BASIC("physics/3d/default_gravity", 9.8); + GLOBAL_DEF_BASIC("physics/3d/default_gravity_vector", Vector3(0, -1, 0)); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/default_linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), 0.1); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), 0.1); + + // PhysicsServer3D + GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1); + GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg_to_rad(8.0)); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 0.5); + GLOBAL_DEF(PropertyInfo(Variant::INT, "physics/3d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"), 16); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.01); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.05); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_allowed_penetration", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.01); + GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/default_contact_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.8); } PhysicsServer3D::~PhysicsServer3D() { diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index d1c644d51a..abf22e68a4 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -316,8 +316,7 @@ public: AREA_PARAM_GRAVITY, AREA_PARAM_GRAVITY_VECTOR, AREA_PARAM_GRAVITY_IS_POINT, - AREA_PARAM_GRAVITY_DISTANCE_SCALE, - AREA_PARAM_GRAVITY_POINT_ATTENUATION, + AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE, AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE, AREA_PARAM_LINEAR_DAMP, AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE, diff --git a/servers/rendering/dummy/environment/fog.h b/servers/rendering/dummy/environment/fog.h index 5531e2a5d0..10aa242060 100644 --- a/servers/rendering/dummy/environment/fog.h +++ b/servers/rendering/dummy/environment/fog.h @@ -44,7 +44,7 @@ public: virtual void fog_volume_free(RID p_rid) override {} virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {} - virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {} + virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) override {} virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override {} virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); } virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; } diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h index 99329055a8..9a3918fd86 100644 --- a/servers/rendering/dummy/storage/light_storage.h +++ b/servers/rendering/dummy/storage/light_storage.h @@ -101,7 +101,7 @@ public: virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {} virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {} virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {} - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {} + virtual void reflection_probe_set_size(RID p_probe, const Vector3 &p_size) override {} virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {} virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {} virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {} @@ -114,7 +114,7 @@ public: virtual AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); } virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; } virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; } - virtual Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); } + virtual Vector3 reflection_probe_get_size(RID p_probe) const override { return Vector3(); } virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); } virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; } virtual bool reflection_probe_renders_shadows(RID p_probe) const override { return false; } diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index fd36e7ac10..41251b348c 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -134,7 +134,7 @@ public: virtual void decal_initialize(RID p_rid) override {} virtual void decal_free(RID p_rid) override{}; - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {} + virtual void decal_set_size(RID p_decal, const Vector3 &p_size) override {} virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {} virtual void decal_set_emission_energy(RID p_decal, float p_energy) override {} virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override {} diff --git a/servers/rendering/environment/renderer_fog.h b/servers/rendering/environment/renderer_fog.h index ac56791711..f5c4134d14 100644 --- a/servers/rendering/environment/renderer_fog.h +++ b/servers/rendering/environment/renderer_fog.h @@ -44,7 +44,7 @@ public: virtual void fog_volume_free(RID p_rid) = 0; virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) = 0; - virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) = 0; + virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) = 0; virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) = 0; virtual AABB fog_volume_get_aabb(RID p_fog_volume) const = 0; virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const = 0; diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h index a13e6c8172..3ca7af70ca 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.h +++ b/servers/rendering/renderer_rd/cluster_builder_rd.h @@ -330,7 +330,7 @@ public: render_element_count++; } - _FORCE_INLINE_ void add_box(BoxType p_box_type, const Transform3D &p_transform, const Vector3 &p_half_extents) { + _FORCE_INLINE_ void add_box(BoxType p_box_type, const Transform3D &p_transform, const Vector3 &p_half_size) { if (p_box_type == BOX_TYPE_DECAL && cluster_count_by_type[ELEMENT_TYPE_DECAL] == max_elements_by_type) { return; // Max number elements reached. } @@ -342,7 +342,7 @@ public: Transform3D xform = view_xform * p_transform; // Extract scale and scale the matrix by it, makes things simpler. - Vector3 scale = p_half_extents; + Vector3 scale = p_half_size; for (uint32_t i = 0; i < 3; i++) { float s = xform.basis.rows[i].length(); scale[i] *= s; diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 2787693aeb..4253ea8610 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -82,11 +82,11 @@ void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } -void Fog::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) { +void Fog::fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); ERR_FAIL_COND(!fog_volume); - fog_volume->extents = p_extents; + fog_volume->size = p_size; fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } @@ -120,8 +120,8 @@ AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const { case RS::FOG_VOLUME_SHAPE_CYLINDER: case RS::FOG_VOLUME_SHAPE_BOX: { AABB aabb; - aabb.position = -fog_volume->extents; - aabb.size = fog_volume->extents * 2; + aabb.position = -fog_volume->size / 2; + aabb.size = fog_volume->size; return aabb; } default: { @@ -131,10 +131,10 @@ AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const { } } -Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const { +Vector3 Fog::fog_volume_get_size(RID p_fog_volume) const { const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); ERR_FAIL_COND_V(!fog_volume, Vector3()); - return fog_volume->extents; + return fog_volume->size; } //////////////////////////////////////////////////////////////////////////////// @@ -210,7 +210,7 @@ void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_lay actions.renames["WORLD_POSITION"] = "world.xyz"; actions.renames["OBJECT_POSITION"] = "params.position"; actions.renames["UVW"] = "uvw"; - actions.renames["EXTENTS"] = "params.extents"; + actions.renames["SIZE"] = "params.size"; actions.renames["ALBEDO"] = "albedo"; actions.renames["DENSITY"] = "density"; actions.renames["EMISSION"] = "emission"; @@ -643,7 +643,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P Vector3 position = fog_volume_instance->transform.get_origin(); RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); - Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_extents(fog_volume); + Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_size(fog_volume) / 2; if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) { // Local fog volume. @@ -683,9 +683,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P push_constant.position[0] = position.x; push_constant.position[1] = position.y; push_constant.position[2] = position.z; - push_constant.extents[0] = extents.x; - push_constant.extents[1] = extents.y; - push_constant.extents[2] = extents.z; + push_constant.size[0] = extents.x * 2; + push_constant.size[1] = extents.y * 2; + push_constant.size[2] = extents.z * 2; push_constant.corner[0] = min.x; push_constant.corner[1] = min.y; push_constant.corner[2] = min.z; diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index eb0a2fc7b5..0b6bcc29fb 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -53,7 +53,7 @@ private: struct FogVolume { RID material; - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(2, 2, 2); RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX; @@ -83,7 +83,7 @@ private: float position[3]; float pad; - float extents[3]; + float size[3]; float pad2; int32_t corner[3]; @@ -239,12 +239,12 @@ public: Dependency *fog_volume_get_dependency(RID p_fog_volume) const; virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override; - virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override; + virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) override; virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override; virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override; RID fog_volume_get_material(RID p_fog_volume) const; virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override; - Vector3 fog_volume_get_extents(RID p_fog_volume) const; + Vector3 fog_volume_get_size(RID p_fog_volume) const; /* FOG VOLUMES INSTANCE */ diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 814d145b66..7fff349b3c 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -574,7 +574,7 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; // half res if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { - if (reflection.layers[0].views[1].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { + if (reflection.layers.size() && reflection.layers[0].views.size() >= 2 && reflection.layers[0].views[1].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { u.append_id(reflection.layers[0].views[1]); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); @@ -594,7 +594,7 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; // quarter res if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { - if (reflection.layers[0].views[2].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { + if (reflection.layers.size() && reflection.layers[0].views.size() >= 3 && reflection.layers[0].views[2].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { u.append_id(reflection.layers[0].views[2]); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); @@ -1323,7 +1323,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, // Note, we ignore environment_get_sky_orientation here as this is applied when we do our lookup in our scene shader. - if (shader_data->uses_quarter_res) { + if (shader_data->uses_quarter_res && roughness_layers >= 3) { RD::get_singleton()->draw_command_begin_label("Render Sky to Quarter Res Cubemap"); PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES]; @@ -1340,9 +1340,11 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); + } else if (shader_data->uses_quarter_res && roughness_layers < 3) { + ERR_PRINT_ED("Cannot use quarter res buffer in sky shader when roughness layers is less than 3. Please increase rendering/reflections/sky_reflections/roughness_layers."); } - if (shader_data->uses_half_res) { + if (shader_data->uses_half_res && roughness_layers >= 2) { RD::get_singleton()->draw_command_begin_label("Render Sky to Half Res Cubemap"); PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES]; @@ -1359,6 +1361,8 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); + } else if (shader_data->uses_half_res && roughness_layers < 2) { + ERR_PRINT_ED("Cannot use half res buffer in sky shader when roughness layers is less than 2. Please increase rendering/reflections/sky_reflections/roughness_layers."); } RD::DrawListID cubemap_draw_list; diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 2e844269e3..59e1f559c7 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1232,9 +1232,9 @@ void RenderForwardClustered::_update_volumetric_fog(Ref<RenderSceneBuffersRD> p_ /* Lighting */ -void RenderForwardClustered::setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents) { +void RenderForwardClustered::setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_size) { if (current_cluster_builder != nullptr) { - current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, p_transform, p_half_extents); + current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, p_transform, p_half_size); } } @@ -1244,9 +1244,9 @@ void RenderForwardClustered::setup_added_light(const RS::LightType p_type, const } } -void RenderForwardClustered::setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents) { +void RenderForwardClustered::setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size) { if (current_cluster_builder != nullptr) { - current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, p_transform, p_half_extents); + current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, p_transform, p_half_size); } } @@ -2615,8 +2615,8 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu render_list[RENDER_LIST_SECONDARY].sort_by_key(); _fill_instance_data(RENDER_LIST_SECONDARY); - Vector3 half_extents = p_bounds.size * 0.5; - Vector3 center = p_bounds.position + half_extents; + Vector3 half_size = p_bounds.size * 0.5; + Vector3 center = p_bounds.position + half_size; Vector<RID> sbs = { p_albedo_texture, @@ -2644,16 +2644,16 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu fb_size.x = p_size[right_axis]; fb_size.y = p_size[up_axis]; - scene_data.cam_transform.origin = center + axis * half_extents; + scene_data.cam_transform.origin = center + axis * half_size; scene_data.cam_transform.basis.set_column(0, right); scene_data.cam_transform.basis.set_column(1, up); scene_data.cam_transform.basis.set_column(2, axis); //print_line("pass: " + itos(i) + " xform " + scene_data.cam_transform); - float h_size = half_extents[right_axis]; - float v_size = half_extents[up_axis]; - float d_size = half_extents[i] * 2.0; + float h_size = half_size[right_axis]; + float v_size = half_size[up_axis]; + float d_size = half_size[i] * 2.0; scene_data.cam_projection.set_orthogonal(-h_size, h_size, -v_size, v_size, 0, d_size); //print_line("pass: " + itos(i) + " cam hsize: " + rtos(h_size) + " vsize: " + rtos(v_size) + " dsize " + rtos(d_size)); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 9245f1b13a..8eb17ba6f4 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -640,9 +640,9 @@ public: RendererRD::SSEffects *get_ss_effects() { return ss_effects; } /* callback from updating our lighting UBOs, used to populate cluster builder */ - virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents) override; + virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_size) override; virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) override; - virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents) override; + virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size) override; virtual void base_uniforms_changed() override; _FORCE_INLINE_ virtual void update_uniform_sets() override { diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 2aaea4288b..3b3979b198 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -353,6 +353,11 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { } int variant = shader_version + shader_flags; + + if (!static_cast<SceneShaderForwardClustered *>(singleton)->shader.is_variant_enabled(variant)) { + continue; + } + RID shader_variant = shader_singleton->shader.version_get_shader(version, variant); color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants); } @@ -503,7 +508,14 @@ void SceneShaderForwardClustered::init(const String p_defines) { shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false); shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW, false); shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW, false); - // TODO Add a way to enable/disable color pass flags + + // Disable Color Passes + for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) { + // Selectively disable any shader pass that includes Multiview. + if ((i & SHADER_COLOR_PASS_FLAG_MULTIVIEW)) { + shader.set_variant_enabled(i + SHADER_VERSION_COLOR_PASS, false); + } + } } } @@ -625,6 +637,7 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "0"; actions.renames["VIEW_RIGHT"] = "1"; + actions.renames["EYE_OFFSET"] = "eye_offset"; //for light actions.renames["VIEW"] = "view"; diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index f9eecf4dc7..cc4a7dfa47 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -517,6 +517,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "0"; actions.renames["VIEW_RIGHT"] = "1"; + actions.renames["EYE_OFFSET"] = "eye_offset"; //for light actions.renames["VIEW"] = "view"; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 0f4fa1b9c4..bd8c11186e 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1550,6 +1550,9 @@ void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) { if (cl->texture == p_texture) { return; } + + ERR_FAIL_COND(p_texture.is_valid() && !texture_storage->owns_texture(p_texture)); + if (cl->texture.is_valid()) { texture_storage->texture_remove_from_decal_atlas(cl->texture); } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 6fa2f7a570..7c43021eb0 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -204,9 +204,9 @@ public: /* LIGHTING */ - virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents){}; + virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_size){}; virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture){}; - virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents){}; + virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size){}; /* GI */ diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl index 4658afd02d..8e4f5762fd 100644 --- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl @@ -37,7 +37,7 @@ layout(push_constant, std430) uniform Params { vec3 position; float pad; - vec3 extents; + vec3 size; float pad2; ivec3 corner; @@ -184,36 +184,37 @@ void main() { vec4 local_pos = params.transform * world; local_pos.xyz /= local_pos.w; + vec3 half_size = params.size / 2.0; float sdf = -1.0; if (params.shape == 0) { // Ellipsoid // https://www.shadertoy.com/view/tdS3DG - float k0 = length(local_pos.xyz / params.extents); - float k1 = length(local_pos.xyz / (params.extents * params.extents)); + float k0 = length(local_pos.xyz / half_size); + float k1 = length(local_pos.xyz / (half_size * half_size)); sdf = k0 * (k0 - 1.0) / k1; } else if (params.shape == 1) { // Cone // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm - // Compute the cone angle automatically to fit within the volume's extents. - float inv_height = 1.0 / max(0.001, params.extents.y); - float radius = 1.0 / max(0.001, (min(params.extents.x, params.extents.z) * 0.5)); + // Compute the cone angle automatically to fit within the volume's size. + float inv_height = 1.0 / max(0.001, half_size.y); + float radius = 1.0 / max(0.001, (min(half_size.x, half_size.z) * 0.5)); float hypotenuse = sqrt(radius * radius + inv_height * inv_height); float rsin = radius / hypotenuse; float rcos = inv_height / hypotenuse; vec2 c = vec2(rsin, rcos); float q = length(local_pos.xz); - sdf = max(dot(c, vec2(q, local_pos.y - params.extents.y)), -params.extents.y - local_pos.y); + sdf = max(dot(c, vec2(q, local_pos.y - half_size.y)), -half_size.y - local_pos.y); } else if (params.shape == 2) { // Cylinder // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm - vec2 d = abs(vec2(length(local_pos.xz), local_pos.y)) - vec2(min(params.extents.x, params.extents.z), params.extents.y); + vec2 d = abs(vec2(length(local_pos.xz), local_pos.y)) - vec2(min(half_size.x, half_size.z), half_size.y); sdf = min(max(d.x, d.y), 0.0) + length(max(d, 0.0)); } else if (params.shape == 3) { // Box // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm - vec3 q = abs(local_pos.xyz) - params.extents; + vec3 q = abs(local_pos.xyz) - half_size; sdf = length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0); } @@ -222,7 +223,7 @@ void main() { #ifndef SDF_USED cull_mask = 1.0 - smoothstep(-0.1, 0.0, sdf); #endif - uvw = clamp((local_pos.xyz + params.extents) / (2.0 * params.extents), 0.0, 1.0); + uvw = clamp((local_pos.xyz + half_size) / params.size, 0.0, 1.0); } if (cull_mask > 0.0) { diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index c6a3c42e57..21fa7fa148 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -315,9 +315,11 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime #ifdef USE_MULTIVIEW mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex]; mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex]; + vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz; #else mat4 projection_matrix = scene_data.projection_matrix; mat4 inv_projection_matrix = scene_data.inv_projection_matrix; + vec3 eye_offset = vec3(0.0, 0.0, 0.0); #endif //USE_MULTIVIEW //using world coordinates @@ -722,8 +724,10 @@ void fragment_shader(in SceneData scene_data) { //lay out everything, whatever is unused is optimized away anyway vec3 vertex = vertex_interp; #ifdef USE_MULTIVIEW - vec3 view = -normalize(vertex_interp - scene_data.eye_offset[ViewIndex].xyz); + vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz; + vec3 view = -normalize(vertex_interp - eye_offset); #else + vec3 eye_offset = vec3(0.0, 0.0, 0.0); vec3 view = -normalize(vertex_interp); #endif vec3 albedo = vec3(1.0); diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 90e902ca33..a8b28bbd4f 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -314,9 +314,11 @@ void main() { #ifdef USE_MULTIVIEW mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex]; mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex]; + vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz; #else mat4 projection_matrix = scene_data.projection_matrix; mat4 inv_projection_matrix = scene_data.inv_projection_matrix; + vec3 eye_offset = vec3(0.0, 0.0, 0.0); #endif //USE_MULTIVIEW //using world coordinates @@ -671,8 +673,10 @@ void main() { //lay out everything, whatever is unused is optimized away anyway vec3 vertex = vertex_interp; #ifdef USE_MULTIVIEW - vec3 view = -normalize(vertex_interp - scene_data.eye_offset[ViewIndex].xyz); + vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz; + vec3 view = -normalize(vertex_interp - eye_offset); #else + vec3 eye_offset = vec3(0.0, 0.0, 0.0); vec3 view = -normalize(vertex_interp); #endif vec3 albedo = vec3(1.0); diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index cdecb3828b..968f804593 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -232,6 +232,8 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) { return; } + ERR_FAIL_COND(p_texture.is_valid() && !texture_storage->owns_texture(p_texture)); + if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) { texture_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI); } @@ -1064,14 +1066,14 @@ void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distan reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } -void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { +void LightStorage::reflection_probe_set_size(RID p_probe, const Vector3 &p_size) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); ERR_FAIL_COND(!reflection_probe); - if (reflection_probe->extents == p_extents) { + if (reflection_probe->size == p_size) { return; } - reflection_probe->extents = p_extents; + reflection_probe->size = p_size; reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } @@ -1143,8 +1145,8 @@ AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const { ERR_FAIL_COND_V(!reflection_probe, AABB()); AABB aabb; - aabb.position = -reflection_probe->extents; - aabb.size = reflection_probe->extents * 2.0; + aabb.position = -reflection_probe->size / 2; + aabb.size = reflection_probe->size; return aabb; } @@ -1163,11 +1165,11 @@ uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const { return reflection_probe->cull_mask; } -Vector3 LightStorage::reflection_probe_get_extents(RID p_probe) const { +Vector3 LightStorage::reflection_probe_get_size(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); ERR_FAIL_COND_V(!reflection_probe, Vector3()); - return reflection_probe->extents; + return reflection_probe->size; } Vector3 LightStorage::reflection_probe_get_origin_offset(RID p_probe) const { @@ -1552,6 +1554,11 @@ bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) { if (rpi->processing_side == 6) { rpi->processing_side = 0; rpi->processing_layer++; + if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) { + rpi->rendering = false; + rpi->processing_layer = 1; + return true; + } } return false; @@ -1667,7 +1674,7 @@ void LightStorage::update_reflection_probe_buffer(RenderDataRD *p_render_data, c ReflectionData &reflection_ubo = reflections[i]; - Vector3 extents = probe->extents; + Vector3 extents = probe->size / 2; rpi->cull_mask = probe->cull_mask; diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index d359219128..68f439ddef 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -226,7 +226,7 @@ private: Color ambient_color; float ambient_color_energy = 1.0; float max_distance = 0; - Vector3 extents = Vector3(10, 10, 10); + Vector3 size = Vector3(20, 20, 20); Vector3 origin_offset; bool interior = false; bool box_projection = false; @@ -791,7 +791,7 @@ public: virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override; virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override; virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override; - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override; + virtual void reflection_probe_set_size(RID p_probe, const Vector3 &p_size) override; virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override; virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override; virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override; @@ -805,7 +805,7 @@ public: virtual AABB reflection_probe_get_aabb(RID p_probe) const override; virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override; virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override; - virtual Vector3 reflection_probe_get_extents(RID p_probe) const override; + virtual Vector3 reflection_probe_get_size(RID p_probe) const override; virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override; virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override; virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override; diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 9124886764..f65676185c 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -986,7 +986,10 @@ void MeshStorage::update_mesh_instances() { push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2; - Transform2D transform = mi->canvas_item_transform_2d.affine_inverse() * sk->base_transform_2d; + Transform2D transform = Transform2D(); + if (sk && sk->use_2d) { + transform = mi->canvas_item_transform_2d.affine_inverse() * sk->base_transform_2d; + } push_constant.skeleton_transform_x[0] = transform.columns[0][0]; push_constant.skeleton_transform_x[1] = transform.columns[0][1]; push_constant.skeleton_transform_y[0] = transform.columns[1][0]; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 2eaa7824fb..5d845ce510 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -1853,10 +1853,10 @@ void TextureStorage::decal_free(RID p_rid) { decal_owner.free(p_rid); } -void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) { +void TextureStorage::decal_set_size(RID p_decal, const Vector3 &p_size) { Decal *decal = decal_owner.get_or_null(p_decal); ERR_FAIL_COND(!decal); - decal->extents = p_extents; + decal->size = p_size; decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } @@ -1949,7 +1949,7 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const { Decal *decal = decal_owner.get_or_null(p_decal); ERR_FAIL_COND_V(!decal, AABB()); - return AABB(-decal->extents, decal->extents * 2.0); + return AABB(-decal->size / 2, decal->size); } Dependency *TextureStorage::decal_get_dependency(RID p_decal) { @@ -2312,7 +2312,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const DecalData &dd = decals[i]; - Vector3 decal_extents = decal->extents; + Vector3 decal_extents = decal->size / 2; Transform3D scale_xform; scale_xform.basis.scale(decal_extents); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index ea0df0b459..aeab3bf3cb 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -235,7 +235,7 @@ private: } decal_atlas; struct Decal { - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(2, 2, 2); RID textures[RS::DECAL_TEXTURE_MAX]; float emission_energy = 1.0; float albedo_mix = 1.0; @@ -561,7 +561,7 @@ public: virtual void decal_initialize(RID p_decal) override; virtual void decal_free(RID p_rid) override; - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override; + virtual void decal_set_size(RID p_decal, const Vector3 &p_size) override; virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override; virtual void decal_set_emission_energy(RID p_decal, float p_energy) override; virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override; @@ -577,9 +577,9 @@ public: virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override; virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override; - _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) { + _FORCE_INLINE_ Vector3 decal_get_size(RID p_decal) { const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->extents; + return decal->size; } _FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) { diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 6f4bb115fc..d696955800 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -3396,13 +3396,13 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int Vector3(0, -1, 0) }; - Vector3 extents = RSG::light_storage->reflection_probe_get_extents(p_instance->base); + Vector3 probe_size = RSG::light_storage->reflection_probe_get_size(p_instance->base); Vector3 origin_offset = RSG::light_storage->reflection_probe_get_origin_offset(p_instance->base); float max_distance = RSG::light_storage->reflection_probe_get_origin_max_distance(p_instance->base); - float size = RSG::light_storage->reflection_atlas_get_size(scenario->reflection_atlas); - float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / size; + float atlas_size = RSG::light_storage->reflection_atlas_get_size(scenario->reflection_atlas); + float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / atlas_size; - Vector3 edge = view_normals[p_step] * extents; + Vector3 edge = view_normals[p_step] * probe_size / 2; float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit max_distance = MAX(max_distance, distance); diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 3886f5b379..aecd0593bc 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -236,7 +236,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { } } - if (!p_viewport->disable_2d && !p_viewport->disable_environment && RSG::scene->is_scenario(p_viewport->scenario)) { + if (!p_viewport->disable_2d && !viewport_is_environment_disabled(p_viewport) && RSG::scene->is_scenario(p_viewport->scenario)) { RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario); if (RSG::scene->is_environment(environment)) { scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS; @@ -992,11 +992,21 @@ void RendererViewport::viewport_set_disable_2d(RID p_viewport, bool p_disable) { viewport->disable_2d = p_disable; } -void RendererViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) { +void RendererViewport::viewport_set_environment_mode(RID p_viewport, RS::ViewportEnvironmentMode p_mode) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); - viewport->disable_environment = p_disable; + viewport->disable_environment = p_mode; +} + +bool RendererViewport::viewport_is_environment_disabled(Viewport *viewport) { + ERR_FAIL_COND_V(!viewport, false); + + if (viewport->parent.is_valid() && viewport->disable_environment == RS::VIEWPORT_ENVIRONMENT_INHERIT) { + Viewport *parent = viewport_owner.get_or_null(viewport->parent); + return viewport_is_environment_disabled(parent); + } + return viewport->disable_environment == RS::VIEWPORT_ENVIRONMENT_DISABLED; } void RendererViewport::viewport_set_disable_3d(RID p_viewport, bool p_disable) { diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index 9b32cc3774..c24275de6e 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -85,7 +85,7 @@ public: bool viewport_render_direct_to_screen; bool disable_2d = false; - bool disable_environment = false; + RS::ViewportEnvironmentMode disable_environment = RS::VIEWPORT_ENVIRONMENT_INHERIT; bool disable_3d = false; bool measure_render_time = false; @@ -238,9 +238,11 @@ public: const RendererSceneRender::CameraData *viewport_get_prev_camera_data(RID p_viewport); void viewport_set_disable_2d(RID p_viewport, bool p_disable); - void viewport_set_disable_environment(RID p_viewport, bool p_disable); + void viewport_set_environment_mode(RID p_viewport, RS::ViewportEnvironmentMode p_mode); void viewport_set_disable_3d(RID p_viewport, bool p_disable); + bool viewport_is_environment_disabled(Viewport *viewport); + void viewport_attach_camera(RID p_viewport, RID p_camera); void viewport_set_scenario(RID p_viewport, RID p_scenario); void viewport_attach_canvas(RID p_viewport, RID p_canvas); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 8ac522bafe..4f52a63b2f 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -387,7 +387,7 @@ public: FUNC2(reflection_probe_set_ambient_energy, RID, float) FUNC2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode) FUNC2(reflection_probe_set_max_distance, RID, float) - FUNC2(reflection_probe_set_extents, RID, const Vector3 &) + FUNC2(reflection_probe_set_size, RID, const Vector3 &) FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &) FUNC2(reflection_probe_set_as_interior, RID, bool) FUNC2(reflection_probe_set_enable_box_projection, RID, bool) @@ -428,7 +428,7 @@ public: FUNCRIDSPLIT(decal) - FUNC2(decal_set_extents, RID, const Vector3 &) + FUNC2(decal_set_size, RID, const Vector3 &) FUNC3(decal_set_texture, RID, DecalTexture, RID) FUNC2(decal_set_emission_energy, RID, float) FUNC2(decal_set_albedo_mix, RID, float) @@ -540,7 +540,7 @@ public: FUNCRIDSPLIT(fog_volume) FUNC2(fog_volume_set_shape, RID, FogVolumeShape) - FUNC2(fog_volume_set_extents, RID, const Vector3 &) + FUNC2(fog_volume_set_size, RID, const Vector3 &) FUNC2(fog_volume_set_material, RID, RID) /* VISIBILITY_NOTIFIER */ @@ -608,7 +608,7 @@ public: FUNC1RC(RID, viewport_get_texture, RID) FUNC2(viewport_set_disable_2d, RID, bool) - FUNC2(viewport_set_disable_environment, RID, bool) + FUNC2(viewport_set_environment_mode, RID, ViewportEnvironmentMode) FUNC2(viewport_set_disable_3d, RID, bool) FUNC2(viewport_set_canvas_cull_mask, RID, uint32_t) diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index ba39328b2e..56d00fa1bb 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -106,6 +106,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["EYE_OFFSET"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VERTEX"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); @@ -151,6 +152,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EYE_OFFSET"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); @@ -464,7 +466,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["WORLD_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["OBJECT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["UVW"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["EXTENTS"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["SIZE"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["SDF"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["DENSITY"] = ShaderLanguage::TYPE_FLOAT; diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h index 413f06bc5b..9f3f5dd8e4 100644 --- a/servers/rendering/storage/light_storage.h +++ b/servers/rendering/storage/light_storage.h @@ -110,7 +110,7 @@ public: virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0; virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0; virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0; - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0; + virtual void reflection_probe_set_size(RID p_probe, const Vector3 &p_size) = 0; virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0; virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0; virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0; @@ -121,7 +121,7 @@ public: virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0; virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0; virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0; - virtual Vector3 reflection_probe_get_extents(RID p_probe) const = 0; + virtual Vector3 reflection_probe_get_size(RID p_probe) const = 0; virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0; virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0; virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0; diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h index 4c4a84d04e..3a9034ad0d 100644 --- a/servers/rendering/storage/texture_storage.h +++ b/servers/rendering/storage/texture_storage.h @@ -107,7 +107,7 @@ public: virtual void decal_initialize(RID p_rid) = 0; virtual void decal_free(RID p_rid) = 0; - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0; + virtual void decal_set_size(RID p_decal, const Vector3 &p_size) = 0; virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0; virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0; virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 0c06ba7c26..1c19b9dcd0 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1968,7 +1968,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("reflection_probe_set_ambient_color", "probe", "color"), &RenderingServer::reflection_probe_set_ambient_color); ClassDB::bind_method(D_METHOD("reflection_probe_set_ambient_energy", "probe", "energy"), &RenderingServer::reflection_probe_set_ambient_energy); ClassDB::bind_method(D_METHOD("reflection_probe_set_max_distance", "probe", "distance"), &RenderingServer::reflection_probe_set_max_distance); - ClassDB::bind_method(D_METHOD("reflection_probe_set_extents", "probe", "extents"), &RenderingServer::reflection_probe_set_extents); + ClassDB::bind_method(D_METHOD("reflection_probe_set_size", "probe", "size"), &RenderingServer::reflection_probe_set_size); ClassDB::bind_method(D_METHOD("reflection_probe_set_origin_offset", "probe", "offset"), &RenderingServer::reflection_probe_set_origin_offset); ClassDB::bind_method(D_METHOD("reflection_probe_set_as_interior", "probe", "enable"), &RenderingServer::reflection_probe_set_as_interior); ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_box_projection", "probe", "enable"), &RenderingServer::reflection_probe_set_enable_box_projection); @@ -1987,7 +1987,7 @@ void RenderingServer::_bind_methods() { /* DECAL */ ClassDB::bind_method(D_METHOD("decal_create"), &RenderingServer::decal_create); - ClassDB::bind_method(D_METHOD("decal_set_extents", "decal", "extents"), &RenderingServer::decal_set_extents); + ClassDB::bind_method(D_METHOD("decal_set_size", "decal", "size"), &RenderingServer::decal_set_size); ClassDB::bind_method(D_METHOD("decal_set_texture", "decal", "type", "texture"), &RenderingServer::decal_set_texture); ClassDB::bind_method(D_METHOD("decal_set_emission_energy", "decal", "energy"), &RenderingServer::decal_set_emission_energy); ClassDB::bind_method(D_METHOD("decal_set_albedo_mix", "decal", "albedo_mix"), &RenderingServer::decal_set_albedo_mix); @@ -2147,7 +2147,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("fog_volume_create"), &RenderingServer::fog_volume_create); ClassDB::bind_method(D_METHOD("fog_volume_set_shape", "fog_volume", "shape"), &RenderingServer::fog_volume_set_shape); - ClassDB::bind_method(D_METHOD("fog_volume_set_extents", "fog_volume", "extents"), &RenderingServer::fog_volume_set_extents); + ClassDB::bind_method(D_METHOD("fog_volume_set_size", "fog_volume", "size"), &RenderingServer::fog_volume_set_size); ClassDB::bind_method(D_METHOD("fog_volume_set_material", "fog_volume", "material"), &RenderingServer::fog_volume_set_material); BIND_ENUM_CONSTANT(FOG_VOLUME_SHAPE_ELLIPSOID); @@ -2200,7 +2200,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &RenderingServer::viewport_get_texture); ClassDB::bind_method(D_METHOD("viewport_set_disable_3d", "viewport", "disable"), &RenderingServer::viewport_set_disable_3d); ClassDB::bind_method(D_METHOD("viewport_set_disable_2d", "viewport", "disable"), &RenderingServer::viewport_set_disable_2d); - ClassDB::bind_method(D_METHOD("viewport_set_disable_environment", "viewport", "disabled"), &RenderingServer::viewport_set_disable_environment); + ClassDB::bind_method(D_METHOD("viewport_set_environment_mode", "viewport", "mode"), &RenderingServer::viewport_set_environment_mode); ClassDB::bind_method(D_METHOD("viewport_attach_camera", "viewport", "camera"), &RenderingServer::viewport_attach_camera); ClassDB::bind_method(D_METHOD("viewport_set_scenario", "viewport", "scenario"), &RenderingServer::viewport_set_scenario); ClassDB::bind_method(D_METHOD("viewport_attach_canvas", "viewport", "canvas"), &RenderingServer::viewport_attach_canvas); @@ -2255,6 +2255,11 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_NEVER); BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ONLY_NEXT_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_ENVIRONMENT_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_ENVIRONMENT_ENABLED); + BIND_ENUM_CONSTANT(VIEWPORT_ENVIRONMENT_INHERIT); + BIND_ENUM_CONSTANT(VIEWPORT_ENVIRONMENT_MAX); + BIND_ENUM_CONSTANT(VIEWPORT_SDF_OVERSIZE_100_PERCENT); BIND_ENUM_CONSTANT(VIEWPORT_SDF_OVERSIZE_120_PERCENT); BIND_ENUM_CONSTANT(VIEWPORT_SDF_OVERSIZE_150_PERCENT); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 231139e9df..1f9bff7c3f 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -541,7 +541,7 @@ public: virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0; virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0; virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0; - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0; + virtual void reflection_probe_set_size(RID p_probe, const Vector3 &p_size) = 0; virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0; virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0; virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0; @@ -561,7 +561,7 @@ public: }; virtual RID decal_create() = 0; - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0; + virtual void decal_set_size(RID p_decal, const Vector3 &p_size) = 0; virtual void decal_set_texture(RID p_decal, DecalTexture p_type, RID p_texture) = 0; virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0; virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0; @@ -750,7 +750,7 @@ public: }; virtual void fog_volume_set_shape(RID p_fog_volume, FogVolumeShape p_shape) = 0; - virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) = 0; + virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) = 0; virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) = 0; /* VISIBILITY NOTIFIER API */ @@ -840,7 +840,14 @@ public: virtual RID viewport_get_texture(RID p_viewport) const = 0; - virtual void viewport_set_disable_environment(RID p_viewport, bool p_disable) = 0; + enum ViewportEnvironmentMode { + VIEWPORT_ENVIRONMENT_DISABLED, + VIEWPORT_ENVIRONMENT_ENABLED, + VIEWPORT_ENVIRONMENT_INHERIT, + VIEWPORT_ENVIRONMENT_MAX, + }; + + virtual void viewport_set_environment_mode(RID p_viewport, ViewportEnvironmentMode p_mode) = 0; virtual void viewport_set_disable_3d(RID p_viewport, bool p_disable) = 0; virtual void viewport_set_disable_2d(RID p_viewport, bool p_disable) = 0; @@ -1639,6 +1646,7 @@ VARIANT_ENUM_CAST(RenderingServer::FogVolumeShape); VARIANT_ENUM_CAST(RenderingServer::ViewportScaling3DMode); VARIANT_ENUM_CAST(RenderingServer::ViewportUpdateMode); VARIANT_ENUM_CAST(RenderingServer::ViewportClearMode); +VARIANT_ENUM_CAST(RenderingServer::ViewportEnvironmentMode); VARIANT_ENUM_CAST(RenderingServer::ViewportMSAA); VARIANT_ENUM_CAST(RenderingServer::ViewportScreenSpaceAA); VARIANT_ENUM_CAST(RenderingServer::ViewportRenderInfo); diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp index 63e862f605..0ff59d2a39 100644 --- a/servers/xr/xr_interface_extension.cpp +++ b/servers/xr/xr_interface_extension.cpp @@ -136,9 +136,9 @@ PackedStringArray XRInterfaceExtension::get_suggested_pose_names(const StringNam } XRInterface::TrackingStatus XRInterfaceExtension::get_tracking_status() const { - uint32_t status = XR_UNKNOWN_TRACKING; + XRInterface::TrackingStatus status = XR_UNKNOWN_TRACKING; GDVIRTUAL_CALL(_get_tracking_status, status); - return TrackingStatus(status); + return status; } void XRInterfaceExtension::trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec) { @@ -152,9 +152,9 @@ bool XRInterfaceExtension::supports_play_area_mode(XRInterface::PlayAreaMode p_m } XRInterface::PlayAreaMode XRInterfaceExtension::get_play_area_mode() const { - uint32_t mode = XR_PLAY_AREA_UNKNOWN; + XRInterface::PlayAreaMode mode = XR_PLAY_AREA_UNKNOWN; GDVIRTUAL_CALL(_get_play_area_mode, mode); - return XRInterface::PlayAreaMode(mode); + return mode; } bool XRInterfaceExtension::set_play_area_mode(XRInterface::PlayAreaMode p_mode) { diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h index 39cd284e5c..454a50cb28 100644 --- a/servers/xr/xr_interface_extension.h +++ b/servers/xr/xr_interface_extension.h @@ -71,7 +71,7 @@ public: GDVIRTUAL0RC(PackedStringArray, _get_suggested_tracker_names); GDVIRTUAL1RC(PackedStringArray, _get_suggested_pose_names, const StringName &); - GDVIRTUAL0RC(uint32_t, _get_tracking_status); + GDVIRTUAL0RC(XRInterface::TrackingStatus, _get_tracking_status); GDVIRTUAL6(_trigger_haptic_pulse, const String &, const StringName &, double, double, double, double); /** specific to VR **/ @@ -81,8 +81,8 @@ public: virtual PackedVector3Array get_play_area() const override; /* if available, returns an array of vectors denoting the play area the player can move around in */ GDVIRTUAL1RC(bool, _supports_play_area_mode, XRInterface::PlayAreaMode); - GDVIRTUAL0RC(uint32_t, _get_play_area_mode); - GDVIRTUAL1RC(bool, _set_play_area_mode, uint32_t); + GDVIRTUAL0RC(XRInterface::PlayAreaMode, _get_play_area_mode); + GDVIRTUAL1RC(bool, _set_play_area_mode, XRInterface::PlayAreaMode); GDVIRTUAL0RC(PackedVector3Array, _get_play_area); /** specific to AR **/ diff --git a/tests/core/io/test_file_access.h b/tests/core/io/test_file_access.h index 7117cb137d..243b75626f 100644 --- a/tests/core/io/test_file_access.h +++ b/tests/core/io/test_file_access.h @@ -39,6 +39,7 @@ namespace TestFileAccess { TEST_CASE("[FileAccess] CSV read") { Ref<FileAccess> f = FileAccess::open(TestUtils::get_data_path("translations.csv"), FileAccess::READ); + REQUIRE(!f.is_null()); Vector<String> header = f->get_csv_line(); // Default delimiter: ",". REQUIRE(header.size() == 3); @@ -81,6 +82,7 @@ TEST_CASE("[FileAccess] CSV read") { TEST_CASE("[FileAccess] Get as UTF-8 String") { Ref<FileAccess> f_lf = FileAccess::open(TestUtils::get_data_path("line_endings_lf.test.txt"), FileAccess::READ); + REQUIRE(!f_lf.is_null()); String s_lf = f_lf->get_as_utf8_string(); f_lf->seek(0); String s_lf_nocr = f_lf->get_as_utf8_string(true); @@ -88,6 +90,7 @@ TEST_CASE("[FileAccess] Get as UTF-8 String") { CHECK(s_lf_nocr == "Hello darkness\nMy old friend\nI've come to talk\nWith you again\n"); Ref<FileAccess> f_crlf = FileAccess::open(TestUtils::get_data_path("line_endings_crlf.test.txt"), FileAccess::READ); + REQUIRE(!f_crlf.is_null()); String s_crlf = f_crlf->get_as_utf8_string(); f_crlf->seek(0); String s_crlf_nocr = f_crlf->get_as_utf8_string(true); @@ -95,6 +98,7 @@ TEST_CASE("[FileAccess] Get as UTF-8 String") { CHECK(s_crlf_nocr == "Hello darkness\nMy old friend\nI've come to talk\nWith you again\n"); Ref<FileAccess> f_cr = FileAccess::open(TestUtils::get_data_path("line_endings_cr.test.txt"), FileAccess::READ); + REQUIRE(!f_cr.is_null()); String s_cr = f_cr->get_as_utf8_string(); f_cr->seek(0); String s_cr_nocr = f_cr->get_as_utf8_string(true); diff --git a/tests/core/io/test_image.h b/tests/core/io/test_image.h index 3d52bc96d1..763eaed2f8 100644 --- a/tests/core/io/test_image.h +++ b/tests/core/io/test_image.h @@ -107,6 +107,7 @@ TEST_CASE("[Image] Saving and loading") { // Load BMP Ref<Image> image_bmp = memnew(Image()); Ref<FileAccess> f_bmp = FileAccess::open(TestUtils::get_data_path("images/icon.bmp"), FileAccess::READ, &err); + REQUIRE(!f_bmp.is_null()); PackedByteArray data_bmp; data_bmp.resize(f_bmp->get_length() + 1); f_bmp->get_buffer(data_bmp.ptrw(), f_bmp->get_length()); @@ -117,6 +118,7 @@ TEST_CASE("[Image] Saving and loading") { // Load JPG Ref<Image> image_jpg = memnew(Image()); Ref<FileAccess> f_jpg = FileAccess::open(TestUtils::get_data_path("images/icon.jpg"), FileAccess::READ, &err); + REQUIRE(!f_jpg.is_null()); PackedByteArray data_jpg; data_jpg.resize(f_jpg->get_length() + 1); f_jpg->get_buffer(data_jpg.ptrw(), f_jpg->get_length()); @@ -127,6 +129,7 @@ TEST_CASE("[Image] Saving and loading") { // Load WebP Ref<Image> image_webp = memnew(Image()); Ref<FileAccess> f_webp = FileAccess::open(TestUtils::get_data_path("images/icon.webp"), FileAccess::READ, &err); + REQUIRE(!f_webp.is_null()); PackedByteArray data_webp; data_webp.resize(f_webp->get_length() + 1); f_webp->get_buffer(data_webp.ptrw(), f_webp->get_length()); @@ -137,6 +140,7 @@ TEST_CASE("[Image] Saving and loading") { // Load PNG Ref<Image> image_png = memnew(Image()); Ref<FileAccess> f_png = FileAccess::open(TestUtils::get_data_path("images/icon.png"), FileAccess::READ, &err); + REQUIRE(!f_png.is_null()); PackedByteArray data_png; data_png.resize(f_png->get_length() + 1); f_png->get_buffer(data_png.ptrw(), f_png->get_length()); @@ -147,6 +151,7 @@ TEST_CASE("[Image] Saving and loading") { // Load TGA Ref<Image> image_tga = memnew(Image()); Ref<FileAccess> f_tga = FileAccess::open(TestUtils::get_data_path("images/icon.tga"), FileAccess::READ, &err); + REQUIRE(!f_tga.is_null()); PackedByteArray data_tga; data_tga.resize(f_tga->get_length() + 1); f_tga->get_buffer(data_tga.ptrw(), f_tga->get_length()); diff --git a/tests/display_server_mock.h b/tests/display_server_mock.h new file mode 100644 index 0000000000..1736f2c452 --- /dev/null +++ b/tests/display_server_mock.h @@ -0,0 +1,150 @@ +/**************************************************************************/ +/* display_server_mock.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DISPLAY_SERVER_MOCK_H +#define DISPLAY_SERVER_MOCK_H + +#include "servers/display_server_headless.h" + +#include "servers/rendering/dummy/rasterizer_dummy.h" + +// Specialized DisplayServer for unittests based on DisplayServerHeadless, that +// additionally supports rudimentary InputEvent handling and mouse position. +class DisplayServerMock : public DisplayServerHeadless { +private: + friend class DisplayServer; + + Point2i mouse_position = Point2i(-1, -1); // Outside of Window. + bool window_over = false; + Callable event_callback; + Callable input_event_callback; + + static Vector<String> get_rendering_drivers_func() { + Vector<String> drivers; + drivers.push_back("dummy"); + return drivers; + } + + static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) { + r_error = OK; + RasterizerDummy::make_current(); + return memnew(DisplayServerMock()); + } + + static void _dispatch_input_events(const Ref<InputEvent> &p_event) { + static_cast<DisplayServerMock *>(get_singleton())->_dispatch_input_event(p_event); + } + + void _dispatch_input_event(const Ref<InputEvent> &p_event) { + Variant ev = p_event; + Variant *evp = &ev; + Variant ret; + Callable::CallError ce; + + if (input_event_callback.is_valid()) { + input_event_callback.callp((const Variant **)&evp, 1, ret, ce); + } + } + + void _set_mouse_position(const Point2i &p_position) { + if (mouse_position == p_position) { + return; + } + mouse_position = p_position; + _set_window_over(Rect2i(Point2i(0, 0), window_get_size()).has_point(p_position)); + } + + void _set_window_over(bool p_over) { + if (p_over == window_over) { + return; + } + window_over = p_over; + _send_window_event(p_over ? WINDOW_EVENT_MOUSE_ENTER : WINDOW_EVENT_MOUSE_EXIT); + } + + void _send_window_event(WindowEvent p_event) { + if (!event_callback.is_null()) { + Variant event = int(p_event); + Variant *eventp = &event; + Variant ret; + Callable::CallError ce; + event_callback.callp((const Variant **)&eventp, 1, ret, ce); + } + } + +public: + bool has_feature(Feature p_feature) const override { + switch (p_feature) { + case FEATURE_MOUSE: + return true; + default: { + } + } + return false; + } + + String get_name() const override { return "mock"; } + + // You can simulate DisplayServer-events by calling this function. + // The events will be deliverd to Godot's Input-system. + // Mouse-events (Button & Motion) will additionally update the DisplayServer's mouse position. + void simulate_event(Ref<InputEvent> p_event) { + Ref<InputEventMouse> me = p_event; + if (me.is_valid()) { + _set_mouse_position(me->get_position()); + } + Input::get_singleton()->parse_input_event(p_event); + } + + virtual Point2i mouse_get_position() const override { return mouse_position; } + + virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override { + return Size2i(1920, 1080); + } + + virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override { + event_callback = p_callable; + } + + virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override { + input_event_callback = p_callable; + } + + static void register_mock_driver() { + register_create_function("mock", create_func, get_rendering_drivers_func); + } + + DisplayServerMock() { + Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events); + } + ~DisplayServerMock() {} +}; + +#endif // DISPLAY_SERVER_MOCK_H diff --git a/tests/scene/test_text_edit.h b/tests/scene/test_text_edit.h index 944f9cb9f6..f2663b037d 100644 --- a/tests/scene/test_text_edit.h +++ b/tests/scene/test_text_edit.h @@ -3271,6 +3271,7 @@ TEST_CASE("[SceneTree][TextEdit] mouse") { TEST_CASE("[SceneTree][TextEdit] caret") { TextEdit *text_edit = memnew(TextEdit); + text_edit->set_context_menu_enabled(false); // Prohibit sending InputEvents to the context menu. SceneTree::get_singleton()->get_root()->add_child(text_edit); text_edit->set_size(Size2(800, 200)); diff --git a/tests/test_macros.h b/tests/test_macros.h index 3074c1abf5..80a93c8327 100644 --- a/tests/test_macros.h +++ b/tests/test_macros.h @@ -31,6 +31,8 @@ #ifndef TEST_MACROS_H #define TEST_MACROS_H +#include "display_server_mock.h" + #include "core/core_globals.h" #include "core/input/input_map.h" #include "core/object/message_queue.h" @@ -139,13 +141,15 @@ int register_test_command(String p_command, TestFunc p_function); // SEND_GUI_MOUSE_MOTION_EVENT - takes an object, position, mouse mask and modifiers e.g SEND_GUI_MOUSE_MOTION_EVENT(code_edit, Vector2(50, 50), MouseButtonMask::LEFT, KeyModifierMask::META); // SEND_GUI_DOUBLE_CLICK - takes an object, position and modifiers. e.g SEND_GUI_DOUBLE_CLICK(code_edit, Vector2(50, 50), KeyModifierMask::META); +#define _SEND_DISPLAYSERVER_EVENT(m_event) ((DisplayServerMock *)(DisplayServer::get_singleton()))->simulate_event(m_event); + #define SEND_GUI_ACTION(m_object, m_action) \ { \ const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(m_action); \ const List<Ref<InputEvent>>::Element *first_event = events->front(); \ Ref<InputEventKey> event = first_event->get(); \ event->set_pressed(true); \ - m_object->get_viewport()->push_input(event); \ + _SEND_DISPLAYSERVER_EVENT(event); \ MessageQueue::get_singleton()->flush(); \ } @@ -153,7 +157,7 @@ int register_test_command(String p_command, TestFunc p_function); { \ Ref<InputEventKey> event = InputEventKey::create_reference(m_input); \ event->set_pressed(true); \ - m_object->get_viewport()->push_input(event); \ + _SEND_DISPLAYSERVER_EVENT(event); \ MessageQueue::get_singleton()->flush(); \ } @@ -176,7 +180,7 @@ int register_test_command(String p_command, TestFunc p_function); #define SEND_GUI_MOUSE_BUTTON_EVENT(m_object, m_local_pos, m_input, m_mask, m_modifers) \ { \ _CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, m_input, m_mask, m_modifers); \ - m_object->get_viewport()->push_input(event); \ + _SEND_DISPLAYSERVER_EVENT(event); \ MessageQueue::get_singleton()->flush(); \ } @@ -184,7 +188,7 @@ int register_test_command(String p_command, TestFunc p_function); { \ _CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, m_input, m_mask, m_modifers); \ event->set_pressed(false); \ - m_object->get_viewport()->push_input(event); \ + _SEND_DISPLAYSERVER_EVENT(event); \ MessageQueue::get_singleton()->flush(); \ } @@ -192,7 +196,7 @@ int register_test_command(String p_command, TestFunc p_function); { \ _CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, MouseButton::LEFT, 0, m_modifers); \ event->set_double_click(true); \ - m_object->get_viewport()->push_input(event); \ + _SEND_DISPLAYSERVER_EVENT(event); \ MessageQueue::get_singleton()->flush(); \ } @@ -207,7 +211,7 @@ int register_test_command(String p_command, TestFunc p_function); event->set_button_mask(m_mask); \ event->set_relative(Vector2(10, 10)); \ _UPDATE_EVENT_MODIFERS(event, m_modifers); \ - m_object->get_viewport()->push_input(event); \ + _SEND_DISPLAYSERVER_EVENT(event); \ MessageQueue::get_singleton()->flush(); \ CoreGlobals::print_error_enabled = errors_enabled; \ } diff --git a/tests/test_main.cpp b/tests/test_main.cpp index c7f2d4cbfb..ea6058f707 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -107,6 +107,7 @@ #include "modules/modules_tests.gen.h" +#include "tests/display_server_mock.h" #include "tests/test_macros.h" #include "scene/theme/theme_db.h" @@ -126,6 +127,7 @@ int test_main(int argc, char *argv[]) { args.push_back(String::utf8(argv[i])); } OS::get_singleton()->set_cmdline("", args, List<String>()); + DisplayServerMock::register_mock_driver(); // Run custom test tools. if (test_commands) { @@ -200,11 +202,12 @@ struct GodotTestCaseListener : public doctest::IReporter { memnew(MessageQueue); memnew(Input); + Input::get_singleton()->set_use_accumulated_input(false); Error err = OK; OS::get_singleton()->set_has_server_feature_callback(nullptr); for (int i = 0; i < DisplayServer::get_create_function_count(); i++) { - if (String("headless") == DisplayServer::get_create_function_name(i)) { + if (String("mock") == DisplayServer::get_create_function_name(i)) { DisplayServer::create(i, "", DisplayServer::WindowMode::WINDOW_MODE_MINIMIZED, DisplayServer::VSyncMode::VSYNC_ENABLED, 0, nullptr, Vector2i(0, 0), DisplayServer::SCREEN_PRIMARY, err); break; } diff --git a/thirdparty/README.md b/thirdparty/README.md index 38001b8782..38ace2c2e3 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -376,7 +376,7 @@ File extracted from upstream release tarball: ## meshoptimizer - Upstream: https://github.com/zeux/meshoptimizer -- Version: git (ea4558d1c0f217f1d67ed7fe0b07896ece88ae18, 2022) +- Version: git (4a287848fd664ae1c3fc8e5e008560534ceeb526, 2022) - License: MIT Files extracted from upstream repository: diff --git a/thirdparty/meshoptimizer/LICENSE.md b/thirdparty/meshoptimizer/LICENSE.md index 3c52415f62..b673c248b2 100644 --- a/thirdparty/meshoptimizer/LICENSE.md +++ b/thirdparty/meshoptimizer/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016-2021 Arseny Kapoulkine +Copyright (c) 2016-2022 Arseny Kapoulkine Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/thirdparty/meshoptimizer/clusterizer.cpp b/thirdparty/meshoptimizer/clusterizer.cpp index b1f7b359c1..c4672ad606 100644 --- a/thirdparty/meshoptimizer/clusterizer.cpp +++ b/thirdparty/meshoptimizer/clusterizer.cpp @@ -283,6 +283,79 @@ static bool appendMeshlet(meshopt_Meshlet& meshlet, unsigned int a, unsigned int return result; } +static unsigned int getNeighborTriangle(const meshopt_Meshlet& meshlet, const Cone* meshlet_cone, unsigned int* meshlet_vertices, const unsigned int* indices, const TriangleAdjacency2& adjacency, const Cone* triangles, const unsigned int* live_triangles, const unsigned char* used, float meshlet_expected_radius, float cone_weight, unsigned int* out_extra) +{ + unsigned int best_triangle = ~0u; + unsigned int best_extra = 5; + float best_score = FLT_MAX; + + for (size_t i = 0; i < meshlet.vertex_count; ++i) + { + unsigned int index = meshlet_vertices[meshlet.vertex_offset + i]; + + unsigned int* neighbors = &adjacency.data[0] + adjacency.offsets[index]; + size_t neighbors_size = adjacency.counts[index]; + + for (size_t j = 0; j < neighbors_size; ++j) + { + unsigned int triangle = neighbors[j]; + unsigned int a = indices[triangle * 3 + 0], b = indices[triangle * 3 + 1], c = indices[triangle * 3 + 2]; + + unsigned int extra = (used[a] == 0xff) + (used[b] == 0xff) + (used[c] == 0xff); + + // triangles that don't add new vertices to meshlets are max. priority + if (extra != 0) + { + // artificially increase the priority of dangling triangles as they're expensive to add to new meshlets + if (live_triangles[a] == 1 || live_triangles[b] == 1 || live_triangles[c] == 1) + extra = 0; + + extra++; + } + + // since topology-based priority is always more important than the score, we can skip scoring in some cases + if (extra > best_extra) + continue; + + float score = 0; + + // caller selects one of two scoring functions: geometrical (based on meshlet cone) or topological (based on remaining triangles) + if (meshlet_cone) + { + const Cone& tri_cone = triangles[triangle]; + + float distance2 = + (tri_cone.px - meshlet_cone->px) * (tri_cone.px - meshlet_cone->px) + + (tri_cone.py - meshlet_cone->py) * (tri_cone.py - meshlet_cone->py) + + (tri_cone.pz - meshlet_cone->pz) * (tri_cone.pz - meshlet_cone->pz); + + float spread = tri_cone.nx * meshlet_cone->nx + tri_cone.ny * meshlet_cone->ny + tri_cone.nz * meshlet_cone->nz; + + score = getMeshletScore(distance2, spread, cone_weight, meshlet_expected_radius); + } + else + { + // each live_triangles entry is >= 1 since it includes the current triangle we're processing + score = float(live_triangles[a] + live_triangles[b] + live_triangles[c] - 3); + } + + // note that topology-based priority is always more important than the score + // this helps maintain reasonable effectiveness of meshlet data and reduces scoring cost + if (extra < best_extra || score < best_score) + { + best_triangle = triangle; + best_extra = extra; + best_score = score; + } + } + } + + if (out_extra) + *out_extra = best_extra; + + return best_triangle; +} + struct KDNode { union @@ -464,13 +537,15 @@ size_t meshopt_buildMeshlets(meshopt_Meshlet* meshlets, unsigned int* meshlet_ve using namespace meshopt; assert(index_count % 3 == 0); - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); assert(max_vertices >= 3 && max_vertices <= kMeshletMaxVertices); assert(max_triangles >= 1 && max_triangles <= kMeshletMaxTriangles); assert(max_triangles % 4 == 0); // ensures the caller will compute output space properly as index data is 4b aligned + assert(cone_weight >= 0 && cone_weight <= 1); + meshopt_Allocator allocator; TriangleAdjacency2 adjacency = {}; @@ -511,65 +586,18 @@ size_t meshopt_buildMeshlets(meshopt_Meshlet* meshlets, unsigned int* meshlet_ve for (;;) { - unsigned int best_triangle = ~0u; - unsigned int best_extra = 5; - float best_score = FLT_MAX; - Cone meshlet_cone = getMeshletCone(meshlet_cone_acc, meshlet.triangle_count); - for (size_t i = 0; i < meshlet.vertex_count; ++i) - { - unsigned int index = meshlet_vertices[meshlet.vertex_offset + i]; - - unsigned int* neighbours = &adjacency.data[0] + adjacency.offsets[index]; - size_t neighbours_size = adjacency.counts[index]; - - for (size_t j = 0; j < neighbours_size; ++j) - { - unsigned int triangle = neighbours[j]; - assert(!emitted_flags[triangle]); - - unsigned int a = indices[triangle * 3 + 0], b = indices[triangle * 3 + 1], c = indices[triangle * 3 + 2]; - assert(a < vertex_count && b < vertex_count && c < vertex_count); - - unsigned int extra = (used[a] == 0xff) + (used[b] == 0xff) + (used[c] == 0xff); - - // triangles that don't add new vertices to meshlets are max. priority - if (extra != 0) - { - // artificially increase the priority of dangling triangles as they're expensive to add to new meshlets - if (live_triangles[a] == 1 || live_triangles[b] == 1 || live_triangles[c] == 1) - extra = 0; - - extra++; - } - - // since topology-based priority is always more important than the score, we can skip scoring in some cases - if (extra > best_extra) - continue; - - const Cone& tri_cone = triangles[triangle]; - - float distance2 = - (tri_cone.px - meshlet_cone.px) * (tri_cone.px - meshlet_cone.px) + - (tri_cone.py - meshlet_cone.py) * (tri_cone.py - meshlet_cone.py) + - (tri_cone.pz - meshlet_cone.pz) * (tri_cone.pz - meshlet_cone.pz); - - float spread = tri_cone.nx * meshlet_cone.nx + tri_cone.ny * meshlet_cone.ny + tri_cone.nz * meshlet_cone.nz; + unsigned int best_extra = 0; + unsigned int best_triangle = getNeighborTriangle(meshlet, &meshlet_cone, meshlet_vertices, indices, adjacency, triangles, live_triangles, used, meshlet_expected_radius, cone_weight, &best_extra); - float score = getMeshletScore(distance2, spread, cone_weight, meshlet_expected_radius); - - // note that topology-based priority is always more important than the score - // this helps maintain reasonable effectiveness of meshlet data and reduces scoring cost - if (extra < best_extra || score < best_score) - { - best_triangle = triangle; - best_extra = extra; - best_score = score; - } - } + // if the best triangle doesn't fit into current meshlet, the spatial scoring we've used is not very meaningful, so we re-select using topological scoring + if (best_triangle != ~0u && (meshlet.vertex_count + best_extra > max_vertices || meshlet.triangle_count >= max_triangles)) + { + best_triangle = getNeighborTriangle(meshlet, NULL, meshlet_vertices, indices, adjacency, triangles, live_triangles, used, meshlet_expected_radius, 0.f, NULL); } + // when we run out of neighboring triangles we need to switch to spatial search; we currently just pick the closest triangle irrespective of connectivity if (best_triangle == ~0u) { float position[3] = {meshlet_cone.px, meshlet_cone.py, meshlet_cone.pz}; @@ -604,16 +632,16 @@ size_t meshopt_buildMeshlets(meshopt_Meshlet* meshlets, unsigned int* meshlet_ve { unsigned int index = indices[best_triangle * 3 + k]; - unsigned int* neighbours = &adjacency.data[0] + adjacency.offsets[index]; - size_t neighbours_size = adjacency.counts[index]; + unsigned int* neighbors = &adjacency.data[0] + adjacency.offsets[index]; + size_t neighbors_size = adjacency.counts[index]; - for (size_t i = 0; i < neighbours_size; ++i) + for (size_t i = 0; i < neighbors_size; ++i) { - unsigned int tri = neighbours[i]; + unsigned int tri = neighbors[i]; if (tri == best_triangle) { - neighbours[i] = neighbours[neighbours_size - 1]; + neighbors[i] = neighbors[neighbors_size - 1]; adjacency.counts[index]--; break; } @@ -687,7 +715,7 @@ meshopt_Bounds meshopt_computeClusterBounds(const unsigned int* indices, size_t assert(index_count % 3 == 0); assert(index_count / 3 <= kMeshletMaxTriangles); - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); (void)vertex_count; @@ -839,7 +867,7 @@ meshopt_Bounds meshopt_computeMeshletBounds(const unsigned int* meshlet_vertices using namespace meshopt; assert(triangle_count <= kMeshletMaxTriangles); - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); unsigned int indices[kMeshletMaxTriangles * 3]; diff --git a/thirdparty/meshoptimizer/indexgenerator.cpp b/thirdparty/meshoptimizer/indexgenerator.cpp index f60db0dc4f..cad808a2b1 100644 --- a/thirdparty/meshoptimizer/indexgenerator.cpp +++ b/thirdparty/meshoptimizer/indexgenerator.cpp @@ -187,7 +187,7 @@ size_t meshopt_generateVertexRemap(unsigned int* destination, const unsigned int using namespace meshopt; assert(indices || index_count == vertex_count); - assert(index_count % 3 == 0); + assert(!indices || index_count % 3 == 0); assert(vertex_size > 0 && vertex_size <= 256); meshopt_Allocator allocator; @@ -412,7 +412,7 @@ void meshopt_generateAdjacencyIndexBuffer(unsigned int* destination, const unsig using namespace meshopt; assert(index_count % 3 == 0); - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); meshopt_Allocator allocator; @@ -483,7 +483,7 @@ void meshopt_generateTessellationIndexBuffer(unsigned int* destination, const un using namespace meshopt; assert(index_count % 3 == 0); - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); meshopt_Allocator allocator; diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h index 463fad29da..46d28d3ea3 100644 --- a/thirdparty/meshoptimizer/meshoptimizer.h +++ b/thirdparty/meshoptimizer/meshoptimizer.h @@ -1,7 +1,7 @@ /** - * meshoptimizer - version 0.17 + * meshoptimizer - version 0.18 * - * Copyright (C) 2016-2021, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Copyright (C) 2016-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) * Report bugs and download new versions at https://github.com/zeux/meshoptimizer * * This library is distributed under the MIT License. See notice at the end of this file. @@ -12,7 +12,7 @@ #include <stddef.h> /* Version macro; major * 1000 + minor * 10 + patch */ -#define MESHOPTIMIZER_VERSION 170 /* 0.17 */ +#define MESHOPTIMIZER_VERSION 180 /* 0.18 */ /* If no API is defined, assume default */ #ifndef MESHOPTIMIZER_API @@ -37,8 +37,8 @@ extern "C" { #endif /** - * Vertex attribute stream, similar to glVertexPointer - * Each element takes size bytes, with stride controlling the spacing between successive elements. + * Vertex attribute stream + * Each element takes size bytes, beginning at data, with stride controlling the spacing between successive elements (stride >= size). */ struct meshopt_Stream { @@ -115,7 +115,7 @@ MESHOPTIMIZER_API void meshopt_generateShadowIndexBufferMulti(unsigned int* dest * This can be used to implement algorithms like silhouette detection/expansion and other forms of GS-driven rendering. * * destination must contain enough space for the resulting index buffer (index_count*2 elements) - * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer + * vertex_positions should have float3 position in the first 12 bytes of each vertex */ MESHOPTIMIZER_API void meshopt_generateAdjacencyIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride); @@ -131,7 +131,7 @@ MESHOPTIMIZER_API void meshopt_generateAdjacencyIndexBuffer(unsigned int* destin * See "Tessellation on Any Budget" (John McDonald, GDC 2011) for implementation details. * * destination must contain enough space for the resulting index buffer (index_count*4 elements) - * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer + * vertex_positions should have float3 position in the first 12 bytes of each vertex */ MESHOPTIMIZER_API void meshopt_generateTessellationIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride); @@ -171,7 +171,7 @@ MESHOPTIMIZER_API void meshopt_optimizeVertexCacheFifo(unsigned int* destination * * destination must contain enough space for the resulting index buffer (index_count elements) * indices must contain index data that is the result of meshopt_optimizeVertexCache (*not* the original mesh indices!) - * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer + * vertex_positions should have float3 position in the first 12 bytes of each vertex * threshold indicates how much the overdraw optimizer can degrade vertex cache efficiency (1.05 = up to 5%) to reduce overdraw more efficiently */ MESHOPTIMIZER_API void meshopt_optimizeOverdraw(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, float threshold); @@ -313,7 +313,21 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeFilterQuat(void* destination, size MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeFilterExp(void* destination, size_t count, size_t stride, int bits, const float* data); /** - * Experimental: Mesh simplifier + * Simplification options + */ +enum +{ + /* Do not move vertices that are located on the topological border (vertices on triangle edges that don't have a paired triangle). Useful for simplifying portions of the larger mesh. */ + meshopt_SimplifyLockBorder = 1 << 0, +}; + +/** + * Experimental: Mesh simplifier with attribute metric; attributes follow xyz position data atm (vertex data must contain 3 + attribute_count floats per vertex) + */ +MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, unsigned int options, float* result_error, const float* attributes, const float* attribute_weights, size_t attribute_count); + +/** + * Mesh simplifier * Reduces the number of triangles in the mesh, attempting to preserve mesh appearance as much as possible * The algorithm tries to preserve mesh topology and can stop short of the target goal based on topology constraints or target error. * If not all attributes from the input mesh are required, it's recommended to reindex the mesh using meshopt_generateShadowIndexBuffer prior to simplification. @@ -322,16 +336,12 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeFilterExp(void* destination, size_ * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended. * * destination must contain enough space for the target index buffer, worst case is index_count elements (*not* target_index_count)! - * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer - * target_error represents the error relative to mesh extents that can be tolerated, e.g. 0.01 = 1% deformation + * vertex_positions should have float3 position in the first 12 bytes of each vertex + * target_error represents the error relative to mesh extents that can be tolerated, e.g. 0.01 = 1% deformation; value range [0..1] + * options must be a bitmask composed of meshopt_SimplifyX options; 0 is a safe default * result_error can be NULL; when it's not NULL, it will contain the resulting (relative) error after simplification */ -MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error); - -/** - * Experimental: Mesh simplifier with attribute metric; attributes follow xyz position data atm (vertex data must contain 3 + attribute_count floats per vertex) - */ -MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* result_error, const float* attributes, const float* attribute_weights, size_t attribute_count); +MESHOPTIMIZER_API size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float* result_error); /** * Experimental: Mesh simplifier (sloppy) @@ -342,8 +352,8 @@ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* d * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended. * * destination must contain enough space for the target index buffer, worst case is index_count elements (*not* target_index_count)! - * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer - * target_error represents the error relative to mesh extents that can be tolerated, e.g. 0.01 = 1% deformation + * vertex_positions should have float3 position in the first 12 bytes of each vertex + * target_error represents the error relative to mesh extents that can be tolerated, e.g. 0.01 = 1% deformation; value range [0..1] * result_error can be NULL; when it's not NULL, it will contain the resulting (relative) error after simplification */ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error); @@ -356,17 +366,17 @@ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(unsigned int* destinati * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended. * * destination must contain enough space for the target index buffer (target_vertex_count elements) - * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer + * vertex_positions should have float3 position in the first 12 bytes of each vertex */ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_vertex_count); /** - * Experimental: Returns the error scaling factor used by the simplifier to convert between absolute and relative extents + * Returns the error scaling factor used by the simplifier to convert between absolute and relative extents * * Absolute error must be *divided* by the scaling factor before passing it to meshopt_simplify as target_error * Relative error returned by meshopt_simplify via result_error must be *multiplied* by the scaling factor to get absolute error. */ -MESHOPTIMIZER_EXPERIMENTAL float meshopt_simplifyScale(const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride); +MESHOPTIMIZER_API float meshopt_simplifyScale(const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride); /** * Mesh stripifier @@ -418,7 +428,7 @@ struct meshopt_OverdrawStatistics * Returns overdraw statistics using a software rasterizer * Results may not match actual GPU performance * - * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer + * vertex_positions should have float3 position in the first 12 bytes of each vertex */ MESHOPTIMIZER_API struct meshopt_OverdrawStatistics meshopt_analyzeOverdraw(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride); @@ -456,7 +466,7 @@ struct meshopt_Meshlet * meshlets must contain enough space for all meshlets, worst case size can be computed with meshopt_buildMeshletsBound * meshlet_vertices must contain enough space for all meshlets, worst case size is equal to max_meshlets * max_vertices * meshlet_triangles must contain enough space for all meshlets, worst case size is equal to max_meshlets * max_triangles * 3 - * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer + * vertex_positions should have float3 position in the first 12 bytes of each vertex * max_vertices and max_triangles must not exceed implementation limits (max_vertices <= 255 - not 256!, max_triangles <= 512) * cone_weight should be set to 0 when cone culling is not used, and a value between 0 and 1 otherwise to balance between cluster size and cone culling efficiency */ @@ -498,7 +508,7 @@ struct meshopt_Bounds * The formula that uses the apex is slightly more accurate but needs the apex; if you are already using bounding sphere * to do frustum/occlusion culling, the formula that doesn't use the apex may be preferable. * - * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer + * vertex_positions should have float3 position in the first 12 bytes of each vertex * index_count/3 should be less than or equal to 512 (the function assumes clusters of limited size) */ MESHOPTIMIZER_API struct meshopt_Bounds meshopt_computeClusterBounds(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride); @@ -518,7 +528,7 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_spatialSortRemap(unsigned int* destinati * Reorders triangles for spatial locality, and generates a new index buffer. The resulting index buffer can be used with other functions like optimizeVertexCache. * * destination must contain enough space for the resulting index buffer (index_count elements) - * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer + * vertex_positions should have float3 position in the first 12 bytes of each vertex */ MESHOPTIMIZER_EXPERIMENTAL void meshopt_spatialSortTriangles(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride); @@ -610,7 +620,7 @@ inline size_t meshopt_encodeIndexSequence(unsigned char* buffer, size_t buffer_s template <typename T> inline int meshopt_decodeIndexSequence(T* destination, size_t index_count, const unsigned char* buffer, size_t buffer_size); template <typename T> -inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error = 0); +inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options = 0, float* result_error = 0); template <typename T> inline size_t meshopt_simplifySloppy(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error = 0); template <typename T> @@ -945,12 +955,12 @@ inline int meshopt_decodeIndexSequence(T* destination, size_t index_count, const } template <typename T> -inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error) +inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float* result_error) { meshopt_IndexAdapter<T> in(0, indices, index_count); meshopt_IndexAdapter<T> out(destination, 0, index_count); - return meshopt_simplify(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count, target_error, result_error); + return meshopt_simplify(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count, target_error, options, result_error); } template <typename T> @@ -1039,7 +1049,7 @@ inline void meshopt_spatialSortTriangles(T* destination, const T* indices, size_ #endif /** - * Copyright (c) 2016-2021 Arseny Kapoulkine + * Copyright (c) 2016-2022 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/thirdparty/meshoptimizer/overdrawanalyzer.cpp b/thirdparty/meshoptimizer/overdrawanalyzer.cpp index 8d5859ba39..8b6f254134 100644 --- a/thirdparty/meshoptimizer/overdrawanalyzer.cpp +++ b/thirdparty/meshoptimizer/overdrawanalyzer.cpp @@ -147,7 +147,7 @@ meshopt_OverdrawStatistics meshopt_analyzeOverdraw(const unsigned int* indices, using namespace meshopt; assert(index_count % 3 == 0); - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); meshopt_Allocator allocator; diff --git a/thirdparty/meshoptimizer/overdrawoptimizer.cpp b/thirdparty/meshoptimizer/overdrawoptimizer.cpp index 143656ed76..cc22dbcffc 100644 --- a/thirdparty/meshoptimizer/overdrawoptimizer.cpp +++ b/thirdparty/meshoptimizer/overdrawoptimizer.cpp @@ -272,7 +272,7 @@ void meshopt_optimizeOverdraw(unsigned int* destination, const unsigned int* ind using namespace meshopt; assert(index_count % 3 == 0); - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); meshopt_Allocator allocator; diff --git a/thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch b/thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch index 21daac6eec..5cac985dc5 100644 --- a/thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch +++ b/thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch @@ -1,5 +1,5 @@ diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp -index 5e92e2dc73..e40c141e76 100644 +index d8d4a67391..3847afc736 100644 --- a/thirdparty/meshoptimizer/simplifier.cpp +++ b/thirdparty/meshoptimizer/simplifier.cpp @@ -20,7 +20,7 @@ @@ -11,7 +11,7 @@ index 5e92e2dc73..e40c141e76 100644 // This work is based on: // Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997 -@@ -453,6 +453,7 @@ struct Collapse +@@ -458,6 +458,7 @@ struct Collapse float error; unsigned int errorui; }; @@ -19,7 +19,7 @@ index 5e92e2dc73..e40c141e76 100644 }; static float normalize(Vector3& v) -@@ -533,6 +534,34 @@ static float quadricError(const Quadric& Q, const Vector3& v) +@@ -538,6 +539,34 @@ static float quadricError(const Quadric& Q, const Vector3& v) return fabsf(r) * s; } @@ -54,7 +54,7 @@ index 5e92e2dc73..e40c141e76 100644 static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, float w) { float aw = a * w; -@@ -688,7 +717,7 @@ static void quadricUpdateAttributes(Quadric& Q, const Vector3& p0, const Vector3 +@@ -693,7 +722,7 @@ static void quadricUpdateAttributes(Quadric& Q, const Vector3& p0, const Vector3 } #endif @@ -63,7 +63,7 @@ index 5e92e2dc73..e40c141e76 100644 { for (size_t i = 0; i < index_count; i += 3) { -@@ -698,6 +727,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic +@@ -703,6 +732,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic Quadric Q; quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f); @@ -73,7 +73,7 @@ index 5e92e2dc73..e40c141e76 100644 #if ATTRIBUTES quadricUpdateAttributes(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], Q.w); -@@ -708,7 +740,7 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic +@@ -713,7 +745,7 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic } } @@ -82,7 +82,7 @@ index 5e92e2dc73..e40c141e76 100644 { for (size_t i = 0; i < index_count; i += 3) { -@@ -752,6 +784,9 @@ static void fillEdgeQuadrics(Quadric* vertex_quadrics, const unsigned int* indic +@@ -757,6 +789,9 @@ static void fillEdgeQuadrics(Quadric* vertex_quadrics, const unsigned int* indic quadricAdd(vertex_quadrics[remap[i0]], Q); quadricAdd(vertex_quadrics[remap[i1]], Q); @@ -92,7 +92,7 @@ index 5e92e2dc73..e40c141e76 100644 } } } -@@ -856,7 +891,7 @@ static size_t pickEdgeCollapses(Collapse* collapses, const unsigned int* indices +@@ -861,7 +896,7 @@ static size_t pickEdgeCollapses(Collapse* collapses, const unsigned int* indices return collapse_count; } @@ -101,7 +101,7 @@ index 5e92e2dc73..e40c141e76 100644 { for (size_t i = 0; i < collapse_count; ++i) { -@@ -876,10 +911,14 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const +@@ -881,10 +916,14 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const float ei = quadricError(qi, vertex_positions[i1]); float ej = quadricError(qj, vertex_positions[j1]); @@ -116,7 +116,7 @@ index 5e92e2dc73..e40c141e76 100644 } } -@@ -976,7 +1015,7 @@ static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapse +@@ -981,7 +1020,7 @@ static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapse } } @@ -125,7 +125,7 @@ index 5e92e2dc73..e40c141e76 100644 { size_t edge_collapses = 0; size_t triangle_collapses = 0; -@@ -1038,6 +1077,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* +@@ -1043,6 +1082,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* assert(collapse_remap[r1] == r1); quadricAdd(vertex_quadrics[r1], vertex_quadrics[r0]); @@ -133,7 +133,7 @@ index 5e92e2dc73..e40c141e76 100644 if (vertex_kind[i0] == Kind_Complex) { -@@ -1075,7 +1115,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* +@@ -1080,7 +1120,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* triangle_collapses += (vertex_kind[i0] == Kind_Border) ? 1 : 2; edge_collapses++; @@ -142,7 +142,7 @@ index 5e92e2dc73..e40c141e76 100644 } #if TRACE -@@ -1463,9 +1503,11 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned +@@ -1469,9 +1509,11 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned Quadric* vertex_quadrics = allocator.allocate<Quadric>(vertex_count); memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric)); @@ -156,7 +156,7 @@ index 5e92e2dc73..e40c141e76 100644 if (result != indices) memcpy(result, indices, index_count * sizeof(unsigned int)); -@@ -1496,7 +1538,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned +@@ -1502,7 +1544,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned if (edge_collapse_count == 0) break; @@ -165,7 +165,7 @@ index 5e92e2dc73..e40c141e76 100644 #if TRACE > 1 dumpEdgeCollapses(edge_collapses, edge_collapse_count, vertex_kind); -@@ -1515,7 +1557,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned +@@ -1521,7 +1563,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned printf("pass %d: ", int(pass_count++)); #endif diff --git a/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch b/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch index 33a17fe9fa..c065026a7d 100644 --- a/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch +++ b/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch @@ -1,21 +1,21 @@ diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h -index be4b765d97..463fad29da 100644 +index d95725dd71..46d28d3ea3 100644 --- a/thirdparty/meshoptimizer/meshoptimizer.h +++ b/thirdparty/meshoptimizer/meshoptimizer.h -@@ -328,6 +328,11 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeFilterExp(void* destination, size_ - */ - MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error); +@@ -321,6 +321,11 @@ enum + meshopt_SimplifyLockBorder = 1 << 0, + }; +/** + * Experimental: Mesh simplifier with attribute metric; attributes follow xyz position data atm (vertex data must contain 3 + attribute_count floats per vertex) + */ -+MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* result_error, const float* attributes, const float* attribute_weights, size_t attribute_count); ++MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, unsigned int options, float* result_error, const float* attributes, const float* attribute_weights, size_t attribute_count); + /** - * Experimental: Mesh simplifier (sloppy) - * Reduces the number of triangles in the mesh, sacrificing mesh appearance for simplification performance + * Mesh simplifier + * Reduces the number of triangles in the mesh, attempting to preserve mesh appearance as much as possible diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp -index a74b08a97d..5e92e2dc73 100644 +index 5f0e9bac31..797329b010 100644 --- a/thirdparty/meshoptimizer/simplifier.cpp +++ b/thirdparty/meshoptimizer/simplifier.cpp @@ -20,6 +20,8 @@ @@ -27,7 +27,7 @@ index a74b08a97d..5e92e2dc73 100644 // This work is based on: // Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997 // Michael Garland. Quadric-based polygonal surface simplification. 1999 -@@ -371,6 +373,10 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned +@@ -376,6 +378,10 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned struct Vector3 { float x, y, z; @@ -38,7 +38,7 @@ index a74b08a97d..5e92e2dc73 100644 }; static float rescalePositions(Vector3* result, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride) -@@ -427,6 +433,13 @@ struct Quadric +@@ -432,6 +438,13 @@ struct Quadric float a10, a20, a21; float b0, b1, b2, c; float w; @@ -52,7 +52,7 @@ index a74b08a97d..5e92e2dc73 100644 }; struct Collapse -@@ -469,6 +482,16 @@ static void quadricAdd(Quadric& Q, const Quadric& R) +@@ -474,6 +487,16 @@ static void quadricAdd(Quadric& Q, const Quadric& R) Q.b2 += R.b2; Q.c += R.c; Q.w += R.w; @@ -69,7 +69,7 @@ index a74b08a97d..5e92e2dc73 100644 } static float quadricError(const Quadric& Q, const Vector3& v) -@@ -494,6 +517,17 @@ static float quadricError(const Quadric& Q, const Vector3& v) +@@ -499,6 +522,17 @@ static float quadricError(const Quadric& Q, const Vector3& v) r += ry * v.y; r += rz * v.z; @@ -87,7 +87,7 @@ index a74b08a97d..5e92e2dc73 100644 float s = Q.w == 0.f ? 0.f : 1.f / Q.w; return fabsf(r) * s; -@@ -517,6 +551,13 @@ static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, flo +@@ -522,6 +556,13 @@ static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, flo Q.b2 = c * dw; Q.c = d * dw; Q.w = w; @@ -101,7 +101,7 @@ index a74b08a97d..5e92e2dc73 100644 } static void quadricFromPoint(Quadric& Q, float x, float y, float z, float w) -@@ -569,6 +610,84 @@ static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3 +@@ -574,6 +615,84 @@ static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3 quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance, length * weight); } @@ -186,7 +186,7 @@ index a74b08a97d..5e92e2dc73 100644 static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap) { for (size_t i = 0; i < index_count; i += 3) -@@ -580,6 +699,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic +@@ -585,6 +704,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic Quadric Q; quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f); @@ -196,29 +196,30 @@ index a74b08a97d..5e92e2dc73 100644 quadricAdd(vertex_quadrics[remap[i0]], Q); quadricAdd(vertex_quadrics[remap[i1]], Q); quadricAdd(vertex_quadrics[remap[i2]], Q); -@@ -1273,13 +1395,19 @@ MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoopBack = 0; +@@ -1278,14 +1400,20 @@ MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoopBack = 0; #endif - size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* out_result_error) + size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float* out_result_error) +{ -+ return meshopt_simplifyWithAttributes(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, target_index_count, target_error, out_result_error, 0, 0, 0); ++ return meshopt_simplifyWithAttributes(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, target_index_count, target_error, options, out_result_error, 0, 0, 0); +} + -+size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* out_result_error, const float* attributes, const float* attribute_weights, size_t attribute_count) ++size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, unsigned int options, float* out_result_error, const float* attributes, const float* attribute_weights, size_t attribute_count) { using namespace meshopt; assert(index_count % 3 == 0); -- assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); +- assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); - assert(vertex_positions_stride % sizeof(float) == 0); -+ assert(vertex_stride > 0 && vertex_stride <= 256); ++ assert(vertex_stride >= 12 && vertex_stride <= 256); + assert(vertex_stride % sizeof(float) == 0); assert(target_index_count <= index_count); + assert((options & ~(meshopt_SimplifyLockBorder)) == 0); + assert(attribute_count <= ATTRIBUTES); meshopt_Allocator allocator; -@@ -1293,7 +1421,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, +@@ -1299,7 +1427,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, // build position remap that maps each vertex to the one with identical position unsigned int* remap = allocator.allocate<unsigned int>(vertex_count); unsigned int* wedge = allocator.allocate<unsigned int>(vertex_count); @@ -227,7 +228,7 @@ index a74b08a97d..5e92e2dc73 100644 // classify vertices; vertex kind determines collapse rules, see kCanCollapse unsigned char* vertex_kind = allocator.allocate<unsigned char>(vertex_count); -@@ -1317,7 +1445,21 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, +@@ -1323,7 +1451,21 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, #endif Vector3* vertex_positions = allocator.allocate<Vector3>(vertex_count); @@ -250,7 +251,7 @@ index a74b08a97d..5e92e2dc73 100644 Quadric* vertex_quadrics = allocator.allocate<Quadric>(vertex_count); memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric)); -@@ -1409,7 +1551,9 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, +@@ -1415,7 +1557,9 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, // result_error is quadratic; we need to remap it back to linear if (out_result_error) diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp index e40c141e76..391a77861a 100644 --- a/thirdparty/meshoptimizer/simplifier.cpp +++ b/thirdparty/meshoptimizer/simplifier.cpp @@ -254,7 +254,7 @@ static bool hasEdge(const EdgeAdjacency& adjacency, unsigned int a, unsigned int return false; } -static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned int* loopback, size_t vertex_count, const EdgeAdjacency& adjacency, const unsigned int* remap, const unsigned int* wedge) +static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned int* loopback, size_t vertex_count, const EdgeAdjacency& adjacency, const unsigned int* remap, const unsigned int* wedge, unsigned int options) { memset(loop, -1, vertex_count * sizeof(unsigned int)); memset(loopback, -1, vertex_count * sizeof(unsigned int)); @@ -364,6 +364,11 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned } } + if (options & meshopt_SimplifyLockBorder) + for (size_t i = 0; i < vertex_count; ++i) + if (result[i] == Kind_Border) + result[i] = Kind_Locked; + #if TRACE printf("locked: many open edges %d, disconnected seam %d, many seam edges %d, many wedges %d\n", int(stats[0]), int(stats[1]), int(stats[2]), int(stats[3])); @@ -1434,19 +1439,20 @@ MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoop = 0; MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoopBack = 0; #endif -size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* out_result_error) +size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float* out_result_error) { - return meshopt_simplifyWithAttributes(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, target_index_count, target_error, out_result_error, 0, 0, 0); + return meshopt_simplifyWithAttributes(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, target_index_count, target_error, options, out_result_error, 0, 0, 0); } -size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, float* out_result_error, const float* attributes, const float* attribute_weights, size_t attribute_count) +size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_data, size_t vertex_count, size_t vertex_stride, size_t target_index_count, float target_error, unsigned int options, float* out_result_error, const float* attributes, const float* attribute_weights, size_t attribute_count) { using namespace meshopt; assert(index_count % 3 == 0); - assert(vertex_stride > 0 && vertex_stride <= 256); + assert(vertex_stride >= 12 && vertex_stride <= 256); assert(vertex_stride % sizeof(float) == 0); assert(target_index_count <= index_count); + assert((options & ~(meshopt_SimplifyLockBorder)) == 0); assert(attribute_count <= ATTRIBUTES); meshopt_Allocator allocator; @@ -1467,7 +1473,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned unsigned char* vertex_kind = allocator.allocate<unsigned char>(vertex_count); unsigned int* loop = allocator.allocate<unsigned int>(vertex_count); unsigned int* loopback = allocator.allocate<unsigned int>(vertex_count); - classifyVertices(vertex_kind, loop, loopback, vertex_count, adjacency, remap, wedge); + classifyVertices(vertex_kind, loop, loopback, vertex_count, adjacency, remap, wedge, options); #if TRACE size_t unique_positions = 0; @@ -1605,7 +1611,7 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind using namespace meshopt; assert(index_count % 3 == 0); - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); assert(target_index_count <= index_count); @@ -1736,7 +1742,7 @@ size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_pos { using namespace meshopt; - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); assert(target_vertex_count <= vertex_count); @@ -1848,7 +1854,7 @@ float meshopt_simplifyScale(const float* vertex_positions, size_t vertex_count, { using namespace meshopt; - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); float extent = rescalePositions(NULL, vertex_positions, vertex_count, vertex_positions_stride); diff --git a/thirdparty/meshoptimizer/spatialorder.cpp b/thirdparty/meshoptimizer/spatialorder.cpp index b09f80ac6f..7b1a069450 100644 --- a/thirdparty/meshoptimizer/spatialorder.cpp +++ b/thirdparty/meshoptimizer/spatialorder.cpp @@ -113,7 +113,7 @@ void meshopt_spatialSortRemap(unsigned int* destination, const float* vertex_pos { using namespace meshopt; - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); meshopt_Allocator allocator; @@ -144,7 +144,7 @@ void meshopt_spatialSortTriangles(unsigned int* destination, const unsigned int* using namespace meshopt; assert(index_count % 3 == 0); - assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); + assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256); assert(vertex_positions_stride % sizeof(float) == 0); (void)vertex_count; diff --git a/thirdparty/meshoptimizer/vcacheoptimizer.cpp b/thirdparty/meshoptimizer/vcacheoptimizer.cpp index fb8ade4b77..ce8fd3a887 100644 --- a/thirdparty/meshoptimizer/vcacheoptimizer.cpp +++ b/thirdparty/meshoptimizer/vcacheoptimizer.cpp @@ -110,7 +110,7 @@ static unsigned int getNextVertexDeadEnd(const unsigned int* dead_end, unsigned return ~0u; } -static unsigned int getNextVertexNeighbour(const unsigned int* next_candidates_begin, const unsigned int* next_candidates_end, const unsigned int* live_triangles, const unsigned int* cache_timestamps, unsigned int timestamp, unsigned int cache_size) +static unsigned int getNextVertexNeighbor(const unsigned int* next_candidates_begin, const unsigned int* next_candidates_end, const unsigned int* live_triangles, const unsigned int* cache_timestamps, unsigned int timestamp, unsigned int cache_size) { unsigned int best_candidate = ~0u; int best_priority = -1; @@ -281,16 +281,16 @@ void meshopt_optimizeVertexCacheTable(unsigned int* destination, const unsigned { unsigned int index = indices[current_triangle * 3 + k]; - unsigned int* neighbours = &adjacency.data[0] + adjacency.offsets[index]; - size_t neighbours_size = adjacency.counts[index]; + unsigned int* neighbors = &adjacency.data[0] + adjacency.offsets[index]; + size_t neighbors_size = adjacency.counts[index]; - for (size_t i = 0; i < neighbours_size; ++i) + for (size_t i = 0; i < neighbors_size; ++i) { - unsigned int tri = neighbours[i]; + unsigned int tri = neighbors[i]; if (tri == current_triangle) { - neighbours[i] = neighbours[neighbours_size - 1]; + neighbors[i] = neighbors[neighbors_size - 1]; adjacency.counts[index]--; break; } @@ -314,10 +314,10 @@ void meshopt_optimizeVertexCacheTable(unsigned int* destination, const unsigned vertex_scores[index] = score; // update scores of vertex triangles - const unsigned int* neighbours_begin = &adjacency.data[0] + adjacency.offsets[index]; - const unsigned int* neighbours_end = neighbours_begin + adjacency.counts[index]; + const unsigned int* neighbors_begin = &adjacency.data[0] + adjacency.offsets[index]; + const unsigned int* neighbors_end = neighbors_begin + adjacency.counts[index]; - for (const unsigned int* it = neighbours_begin; it != neighbours_end; ++it) + for (const unsigned int* it = neighbors_begin; it != neighbors_end; ++it) { unsigned int tri = *it; assert(!emitted_flags[tri]); @@ -412,11 +412,11 @@ void meshopt_optimizeVertexCacheFifo(unsigned int* destination, const unsigned i { const unsigned int* next_candidates_begin = &dead_end[0] + dead_end_top; - // emit all vertex neighbours - const unsigned int* neighbours_begin = &adjacency.data[0] + adjacency.offsets[current_vertex]; - const unsigned int* neighbours_end = neighbours_begin + adjacency.counts[current_vertex]; + // emit all vertex neighbors + const unsigned int* neighbors_begin = &adjacency.data[0] + adjacency.offsets[current_vertex]; + const unsigned int* neighbors_end = neighbors_begin + adjacency.counts[current_vertex]; - for (const unsigned int* it = neighbours_begin; it != neighbours_end; ++it) + for (const unsigned int* it = neighbors_begin; it != neighbors_end; ++it) { unsigned int triangle = *it; @@ -461,7 +461,7 @@ void meshopt_optimizeVertexCacheFifo(unsigned int* destination, const unsigned i const unsigned int* next_candidates_end = &dead_end[0] + dead_end_top; // get next vertex - current_vertex = getNextVertexNeighbour(next_candidates_begin, next_candidates_end, &live_triangles[0], &cache_timestamps[0], timestamp, cache_size); + current_vertex = getNextVertexNeighbor(next_candidates_begin, next_candidates_end, &live_triangles[0], &cache_timestamps[0], timestamp, cache_size); if (current_vertex == ~0u) { diff --git a/thirdparty/meshoptimizer/vertexcodec.cpp b/thirdparty/meshoptimizer/vertexcodec.cpp index 7925ea862c..4bd11121d2 100644 --- a/thirdparty/meshoptimizer/vertexcodec.cpp +++ b/thirdparty/meshoptimizer/vertexcodec.cpp @@ -50,6 +50,12 @@ #define SIMD_TARGET #endif +// When targeting AArch64/x64, optimize for latency to allow decoding of individual 16-byte groups to overlap +// We don't do this for 32-bit systems because we need 64-bit math for this and this will hurt in-order CPUs +#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) +#define SIMD_LATENCYOPT +#endif + #endif // !MESHOPTIMIZER_NO_SIMD #ifdef SIMD_SSE @@ -472,6 +478,18 @@ static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsi typedef int unaligned_int; #endif +#ifdef SIMD_LATENCYOPT + unsigned int data32; + memcpy(&data32, data, 4); + data32 &= data32 >> 1; + + // arrange bits such that low bits of nibbles of data64 contain all 2-bit elements of data32 + unsigned long long data64 = ((unsigned long long)data32 << 30) | (data32 & 0x3fffffff); + + // adds all 1-bit nibbles together; the sum fits in 4 bits because datacnt=16 would have used mode 3 + int datacnt = int(((data64 & 0x1111111111111111ull) * 0x1111111111111111ull) >> 60); +#endif + __m128i sel2 = _mm_cvtsi32_si128(*reinterpret_cast<const unaligned_int*>(data)); __m128i rest = _mm_loadu_si128(reinterpret_cast<const __m128i*>(data + 4)); @@ -490,11 +508,25 @@ static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsi _mm_storeu_si128(reinterpret_cast<__m128i*>(buffer), result); +#ifdef SIMD_LATENCYOPT + return data + 4 + datacnt; +#else return data + 4 + kDecodeBytesGroupCount[mask0] + kDecodeBytesGroupCount[mask1]; +#endif } case 2: { +#ifdef SIMD_LATENCYOPT + unsigned long long data64; + memcpy(&data64, data, 8); + data64 &= data64 >> 1; + data64 &= data64 >> 2; + + // adds all 1-bit nibbles together; the sum fits in 4 bits because datacnt=16 would have used mode 3 + int datacnt = int(((data64 & 0x1111111111111111ull) * 0x1111111111111111ull) >> 60); +#endif + __m128i sel4 = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(data)); __m128i rest = _mm_loadu_si128(reinterpret_cast<const __m128i*>(data + 8)); @@ -512,7 +544,11 @@ static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsi _mm_storeu_si128(reinterpret_cast<__m128i*>(buffer), result); +#ifdef SIMD_LATENCYOPT + return data + 8 + datacnt; +#else return data + 8 + kDecodeBytesGroupCount[mask0] + kDecodeBytesGroupCount[mask1]; +#endif } case 3: @@ -604,24 +640,13 @@ static uint8x16_t shuffleBytes(unsigned char mask0, unsigned char mask1, uint8x8 static void neonMoveMask(uint8x16_t mask, unsigned char& mask0, unsigned char& mask1) { - static const unsigned char byte_mask_data[16] = {1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128}; - - uint8x16_t byte_mask = vld1q_u8(byte_mask_data); - uint8x16_t masked = vandq_u8(mask, byte_mask); + // magic constant found using z3 SMT assuming mask has 8 groups of 0xff or 0x00 + const uint64_t magic = 0x000103070f1f3f80ull; -#ifdef __aarch64__ - // aarch64 has horizontal sums; MSVC doesn't expose this via arm64_neon.h so this path is exclusive to clang/gcc - mask0 = vaddv_u8(vget_low_u8(masked)); - mask1 = vaddv_u8(vget_high_u8(masked)); -#else - // we need horizontal sums of each half of masked, which can be done in 3 steps (yielding sums of sizes 2, 4, 8) - uint8x8_t sum1 = vpadd_u8(vget_low_u8(masked), vget_high_u8(masked)); - uint8x8_t sum2 = vpadd_u8(sum1, sum1); - uint8x8_t sum3 = vpadd_u8(sum2, sum2); + uint64x2_t mask2 = vreinterpretq_u64_u8(mask); - mask0 = vget_lane_u8(sum3, 0); - mask1 = vget_lane_u8(sum3, 1); -#endif + mask0 = uint8_t((vgetq_lane_u64(mask2, 0) * magic) >> 56); + mask1 = uint8_t((vgetq_lane_u64(mask2, 1) * magic) >> 56); } static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsigned char* buffer, int bitslog2) @@ -639,6 +664,18 @@ static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsi case 1: { +#ifdef SIMD_LATENCYOPT + unsigned int data32; + memcpy(&data32, data, 4); + data32 &= data32 >> 1; + + // arrange bits such that low bits of nibbles of data64 contain all 2-bit elements of data32 + unsigned long long data64 = ((unsigned long long)data32 << 30) | (data32 & 0x3fffffff); + + // adds all 1-bit nibbles together; the sum fits in 4 bits because datacnt=16 would have used mode 3 + int datacnt = int(((data64 & 0x1111111111111111ull) * 0x1111111111111111ull) >> 60); +#endif + uint8x8_t sel2 = vld1_u8(data); uint8x8_t sel22 = vzip_u8(vshr_n_u8(sel2, 4), sel2).val[0]; uint8x8x2_t sel2222 = vzip_u8(vshr_n_u8(sel22, 2), sel22); @@ -655,11 +692,25 @@ static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsi vst1q_u8(buffer, result); +#ifdef SIMD_LATENCYOPT + return data + 4 + datacnt; +#else return data + 4 + kDecodeBytesGroupCount[mask0] + kDecodeBytesGroupCount[mask1]; +#endif } case 2: { +#ifdef SIMD_LATENCYOPT + unsigned long long data64; + memcpy(&data64, data, 8); + data64 &= data64 >> 1; + data64 &= data64 >> 2; + + // adds all 1-bit nibbles together; the sum fits in 4 bits because datacnt=16 would have used mode 3 + int datacnt = int(((data64 & 0x1111111111111111ull) * 0x1111111111111111ull) >> 60); +#endif + uint8x8_t sel4 = vld1_u8(data); uint8x8x2_t sel44 = vzip_u8(vshr_n_u8(sel4, 4), vand_u8(sel4, vdup_n_u8(15))); uint8x16_t sel = vcombine_u8(sel44.val[0], sel44.val[1]); @@ -675,7 +726,11 @@ static const unsigned char* decodeBytesGroupSimd(const unsigned char* data, unsi vst1q_u8(buffer, result); +#ifdef SIMD_LATENCYOPT + return data + 8 + datacnt; +#else return data + 8 + kDecodeBytesGroupCount[mask0] + kDecodeBytesGroupCount[mask1]; +#endif } case 3: @@ -715,7 +770,6 @@ static void wasmMoveMask(v128_t mask, unsigned char& mask0, unsigned char& mask1 // magic constant found using z3 SMT assuming mask has 8 groups of 0xff or 0x00 const uint64_t magic = 0x000103070f1f3f80ull; - // TODO: This can use v8x16_bitmask in the future mask0 = uint8_t((wasm_i64x2_extract_lane(mask, 0) * magic) >> 56); mask1 = uint8_t((wasm_i64x2_extract_lane(mask, 1) * magic) >> 56); } diff --git a/thirdparty/meshoptimizer/vertexfilter.cpp b/thirdparty/meshoptimizer/vertexfilter.cpp index 606a280aa9..14a73b1ddd 100644 --- a/thirdparty/meshoptimizer/vertexfilter.cpp +++ b/thirdparty/meshoptimizer/vertexfilter.cpp @@ -931,7 +931,7 @@ void meshopt_encodeFilterExp(void* destination_, size_t count, size_t stride, in const float* v = &data[i * stride_float]; unsigned int* d = &destination[i * stride_float]; - // use maximum exponent to encode values; this guarantess that mantissa is [-1, 1] + // use maximum exponent to encode values; this guarantees that mantissa is [-1, 1] int exp = -100; for (size_t j = 0; j < stride_float; ++j) |