feat: updated engine version to 4.4-rc1

This commit is contained in:
Sara 2025-02-23 14:38:14 +01:00
parent ee00efde1f
commit 21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View file

@ -60,8 +60,13 @@ bool CharacterBody3D::move_and_slide() {
// We need to check the platform_rid object still exists before accessing.
// A valid RID is no guarantee that the object has not been deleted.
if (ObjectDB::get_instance(platform_object_id)) {
//this approach makes sure there is less delay between the actual body velocity and the one we saved
// We can only perform the ObjectDB lifetime check on Object derived objects.
// Note that physics also creates RIDs for non-Object derived objects, these cannot
// be lifetime checked through ObjectDB, and therefore there is a still a vulnerability
// to dangling RIDs (access after free) in this scenario.
if (platform_object_id.is_null() || ObjectDB::get_instance(platform_object_id)) {
// This approach makes sure there is less delay between the actual body velocity and the one we saved.
bs = PhysicsServer3D::get_singleton()->body_get_direct_state(platform_rid);
}
@ -464,14 +469,14 @@ void CharacterBody3D::apply_floor_snap() {
_set_collision_direction(result, result_state, CollisionState(true, false, false));
if (result_state.floor) {
if (floor_stop_on_slope) {
// move and collide may stray the object a bit because of pre un-stucking,
// so only ensure that motion happens on floor direction in this case.
if (result.travel.length() > margin) {
result.travel = up_direction * up_direction.dot(result.travel);
} else {
result.travel = Vector3();
}
// Ensure that we only move the body along the up axis, because
// move_and_collide may stray the object a bit when getting it unstuck.
// Canceling this motion should not affect move_and_slide, as previous
// calls to move_and_collide already took care of freeing the body.
if (result.travel.length() > margin) {
result.travel = up_direction * up_direction.dot(result.travel);
} else {
result.travel = Vector3();
}
parameters.from.origin += result.travel;

View file

@ -70,7 +70,7 @@ void CollisionObject3D::_notification(int p_what) {
if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) {
Ref<World3D> world_ref = get_world_3d();
ERR_FAIL_COND(!world_ref.is_valid());
ERR_FAIL_COND(world_ref.is_null());
RID space = world_ref->get_space();
if (area) {
PhysicsServer3D::get_singleton()->area_set_space(rid, space);
@ -731,7 +731,7 @@ bool CollisionObject3D::get_capture_input_on_drag() const {
}
PackedStringArray CollisionObject3D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
PackedStringArray warnings = Node3D::get_configuration_warnings();
if (shapes.is_empty()) {
warnings.push_back(RTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape3D or CollisionPolygon3D as a child to define its shape."));

View file

@ -70,6 +70,8 @@ void CollisionPolygon3D::_build_polygon() {
convex->set_points(cp);
convex->set_margin(margin);
convex->set_debug_color(debug_color);
convex->set_debug_fill(debug_fill);
collision_object->shape_owner_add_shape(owner_id, convex);
collision_object->shape_owner_set_disabled(owner_id, disabled);
}
@ -157,6 +159,68 @@ bool CollisionPolygon3D::is_disabled() const {
return disabled;
}
Color CollisionPolygon3D::_get_default_debug_color() const {
const SceneTree *st = SceneTree::get_singleton();
return st ? st->get_debug_collisions_color() : Color(0.0, 0.0, 0.0, 0.0);
}
void CollisionPolygon3D::set_debug_color(const Color &p_color) {
if (debug_color == p_color) {
return;
}
debug_color = p_color;
update_gizmos();
}
Color CollisionPolygon3D::get_debug_color() const {
return debug_color;
}
void CollisionPolygon3D::set_debug_fill_enabled(bool p_enable) {
if (debug_fill == p_enable) {
return;
}
debug_fill = p_enable;
update_gizmos();
}
bool CollisionPolygon3D::get_debug_fill_enabled() const {
return debug_fill;
}
#ifdef DEBUG_ENABLED
bool CollisionPolygon3D::_property_can_revert(const StringName &p_name) const {
if (p_name == "debug_color") {
return true;
}
return false;
}
bool CollisionPolygon3D::_property_get_revert(const StringName &p_name, Variant &r_property) const {
if (p_name == "debug_color") {
r_property = _get_default_debug_color();
return true;
}
return false;
}
void CollisionPolygon3D::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "debug_color") {
if (debug_color == _get_default_debug_color()) {
p_property.usage = PROPERTY_USAGE_DEFAULT & ~PROPERTY_USAGE_STORAGE;
} else {
p_property.usage = PROPERTY_USAGE_DEFAULT;
}
}
}
#endif // DEBUG_ENABLED
real_t CollisionPolygon3D::get_margin() const {
return margin;
}
@ -169,7 +233,7 @@ void CollisionPolygon3D::set_margin(real_t p_margin) {
}
PackedStringArray CollisionPolygon3D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
PackedStringArray warnings = Node3D::get_configuration_warnings();
if (!Object::cast_to<CollisionObject3D>(get_parent())) {
warnings.push_back(RTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node.\nPlease only use it as a child of Area3D, StaticBody3D, RigidBody3D, CharacterBody3D, etc. to give them a shape."));
@ -201,6 +265,12 @@ void CollisionPolygon3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_disabled", "disabled"), &CollisionPolygon3D::set_disabled);
ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionPolygon3D::is_disabled);
ClassDB::bind_method(D_METHOD("set_debug_color", "color"), &CollisionPolygon3D::set_debug_color);
ClassDB::bind_method(D_METHOD("get_debug_color"), &CollisionPolygon3D::get_debug_color);
ClassDB::bind_method(D_METHOD("set_enable_debug_fill", "enable"), &CollisionPolygon3D::set_debug_fill_enabled);
ClassDB::bind_method(D_METHOD("get_enable_debug_fill"), &CollisionPolygon3D::get_debug_fill_enabled);
ClassDB::bind_method(D_METHOD("set_margin", "margin"), &CollisionPolygon3D::set_margin);
ClassDB::bind_method(D_METHOD("get_margin"), &CollisionPolygon3D::get_margin);
@ -210,8 +280,15 @@ void CollisionPolygon3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0.001,10,0.001,suffix:m"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_color"), "set_debug_color", "get_debug_color");
// Default value depends on a project setting, override for doc generation purposes.
ADD_PROPERTY_DEFAULT("debug_color", Color(0.0, 0.0, 0.0, 0.0));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_fill"), "set_enable_debug_fill", "get_enable_debug_fill");
}
CollisionPolygon3D::CollisionPolygon3D() {
set_notify_local_transform(true);
debug_color = _get_default_debug_color();
}

View file

@ -32,7 +32,6 @@
#define COLLISION_POLYGON_3D_H
#include "scene/3d/node_3d.h"
#include "scene/resources/3d/shape_3d.h"
class CollisionObject3D;
class CollisionPolygon3D : public Node3D {
@ -47,6 +46,11 @@ protected:
uint32_t owner_id = 0;
CollisionObject3D *collision_object = nullptr;
Color debug_color;
bool debug_fill = true;
Color _get_default_debug_color() const;
bool disabled = false;
void _build_polygon();
@ -59,6 +63,12 @@ protected:
void _notification(int p_what);
static void _bind_methods();
#ifdef DEBUG_ENABLED
bool _property_can_revert(const StringName &p_name) const;
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
void _validate_property(PropertyInfo &p_property) const;
#endif // DEBUG_ENABLED
public:
void set_depth(real_t p_depth);
real_t get_depth() const;
@ -69,6 +79,12 @@ public:
void set_disabled(bool p_disabled);
bool is_disabled() const;
void set_debug_color(const Color &p_color);
Color get_debug_color() const;
void set_debug_fill_enabled(bool p_enable);
bool get_debug_fill_enabled() const;
virtual AABB get_item_rect() const;
real_t get_margin() const;

View file

@ -32,7 +32,6 @@
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/physics/character_body_3d.h"
#include "scene/3d/physics/physics_body_3d.h"
#include "scene/3d/physics/vehicle_body_3d.h"
#include "scene/resources/3d/concave_polygon_shape_3d.h"
#include "scene/resources/3d/convex_polygon_shape_3d.h"
@ -87,6 +86,7 @@ void CollisionShape3D::_notification(int p_what) {
if (shape.is_valid()) {
collision_object->shape_owner_add_shape(owner_id, shape);
}
_update_in_shape_owner();
}
} break;
@ -120,14 +120,14 @@ void CollisionShape3D::resource_changed(Ref<Resource> res) {
#endif
PackedStringArray CollisionShape3D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
PackedStringArray warnings = Node3D::get_configuration_warnings();
CollisionObject3D *col_object = Object::cast_to<CollisionObject3D>(get_parent());
if (col_object == nullptr) {
warnings.push_back(RTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node.\nPlease only use it as a child of Area3D, StaticBody3D, RigidBody3D, CharacterBody3D, etc. to give them a shape."));
}
if (!shape.is_valid()) {
if (shape.is_null()) {
warnings.push_back(RTR("A shape must be provided for CollisionShape3D to function. Please create a shape resource for it."));
}
@ -166,11 +166,24 @@ void CollisionShape3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape3D::get_shape);
ClassDB::bind_method(D_METHOD("set_disabled", "enable"), &CollisionShape3D::set_disabled);
ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape3D::is_disabled);
ClassDB::bind_method(D_METHOD("make_convex_from_siblings"), &CollisionShape3D::make_convex_from_siblings);
ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_siblings", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
ClassDB::bind_method(D_METHOD("set_debug_color", "color"), &CollisionShape3D::set_debug_color);
ClassDB::bind_method(D_METHOD("get_debug_color"), &CollisionShape3D::get_debug_color);
ClassDB::bind_method(D_METHOD("set_enable_debug_fill", "enable"), &CollisionShape3D::set_debug_fill_enabled);
ClassDB::bind_method(D_METHOD("get_enable_debug_fill"), &CollisionShape3D::get_debug_fill_enabled);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "debug_color"), "set_debug_color", "get_debug_color");
// Default value depends on a project setting, override for doc generation purposes.
ADD_PROPERTY_DEFAULT("debug_color", Color(0.0, 0.0, 0.0, 0.0));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_fill"), "set_enable_debug_fill", "get_enable_debug_fill");
}
void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) {
@ -178,11 +191,27 @@ void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) {
return;
}
if (shape.is_valid()) {
#ifdef DEBUG_ENABLED
shape->disconnect_changed(callable_mp(this, &CollisionShape3D::_shape_changed));
#endif // DEBUG_ENABLED
shape->disconnect_changed(callable_mp((Node3D *)this, &Node3D::update_gizmos));
}
shape = p_shape;
if (shape.is_valid()) {
#ifdef DEBUG_ENABLED
if (shape->are_debug_properties_edited()) {
set_debug_color(shape->get_debug_color());
set_debug_fill_enabled(shape->get_debug_fill());
} else {
shape->set_debug_color(debug_color);
shape->set_debug_fill(debug_fill);
}
#endif // DEBUG_ENABLED
shape->connect_changed(callable_mp((Node3D *)this, &Node3D::update_gizmos));
#ifdef DEBUG_ENABLED
shape->connect_changed(callable_mp(this, &CollisionShape3D::_shape_changed));
#endif // DEBUG_ENABLED
}
update_gizmos();
if (collision_object) {
@ -215,9 +244,85 @@ bool CollisionShape3D::is_disabled() const {
return disabled;
}
Color CollisionShape3D::_get_default_debug_color() const {
const SceneTree *st = SceneTree::get_singleton();
return st ? st->get_debug_collisions_color() : Color(0.0, 0.0, 0.0, 0.0);
}
void CollisionShape3D::set_debug_color(const Color &p_color) {
if (debug_color == p_color) {
return;
}
debug_color = p_color;
if (shape.is_valid()) {
shape->set_debug_color(p_color);
}
}
Color CollisionShape3D::get_debug_color() const {
return debug_color;
}
void CollisionShape3D::set_debug_fill_enabled(bool p_enable) {
if (debug_fill == p_enable) {
return;
}
debug_fill = p_enable;
if (shape.is_valid()) {
shape->set_debug_fill(p_enable);
}
}
bool CollisionShape3D::get_debug_fill_enabled() const {
return debug_fill;
}
#ifdef DEBUG_ENABLED
bool CollisionShape3D::_property_can_revert(const StringName &p_name) const {
if (p_name == "debug_color") {
return true;
}
return false;
}
bool CollisionShape3D::_property_get_revert(const StringName &p_name, Variant &r_property) const {
if (p_name == "debug_color") {
r_property = _get_default_debug_color();
return true;
}
return false;
}
void CollisionShape3D::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "debug_color") {
if (debug_color == _get_default_debug_color()) {
p_property.usage = PROPERTY_USAGE_DEFAULT & ~PROPERTY_USAGE_STORAGE;
} else {
p_property.usage = PROPERTY_USAGE_DEFAULT;
}
}
}
void CollisionShape3D::_shape_changed() {
if (shape->get_debug_color() != debug_color) {
set_debug_color(shape->get_debug_color());
}
if (shape->get_debug_fill() != debug_fill) {
set_debug_fill_enabled(shape->get_debug_fill());
}
}
#endif // DEBUG_ENABLED
CollisionShape3D::CollisionShape3D() {
//indicator = RenderingServer::get_singleton()->mesh_create();
set_notify_local_transform(true);
debug_color = _get_default_debug_color();
}
CollisionShape3D::~CollisionShape3D() {

View file

@ -43,6 +43,15 @@ class CollisionShape3D : public Node3D {
uint32_t owner_id = 0;
CollisionObject3D *collision_object = nullptr;
Color debug_color;
bool debug_fill = true;
Color _get_default_debug_color() const;
#ifdef DEBUG_ENABLED
void _shape_changed();
#endif // DEBUG_ENABLED
#ifndef DISABLE_DEPRECATED
void resource_changed(Ref<Resource> res);
#endif
@ -55,6 +64,12 @@ protected:
void _notification(int p_what);
static void _bind_methods();
#ifdef DEBUG_ENABLED
bool _property_can_revert(const StringName &p_name) const;
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
void _validate_property(PropertyInfo &p_property) const;
#endif // DEBUG_ENABLED
public:
void make_convex_from_siblings();
@ -64,6 +79,12 @@ public:
void set_disabled(bool p_disabled);
bool is_disabled() const;
void set_debug_color(const Color &p_color);
Color get_debug_color() const;
void set_debug_fill_enabled(bool p_enable);
bool get_debug_fill_enabled() const;
PackedStringArray get_configuration_warnings() const override;
CollisionShape3D();

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View file

@ -30,7 +30,6 @@
#include "kinematic_collision_3d.h"
#include "scene/3d/physics/character_body_3d.h"
#include "scene/3d/physics/physics_body_3d.h"
Vector3 KinematicCollision3D::get_travel() const {

View file

@ -34,9 +34,6 @@
#include "core/object/ref_counted.h"
#include "servers/physics_server_3d.h"
class CharacterBody3D;
class PhysicsBody3D;
class KinematicCollision3D : public RefCounted {
GDCLASS(KinematicCollision3D, RefCounted);

View file

@ -29,6 +29,8 @@
/**************************************************************************/
#include "physical_bone_3d.h"
#include "scene/3d/physical_bone_simulator_3d.h"
#ifndef DISABLE_DEPRECATED
#include "scene/3d/skeleton_3d.h"
#endif //_DISABLE_DEPRECATED

View file

@ -31,8 +31,8 @@
#ifndef PHYSICAL_BONE_3D_H
#define PHYSICAL_BONE_3D_H
#include "scene/3d/physical_bone_simulator_3d.h"
#include "scene/3d/physics/physics_body_3d.h"
#include "scene/3d/skeleton_3d.h"
class PhysicalBoneSimulator3D;

View file

@ -167,8 +167,7 @@ bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_motion
PhysicsServer3D::MotionResult *r = nullptr;
PhysicsServer3D::MotionResult temp_result;
if (r_collision.is_valid()) {
// Needs const_cast because method bindings don't support non-const Ref.
r = const_cast<PhysicsServer3D::MotionResult *>(&r_collision->result);
r = &r_collision->result;
} else {
r = &temp_result;
}

View file

@ -31,7 +31,6 @@
#ifndef PHYSICS_BODY_3D_H
#define PHYSICS_BODY_3D_H
#include "core/templates/vset.h"
#include "scene/3d/physics/collision_object_3d.h"
#include "scene/3d/physics/kinematic_collision_3d.h"
#include "scene/resources/physics_material.h"

View file

@ -30,7 +30,6 @@
#include "ray_cast_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/physics/collision_object_3d.h"
void RayCast3D::set_target_position(const Vector3 &p_point) {
@ -464,12 +463,12 @@ void RayCast3D::_create_debug_shape() {
}
if (debug_mesh.is_null()) {
debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
debug_mesh.instantiate();
}
}
void RayCast3D::_update_debug_shape_material(bool p_check_collision) {
if (!debug_material.is_valid()) {
if (debug_material.is_null()) {
Ref<StandardMaterial3D> material = memnew(StandardMaterial3D);
debug_material = material;

View file

@ -659,7 +659,7 @@ void RigidBody3D::_reload_physics_characteristics() {
}
PackedStringArray RigidBody3D::get_configuration_warnings() const {
PackedStringArray warnings = CollisionObject3D::get_configuration_warnings();
PackedStringArray warnings = PhysicsBody3D::get_configuration_warnings();
Vector3 scale = get_transform().get_basis().get_scale();
if (ABS(scale.x - 1.0) > 0.05 || ABS(scale.y - 1.0) > 0.05 || ABS(scale.z - 1.0) > 0.05) {

View file

@ -31,7 +31,8 @@
#ifndef RIGID_BODY_3D_H
#define RIGID_BODY_3D_H
#include "scene/3d/physics/static_body_3d.h"
#include "core/templates/vset.h"
#include "scene/3d/physics/physics_body_3d.h"
class RigidBody3D : public PhysicsBody3D {
GDCLASS(RigidBody3D, PhysicsBody3D);

View file

@ -30,7 +30,6 @@
#include "shape_cast_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/physics/collision_object_3d.h"
#include "scene/resources/3d/concave_polygon_shape_3d.h"
@ -157,7 +156,7 @@ void ShapeCast3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &ShapeCast3D::set_collide_with_bodies);
ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &ShapeCast3D::is_collide_with_bodies_enabled);
ClassDB::bind_method(D_METHOD("_get_collision_result"), &ShapeCast3D::_get_collision_result);
ClassDB::bind_method(D_METHOD("get_collision_result"), &ShapeCast3D::get_collision_result);
ClassDB::bind_method(D_METHOD("set_debug_shape_custom_color", "debug_shape_custom_color"), &ShapeCast3D::set_debug_shape_custom_color);
ClassDB::bind_method(D_METHOD("get_debug_shape_custom_color"), &ShapeCast3D::get_debug_shape_custom_color);
@ -169,7 +168,7 @@ void ShapeCast3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01,suffix:m"), "set_margin", "get_margin");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_results"), "set_max_results", "get_max_results");
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "collision_result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "", "_get_collision_result");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "collision_result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "", "get_collision_result");
ADD_GROUP("Collide With", "collide_with");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collide_with_areas", "is_collide_with_areas_enabled");
@ -475,7 +474,7 @@ bool ShapeCast3D::is_collide_with_bodies_enabled() const {
return collide_with_bodies;
}
Array ShapeCast3D::_get_collision_result() const {
Array ShapeCast3D::get_collision_result() const {
Array ret;
for (int i = 0; i < result.size(); ++i) {
@ -499,7 +498,7 @@ void ShapeCast3D::_update_debug_shape_vertices() {
debug_shape_vertices.clear();
debug_line_vertices.clear();
if (!shape.is_null()) {
if (shape.is_valid()) {
debug_shape_vertices.append_array(shape->get_debug_mesh_lines());
for (int i = 0; i < debug_shape_vertices.size(); i++) {
debug_shape_vertices.set(i, debug_shape_vertices[i] + Vector3(target_position * get_closest_collision_safe_fraction()));
@ -546,12 +545,12 @@ void ShapeCast3D::_create_debug_shape() {
}
if (debug_mesh.is_null()) {
debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
debug_mesh.instantiate();
}
}
void ShapeCast3D::_update_debug_shape_material(bool p_check_collision) {
if (!debug_material.is_valid()) {
if (debug_material.is_null()) {
Ref<StandardMaterial3D> material = memnew(StandardMaterial3D);
debug_material = material;

View file

@ -73,8 +73,6 @@ class ShapeCast3D : public Node3D {
real_t collision_safe_fraction = 1.0;
real_t collision_unsafe_fraction = 1.0;
Array _get_collision_result() const;
RID debug_instance;
Ref<ArrayMesh> debug_mesh;
@ -123,6 +121,7 @@ public:
Ref<StandardMaterial3D> get_debug_material();
Array get_collision_result() const;
int get_collision_count() const;
Object *get_collider(int p_idx) const;
RID get_collider_rid(int p_idx) const;

View file

@ -30,6 +30,24 @@
#include "static_body_3d.h"
#include "core/math/convex_hull.h"
#include "scene/resources/3d/box_shape_3d.h"
#include "scene/resources/3d/capsule_shape_3d.h"
#include "scene/resources/3d/concave_polygon_shape_3d.h"
#include "scene/resources/3d/convex_polygon_shape_3d.h"
#include "scene/resources/3d/cylinder_shape_3d.h"
#include "scene/resources/3d/height_map_shape_3d.h"
#include "scene/resources/3d/navigation_mesh_source_geometry_data_3d.h"
#include "scene/resources/3d/primitive_meshes.h"
#include "scene/resources/3d/shape_3d.h"
#include "scene/resources/3d/sphere_shape_3d.h"
#include "scene/resources/3d/world_boundary_shape_3d.h"
#include "scene/resources/navigation_mesh.h"
#include "servers/navigation_server_3d.h"
Callable StaticBody3D::_navmesh_source_geometry_parsing_callback;
RID StaticBody3D::_navmesh_source_geometry_parser;
void StaticBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
if (physics_material_override.is_valid()) {
physics_material_override->disconnect_changed(callable_mp(this, &StaticBody3D::_reload_physics_characteristics));
@ -77,6 +95,138 @@ void StaticBody3D::_reload_physics_characteristics() {
}
}
void StaticBody3D::navmesh_parse_init() {
ERR_FAIL_NULL(NavigationServer3D::get_singleton());
if (!_navmesh_source_geometry_parser.is_valid()) {
_navmesh_source_geometry_parsing_callback = callable_mp_static(&StaticBody3D::navmesh_parse_source_geometry);
_navmesh_source_geometry_parser = NavigationServer3D::get_singleton()->source_geometry_parser_create();
NavigationServer3D::get_singleton()->source_geometry_parser_set_callback(_navmesh_source_geometry_parser, _navmesh_source_geometry_parsing_callback);
}
}
void StaticBody3D::navmesh_parse_source_geometry(const Ref<NavigationMesh> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Node *p_node) {
StaticBody3D *static_body = Object::cast_to<StaticBody3D>(p_node);
if (static_body == nullptr) {
return;
}
NavigationMesh::ParsedGeometryType parsed_geometry_type = p_navigation_mesh->get_parsed_geometry_type();
uint32_t parsed_collision_mask = p_navigation_mesh->get_collision_mask();
if ((parsed_geometry_type == NavigationMesh::PARSED_GEOMETRY_STATIC_COLLIDERS || parsed_geometry_type == NavigationMesh::PARSED_GEOMETRY_BOTH) && (static_body->get_collision_layer() & parsed_collision_mask)) {
List<uint32_t> shape_owners;
static_body->get_shape_owners(&shape_owners);
for (uint32_t shape_owner : shape_owners) {
if (static_body->is_shape_owner_disabled(shape_owner)) {
continue;
}
const int shape_count = static_body->shape_owner_get_shape_count(shape_owner);
for (int shape_index = 0; shape_index < shape_count; shape_index++) {
Ref<Shape3D> s = static_body->shape_owner_get_shape(shape_owner, shape_index);
if (s.is_null()) {
continue;
}
const Transform3D transform = static_body->get_global_transform() * static_body->shape_owner_get_transform(shape_owner);
BoxShape3D *box = Object::cast_to<BoxShape3D>(*s);
if (box) {
Array arr;
arr.resize(RS::ARRAY_MAX);
BoxMesh::create_mesh_array(arr, box->get_size());
p_source_geometry_data->add_mesh_array(arr, transform);
}
CapsuleShape3D *capsule = Object::cast_to<CapsuleShape3D>(*s);
if (capsule) {
Array arr;
arr.resize(RS::ARRAY_MAX);
CapsuleMesh::create_mesh_array(arr, capsule->get_radius(), capsule->get_height());
p_source_geometry_data->add_mesh_array(arr, transform);
}
CylinderShape3D *cylinder = Object::cast_to<CylinderShape3D>(*s);
if (cylinder) {
Array arr;
arr.resize(RS::ARRAY_MAX);
CylinderMesh::create_mesh_array(arr, cylinder->get_radius(), cylinder->get_radius(), cylinder->get_height());
p_source_geometry_data->add_mesh_array(arr, transform);
}
SphereShape3D *sphere = Object::cast_to<SphereShape3D>(*s);
if (sphere) {
Array arr;
arr.resize(RS::ARRAY_MAX);
SphereMesh::create_mesh_array(arr, sphere->get_radius(), sphere->get_radius() * 2.0);
p_source_geometry_data->add_mesh_array(arr, transform);
}
ConcavePolygonShape3D *concave_polygon = Object::cast_to<ConcavePolygonShape3D>(*s);
if (concave_polygon) {
p_source_geometry_data->add_faces(concave_polygon->get_faces(), transform);
}
ConvexPolygonShape3D *convex_polygon = Object::cast_to<ConvexPolygonShape3D>(*s);
if (convex_polygon) {
Vector<Vector3> varr = Variant(convex_polygon->get_points());
Geometry3D::MeshData md;
Error err = ConvexHullComputer::convex_hull(varr, md);
if (err == OK) {
PackedVector3Array faces;
for (const Geometry3D::MeshData::Face &face : md.faces) {
for (uint32_t k = 2; k < face.indices.size(); ++k) {
faces.push_back(md.vertices[face.indices[0]]);
faces.push_back(md.vertices[face.indices[k - 1]]);
faces.push_back(md.vertices[face.indices[k]]);
}
}
p_source_geometry_data->add_faces(faces, transform);
}
}
HeightMapShape3D *heightmap_shape = Object::cast_to<HeightMapShape3D>(*s);
if (heightmap_shape) {
int heightmap_depth = heightmap_shape->get_map_depth();
int heightmap_width = heightmap_shape->get_map_width();
if (heightmap_depth >= 2 && heightmap_width >= 2) {
const Vector<real_t> &map_data = heightmap_shape->get_map_data();
Vector2 heightmap_gridsize(heightmap_width - 1, heightmap_depth - 1);
Vector3 start = Vector3(heightmap_gridsize.x, 0, heightmap_gridsize.y) * -0.5;
Vector<Vector3> vertex_array;
vertex_array.resize((heightmap_depth - 1) * (heightmap_width - 1) * 6);
Vector3 *vertex_array_ptrw = vertex_array.ptrw();
const real_t *map_data_ptr = map_data.ptr();
int vertex_index = 0;
for (int d = 0; d < heightmap_depth - 1; d++) {
for (int w = 0; w < heightmap_width - 1; w++) {
vertex_array_ptrw[vertex_index] = start + Vector3(w, map_data_ptr[(heightmap_width * d) + w], d);
vertex_array_ptrw[vertex_index + 1] = start + Vector3(w + 1, map_data_ptr[(heightmap_width * d) + w + 1], d);
vertex_array_ptrw[vertex_index + 2] = start + Vector3(w, map_data_ptr[(heightmap_width * d) + heightmap_width + w], d + 1);
vertex_array_ptrw[vertex_index + 3] = start + Vector3(w + 1, map_data_ptr[(heightmap_width * d) + w + 1], d);
vertex_array_ptrw[vertex_index + 4] = start + Vector3(w + 1, map_data_ptr[(heightmap_width * d) + heightmap_width + w + 1], d + 1);
vertex_array_ptrw[vertex_index + 5] = start + Vector3(w, map_data_ptr[(heightmap_width * d) + heightmap_width + w], d + 1);
vertex_index += 6;
}
}
if (vertex_array.size() > 0) {
p_source_geometry_data->add_faces(vertex_array, transform);
}
}
}
}
}
}
}
void StaticBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody3D::set_constant_linear_velocity);
ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody3D::set_constant_angular_velocity);

View file

@ -33,6 +33,9 @@
#include "scene/3d/physics/physics_body_3d.h"
class NavigationMesh;
class NavigationMeshSourceGeometryData3D;
class StaticBody3D : public PhysicsBody3D {
GDCLASS(StaticBody3D, PhysicsBody3D);
@ -59,6 +62,13 @@ public:
private:
void _reload_physics_characteristics();
static Callable _navmesh_source_geometry_parsing_callback;
static RID _navmesh_source_geometry_parser;
public:
static void navmesh_parse_init();
static void navmesh_parse_source_geometry(const Ref<NavigationMesh> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Node *p_node);
};
#endif // STATIC_BODY_3D_H

View file

@ -106,7 +106,7 @@ void VehicleWheel3D::_notification(int p_what) {
}
PackedStringArray VehicleWheel3D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
PackedStringArray warnings = Node3D::get_configuration_warnings();
if (!Object::cast_to<VehicleBody3D>(get_parent())) {
warnings.push_back(RTR("VehicleWheel3D serves to provide a wheel system to a VehicleBody3D. Please use it as a child of a VehicleBody3D."));
@ -219,6 +219,14 @@ bool VehicleWheel3D::is_in_contact() const {
return m_raycastInfo.m_isInContact;
}
Vector3 VehicleWheel3D::get_contact_point() const {
return m_raycastInfo.m_contactPointWS;
}
Vector3 VehicleWheel3D::get_contact_normal() const {
return m_raycastInfo.m_contactNormalWS;
}
Node3D *VehicleWheel3D::get_contact_body() const {
return m_raycastInfo.m_groundObject;
}
@ -256,6 +264,8 @@ void VehicleWheel3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_in_contact"), &VehicleWheel3D::is_in_contact);
ClassDB::bind_method(D_METHOD("get_contact_body"), &VehicleWheel3D::get_contact_body);
ClassDB::bind_method(D_METHOD("get_contact_point"), &VehicleWheel3D::get_contact_point);
ClassDB::bind_method(D_METHOD("get_contact_normal"), &VehicleWheel3D::get_contact_normal);
ClassDB::bind_method(D_METHOD("set_roll_influence", "roll_influence"), &VehicleWheel3D::set_roll_influence);
ClassDB::bind_method(D_METHOD("get_roll_influence"), &VehicleWheel3D::get_roll_influence);
@ -287,11 +297,11 @@ void VehicleWheel3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wheel_friction_slip"), "set_friction_slip", "get_friction_slip");
ADD_GROUP("Suspension", "suspension_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "suspension_travel", PROPERTY_HINT_NONE, "suffix:m"), "set_suspension_travel", "get_suspension_travel");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "suspension_stiffness"), "set_suspension_stiffness", "get_suspension_stiffness");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "suspension_stiffness", PROPERTY_HINT_NONE, U"suffix:N/mm"), "set_suspension_stiffness", "get_suspension_stiffness");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "suspension_max_force", PROPERTY_HINT_NONE, U"suffix:kg\u22C5m/s\u00B2 (N)"), "set_suspension_max_force", "get_suspension_max_force");
ADD_GROUP("Damping", "damping_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_compression"), "set_damping_compression", "get_damping_compression");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_relaxation"), "set_damping_relaxation", "get_damping_relaxation");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_compression", PROPERTY_HINT_NONE, U"suffix:N\u22C5s/mm"), "set_damping_compression", "get_damping_compression");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping_relaxation", PROPERTY_HINT_NONE, U"suffix:N\u22C5s/mm"), "set_damping_relaxation", "get_damping_relaxation");
}
void VehicleWheel3D::set_engine_force(real_t p_engine_force) {
@ -532,7 +542,7 @@ void VehicleBody3D::_resolve_single_bilateral(PhysicsDirectBodyState3D *s, const
if (body2) {
rel_pos2 = pos2 - body2->get_global_transform().origin;
}
//this jacobian entry could be re-used for all iterations
// This Jacobian entry could be reused for all iterations.
Vector3 vel1 = s->get_linear_velocity() + (s->get_angular_velocity()).cross(rel_pos1); // * mPos);
Vector3 vel2;

View file

@ -130,6 +130,10 @@ public:
bool is_in_contact() const;
Vector3 get_contact_point() const;
Vector3 get_contact_normal() const;
Node3D *get_contact_body() const;
void set_roll_influence(real_t p_value);