diff options
Diffstat (limited to 'servers')
29 files changed, 871 insertions, 463 deletions
diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp index 109914d585..442c580920 100644 --- a/servers/physics_2d/godot_body_2d.cpp +++ b/servers/physics_2d/godot_body_2d.cpp @@ -221,7 +221,7 @@ Variant GodotBody2D::get_param(PhysicsServer2D::BodyParameter p_param) const { return inertia; } case PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS: { - return center_of_mass; + return center_of_mass_local; } case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: { return gravity_scale; diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h index 817d5f1b0d..7b11b50739 100644 --- a/servers/physics_2d/godot_body_2d.h +++ b/servers/physics_2d/godot_body_2d.h @@ -282,6 +282,7 @@ public: void reset_mass_properties(); _FORCE_INLINE_ const Vector2 &get_center_of_mass() const { return center_of_mass; } + _FORCE_INLINE_ const Vector2 &get_center_of_mass_local() const { return center_of_mass_local; } _FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; } _FORCE_INLINE_ real_t get_inv_inertia() const { return _inv_inertia; } _FORCE_INLINE_ real_t get_friction() const { return friction; } diff --git a/servers/physics_2d/godot_body_direct_state_2d.cpp b/servers/physics_2d/godot_body_direct_state_2d.cpp index deebc57f37..9c9bd56268 100644 --- a/servers/physics_2d/godot_body_direct_state_2d.cpp +++ b/servers/physics_2d/godot_body_direct_state_2d.cpp @@ -50,6 +50,10 @@ Vector2 GodotPhysicsDirectBodyState2D::get_center_of_mass() const { return body->get_center_of_mass(); } +Vector2 GodotPhysicsDirectBodyState2D::get_center_of_mass_local() const { + return body->get_center_of_mass_local(); +} + real_t GodotPhysicsDirectBodyState2D::get_inverse_mass() const { return body->get_inv_mass(); } diff --git a/servers/physics_2d/godot_body_direct_state_2d.h b/servers/physics_2d/godot_body_direct_state_2d.h index 2f3e8e5095..ff25205d52 100644 --- a/servers/physics_2d/godot_body_direct_state_2d.h +++ b/servers/physics_2d/godot_body_direct_state_2d.h @@ -46,6 +46,7 @@ public: virtual real_t get_total_linear_damp() const override; virtual Vector2 get_center_of_mass() const override; + virtual Vector2 get_center_of_mass_local() const override; virtual real_t get_inverse_mass() const override; virtual real_t get_inverse_inertia() const override; diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp index cf66b80076..617fa6470a 100644 --- a/servers/physics_2d/godot_physics_server_2d.cpp +++ b/servers/physics_2d/godot_physics_server_2d.cpp @@ -963,10 +963,17 @@ bool GodotPhysicsServer2D::body_test_motion(RID p_body, const MotionParameters & PhysicsDirectBodyState2D *GodotPhysicsServer2D::body_get_direct_state(RID p_body) { ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); + if (!body_owner.owns(p_body)) { + return nullptr; + } + GodotBody2D *body = body_owner.get_or_null(p_body); ERR_FAIL_COND_V(!body, nullptr); - ERR_FAIL_COND_V(!body->get_space(), nullptr); + if (!body->get_space()) { + return nullptr; + } + ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); return body->get_direct_state(); diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index d72014a8ed..5c189aa06a 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -54,13 +54,13 @@ _FORCE_INLINE_ static bool _can_collide_with(GodotCollisionObject2D *p_object, u return true; } -int GodotPhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) { +int GodotPhysicsDirectSpaceState2D::intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) { if (p_result_max <= 0) { return 0; } Rect2 aabb; - aabb.position = p_point - Vector2(0.00001, 0.00001); + aabb.position = p_parameters.position - Vector2(0.00001, 0.00001); aabb.size = Vector2(0.00002, 0.00002); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -68,21 +68,21 @@ int GodotPhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point int cc = 0; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; - if (p_pick_point && !col_obj->is_pickable()) { + if (p_parameters.pick_point && !col_obj->is_pickable()) { continue; } - if (p_filter_by_canvas && col_obj->get_canvas_instance_id() != p_canvas_instance_id) { + if (p_parameters.canvas_instance_id.is_valid() && col_obj->get_canvas_instance_id() != p_parameters.canvas_instance_id) { continue; } @@ -90,7 +90,7 @@ int GodotPhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point GodotShape2D *shape = col_obj->get_shape(shape_idx); - Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_point); + Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_parameters.position); if (!shape->contains_point(local_point)) { continue; @@ -113,21 +113,13 @@ int GodotPhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point return cc; } -int GodotPhysicsDirectSpaceState2D::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) { - return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point); -} - -int GodotPhysicsDirectSpaceState2D::intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) { - return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point, true, p_canvas_instance_id); -} - -bool GodotPhysicsDirectSpaceState2D::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +bool GodotPhysicsDirectSpaceState2D::intersect_ray(const RayParameters &p_parameters, RayResult &r_result) { ERR_FAIL_COND_V(space->locked, false); Vector2 begin, end; Vector2 normal; - begin = p_from; - end = p_to; + begin = p_parameters.from; + end = p_parameters.to; normal = (end - begin).normalized(); int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -141,11 +133,11 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const Vector2 &p_from, const real_t min_d = 1e10; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } @@ -157,12 +149,6 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const Vector2 &p_from, const Vector2 local_from = inv_xform.xform(begin); Vector2 local_to = inv_xform.xform(end); - /*local_from = col_obj->get_inv_transform().xform(begin); - local_from = col_obj->get_shape_inv_transform(shape_idx).xform(local_from); - - local_to = col_obj->get_inv_transform().xform(end); - local_to = col_obj->get_shape_inv_transform(shape_idx).xform(local_to);*/ - const GodotShape2D *shape = col_obj->get_shape(shape_idx); Vector2 shape_point, shape_normal; @@ -200,16 +186,17 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const Vector2 &p_from, const return true; } -int GodotPhysicsDirectSpaceState2D::intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +int GodotPhysicsDirectSpaceState2D::intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) { if (p_result_max <= 0) { return 0; } - GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - Rect2 aabb = p_xform.xform(shape->get_aabb()); - aabb = aabb.grow(p_margin); + Rect2 aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -220,18 +207,18 @@ int GodotPhysicsDirectSpaceState2D::intersect_shape(const RID &p_shape, const Tr break; } - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; int shape_idx = space->intersection_query_subindex_results[i]; - if (!GodotCollisionSolver2D::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), nullptr, nullptr, nullptr, p_margin)) { + if (!GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), nullptr, nullptr, nullptr, p_parameters.margin)) { continue; } @@ -248,13 +235,13 @@ int GodotPhysicsDirectSpaceState2D::intersect_shape(const RID &p_shape, const Tr return cc; } -bool GodotPhysicsDirectSpaceState2D::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState2D::cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe) { + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, false); - Rect2 aabb = p_xform.xform(shape->get_aabb()); - aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion - aabb = aabb.grow(p_margin); + Rect2 aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -262,11 +249,11 @@ bool GodotPhysicsDirectSpaceState2D::cast_motion(const RID &p_shape, const Trans real_t best_unsafe = 1; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; //ignore excluded } @@ -275,16 +262,16 @@ bool GodotPhysicsDirectSpaceState2D::cast_motion(const RID &p_shape, const Trans Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? - if (!GodotCollisionSolver2D::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) { + if (!GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_parameters.margin)) { continue; } //test initial overlap, ignore objects it's inside of. - if (GodotCollisionSolver2D::solve(shape, p_xform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) { + if (GodotCollisionSolver2D::solve(shape, p_parameters.transform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_parameters.margin)) { continue; } - Vector2 mnormal = p_motion.normalized(); + Vector2 mnormal = p_parameters.motion.normalized(); //just do kinematic solving real_t low = 0.0; @@ -294,7 +281,7 @@ bool GodotPhysicsDirectSpaceState2D::cast_motion(const RID &p_shape, const Trans real_t fraction = low + (hi - low) * fraction_coeff; Vector2 sep = mnormal; //important optimization for this to work fast enough - bool collided = GodotCollisionSolver2D::solve(shape, p_xform, p_motion * fraction, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, &sep, p_margin); + bool collided = GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion * fraction, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, &sep, p_parameters.margin); if (collided) { hi = fraction; @@ -331,17 +318,17 @@ bool GodotPhysicsDirectSpaceState2D::cast_motion(const RID &p_shape, const Trans return true; } -bool GodotPhysicsDirectSpaceState2D::collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +bool GodotPhysicsDirectSpaceState2D::collide_shape(const ShapeParameters &p_parameters, Vector2 *r_results, int p_result_max, int &r_result_count) { if (p_result_max <= 0) { return false; } - GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - Rect2 aabb = p_shape_xform.xform(shape->get_aabb()); - aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion - aabb = aabb.grow(p_margin); + Rect2 aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -358,13 +345,13 @@ bool GodotPhysicsDirectSpaceState2D::collide_shape(RID p_shape, const Transform2 GodotPhysicsServer2D::CollCbkData *cbkptr = &cbk; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude.has(col_obj->get_self())) { continue; } @@ -373,7 +360,7 @@ bool GodotPhysicsDirectSpaceState2D::collide_shape(RID p_shape, const Transform2 cbk.valid_dir = Vector2(); cbk.valid_depth = 0; - if (GodotCollisionSolver2D::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, nullptr, p_margin)) { + if (GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, nullptr, p_parameters.margin)) { collided = cbk.amount > 0; } } @@ -432,15 +419,15 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, rd->best_local_shape = rd->local_shape; } -bool GodotPhysicsDirectSpaceState2D::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState2D::rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) { + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; + real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; - Rect2 aabb = p_shape_xform.xform(shape->get_aabb()); - aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion - aabb = aabb.grow(p_margin); + Rect2 aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -451,13 +438,13 @@ bool GodotPhysicsDirectSpaceState2D::rest_info(RID p_shape, const Transform2D &p rcd.min_allowed_depth = min_contact_depth; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude.has(col_obj->get_self())) { continue; } @@ -467,7 +454,7 @@ bool GodotPhysicsDirectSpaceState2D::rest_info(RID p_shape, const Transform2D &p rcd.object = col_obj; rcd.shape = shape_idx; rcd.local_shape = 0; - bool sc = GodotCollisionSolver2D::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, nullptr, p_margin); + bool sc = GodotCollisionSolver2D::solve(shape, p_parameters.transform, p_parameters.motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, nullptr, p_parameters.margin); if (!sc) { continue; } diff --git a/servers/physics_2d/godot_space_2d.h b/servers/physics_2d/godot_space_2d.h index 97e2928a9d..b155a834b6 100644 --- a/servers/physics_2d/godot_space_2d.h +++ b/servers/physics_2d/godot_space_2d.h @@ -45,18 +45,15 @@ class GodotPhysicsDirectSpaceState2D : public PhysicsDirectSpaceState2D { GDCLASS(GodotPhysicsDirectSpaceState2D, PhysicsDirectSpaceState2D); - int _intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID()); - public: GodotSpace2D *space = nullptr; - virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override; - virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override; - virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; + virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override; + virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override; + virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override; + virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe) override; + virtual bool collide_shape(const ShapeParameters &p_parameters, Vector2 *r_results, int p_result_max, int &r_result_count) override; + virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override; GodotPhysicsDirectSpaceState2D() {} }; diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index 3010315571..84ec0e3c63 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -255,11 +255,7 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta, int p_iterations) // Warning: _solve_island modifies the constraint islands for optimization purpose, // their content is not reliable after these calls and shouldn't be used anymore. - if (island_count > 1) { - work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr); - } else if (island_count > 0) { - _solve_island(0); - } + work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr); { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp index 768c9e6572..acf60d61c2 100644 --- a/servers/physics_3d/godot_body_3d.cpp +++ b/servers/physics_3d/godot_body_3d.cpp @@ -267,7 +267,7 @@ Variant GodotBody3D::get_param(PhysicsServer3D::BodyParameter p_param) const { } } break; case PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS: { - return center_of_mass; + return center_of_mass_local; } break; case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: { return gravity_scale; diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h index 4993ea6a1b..7fc2f58168 100644 --- a/servers/physics_3d/godot_body_3d.h +++ b/servers/physics_3d/godot_body_3d.h @@ -200,6 +200,7 @@ public: _FORCE_INLINE_ Basis get_principal_inertia_axes() const { return principal_inertia_axes; } _FORCE_INLINE_ Vector3 get_center_of_mass() const { return center_of_mass; } + _FORCE_INLINE_ Vector3 get_center_of_mass_local() const { return center_of_mass_local; } _FORCE_INLINE_ Vector3 xform_local_to_principal(const Vector3 &p_pos) const { return principal_inertia_axes_local.xform(p_pos - center_of_mass_local); } _FORCE_INLINE_ void set_linear_velocity(const Vector3 &p_velocity) { linear_velocity = p_velocity; } diff --git a/servers/physics_3d/godot_body_direct_state_3d.cpp b/servers/physics_3d/godot_body_direct_state_3d.cpp index 9c234a5752..a929cab6f9 100644 --- a/servers/physics_3d/godot_body_direct_state_3d.cpp +++ b/servers/physics_3d/godot_body_direct_state_3d.cpp @@ -49,6 +49,10 @@ Vector3 GodotPhysicsDirectBodyState3D::get_center_of_mass() const { return body->get_center_of_mass(); } +Vector3 GodotPhysicsDirectBodyState3D::get_center_of_mass_local() const { + return body->get_center_of_mass_local(); +} + Basis GodotPhysicsDirectBodyState3D::get_principal_inertia_axes() const { return body->get_principal_inertia_axes(); } diff --git a/servers/physics_3d/godot_body_direct_state_3d.h b/servers/physics_3d/godot_body_direct_state_3d.h index 6c584a2634..35fd1543b0 100644 --- a/servers/physics_3d/godot_body_direct_state_3d.h +++ b/servers/physics_3d/godot_body_direct_state_3d.h @@ -46,6 +46,7 @@ public: virtual real_t get_total_linear_damp() const override; virtual Vector3 get_center_of_mass() const override; + virtual Vector3 get_center_of_mass_local() const override; virtual Basis get_principal_inertia_axes() const override; virtual real_t get_inverse_mass() const override; diff --git a/servers/physics_3d/godot_collision_object_3d.cpp b/servers/physics_3d/godot_collision_object_3d.cpp index 80a3d18ce0..deb058b3ac 100644 --- a/servers/physics_3d/godot_collision_object_3d.cpp +++ b/servers/physics_3d/godot_collision_object_3d.cpp @@ -171,7 +171,7 @@ void GodotCollisionObject3D::_update_shapes() { s.aabb_cache = shape_aabb; Vector3 scale = xform.get_basis().get_scale(); - s.area_cache = s.shape->get_area() * scale.x * scale.y * scale.z; + s.area_cache = s.shape->get_volume() * scale.x * scale.y * scale.z; if (s.bpid == 0) { s.bpid = space->get_broadphase()->create(this, i, shape_aabb, _static); diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp index 73654939ca..3e7f9faa27 100644 --- a/servers/physics_3d/godot_physics_server_3d.cpp +++ b/servers/physics_3d/godot_physics_server_3d.cpp @@ -881,10 +881,17 @@ bool GodotPhysicsServer3D::body_test_motion(RID p_body, const MotionParameters & PhysicsDirectBodyState3D *GodotPhysicsServer3D::body_get_direct_state(RID p_body) { ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); + if (!body_owner.owns(p_body)) { + return nullptr; + } + GodotBody3D *body = body_owner.get_or_null(p_body); ERR_FAIL_NULL_V(body, nullptr); - ERR_FAIL_NULL_V(body->get_space(), nullptr); + if (!body->get_space()) { + return nullptr; + } + ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); return body->get_direct_state(); diff --git a/servers/physics_3d/godot_shape_3d.h b/servers/physics_3d/godot_shape_3d.h index 8822d9487b..1bbcd903f7 100644 --- a/servers/physics_3d/godot_shape_3d.h +++ b/servers/physics_3d/godot_shape_3d.h @@ -64,7 +64,7 @@ public: FEATURE_CIRCLE, }; - virtual real_t get_area() const { return aabb.get_area(); } + virtual real_t get_volume() const { return aabb.get_volume(); } _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } _FORCE_INLINE_ RID get_self() const { return self; } @@ -120,7 +120,7 @@ class GodotWorldBoundaryShape3D : public GodotShape3D { public: Plane get_plane() const; - virtual real_t get_area() const override { return INFINITY; } + virtual real_t get_volume() const override { return INFINITY; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_WORLD_BOUNDARY; } virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; @@ -147,7 +147,7 @@ public: real_t get_length() const; bool get_slide_on_slope() const; - virtual real_t get_area() const override { return 0.0; } + virtual real_t get_volume() const override { return 0.0; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_SEPARATION_RAY; } virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const override; virtual Vector3 get_support(const Vector3 &p_normal) const override; @@ -173,7 +173,7 @@ class GodotSphereShape3D : public GodotShape3D { public: real_t get_radius() const; - virtual real_t get_area() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius; } + virtual real_t get_volume() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_SPHERE; } @@ -198,7 +198,7 @@ class GodotBoxShape3D : public GodotShape3D { public: _FORCE_INLINE_ Vector3 get_half_extents() const { return half_extents; } - virtual real_t get_area() const override { return 8 * half_extents.x * half_extents.y * half_extents.z; } + virtual real_t get_volume() const override { return 8 * half_extents.x * half_extents.y * half_extents.z; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_BOX; } @@ -227,7 +227,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 override { return 4.0 / 3.0 * Math_PI * radius * radius * radius + (height - radius * 2.0) * Math_PI * radius * radius; } + virtual real_t get_volume() const override { return 4.0 / 3.0 * Math_PI * radius * radius * radius + (height - radius * 2.0) * Math_PI * radius * radius; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CAPSULE; } @@ -256,7 +256,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 override { return 4.0 / 3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; } + virtual real_t get_volume() const override { return height * Math_PI * radius * radius; } virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CYLINDER; } diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index 750bf3a16d..77b37a2353 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -57,9 +57,9 @@ _FORCE_INLINE_ static bool _can_collide_with(GodotCollisionObject3D *p_object, u return true; } -int GodotPhysicsDirectSpaceState3D::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +int GodotPhysicsDirectSpaceState3D::intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) { ERR_FAIL_COND_V(space->locked, false); - int amount = space->broadphase->cull_point(p_point, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_point(p_parameters.position, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); int cc = 0; //Transform3D ai = p_xform.affine_inverse(); @@ -69,13 +69,13 @@ int GodotPhysicsDirectSpaceState3D::intersect_point(const Vector3 &p_point, Shap break; } - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } //area can't be picked by ray (default) - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } @@ -85,7 +85,7 @@ int GodotPhysicsDirectSpaceState3D::intersect_point(const Vector3 &p_point, Shap Transform3D inv_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); inv_xform.affine_invert(); - if (!col_obj->get_shape(shape_idx)->intersect_point(inv_xform.xform(p_point))) { + if (!col_obj->get_shape(shape_idx)->intersect_point(inv_xform.xform(p_parameters.position))) { continue; } @@ -104,13 +104,13 @@ int GodotPhysicsDirectSpaceState3D::intersect_point(const Vector3 &p_point, Shap return cc; } -bool GodotPhysicsDirectSpaceState3D::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) { +bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parameters, RayResult &r_result) { ERR_FAIL_COND_V(space->locked, false); Vector3 begin, end; Vector3 normal; - begin = p_from; - end = p_to; + begin = p_parameters.from; + end = p_parameters.to; normal = (end - begin).normalized(); int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -124,15 +124,15 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const Vector3 &p_from, const real_t min_d = 1e10; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_pick_ray && !(space->intersection_query_results[i]->is_ray_pickable())) { + if (p_parameters.pick_ray && !(space->intersection_query_results[i]->is_ray_pickable())) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } @@ -183,15 +183,15 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const Vector3 &p_from, const return true; } -int GodotPhysicsDirectSpaceState3D::intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +int GodotPhysicsDirectSpaceState3D::intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) { if (p_result_max <= 0) { return 0; } - GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - AABB aabb = p_xform.xform(shape->get_aabb()); + AABB aabb = p_parameters.transform.xform(shape->get_aabb()); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -204,20 +204,20 @@ int GodotPhysicsDirectSpaceState3D::intersect_shape(const RID &p_shape, const Tr break; } - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } //area can't be picked by ray (default) - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; } const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; int shape_idx = space->intersection_query_subindex_results[i]; - if (!GodotCollisionSolver3D::solve_static(shape, p_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), nullptr, nullptr, nullptr, p_margin, 0)) { + if (!GodotCollisionSolver3D::solve_static(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), nullptr, nullptr, nullptr, p_parameters.margin, 0)) { continue; } @@ -238,36 +238,36 @@ int GodotPhysicsDirectSpaceState3D::intersect_shape(const RID &p_shape, const Tr return cc; } -bool GodotPhysicsDirectSpaceState3D::cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) { - GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState3D::cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info) { + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, false); - AABB aabb = p_xform.xform(shape->get_aabb()); - aabb = aabb.merge(AABB(aabb.position + p_motion, aabb.size)); //motion - aabb = aabb.grow(p_margin); + AABB aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.merge(AABB(aabb.position + p_parameters.motion, aabb.size)); //motion + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); real_t best_safe = 1; real_t best_unsafe = 1; - Transform3D xform_inv = p_xform.affine_inverse(); + Transform3D xform_inv = p_parameters.transform.affine_inverse(); GodotMotionShape3D mshape; mshape.shape = shape; - mshape.motion = xform_inv.basis.xform(p_motion); + mshape.motion = xform_inv.basis.xform(p_parameters.motion); bool best_first = true; - Vector3 motion_normal = p_motion.normalized(); + Vector3 motion_normal = p_parameters.motion.normalized(); Vector3 closest_A, closest_B; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } - if (p_exclude.has(space->intersection_query_results[i]->get_self())) { + if (p_parameters.exclude.has(space->intersection_query_results[i]->get_self())) { continue; //ignore excluded } @@ -279,14 +279,14 @@ bool GodotPhysicsDirectSpaceState3D::cast_motion(const RID &p_shape, const Trans Transform3D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? - if (GodotCollisionSolver3D::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { + if (GodotCollisionSolver3D::solve_distance(&mshape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { continue; } //test initial overlap, ignore objects it's inside of. sep_axis = motion_normal; - if (!GodotCollisionSolver3D::solve_distance(shape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { + if (!GodotCollisionSolver3D::solve_distance(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { continue; } @@ -297,11 +297,11 @@ bool GodotPhysicsDirectSpaceState3D::cast_motion(const RID &p_shape, const Trans for (int j = 0; j < 8; j++) { //steps should be customizable.. real_t fraction = low + (hi - low) * fraction_coeff; - mshape.motion = xform_inv.basis.xform(p_motion * fraction); + mshape.motion = xform_inv.basis.xform(p_parameters.motion * fraction); Vector3 lA, lB; Vector3 sep = motion_normal; //important optimization for this to work fast enough - bool collided = !GodotCollisionSolver3D::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, aabb, &sep); + bool collided = !GodotCollisionSolver3D::solve_distance(&mshape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, aabb, &sep); if (collided) { hi = fraction; @@ -357,16 +357,16 @@ bool GodotPhysicsDirectSpaceState3D::cast_motion(const RID &p_shape, const Trans return true; } -bool GodotPhysicsDirectSpaceState3D::collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +bool GodotPhysicsDirectSpaceState3D::collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) { if (p_result_max <= 0) { return false; } - GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - AABB aabb = p_shape_xform.xform(shape->get_aabb()); - aabb = aabb.grow(p_margin); + AABB aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -382,19 +382,19 @@ bool GodotPhysicsDirectSpaceState3D::collide_shape(RID p_shape, const Transform3 GodotPhysicsServer3D::CollCbkData *cbkptr = &cbk; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude.has(col_obj->get_self())) { continue; } int shape_idx = space->intersection_query_subindex_results[i]; - if (GodotCollisionSolver3D::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) { + if (GodotCollisionSolver3D::solve_static(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_parameters.margin)) { collided = true; } } @@ -487,14 +487,14 @@ static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vect rd->best_result.local_shape = rd->local_shape; } -bool GodotPhysicsDirectSpaceState3D::rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState3D::rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) { + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; + real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; - AABB aabb = p_shape_xform.xform(shape->get_aabb()); - aabb = aabb.grow(p_margin); + AABB aabb = p_parameters.transform.xform(shape->get_aabb()); + aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); @@ -502,13 +502,13 @@ bool GodotPhysicsDirectSpaceState3D::rest_info(RID p_shape, const Transform3D &p rcd.min_allowed_depth = min_contact_depth; for (int i = 0; i < amount; i++) { - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { + if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { continue; } const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude.has(col_obj->get_self())) { continue; } @@ -516,7 +516,7 @@ bool GodotPhysicsDirectSpaceState3D::rest_info(RID p_shape, const Transform3D &p rcd.object = col_obj; rcd.shape = shape_idx; - bool sc = GodotCollisionSolver3D::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin); + bool sc = GodotCollisionSolver3D::solve_static(shape, p_parameters.transform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_parameters.margin); if (!sc) { continue; } diff --git a/servers/physics_3d/godot_space_3d.h b/servers/physics_3d/godot_space_3d.h index 3b36dd346c..aa5e965751 100644 --- a/servers/physics_3d/godot_space_3d.h +++ b/servers/physics_3d/godot_space_3d.h @@ -49,12 +49,12 @@ class GodotPhysicsDirectSpaceState3D : public PhysicsDirectSpaceState3D { public: GodotSpace3D *space; - virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) override; - virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) override; - virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; + virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override; + virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override; + virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override; + virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info = nullptr) override; + virtual bool collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) override; + virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override; virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override; GodotPhysicsDirectSpaceState3D(); diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index a8654c617b..331d65df49 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -359,11 +359,7 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta, int p_iterations) // Warning: _solve_island modifies the constraint islands for optimization purpose, // their content is not reliable after these calls and shouldn't be used anymore. - if (island_count > 1) { - work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr); - } else if (island_count > 0) { - _solve_island(0); - } + work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr); { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index abe173b078..fa89ccec65 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -78,6 +78,7 @@ void PhysicsDirectBodyState2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_total_angular_damp"), &PhysicsDirectBodyState2D::get_total_angular_damp); ClassDB::bind_method(D_METHOD("get_center_of_mass"), &PhysicsDirectBodyState2D::get_center_of_mass); + ClassDB::bind_method(D_METHOD("get_center_of_mass_local"), &PhysicsDirectBodyState2D::get_center_of_mass_local); ClassDB::bind_method(D_METHOD("get_inverse_mass"), &PhysicsDirectBodyState2D::get_inverse_mass); ClassDB::bind_method(D_METHOD("get_inverse_inertia"), &PhysicsDirectBodyState2D::get_inverse_inertia); @@ -124,6 +125,7 @@ void PhysicsDirectBodyState2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_linear_damp"), "", "get_total_linear_damp"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "total_gravity"), "", "get_total_gravity"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass"), "", "get_center_of_mass"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "center_of_mass_local"), "", "get_center_of_mass_local"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleep_state", "is_sleeping"); @@ -134,95 +136,132 @@ PhysicsDirectBodyState2D::PhysicsDirectBodyState2D() {} /////////////////////////////////////////////////////// -void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape_ref) { - ERR_FAIL_COND(p_shape_ref.is_null()); - shape_ref = p_shape_ref; - shape = p_shape_ref->get_rid(); -} - -RES PhysicsShapeQueryParameters2D::get_shape() const { - return shape_ref; -} - -void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) { - if (shape != p_shape) { - shape_ref = RES(); - shape = p_shape; +void PhysicsRayQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); + for (int i = 0; i < p_exclude.size(); i++) { + parameters.exclude.insert(p_exclude[i]); } } -RID PhysicsShapeQueryParameters2D::get_shape_rid() const { - return shape; +Vector<RID> PhysicsRayQueryParameters2D::get_exclude() const { + Vector<RID> ret; + ret.resize(parameters.exclude.size()); + int idx = 0; + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + ret.write[idx++] = E->get(); + } + return ret; } -void PhysicsShapeQueryParameters2D::set_transform(const Transform2D &p_transform) { - transform = p_transform; -} +void PhysicsRayQueryParameters2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters2D::set_from); + ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters2D::get_from); -Transform2D PhysicsShapeQueryParameters2D::get_transform() const { - return transform; -} + ClassDB::bind_method(D_METHOD("set_to", "to"), &PhysicsRayQueryParameters2D::set_to); + ClassDB::bind_method(D_METHOD("get_to"), &PhysicsRayQueryParameters2D::get_to); -void PhysicsShapeQueryParameters2D::set_motion(const Vector2 &p_motion) { - motion = p_motion; -} + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsRayQueryParameters2D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsRayQueryParameters2D::get_collision_mask); -Vector2 PhysicsShapeQueryParameters2D::get_motion() const { - return motion; -} + ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsRayQueryParameters2D::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsRayQueryParameters2D::get_exclude); -void PhysicsShapeQueryParameters2D::set_margin(real_t p_margin) { - margin = p_margin; -} + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsRayQueryParameters2D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsRayQueryParameters2D::is_collide_with_bodies_enabled); -real_t PhysicsShapeQueryParameters2D::get_margin() const { - return margin; -} + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters2D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters2D::is_collide_with_areas_enabled); -void PhysicsShapeQueryParameters2D::set_collision_mask(uint32_t p_collision_mask) { - collision_mask = p_collision_mask; + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "from"), "set_from", "get_from"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "to"), "set_to", "get_to"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); } -uint32_t PhysicsShapeQueryParameters2D::get_collision_mask() const { - return collision_mask; -} +/////////////////////////////////////////////////////// -void PhysicsShapeQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { - exclude.clear(); +void PhysicsPointQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); + parameters.exclude.insert(p_exclude[i]); } } -Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const { +Vector<RID> PhysicsPointQueryParameters2D::get_exclude() const { Vector<RID> ret; - ret.resize(exclude.size()); + ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = exclude.front(); E; E = E->next()) { + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; } -void PhysicsShapeQueryParameters2D::set_collide_with_bodies(bool p_enable) { - collide_with_bodies = p_enable; +void PhysicsPointQueryParameters2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_position", "position"), &PhysicsPointQueryParameters2D::set_position); + ClassDB::bind_method(D_METHOD("get_position"), &PhysicsPointQueryParameters2D::get_position); + + ClassDB::bind_method(D_METHOD("set_canvas_instance_id", "canvas_instance_id"), &PhysicsPointQueryParameters2D::set_canvas_instance_id); + ClassDB::bind_method(D_METHOD("get_canvas_instance_id"), &PhysicsPointQueryParameters2D::get_canvas_instance_id); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsPointQueryParameters2D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsPointQueryParameters2D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsPointQueryParameters2D::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsPointQueryParameters2D::get_exclude); + + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsPointQueryParameters2D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsPointQueryParameters2D::is_collide_with_bodies_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsPointQueryParameters2D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsPointQueryParameters2D::is_collide_with_areas_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_instance_id", PROPERTY_HINT_OBJECT_ID), "set_canvas_instance_id", "get_canvas_instance_id"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); +} + +/////////////////////////////////////////////////////// + +void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape_ref) { + ERR_FAIL_COND(p_shape_ref.is_null()); + shape_ref = p_shape_ref; + parameters.shape_rid = p_shape_ref->get_rid(); } -bool PhysicsShapeQueryParameters2D::is_collide_with_bodies_enabled() const { - return collide_with_bodies; +void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) { + if (parameters.shape_rid != p_shape) { + shape_ref = RES(); + parameters.shape_rid = p_shape; + } } -void PhysicsShapeQueryParameters2D::set_collide_with_areas(bool p_enable) { - collide_with_areas = p_enable; +void PhysicsShapeQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); + for (int i = 0; i < p_exclude.size(); i++) { + parameters.exclude.insert(p_exclude[i]); + } } -bool PhysicsShapeQueryParameters2D::is_collide_with_areas_enabled() const { - return collide_with_areas; +Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const { + Vector<RID> ret; + ret.resize(parameters.exclude.size()); + int idx = 0; + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + ret.write[idx++] = E->get(); + } + return ret; } void PhysicsShapeQueryParameters2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters2D::set_shape); ClassDB::bind_method(D_METHOD("get_shape"), &PhysicsShapeQueryParameters2D::get_shape); + ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters2D::set_shape_rid); ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters2D::get_shape_rid); @@ -248,7 +287,7 @@ void PhysicsShapeQueryParameters2D::_bind_methods() { ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsShapeQueryParameters2D::is_collide_with_areas_enabled); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::RID) + ":"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape"); @@ -258,36 +297,58 @@ void PhysicsShapeQueryParameters2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); } -Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { - RayResult inters; - Set<RID> exclude; - for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); - } +/////////////////////////////////////////////////////// - bool res = intersect_ray(p_from, p_to, inters, exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); +Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Ref<PhysicsRayQueryParameters2D> &p_ray_query) { + ERR_FAIL_COND_V(!p_ray_query.is_valid(), Dictionary()); + + RayResult result; + bool res = intersect_ray(p_ray_query->get_parameters(), result); if (!res) { return Dictionary(); } Dictionary d; - d["position"] = inters.position; - d["normal"] = inters.normal; - d["collider_id"] = inters.collider_id; - d["collider"] = inters.collider; - d["shape"] = inters.shape; - d["rid"] = inters.rid; + d["position"] = result.position; + d["normal"] = result.normal; + d["collider_id"] = result.collider_id; + d["collider"] = result.collider; + d["shape"] = result.shape; + d["rid"] = result.rid; return d; } +Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results) { + Vector<ShapeResult> ret; + ret.resize(p_max_results); + + int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size()); + + if (rc == 0) { + return Array(); + } + + Array r; + r.resize(rc); + for (int i = 0; i < rc; i++) { + Dictionary d; + d["rid"] = ret[i].rid; + d["collider_id"] = ret[i].collider_id; + d["collider"] = ret[i].collider; + d["shape"] = ret[i].shape; + r[i] = d; + } + return r; +} + Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); Vector<ShapeResult> sr; sr.resize(p_max_results); - int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size()); Array ret; ret.resize(rc); for (int i = 0; i < rc; i++) { @@ -306,7 +367,7 @@ Array PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParamet ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); real_t closest_safe, closest_unsafe; - bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe); if (!res) { return Array(); } @@ -317,54 +378,13 @@ Array PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParamet return ret; } -Array PhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) { - Set<RID> exclude; - for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); - } - - Vector<ShapeResult> ret; - ret.resize(p_max_results); - - int rc; - if (p_filter_by_canvas) { - rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); - } else { - rc = intersect_point_on_canvas(p_point, p_canvas_instance_id, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); - } - - if (rc == 0) { - return Array(); - } - - Array r; - r.resize(rc); - for (int i = 0; i < rc; i++) { - Dictionary d; - d["rid"] = ret[i].rid; - d["collider_id"] = ret[i].collider_id; - d["collider"] = ret[i].collider; - d["shape"] = ret[i].shape; - r[i] = d; - } - return r; -} - -Array PhysicsDirectSpaceState2D::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { - return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); -} - -Array PhysicsDirectSpaceState2D::_intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results, const Vector<RID> &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { - return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas, true, p_canvas_intance_id); -} - Array PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); Vector<Vector2> ret; ret.resize(p_max_results * 2); int rc = 0; - bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc); if (!res) { return Array(); } @@ -381,7 +401,7 @@ Dictionary PhysicsDirectSpaceState2D::_get_rest_info(const Ref<PhysicsShapeQuery ShapeRestInfo sri; - bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = rest_info(p_shape_query->get_parameters(), &sri); Dictionary r; if (!res) { return r; @@ -401,13 +421,12 @@ PhysicsDirectSpaceState2D::PhysicsDirectSpaceState2D() { } void PhysicsDirectSpaceState2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_ray, DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_intersect_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &PhysicsDirectSpaceState2D::_cast_motion); - ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_collide_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &PhysicsDirectSpaceState2D::_get_rest_info); + ClassDB::bind_method(D_METHOD("intersect_point", "parameters", "max_results"), &PhysicsDirectSpaceState2D::_intersect_point, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("intersect_ray", "parameters"), &PhysicsDirectSpaceState2D::_intersect_ray); + ClassDB::bind_method(D_METHOD("intersect_shape", "parameters", "max_results"), &PhysicsDirectSpaceState2D::_intersect_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("cast_motion", "parameters"), &PhysicsDirectSpaceState2D::_cast_motion); + ClassDB::bind_method(D_METHOD("collide_shape", "parameters", "max_results"), &PhysicsDirectSpaceState2D::_collide_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("get_rest_info", "parameters"), &PhysicsDirectSpaceState2D::_get_rest_info); } /////////////////////////////// @@ -473,7 +492,7 @@ void PhysicsTestMotionParameters2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects"); } diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index e6acebd5dd..fec03a8111 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -49,6 +49,7 @@ public: virtual real_t get_total_angular_damp() const = 0; // get density of this body space/area virtual Vector2 get_center_of_mass() const = 0; + virtual Vector2 get_center_of_mass_local() const = 0; virtual real_t get_inverse_mass() const = 0; // get the mass virtual real_t get_inverse_inertia() const = 0; // get density of this body space @@ -94,60 +95,15 @@ public: PhysicsDirectBodyState2D(); }; -//used for script -class PhysicsShapeQueryParameters2D : public RefCounted { - GDCLASS(PhysicsShapeQueryParameters2D, RefCounted); - friend class PhysicsDirectSpaceState2D; - - RES shape_ref; - RID shape; - Transform2D transform; - Vector2 motion; - real_t margin = 0.0; - Set<RID> exclude; - uint32_t collision_mask = UINT32_MAX; - - bool collide_with_bodies = true; - bool collide_with_areas = false; - -protected: - static void _bind_methods(); - -public: - void set_shape(const RES &p_shape_ref); - RES get_shape() const; - void set_shape_rid(const RID &p_shape); - RID get_shape_rid() const; - - void set_transform(const Transform2D &p_transform); - Transform2D get_transform() const; - - void set_motion(const Vector2 &p_motion); - Vector2 get_motion() const; - - void set_margin(real_t p_margin); - real_t get_margin() const; - - void set_collision_mask(uint32_t p_mask); - uint32_t get_collision_mask() const; - - void set_collide_with_bodies(bool p_enable); - bool is_collide_with_bodies_enabled() const; - - void set_collide_with_areas(bool p_enable); - bool is_collide_with_areas_enabled() const; - - void set_exclude(const Vector<RID> &p_exclude); - Vector<RID> get_exclude() const; -}; +class PhysicsRayQueryParameters2D; +class PhysicsPointQueryParameters2D; +class PhysicsShapeQueryParameters2D; class PhysicsDirectSpaceState2D : public Object { GDCLASS(PhysicsDirectSpaceState2D, Object); - Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results = 32, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector<RID> &p_exclud, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID()); + Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters2D> &p_ray_query); + Array _intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results = 32); Array _intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32); Array _cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query); Array _collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32); @@ -157,6 +113,16 @@ protected: static void _bind_methods(); public: + struct RayParameters { + Vector2 from; + Vector2 to; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; + + bool collide_with_bodies = true; + bool collide_with_areas = false; + }; + struct RayResult { Vector2 position; Vector2 normal; @@ -166,7 +132,7 @@ public: int shape = 0; }; - virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) = 0; struct ShapeResult { RID rid; @@ -175,14 +141,31 @@ public: int shape = 0; }; - virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0; - virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0; + struct PointParameters { + Vector2 position; + ObjectID canvas_instance_id; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; + + bool collide_with_bodies = true; + bool collide_with_areas = false; - virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + bool pick_point = false; + }; + + virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0; - virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + struct ShapeParameters { + RID shape_rid; + Transform2D transform; + Vector2 motion; + real_t margin = 0.0; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; - virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + bool collide_with_bodies = true; + bool collide_with_areas = false; + }; struct ShapeRestInfo { Vector2 point; @@ -190,10 +173,13 @@ public: RID rid; ObjectID collider_id; int shape = 0; - Vector2 linear_velocity; //velocity at contact point + Vector2 linear_velocity; // Velocity at contact point. }; - virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0; + virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe) = 0; + virtual bool collide_shape(const ShapeParameters &p_parameters, Vector2 *r_results, int p_result_max, int &r_result_count) = 0; + virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) = 0; PhysicsDirectSpaceState2D(); }; @@ -592,6 +578,107 @@ public: ~PhysicsServer2D(); }; +class PhysicsRayQueryParameters2D : public RefCounted { + GDCLASS(PhysicsRayQueryParameters2D, RefCounted); + + PhysicsDirectSpaceState2D::RayParameters parameters; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState2D::RayParameters &get_parameters() const { return parameters; } + + void set_from(const Vector2 &p_from) { parameters.from = p_from; } + const Vector2 &get_from() const { return parameters.from; } + + void set_to(const Vector2 &p_to) { parameters.to = p_to; } + const Vector2 &get_to() const { return parameters.to; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + +class PhysicsPointQueryParameters2D : public RefCounted { + GDCLASS(PhysicsPointQueryParameters2D, RefCounted); + + PhysicsDirectSpaceState2D::PointParameters parameters; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState2D::PointParameters &get_parameters() const { return parameters; } + + void set_position(const Vector2 &p_position) { parameters.position = p_position; } + const Vector2 &get_position() const { return parameters.position; } + + void set_canvas_instance_id(ObjectID p_canvas_instance_id) { parameters.canvas_instance_id = p_canvas_instance_id; } + ObjectID get_canvas_instance_id() const { return parameters.canvas_instance_id; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + +class PhysicsShapeQueryParameters2D : public RefCounted { + GDCLASS(PhysicsShapeQueryParameters2D, RefCounted); + + PhysicsDirectSpaceState2D::ShapeParameters parameters; + + RES shape_ref; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState2D::ShapeParameters &get_parameters() const { return parameters; } + + void set_shape(const RES &p_shape_ref); + RES get_shape() const { return shape_ref; } + + void set_shape_rid(const RID &p_shape); + RID get_shape_rid() const { return parameters.shape_rid; } + + void set_transform(const Transform2D &p_transform) { parameters.transform = p_transform; } + const Transform2D &get_transform() const { return parameters.transform; } + + void set_motion(const Vector2 &p_motion) { parameters.motion = p_motion; } + const Vector2 &get_motion() const { return parameters.motion; } + + void set_margin(real_t p_margin) { parameters.margin = p_margin; } + real_t get_margin() const { return parameters.margin; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + class PhysicsTestMotionParameters2D : public RefCounted { GDCLASS(PhysicsTestMotionParameters2D, RefCounted); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 8f66a207aa..eb52cbfe5a 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -77,6 +77,7 @@ void PhysicsDirectBodyState3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_total_angular_damp"), &PhysicsDirectBodyState3D::get_total_angular_damp); ClassDB::bind_method(D_METHOD("get_center_of_mass"), &PhysicsDirectBodyState3D::get_center_of_mass); + ClassDB::bind_method(D_METHOD("get_center_of_mass_local"), &PhysicsDirectBodyState3D::get_center_of_mass_local); ClassDB::bind_method(D_METHOD("get_principal_inertia_axes"), &PhysicsDirectBodyState3D::get_principal_inertia_axes); ClassDB::bind_method(D_METHOD("get_inverse_mass"), &PhysicsDirectBodyState3D::get_inverse_mass); @@ -126,6 +127,7 @@ void PhysicsDirectBodyState3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "inverse_inertia"), "", "get_inverse_inertia"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "total_gravity"), "", "get_total_gravity"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass"), "", "get_center_of_mass"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass_local"), "", "get_center_of_mass_local"); ADD_PROPERTY(PropertyInfo(Variant::BASIS, "principal_inertia_axes"), "", "get_principal_inertia_axes"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); @@ -137,93 +139,137 @@ PhysicsDirectBodyState3D::PhysicsDirectBodyState3D() {} /////////////////////////////////////////////////////// -void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape_ref) { - ERR_FAIL_COND(p_shape_ref.is_null()); - shape_ref = p_shape_ref; - shape = p_shape_ref->get_rid(); -} - -RES PhysicsShapeQueryParameters3D::get_shape() const { - return shape_ref; +void PhysicsRayQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); + for (int i = 0; i < p_exclude.size(); i++) { + parameters.exclude.insert(p_exclude[i]); + } } -void PhysicsShapeQueryParameters3D::set_shape_rid(const RID &p_shape) { - if (shape != p_shape) { - shape_ref = RES(); - shape = p_shape; +Vector<RID> PhysicsRayQueryParameters3D::get_exclude() const { + Vector<RID> ret; + ret.resize(parameters.exclude.size()); + int idx = 0; + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + ret.write[idx++] = E->get(); } + return ret; } -RID PhysicsShapeQueryParameters3D::get_shape_rid() const { - return shape; -} +void PhysicsRayQueryParameters3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters3D::set_from); + ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters3D::get_from); -void PhysicsShapeQueryParameters3D::set_transform(const Transform3D &p_transform) { - transform = p_transform; -} + ClassDB::bind_method(D_METHOD("set_to", "to"), &PhysicsRayQueryParameters3D::set_to); + ClassDB::bind_method(D_METHOD("get_to"), &PhysicsRayQueryParameters3D::get_to); -Transform3D PhysicsShapeQueryParameters3D::get_transform() const { - return transform; -} + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsRayQueryParameters3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsRayQueryParameters3D::get_collision_mask); -void PhysicsShapeQueryParameters3D::set_margin(real_t p_margin) { - margin = p_margin; -} + ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsRayQueryParameters3D::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsRayQueryParameters3D::get_exclude); -real_t PhysicsShapeQueryParameters3D::get_margin() const { - return margin; -} + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsRayQueryParameters3D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsRayQueryParameters3D::is_collide_with_bodies_enabled); -void PhysicsShapeQueryParameters3D::set_collision_mask(uint32_t p_collision_mask) { - collision_mask = p_collision_mask; -} + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsRayQueryParameters3D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsRayQueryParameters3D::is_collide_with_areas_enabled); -uint32_t PhysicsShapeQueryParameters3D::get_collision_mask() const { - return collision_mask; + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "from"), "set_from", "get_from"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "to"), "set_to", "get_to"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); } -void PhysicsShapeQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) { - exclude.clear(); +/////////////////////////////////////////////////////// + +void PhysicsPointQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); + parameters.exclude.insert(p_exclude[i]); } } -Vector<RID> PhysicsShapeQueryParameters3D::get_exclude() const { +Vector<RID> PhysicsPointQueryParameters3D::get_exclude() const { Vector<RID> ret; - ret.resize(exclude.size()); + ret.resize(parameters.exclude.size()); int idx = 0; - for (Set<RID>::Element *E = exclude.front(); E; E = E->next()) { + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { ret.write[idx++] = E->get(); } return ret; } -void PhysicsShapeQueryParameters3D::set_collide_with_bodies(bool p_enable) { - collide_with_bodies = p_enable; +void PhysicsPointQueryParameters3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_position", "position"), &PhysicsPointQueryParameters3D::set_position); + ClassDB::bind_method(D_METHOD("get_position"), &PhysicsPointQueryParameters3D::get_position); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsPointQueryParameters3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsPointQueryParameters3D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsPointQueryParameters3D::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsPointQueryParameters3D::get_exclude); + + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsPointQueryParameters3D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsPointQueryParameters3D::is_collide_with_bodies_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsPointQueryParameters3D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsPointQueryParameters3D::is_collide_with_areas_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); } -bool PhysicsShapeQueryParameters3D::is_collide_with_bodies_enabled() const { - return collide_with_bodies; +/////////////////////////////////////////////////////// + +void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape_ref) { + ERR_FAIL_COND(p_shape_ref.is_null()); + shape_ref = p_shape_ref; + parameters.shape_rid = p_shape_ref->get_rid(); } -void PhysicsShapeQueryParameters3D::set_collide_with_areas(bool p_enable) { - collide_with_areas = p_enable; +void PhysicsShapeQueryParameters3D::set_shape_rid(const RID &p_shape) { + if (parameters.shape_rid != p_shape) { + shape_ref = RES(); + parameters.shape_rid = p_shape; + } } -bool PhysicsShapeQueryParameters3D::is_collide_with_areas_enabled() const { - return collide_with_areas; +void PhysicsShapeQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) { + parameters.exclude.clear(); + for (int i = 0; i < p_exclude.size(); i++) { + parameters.exclude.insert(p_exclude[i]); + } +} + +Vector<RID> PhysicsShapeQueryParameters3D::get_exclude() const { + Vector<RID> ret; + ret.resize(parameters.exclude.size()); + int idx = 0; + for (Set<RID>::Element *E = parameters.exclude.front(); E; E = E->next()) { + ret.write[idx++] = E->get(); + } + return ret; } void PhysicsShapeQueryParameters3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters3D::set_shape); ClassDB::bind_method(D_METHOD("get_shape"), &PhysicsShapeQueryParameters3D::get_shape); + ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters3D::set_shape_rid); ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters3D::get_shape_rid); ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsShapeQueryParameters3D::set_transform); ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsShapeQueryParameters3D::get_transform); + ClassDB::bind_method(D_METHOD("set_motion", "motion"), &PhysicsShapeQueryParameters3D::set_motion); + ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsShapeQueryParameters3D::get_motion); + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &PhysicsShapeQueryParameters3D::set_margin); ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsShapeQueryParameters3D::get_margin); @@ -240,8 +286,9 @@ void PhysicsShapeQueryParameters3D::_bind_methods() { ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsShapeQueryParameters3D::is_collide_with_areas_enabled); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::RID) + ":"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform"), "set_transform", "get_transform"); @@ -251,36 +298,56 @@ void PhysicsShapeQueryParameters3D::_bind_methods() { ///////////////////////////////////// -Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - RayResult inters; - Set<RID> exclude; - for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); - } +Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Ref<PhysicsRayQueryParameters3D> &p_ray_query) { + ERR_FAIL_COND_V(!p_ray_query.is_valid(), Dictionary()); - bool res = intersect_ray(p_from, p_to, inters, exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas); + RayResult result; + bool res = intersect_ray(p_ray_query->get_parameters(), result); if (!res) { return Dictionary(); } Dictionary d; - d["position"] = inters.position; - d["normal"] = inters.normal; - d["collider_id"] = inters.collider_id; - d["collider"] = inters.collider; - d["shape"] = inters.shape; - d["rid"] = inters.rid; + d["position"] = result.position; + d["normal"] = result.normal; + d["collider_id"] = result.collider_id; + d["collider"] = result.collider; + d["shape"] = result.shape; + d["rid"] = result.rid; return d; } +Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results) { + Vector<ShapeResult> ret; + ret.resize(p_max_results); + + int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size()); + + if (rc == 0) { + return Array(); + } + + Array r; + r.resize(rc); + for (int i = 0; i < rc; i++) { + Dictionary d; + d["rid"] = ret[i].rid; + d["collider_id"] = ret[i].collider_id; + d["collider"] = ret[i].collider; + d["shape"] = ret[i].shape; + r[i] = d; + } + return r; +} + Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); Vector<ShapeResult> sr; sr.resize(p_max_results); - int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size()); Array ret; ret.resize(rc); for (int i = 0; i < rc; i++) { @@ -295,11 +362,11 @@ Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryPar return ret; } -Array PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, const Vector3 &p_motion) { +Array PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); real_t closest_safe = 1.0f, closest_unsafe = 1.0f; - bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe); if (!res) { return Array(); } @@ -316,7 +383,7 @@ Array PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParam Vector<Vector3> ret; ret.resize(p_max_results * 2); int rc = 0; - bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc); if (!res) { return Array(); } @@ -333,7 +400,7 @@ Dictionary PhysicsDirectSpaceState3D::_get_rest_info(const Ref<PhysicsShapeQuery ShapeRestInfo sri; - bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + bool res = rest_info(p_shape_query->get_parameters(), &sri); Dictionary r; if (!res) { return r; @@ -353,11 +420,12 @@ PhysicsDirectSpaceState3D::PhysicsDirectSpaceState3D() { } void PhysicsDirectSpaceState3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState3D::_intersect_ray, DEFVAL(Array()), DEFVAL(UINT32_MAX), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState3D::_intersect_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("cast_motion", "shape", "motion"), &PhysicsDirectSpaceState3D::_cast_motion); - ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState3D::_collide_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &PhysicsDirectSpaceState3D::_get_rest_info); + ClassDB::bind_method(D_METHOD("intersect_point", "parameters", "max_results"), &PhysicsDirectSpaceState3D::_intersect_point, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("intersect_ray", "parameters"), &PhysicsDirectSpaceState3D::_intersect_ray); + ClassDB::bind_method(D_METHOD("intersect_shape", "parameters", "max_results"), &PhysicsDirectSpaceState3D::_intersect_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("cast_motion", "parameters"), &PhysicsDirectSpaceState3D::_cast_motion); + ClassDB::bind_method(D_METHOD("collide_shape", "parameters", "max_results"), &PhysicsDirectSpaceState3D::_collide_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("get_rest_info", "parameters"), &PhysicsDirectSpaceState3D::_get_rest_info); } /////////////////////////////// @@ -427,7 +495,7 @@ void PhysicsTestMotionParameters3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_collisions"), "set_max_collisions", "get_max_collisions"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects"); } diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 6e9f8c7704..b5113fd35f 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -48,6 +48,7 @@ public: virtual real_t get_total_linear_damp() const = 0; virtual Vector3 get_center_of_mass() const = 0; + virtual Vector3 get_center_of_mass_local() const = 0; virtual Basis get_principal_inertia_axes() const = 0; virtual real_t get_inverse_mass() const = 0; // get the mass virtual Vector3 get_inverse_inertia() const = 0; // get density of this body space @@ -96,55 +97,18 @@ public: PhysicsDirectBodyState3D(); }; -class PhysicsShapeQueryParameters3D : public RefCounted { - GDCLASS(PhysicsShapeQueryParameters3D, RefCounted); - friend class PhysicsDirectSpaceState3D; - - RES shape_ref; - RID shape; - Transform3D transform; - real_t margin = 0.0; - Set<RID> exclude; - uint32_t collision_mask = UINT32_MAX; - - bool collide_with_bodies = true; - bool collide_with_areas = false; - -protected: - static void _bind_methods(); - -public: - void set_shape(const RES &p_shape_ref); - RES get_shape() const; - void set_shape_rid(const RID &p_shape); - RID get_shape_rid() const; - - void set_transform(const Transform3D &p_transform); - Transform3D get_transform() const; - - void set_margin(real_t p_margin); - real_t get_margin() const; - - void set_collision_mask(uint32_t p_collision_mask); - uint32_t get_collision_mask() const; - - void set_exclude(const Vector<RID> &p_exclude); - Vector<RID> get_exclude() const; - - void set_collide_with_bodies(bool p_enable); - bool is_collide_with_bodies_enabled() const; - - void set_collide_with_areas(bool p_enable); - bool is_collide_with_areas_enabled() const; -}; +class PhysicsRayQueryParameters3D; +class PhysicsPointQueryParameters3D; +class PhysicsShapeQueryParameters3D; class PhysicsDirectSpaceState3D : public Object { GDCLASS(PhysicsDirectSpaceState3D, Object); private: - Dictionary _intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector<RID> &p_exclude = Vector<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters3D> &p_ray_query); + Array _intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results = 32); Array _intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32); - Array _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, const Vector3 &p_motion); + Array _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query); Array _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32); Dictionary _get_rest_info(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query); @@ -152,27 +116,58 @@ protected: static void _bind_methods(); public: - struct ShapeResult { + struct RayParameters { + Vector3 from; + Vector3 to; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; + + bool collide_with_bodies = true; + bool collide_with_areas = false; + + bool pick_ray = false; + }; + + struct RayResult { + Vector3 position; + Vector3 normal; RID rid; ObjectID collider_id; Object *collider = nullptr; int shape = 0; }; - virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) = 0; - struct RayResult { - Vector3 position; - Vector3 normal; + struct ShapeResult { RID rid; ObjectID collider_id; Object *collider = nullptr; int shape = 0; }; - virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0; + struct PointParameters { + Vector3 position; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; + + bool collide_with_bodies = true; + bool collide_with_areas = false; + }; - virtual int intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0; + + struct ShapeParameters { + RID shape_rid; + Transform3D transform; + Vector3 motion; + real_t margin = 0.0; + Set<RID> exclude; + uint32_t collision_mask = UINT32_MAX; + + bool collide_with_bodies = true; + bool collide_with_areas = false; + }; struct ShapeRestInfo { Vector3 point; @@ -180,14 +175,13 @@ public: RID rid; ObjectID collider_id; int shape = 0; - Vector3 linear_velocity; //velocity at contact point + Vector3 linear_velocity; // Velocity at contact point. }; - virtual bool cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) = 0; - - virtual bool collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - - virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) = 0; + virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info = nullptr) = 0; + virtual bool collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) = 0; + virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) = 0; virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const = 0; @@ -785,6 +779,104 @@ public: ~PhysicsServer3D(); }; +class PhysicsRayQueryParameters3D : public RefCounted { + GDCLASS(PhysicsRayQueryParameters3D, RefCounted); + + PhysicsDirectSpaceState3D::RayParameters parameters; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState3D::RayParameters &get_parameters() const { return parameters; } + + void set_from(const Vector3 &p_from) { parameters.from = p_from; } + const Vector3 &get_from() const { return parameters.from; } + + void set_to(const Vector3 &p_to) { parameters.to = p_to; } + const Vector3 &get_to() const { return parameters.to; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + +class PhysicsPointQueryParameters3D : public RefCounted { + GDCLASS(PhysicsPointQueryParameters3D, RefCounted); + + PhysicsDirectSpaceState3D::PointParameters parameters; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState3D::PointParameters &get_parameters() const { return parameters; } + + void set_position(const Vector3 &p_position) { parameters.position = p_position; } + const Vector3 &get_position() const { return parameters.position; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + +class PhysicsShapeQueryParameters3D : public RefCounted { + GDCLASS(PhysicsShapeQueryParameters3D, RefCounted); + + PhysicsDirectSpaceState3D::ShapeParameters parameters; + + RES shape_ref; + +protected: + static void _bind_methods(); + +public: + const PhysicsDirectSpaceState3D::ShapeParameters &get_parameters() const { return parameters; } + + void set_shape(const RES &p_shape_ref); + RES get_shape() const { return shape_ref; } + + void set_shape_rid(const RID &p_shape); + RID get_shape_rid() const { return parameters.shape_rid; } + + void set_transform(const Transform3D &p_transform) { parameters.transform = p_transform; } + const Transform3D &get_transform() const { return parameters.transform; } + + void set_motion(const Vector3 &p_motion) { parameters.motion = p_motion; } + const Vector3 &get_motion() const { return parameters.motion; } + + void set_margin(real_t p_margin) { parameters.margin = p_margin; } + real_t get_margin() const { return parameters.margin; } + + void set_collision_mask(uint32_t p_mask) { parameters.collision_mask = p_mask; } + uint32_t get_collision_mask() const { return parameters.collision_mask; } + + void set_collide_with_bodies(bool p_enable) { parameters.collide_with_bodies = p_enable; } + bool is_collide_with_bodies_enabled() const { return parameters.collide_with_bodies; } + + void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } + bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } + + void set_exclude(const Vector<RID> &p_exclude); + Vector<RID> get_exclude() const; +}; + class PhysicsTestMotionParameters3D : public RefCounted { GDCLASS(PhysicsTestMotionParameters3D, RefCounted); diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 8be9c2114f..7004b2317c 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -209,13 +209,17 @@ void register_server_types() { GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2D); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2D); + GDREGISTER_CLASS(PhysicsRayQueryParameters2D); + GDREGISTER_CLASS(PhysicsPointQueryParameters2D); + GDREGISTER_CLASS(PhysicsShapeQueryParameters2D); GDREGISTER_CLASS(PhysicsTestMotionParameters2D); GDREGISTER_CLASS(PhysicsTestMotionResult2D); - GDREGISTER_CLASS(PhysicsShapeQueryParameters2D); - GDREGISTER_CLASS(PhysicsShapeQueryParameters3D); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3D); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3D); + GDREGISTER_CLASS(PhysicsRayQueryParameters3D); + GDREGISTER_CLASS(PhysicsPointQueryParameters3D); + GDREGISTER_CLASS(PhysicsShapeQueryParameters3D); GDREGISTER_CLASS(PhysicsTestMotionParameters3D); GDREGISTER_CLASS(PhysicsTestMotionResult3D); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 0ca2f051fa..9441c7cfb5 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2086,7 +2086,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende ERR_FAIL_COND(!rb); RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment); - //glow (if enabled) + // Glow and override exposure (if enabled). CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects); bool can_use_effects = rb->width >= 8 && rb->height >= 8; @@ -2102,7 +2102,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende EffectsRD::BokehBuffers buffers; - // textures we use + // Textures we use. buffers.base_texture_size = Size2i(rb->width, rb->height); buffers.base_texture = rb->texture; buffers.depth_texture = rb->depth_texture; @@ -2114,7 +2114,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende if (can_use_storage) { storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); } else { - // set framebuffers + // Set framebuffers. buffers.base_fb = rb->texture_fb; buffers.secondary_fb = rb->weight_buffers[1].fb; buffers.half_fb[0] = rb->weight_buffers[2].fb; @@ -2124,7 +2124,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende buffers.weight_texture[2] = rb->weight_buffers[2].weight; buffers.weight_texture[3] = rb->weight_buffers[3].weight; - // set weight buffers + // Set weight buffers. buffers.base_weight_fb = rb->base_weight_fb; storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); @@ -2147,13 +2147,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } else { storage->get_effects()->luminance_reduction_raster(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); } - //swap final reduce with prev luminance + // Swap final reduce with prev luminance. SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]); if (!can_use_storage) { SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]); } - RenderingServerDefault::redraw_request(); //redraw all the time if auto exposure rendering is on + RenderingServerDefault::redraw_request(); // Redraw all the time if auto exposure rendering is on. RD::get_singleton()->draw_command_end_label(); } @@ -2207,7 +2207,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende { RD::get_singleton()->draw_command_begin_label("Tonemap"); - //tonemap EffectsRD::TonemapSettings tonemap; if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) { @@ -2246,6 +2245,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.exposure = env->exposure; } + if (camfx && camfx->override_exposure_enabled) { + tonemap.exposure = camfx->override_exposure; + } + tonemap.use_color_correction = false; tonemap.use_1d_color_correction = false; tonemap.color_correction_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); @@ -2280,6 +2283,8 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr ERR_FAIL_COND(!rb); RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment); + // Override exposure (if enabled). + CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects); bool can_use_effects = rb->width >= 8 && rb->height >= 8; @@ -2293,6 +2298,10 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr tonemap.white = env->white; } + if (camfx && camfx->override_exposure_enabled) { + tonemap.exposure = camfx->override_exposure; + } + // We don't support glow or auto exposure here, if they are needed, don't use subpasses! // The problem is that we need to use the result so far and process them before we can // apply this to our results. diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 04cc844483..d803d5fcf8 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -7439,7 +7439,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct int texture_uniforms = 0; int texture_binding = 0; - int uniforms = 0; int instance_index = 0; ShaderNode::Uniform::Scope uniform_scope = ShaderNode::Uniform::SCOPE_LOCAL; @@ -7790,9 +7789,6 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } uniform2.texture_order = -1; - if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) { - uniform2.order = uniforms++; - } } if (uniform2.array_size > 0) { @@ -8771,6 +8767,20 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct tk = _get_token(); } + int uniforms = 0; + + // Need to push arrays to first place in a uniform buffer in order to correct work. + for (Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) { + if (E->get().texture_order == -1 && E->get().scope != ShaderNode::Uniform::SCOPE_INSTANCE && E->get().array_size > 0) { + E->get().order = uniforms++; + } + } + for (Map<StringName, ShaderNode::Uniform>::Element *E = shader->uniforms.front(); E; E = E->next()) { + if (E->get().texture_order == -1 && E->get().scope != ShaderNode::Uniform::SCOPE_INSTANCE && E->get().array_size == 0) { + E->get().order = uniforms++; + } + } + int error_line; String error_message; if (!_check_varying_usages(&error_line, &error_message)) { diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index a44fee7c95..0a7523e33a 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -55,6 +55,15 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(_font_set_data, "font_rid", "data"); GDVIRTUAL_BIND(_font_set_data_ptr, "font_rid", "data_ptr", "data_size"); + GDVIRTUAL_BIND(_font_set_style, "font_rid", "style"); + GDVIRTUAL_BIND(_font_get_style, "font_rid"); + + GDVIRTUAL_BIND(_font_set_name, "font_rid", "name"); + GDVIRTUAL_BIND(_font_get_name, "font_rid"); + + GDVIRTUAL_BIND(_font_set_style_name, "font_rid", "name_style"); + GDVIRTUAL_BIND(_font_get_style_name, "font_rid"); + GDVIRTUAL_BIND(_font_set_antialiased, "font_rid", "antialiased"); GDVIRTUAL_BIND(_font_is_antialiased, "font_rid"); @@ -185,6 +194,9 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(_shaped_text_set_bidi_override, "shaped", "override"); + GDVIRTUAL_BIND(_shaped_text_set_custom_punctuation, "shaped", "punct"); + GDVIRTUAL_BIND(_shaped_text_get_custom_punctuation, "shaped"); + GDVIRTUAL_BIND(_shaped_text_set_orientation, "shaped", "orientation"); GDVIRTUAL_BIND(_shaped_text_get_orientation, "shaped"); @@ -368,6 +380,42 @@ void TextServerExtension::font_set_data_ptr(RID p_font_rid, const uint8_t *p_dat GDVIRTUAL_CALL(_font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size); } +void TextServerExtension::font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) { + GDVIRTUAL_CALL(_font_set_style, p_font_rid, p_style); +} + +uint32_t /*FontStyle*/ TextServerExtension::font_get_style(RID p_font_rid) const { + uint32_t ret; + if (GDVIRTUAL_CALL(_font_get_style, p_font_rid, ret)) { + return ret; + } + return 0; +} + +void TextServerExtension::font_set_style_name(RID p_font_rid, const String &p_name) { + GDVIRTUAL_CALL(_font_set_style_name, p_font_rid, p_name); +} + +String TextServerExtension::font_get_style_name(RID p_font_rid) const { + String ret; + if (GDVIRTUAL_CALL(_font_get_style_name, p_font_rid, ret)) { + return ret; + } + return String(); +} + +void TextServerExtension::font_set_name(RID p_font_rid, const String &p_name) { + GDVIRTUAL_CALL(_font_set_name, p_font_rid, p_name); +} + +String TextServerExtension::font_get_name(RID p_font_rid) const { + String ret; + if (GDVIRTUAL_CALL(_font_get_name, p_font_rid, ret)) { + return ret; + } + return String(); +} + void TextServerExtension::font_set_antialiased(RID p_font_rid, bool p_antialiased) { GDVIRTUAL_CALL(_font_set_antialiased, p_font_rid, p_antialiased); } @@ -906,6 +954,18 @@ void TextServerExtension::shaped_text_set_bidi_override(RID p_shaped, const Arra GDVIRTUAL_CALL(_shaped_text_set_bidi_override, p_shaped, p_override); } +void TextServerExtension::shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) { + GDVIRTUAL_CALL(_shaped_text_set_custom_punctuation, p_shaped, p_punct); +} + +String TextServerExtension::shaped_text_get_custom_punctuation(RID p_shaped) const { + String ret; + if (GDVIRTUAL_CALL(_shaped_text_get_custom_punctuation, p_shaped, ret)) { + return ret; + } + return String(); +} + void TextServerExtension::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) { GDVIRTUAL_CALL(_shaped_text_set_preserve_invalid, p_shaped, p_enabled); } diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index 954b2cf660..e419b4055d 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -84,6 +84,21 @@ public: GDVIRTUAL2(_font_set_data, RID, const PackedByteArray &); GDVIRTUAL3(_font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, uint64_t); + virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) override; + virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const override; + GDVIRTUAL2(_font_set_style, RID, uint32_t); + GDVIRTUAL1RC(uint32_t, _font_get_style, RID); + + virtual void font_set_name(RID p_font_rid, const String &p_name) override; + virtual String font_get_name(RID p_font_rid) const override; + GDVIRTUAL2(_font_set_name, RID, const String &); + GDVIRTUAL1RC(String, _font_get_name, RID); + + virtual void font_set_style_name(RID p_font_rid, const String &p_name) override; + virtual String font_get_style_name(RID p_font_rid) const override; + GDVIRTUAL2(_font_set_style_name, RID, const String &); + GDVIRTUAL1RC(String, _font_get_style_name, RID); + virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) override; virtual bool font_is_antialiased(RID p_font_rid) const override; GDVIRTUAL2(_font_set_antialiased, RID, bool); @@ -301,6 +316,11 @@ public: virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override; GDVIRTUAL2(_shaped_text_set_bidi_override, RID, const Array &); + virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) override; + virtual String shaped_text_get_custom_punctuation(RID p_shaped) const override; + GDVIRTUAL2(_shaped_text_set_custom_punctuation, RID, String); + GDVIRTUAL1RC(String, _shaped_text_get_custom_punctuation, RID); + virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation); diff --git a/servers/text_server.cpp b/servers/text_server.cpp index af4718678e..9034239fe0 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -208,6 +208,15 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("font_set_data", "font_rid", "data"), &TextServer::font_set_data); + ClassDB::bind_method(D_METHOD("font_set_style", "font_rid", "style"), &TextServer::font_set_style); + ClassDB::bind_method(D_METHOD("font_get_style", "font_rid"), &TextServer::font_get_style); + + ClassDB::bind_method(D_METHOD("font_set_name", "font_rid", "name"), &TextServer::font_set_name); + ClassDB::bind_method(D_METHOD("font_get_name", "font_rid"), &TextServer::font_get_name); + + ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name); + ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name); + ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased); ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased); @@ -338,6 +347,9 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("shaped_text_set_bidi_override", "shaped", "override"), &TextServer::shaped_text_set_bidi_override); + ClassDB::bind_method(D_METHOD("shaped_text_set_custom_punctuation", "shaped", "punct"), &TextServer::shaped_text_set_custom_punctuation); + ClassDB::bind_method(D_METHOD("shaped_text_get_custom_punctuation", "shaped"), &TextServer::shaped_text_get_custom_punctuation); + ClassDB::bind_method(D_METHOD("shaped_text_set_orientation", "shaped", "orientation"), &TextServer::shaped_text_set_orientation, DEFVAL(ORIENTATION_HORIZONTAL)); ClassDB::bind_method(D_METHOD("shaped_text_get_orientation", "shaped"), &TextServer::shaped_text_get_orientation); @@ -470,11 +482,16 @@ void TextServer::_bind_methods() { BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CONIC); BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_OFF_CUBIC); - /* Font Spacing*/ + /* Font Spacing */ BIND_ENUM_CONSTANT(SPACING_GLYPH); BIND_ENUM_CONSTANT(SPACING_SPACE); BIND_ENUM_CONSTANT(SPACING_TOP); BIND_ENUM_CONSTANT(SPACING_BOTTOM); + + /* Font Style */ + BIND_ENUM_CONSTANT(FONT_BOLD); + BIND_ENUM_CONSTANT(FONT_ITALIC); + BIND_ENUM_CONSTANT(FONT_FIXED_WIDTH); } Vector2 TextServer::get_hex_code_box_size(int p_size, char32_t p_index) const { diff --git a/servers/text_server.h b/servers/text_server.h index a5484d8fbd..4f55f881e6 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -125,6 +125,12 @@ public: SPACING_BOTTOM, }; + enum FontStyle { + FONT_BOLD = 1 << 0, + FONT_ITALIC = 1 << 1, + FONT_FIXED_WIDTH = 1 << 2, + }; + void _draw_hex_code_box_number(RID p_canvas, int p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const; protected: @@ -144,6 +150,7 @@ protected: int end = 0; // Substring end offset in the parent string. String text; + String custom_punct; TextServer::Direction direction = DIRECTION_LTR; // Desired text direction. TextServer::Orientation orientation = ORIENTATION_HORIZONTAL; @@ -224,6 +231,15 @@ public: virtual void font_set_data(RID p_font_rid, const PackedByteArray &p_data) = 0; virtual void font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) = 0; + virtual void font_set_style(RID p_font_rid, uint32_t /*FontStyle*/ p_style) = 0; + virtual uint32_t /*FontStyle*/ font_get_style(RID p_font_rid) const = 0; + + virtual void font_set_name(RID p_font_rid, const String &p_name) = 0; + virtual String font_get_name(RID p_font_rid) const = 0; + + virtual void font_set_style_name(RID p_font_rid, const String &p_name) = 0; + virtual String font_get_style_name(RID p_font_rid) const = 0; + virtual void font_set_antialiased(RID p_font_rid, bool p_antialiased) = 0; virtual bool font_is_antialiased(RID p_font_rid) const = 0; @@ -354,6 +370,9 @@ public: virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) = 0; + virtual void shaped_text_set_custom_punctuation(RID p_shaped, const String &p_punct) = 0; + virtual String shaped_text_get_custom_punctuation(RID p_shaped) const = 0; + virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) = 0; virtual Orientation shaped_text_get_orientation(RID p_shaped) const = 0; @@ -535,6 +554,7 @@ VARIANT_ENUM_CAST(TextServer::Hinting); VARIANT_ENUM_CAST(TextServer::Feature); VARIANT_ENUM_CAST(TextServer::ContourPointTag); VARIANT_ENUM_CAST(TextServer::SpacingType); +VARIANT_ENUM_CAST(TextServer::FontStyle); GDVIRTUAL_NATIVE_PTR(Glyph); GDVIRTUAL_NATIVE_PTR(Glyph *); |