diff options
24 files changed, 140 insertions, 77 deletions
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 7c954df77d..d4680d1836 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -96,7 +96,7 @@ <argument index="0" name="bytes" type="PackedByteArray" /> <description> Decodes a byte array back to a [Variant] value. Decoding objects is allowed. - [b]WARNING:[/b] Deserialized object can contain code which gets executed. Do not use this option if the serialized object comes from untrusted sources to avoid potential security threats (remote code execution). + [b]Warning:[/b] Deserialized object can contain code which gets executed. Do not use this option if the serialized object comes from untrusted sources to avoid potential security threats (remote code execution). </description> </method> <method name="cartesian2polar"> @@ -518,7 +518,7 @@ nearest_po2(0) # Returns 0 (this may not be what you expect) nearest_po2(-1) # Returns 0 (this may not be what you expect) [/codeblock] - [b]WARNING:[/b] Due to the way it is implemented, this function returns [code]0[/code] rather than [code]1[/code] for non-positive values of [code]value[/code] (in reality, 1 is the smallest integer power of 2). + [b]Warning:[/b] Due to the way it is implemented, this function returns [code]0[/code] rather than [code]1[/code] for non-positive values of [code]value[/code] (in reality, 1 is the smallest integer power of 2). </description> </method> <method name="polar2cartesian"> diff --git a/doc/classes/CapsuleMesh.xml b/doc/classes/CapsuleMesh.xml index 031abd0112..b8605ccaec 100644 --- a/doc/classes/CapsuleMesh.xml +++ b/doc/classes/CapsuleMesh.xml @@ -11,9 +11,8 @@ <methods> </methods> <members> - <member name="mid_height" type="float" setter="set_mid_height" getter="get_mid_height" default="1.0"> - Height of the middle cylindrical part of the capsule (without the hemispherical ends). - [b]Note:[/b] The capsule's total height is equal to [member mid_height] + 2 * [member radius]. + <member name="height" type="float" setter="set_height" getter="get_height" default="3.0"> + Total height of the capsule mesh (including the hemispherical ends). </member> <member name="radial_segments" type="int" setter="set_radial_segments" getter="get_radial_segments" default="64"> Number of radial segments on the capsule mesh. diff --git a/doc/classes/CapsuleShape3D.xml b/doc/classes/CapsuleShape3D.xml index 27a6242bc9..c2b13224cf 100644 --- a/doc/classes/CapsuleShape3D.xml +++ b/doc/classes/CapsuleShape3D.xml @@ -12,7 +12,7 @@ <methods> </methods> <members> - <member name="height" type="float" setter="set_height" getter="get_height" default="1.0"> + <member name="height" type="float" setter="set_height" getter="get_height" default="3.0"> The capsule's height. </member> <member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0"> diff --git a/doc/classes/JSONRPC.xml b/doc/classes/JSONRPC.xml index 30e99f4a30..8f1d1581b1 100644 --- a/doc/classes/JSONRPC.xml +++ b/doc/classes/JSONRPC.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="JSONRPC" inherits="Object" version="4.0"> <brief_description> + A helper to handle dictionaries which look like JSONRPC documents. </brief_description> <description> + [url=https://www.jsonrpc.org/]JSON-RPC[/url] is a standard which wraps a method call in a [JSON] object. The object has a particular structure and identifies which method is called, the parameters to that function, and carries an ID to keep track of responses. This class implements that standard on top of [Dictionary]; you will have to convert between a [Dictionary] and [JSON] with other functions. </description> <tutorials> </tutorials> @@ -12,6 +14,9 @@ <argument index="0" name="method" type="String" /> <argument index="1" name="params" type="Variant" /> <description> + Returns a dictionary in the form of a JSON-RPC notification. Notifications are one-shot messages which do not expect a response. + - [code]method[/code]: Name of the method being called. + - [code]params[/code]: An array or dictionary of parameters being passed to the method. </description> </method> <method name="make_request"> @@ -20,6 +25,10 @@ <argument index="1" name="params" type="Variant" /> <argument index="2" name="id" type="Variant" /> <description> + Returns a dictionary in the form of a JSON-RPC request. Requests are sent to a server with the expectation of a response. The ID field is used for the server to specify which exact request it is responding to. + - [code]method[/code]: Name of the method being called. + - [code]params[/code]: An array or dictionary of parameters being passed to the method. + - [code]id[/code]: Uniquely identifies this request. The server is expected to send a response with the same ID. </description> </method> <method name="make_response"> @@ -27,6 +36,9 @@ <argument index="0" name="result" type="Variant" /> <argument index="1" name="id" type="Variant" /> <description> + When a server has received and processed a request, it is expected to send a response. If you did not want a response then you need to have sent a Notification instead. + - [code]result[/code]: The return value of the function which was called. + - [code]id[/code]: The ID of the request this response is targeted to. </description> </method> <method name="make_response_error" qualifiers="const"> @@ -35,6 +47,10 @@ <argument index="1" name="message" type="String" /> <argument index="2" name="id" type="Variant" default="null" /> <description> + Creates a response which indicates a previous reply has failed in some way. + - [code]code[/code]: The error code corresponding to what kind of error this is. See the [enum ErrorCode] constants. + - [code]message[/code]: A custom message about this error. + - [code]id[/code]: The request this error is a response to. </description> </method> <method name="process_action"> @@ -42,6 +58,9 @@ <argument index="0" name="action" type="Variant" /> <argument index="1" name="recurse" type="bool" default="false" /> <description> + Given a Dictionary which takes the form of a JSON-RPC request: unpack the request and run it. Methods are resolved by looking at the field called "method" and looking for an equivalently named function in the JSONRPC object. If one is found that method is called. + To add new supported methods extend the JSONRPC class and call [method process_action] on your subclass. + [code]action[/code]: The action to be run, as a Dictionary in the form of a JSON-RPC request or notification. </description> </method> <method name="process_string"> @@ -64,6 +83,7 @@ <constant name="INVALID_REQUEST" value="-32600" enum="ErrorCode"> </constant> <constant name="METHOD_NOT_FOUND" value="-32601" enum="ErrorCode"> + A method call was requested but no function of that name existed in the JSONRPC subclass. </constant> <constant name="INVALID_PARAMS" value="-32602" enum="ErrorCode"> </constant> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index f53c854fa9..24caceec1c 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -1713,9 +1713,11 @@ </member> <member name="rendering/textures/default_filters/anisotropic_filtering_level" type="int" setter="" getter="" default="2"> Sets the maximum number of samples to take when using anisotropic filtering on textures (as a power of two). A higher sample count will result in sharper textures at oblique angles, but is more expensive to compute. A value of [code]0[/code] forcibly disables anisotropic filtering, even on materials where it is enabled. + [b]Note:[/b] This property is only read when the project starts. There is currently no way to change this setting at run-time. </member> <member name="rendering/textures/default_filters/use_nearest_mipmap_filter" type="bool" setter="" getter="" default="false"> If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used. + [b]Note:[/b] This property is only read when the project starts. There is currently no way to change this setting at run-time. </member> <member name="rendering/textures/light_projectors/filter" type="int" setter="" getter="" default="3"> </member> diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 8748d021b6..30edbd1e87 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1606,7 +1606,9 @@ static void _reset_animation_players(Node *p_node, List<Ref<AnimatedValuesBackup AnimationPlayer *player = Object::cast_to<AnimationPlayer>(p_node->get_child(i)); if (player && player->is_reset_on_save_enabled() && player->can_apply_reset()) { Ref<AnimatedValuesBackup> old_values = player->apply_reset(); - r_anim_backups->push_back(old_values); + if (old_values.is_valid()) { + r_anim_backups->push_back(old_values); + } } _reset_animation_players(p_node->get_child(i), r_anim_backups); } diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 8b098ad23b..dcea7b26f3 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -4168,14 +4168,11 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i if (Object::cast_to<CapsuleShape3D>(*s)) { Vector3 axis; - axis[p_id == 0 ? 0 : 2] = 1.0; + axis[p_id == 0 ? 0 : 1] = 1.0; Ref<CapsuleShape3D> cs2 = s; Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); - if (p_id == 1) { - d -= cs2->get_radius(); - } if (Node3DEditor::get_singleton()->is_snap_enabled()) { d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); @@ -4397,7 +4394,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> points; - Vector3 d(0, height * 0.5, 0); + Vector3 d(0, height * 0.5 - radius, 0); for (int i = 0; i < 360; i++) { float ra = Math::deg2rad((float)i); float rb = Math::deg2rad((float)i + 1); @@ -4456,7 +4453,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> handles; handles.push_back(Vector3(cs2->get_radius(), 0, 0)); - handles.push_back(Vector3(0, cs2->get_height() * 0.5 + cs2->get_radius(), 0)); + handles.push_back(Vector3(0, cs2->get_height() * 0.5, 0)); p_gizmo->add_handles(handles, handles_material); } diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 3de2ffc137..0bb0bfde6f 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -386,7 +386,7 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi const real_t radius(half_height * 0.2); CapsuleShape3D *bone_shape_capsule = memnew(CapsuleShape3D); - bone_shape_capsule->set_height((half_height - radius) * 2); + bone_shape_capsule->set_height(half_height * 2); bone_shape_capsule->set_radius(radius); CollisionShape3D *bone_shape = memnew(CollisionShape3D); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 8994adf112..0b228c2695 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1143,6 +1143,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { editor_selection->clear(); editor_selection->add_node(new_node); + scene_tree->get_scene_tree()->grab_focus(); } break; default: { @@ -2279,7 +2280,7 @@ void SceneTreeDock::_create() { _do_reparent(last_created, -1, nodes, true); } - scene_tree->get_scene_tree()->call_deferred(SNAME("grab_focus")); + scene_tree->get_scene_tree()->grab_focus(); } void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_properties, bool p_remove_old) { diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp index 74da939e6f..905d10c9d4 100644 --- a/modules/navigation/navigation_mesh_generator.cpp +++ b/modules/navigation/navigation_mesh_generator.cpp @@ -187,7 +187,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform3D p_accumulated_transfor Ref<CapsuleMesh> capsule_mesh; capsule_mesh.instantiate(); capsule_mesh->set_radius(capsule->get_radius()); - capsule_mesh->set_mid_height(capsule->get_height() / 2.0); + capsule_mesh->set_height(capsule->get_height()); mesh = capsule_mesh; } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 1b3935dd25..985abf8e55 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1584,6 +1584,12 @@ void TextEdit::_move_cursor_left(bool p_select, bool p_move_by_word) { // Handle selection if (p_select) { _pre_shift_selection(); + } else if (selection.active && !p_move_by_word) { + // If a selection is active, move cursor to start of selection + cursor_set_line(selection.from_line); + cursor_set_column(selection.from_column); + deselect(); + return; } else { deselect(); } @@ -1629,6 +1635,12 @@ void TextEdit::_move_cursor_right(bool p_select, bool p_move_by_word) { // Handle selection if (p_select) { _pre_shift_selection(); + } else if (selection.active && !p_move_by_word) { + // If a selection is active, move cursor to end of selection + cursor_set_line(selection.to_line); + cursor_set_column(selection.to_column); + deselect(); + return; } else { deselect(); } @@ -2246,7 +2258,10 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { selection.selecting_column = col; } - if (!mb->is_double_click() && (OS::get_singleton()->get_ticks_msec() - last_dblclk) < 600 && cursor.line == prev_line) { + const int triple_click_timeout = 600; + const int triple_click_tolerance = 5; + + if (!mb->is_double_click() && (OS::get_singleton()->get_ticks_msec() - last_dblclk) < triple_click_timeout && mb->get_position().distance_to(last_dblclk_pos) < triple_click_tolerance) { // Triple-click select line. selection.selecting_mode = SelectionMode::SELECTION_MODE_LINE; _update_selection_mode_line(); @@ -2256,6 +2271,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { selection.selecting_mode = SelectionMode::SELECTION_MODE_WORD; _update_selection_mode_word(); last_dblclk = OS::get_singleton()->get_ticks_msec(); + last_dblclk_pos = mb->get_position(); } update(); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 9e6dedb267..c5853786cf 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -308,6 +308,7 @@ private: String lookup_symbol_word; uint64_t last_dblclk = 0; + Vector2 last_dblclk_pos; Timer *idle_detect; Timer *click_select_held; diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp index 8f7f3edc28..596fa70f15 100644 --- a/scene/resources/capsule_shape_2d.cpp +++ b/scene/resources/capsule_shape_2d.cpp @@ -59,10 +59,7 @@ void CapsuleShape2D::_update_shape() { } void CapsuleShape2D::set_radius(real_t p_radius) { - radius = p_radius; - if (radius > height * 0.5) { - height = radius * 2; - } + radius = MIN(p_radius, height * 0.5); _update_shape(); } @@ -71,11 +68,7 @@ real_t CapsuleShape2D::get_radius() const { } void CapsuleShape2D::set_height(real_t p_height) { - height = p_height; - if (radius > height * 0.5) { - height = radius * 2; - } - + height = MAX(p_height, radius * 2); _update_shape(); } diff --git a/scene/resources/capsule_shape_3d.cpp b/scene/resources/capsule_shape_3d.cpp index 226fe1ecd2..e267941d6a 100644 --- a/scene/resources/capsule_shape_3d.cpp +++ b/scene/resources/capsule_shape_3d.cpp @@ -37,7 +37,7 @@ Vector<Vector3> CapsuleShape3D::get_debug_mesh_lines() const { Vector<Vector3> points; - Vector3 d(0, height * 0.5, 0); + Vector3 d(0, height * 0.5 - radius, 0); for (int i = 0; i < 360; i++) { float ra = Math::deg2rad((float)i); float rb = Math::deg2rad((float)i + 1); @@ -67,7 +67,7 @@ Vector<Vector3> CapsuleShape3D::get_debug_mesh_lines() const { } real_t CapsuleShape3D::get_enclosing_radius() const { - return radius + height * 0.5; + return height * 0.5; } void CapsuleShape3D::_update_shape() { @@ -80,6 +80,9 @@ void CapsuleShape3D::_update_shape() { void CapsuleShape3D::set_radius(float p_radius) { radius = p_radius; + if (radius > height * 0.5) { + radius = height * 0.5; + } _update_shape(); notify_change_to_owners(); } @@ -90,6 +93,9 @@ float CapsuleShape3D::get_radius() const { void CapsuleShape3D::set_height(float p_height) { height = p_height; + if (radius > height * 0.5) { + height = radius * 2; + } _update_shape(); notify_change_to_owners(); } diff --git a/scene/resources/capsule_shape_3d.h b/scene/resources/capsule_shape_3d.h index 25645ecf9d..f09b4fb77d 100644 --- a/scene/resources/capsule_shape_3d.h +++ b/scene/resources/capsule_shape_3d.h @@ -36,7 +36,7 @@ class CapsuleShape3D : public Shape3D { GDCLASS(CapsuleShape3D, Shape3D); float radius = 1.0; - float height = 1.0; + float height = 3.0; protected: static void _bind_methods(); diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index dfa45cc810..ba85ea4a6c 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -300,7 +300,7 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { z = cos(u * Math_TAU); Vector3 p = Vector3(x * radius * w, y, -z * radius * w); - points.push_back(p + Vector3(0.0, 0.5 * mid_height, 0.0)); + points.push_back(p + Vector3(0.0, 0.5 * height - radius, 0.0)); normals.push_back(p.normalized()); ADD_TANGENT(z, 0.0, x, 1.0) uvs.push_back(Vector2(u, v * onethird)); @@ -328,8 +328,8 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { v = j; v /= (rings + 1); - y = mid_height * v; - y = (mid_height * 0.5) - y; + y = (height - 2.0 * radius) * v; + y = (0.5 * height - radius) - y; for (i = 0; i <= radial_segments; i++) { u = i; @@ -379,7 +379,7 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { z = cos(u2 * Math_TAU); Vector3 p = Vector3(x * radius * w, y, -z * radius * w); - points.push_back(p + Vector3(0.0, -0.5 * mid_height, 0.0)); + points.push_back(p + Vector3(0.0, -0.5 * height + radius, 0.0)); normals.push_back(p.normalized()); ADD_TANGENT(z, 0.0, x, 1.0) uvs.push_back(Vector2(u2, twothirds + ((v - 1.0) * onethird))); @@ -410,8 +410,8 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { void CapsuleMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleMesh::set_radius); ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleMesh::get_radius); - ClassDB::bind_method(D_METHOD("set_mid_height", "mid_height"), &CapsuleMesh::set_mid_height); - ClassDB::bind_method(D_METHOD("get_mid_height"), &CapsuleMesh::get_mid_height); + ClassDB::bind_method(D_METHOD("set_height", "height"), &CapsuleMesh::set_height); + ClassDB::bind_method(D_METHOD("get_height"), &CapsuleMesh::get_height); ClassDB::bind_method(D_METHOD("set_radial_segments", "segments"), &CapsuleMesh::set_radial_segments); ClassDB::bind_method(D_METHOD("get_radial_segments"), &CapsuleMesh::get_radial_segments); @@ -419,13 +419,16 @@ void CapsuleMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_rings"), &CapsuleMesh::get_rings); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mid_height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_mid_height", "get_mid_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_height", "get_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings"); } void CapsuleMesh::set_radius(const float p_radius) { radius = p_radius; + if (radius > height * 0.5) { + radius = height * 0.5; + } _request_update(); } @@ -433,13 +436,16 @@ float CapsuleMesh::get_radius() const { return radius; } -void CapsuleMesh::set_mid_height(const float p_mid_height) { - mid_height = p_mid_height; +void CapsuleMesh::set_height(const float p_height) { + height = p_height; + if (radius > height * 0.5) { + height = radius * 2; + } _request_update(); } -float CapsuleMesh::get_mid_height() const { - return mid_height; +float CapsuleMesh::get_height() const { + return height; } void CapsuleMesh::set_radial_segments(const int p_segments) { diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index a3de34d3e3..7915cb0028 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -108,7 +108,7 @@ class CapsuleMesh : public PrimitiveMesh { private: float radius = 1.0; - float mid_height = 1.0; + float height = 3.0; int radial_segments = 64; int rings = 8; @@ -120,8 +120,8 @@ public: void set_radius(const float p_radius); float get_radius() const; - void set_mid_height(const float p_mid_height); - float get_mid_height() const; + void set_height(const float p_height); + float get_height() const; void set_radial_segments(const int p_segments); int get_radial_segments() const; diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp index e6a17b3a1a..6e6a2cb9e7 100644 --- a/servers/physics_3d/collision_solver_3d_sat.cpp +++ b/servers/physics_3d/collision_solver_3d_sat.cpp @@ -848,7 +848,7 @@ static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform3D &p //capsule sphere 1, sphere - Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5); + Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius()); Vector3 capsule_ball_1 = p_transform_b.origin + capsule_axis; @@ -1207,7 +1207,7 @@ static void _collision_box_capsule(const Shape3DSW *p_a, const Transform3D &p_tr // capsule balls, edges of A for (int i = 0; i < 2; i++) { - Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5); + Vector3 capsule_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius()); Vector3 sphere_pos = p_transform_b.origin + ((i == 0) ? capsule_axis : -capsule_axis); @@ -1607,8 +1607,8 @@ static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform3D & // some values - Vector3 capsule_A_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5); - Vector3 capsule_B_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5); + Vector3 capsule_A_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius()); + Vector3 capsule_B_axis = p_transform_b.basis.get_axis(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius()); Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis; Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis; @@ -1679,8 +1679,8 @@ static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform3D Vector3 capsule_A_axis = p_transform_a.basis.get_axis(1); - Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis * (capsule_A->get_height() * 0.5); - Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis * (capsule_A->get_height() * 0.5); + Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis * (capsule_A->get_height() * 0.5 - capsule_A->get_radius()); + Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis * (capsule_A->get_height() * 0.5 - capsule_A->get_radius()); if (!separator.test_axis((p_transform_b.origin - capsule_A_ball_1).cross(cylinder_B_axis).cross(cylinder_B_axis).normalized())) { return; @@ -1768,7 +1768,7 @@ static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transf for (int i = 0; i < 2; i++) { // edges of B, capsule cylinder - Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5); + Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius()); Vector3 sphere_pos = p_transform_a.origin + ((i == 0) ? capsule_axis : -capsule_axis); @@ -1808,7 +1808,7 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_t // edges of B, capsule cylinder - Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5); + Vector3 capsule_axis = p_transform_a.basis.get_axis(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius()); for (int i = 0; i < 3; i++) { // edge-cylinder diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp index 526a098a05..a84405de81 100644 --- a/servers/physics_3d/shape_3d_sw.cpp +++ b/servers/physics_3d/shape_3d_sw.cpp @@ -424,10 +424,10 @@ BoxShape3DSW::BoxShape3DSW() { void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { Vector3 n = p_transform.basis.xform_inv(p_normal).normalized(); - real_t h = (n.y > 0) ? height : -height; + real_t h = height * 0.5 - radius; n *= radius; - n.y += h * 0.5; + n.y += (n.y > 0) ? h : -h; r_max = p_normal.dot(p_transform.xform(n)); r_min = p_normal.dot(p_transform.xform(-n)); @@ -436,10 +436,10 @@ void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform3D Vector3 CapsuleShape3DSW::get_support(const Vector3 &p_normal) const { Vector3 n = p_normal; - real_t h = (n.y > 0) ? height : -height; + real_t h = height * 0.5 - radius; n *= radius; - n.y += h * 0.5; + n.y += (n.y > 0) ? h : -h; return n; } @@ -457,15 +457,15 @@ void CapsuleShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 r_amount = 2; r_type = FEATURE_EDGE; r_supports[0] = n; - r_supports[0].y += height * 0.5; + r_supports[0].y += height * 0.5 - radius; r_supports[1] = n; - r_supports[1].y -= height * 0.5; + r_supports[1].y -= height * 0.5 - radius; } else { - real_t h = (d > 0) ? height : -height; + real_t h = height * 0.5 - radius; n *= radius; - n.y += h * 0.5; + n.y += (d > 0) ? h : -h; r_amount = 1; r_type = FEATURE_POINT; *r_supports = n; @@ -484,7 +484,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 & // test against cylinder and spheres :-| - collided = Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &auxres, &auxn, 1); + collided = Geometry3D::segment_intersects_cylinder(p_begin, p_end, height - radius * 2.0, radius, &auxres, &auxn, 1); if (collided) { real_t d = norm.dot(auxres); @@ -496,7 +496,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 & } } - collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, height * 0.5, 0), radius, &auxres, &auxn); + collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, height * 0.5 - radius, 0), radius, &auxres, &auxn); if (collided) { real_t d = norm.dot(auxres); @@ -508,7 +508,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 & } } - collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, height * -0.5, 0), radius, &auxres, &auxn); + collided = Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(0, height * -0.5 + radius, 0), radius, &auxres, &auxn); if (collided) { real_t d = norm.dot(auxres); @@ -529,19 +529,19 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 & } bool CapsuleShape3DSW::intersect_point(const Vector3 &p_point) const { - if (Math::abs(p_point.y) < height * 0.5) { + if (Math::abs(p_point.y) < height * 0.5 - radius) { return Vector3(p_point.x, 0, p_point.z).length() < radius; } else { Vector3 p = p_point; - p.y = Math::abs(p.y) - height * 0.5; + p.y = Math::abs(p.y) - height * 0.5 + radius; return p.length() < radius; } } Vector3 CapsuleShape3DSW::get_closest_point_to(const Vector3 &p_point) const { Vector3 s[2] = { - Vector3(0, -height * 0.5, 0), - Vector3(0, height * 0.5, 0), + Vector3(0, -height * 0.5 + radius, 0), + Vector3(0, height * 0.5 - radius, 0), }; Vector3 p = Geometry3D::get_closest_point_to_segment(p_point, s); @@ -566,7 +566,7 @@ Vector3 CapsuleShape3DSW::get_moment_of_inertia(real_t p_mass) const { void CapsuleShape3DSW::_setup(real_t p_height, real_t p_radius) { height = p_height; radius = p_radius; - configure(AABB(Vector3(-radius, -height * 0.5 - radius, -radius), Vector3(radius * 2, height + radius * 2.0, radius * 2))); + configure(AABB(Vector3(-radius, -height * 0.5, -radius), Vector3(radius * 2, height, radius * 2))); } void CapsuleShape3DSW::set_data(const Variant &p_data) { diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h index dde423ad60..c11c3a08f6 100644 --- a/servers/physics_3d/shape_3d_sw.h +++ b/servers/physics_3d/shape_3d_sw.h @@ -207,7 +207,7 @@ public: _FORCE_INLINE_ real_t get_height() const { return height; } _FORCE_INLINE_ real_t get_radius() const { return radius; } - virtual real_t get_area() const { return 4.0 / 3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; } + virtual real_t get_area() const { return 4.0 / 3.0 * Math_PI * radius * radius * radius + (height - radius * 2.0) * Math_PI * radius * radius; } virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CAPSULE; } 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 333e87bdbd..89d14e871a 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 @@ -131,8 +131,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton; Error err = shader_singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code); - - ERR_FAIL_COND(err != OK); + if (err != OK) { + return; + } if (version.is_null()) { version = shader_singleton->shader.version_create(); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 5b845cbb88..4feaf08808 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -3453,6 +3453,7 @@ void RendererStorageRD::multimesh_allocate_data(RID p_multimesh, int p_instances if (multimesh->buffer.is_valid()) { RD::get_singleton()->free(multimesh->buffer); multimesh->buffer = RID(); + multimesh->uniform_set_2d = RID(); //cleared by dependency multimesh->uniform_set_3d = RID(); //cleared by dependency } @@ -9129,25 +9130,41 @@ RendererStorageRD::RendererStorageRD() { case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { + sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; + } else { + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + } } break; case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { + sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; + } else { + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + } } break; case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { + sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; + } else { + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + } sampler_state.use_anisotropy = true; sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); } break; case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { + sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; + } else { + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + } sampler_state.use_anisotropy = true; sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h index 529328f0ed..44705b2bd6 100644 --- a/servers/rendering/renderer_rd/shader_rd.h +++ b/servers/rendering/renderer_rd/shader_rd.h @@ -142,7 +142,9 @@ public: ERR_FAIL_COND_V(!variants_enabled[p_variant], RID()); Version *version = version_owner.getornull(p_version); - ERR_FAIL_COND_V(!version, RID()); + if (!version) { + return RID(); + } if (version->dirty) { _compile_version(version); diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 9d8a63085d..6c4fb31efd 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2826,8 +2826,8 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/driver/depth_prepass/enable", true); GLOBAL_DEF("rendering/driver/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple"); - GLOBAL_DEF("rendering/textures/default_filters/use_nearest_mipmap_filter", false); - GLOBAL_DEF("rendering/textures/default_filters/anisotropic_filtering_level", 2); + GLOBAL_DEF_RST("rendering/textures/default_filters/use_nearest_mipmap_filter", false); + GLOBAL_DEF_RST("rendering/textures/default_filters/anisotropic_filtering_level", 2); ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/default_filters/anisotropic_filtering_level", PropertyInfo(Variant::INT, "rendering/textures/default_filters/anisotropic_filtering_level", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Faster),4x (Fast),8x (Average),16x (Slow)")); GLOBAL_DEF("rendering/camera/depth_of_field/depth_of_field_bokeh_shape", 1); |