Merge pull request #21245 from RandomShaper/fix-physics-canvas-xform
Take CanvasLayer transform into account for 2D physics
This commit is contained in:
commit
ed10ff65fd
|
@ -349,23 +349,12 @@ void CanvasItem::_update_callback() {
|
|||
|
||||
Transform2D CanvasItem::get_global_transform_with_canvas() const {
|
||||
|
||||
const CanvasItem *ci = this;
|
||||
Transform2D xform;
|
||||
const CanvasItem *last_valid = NULL;
|
||||
|
||||
while (ci) {
|
||||
|
||||
last_valid = ci;
|
||||
xform = ci->get_transform() * xform;
|
||||
ci = ci->get_parent_item();
|
||||
}
|
||||
|
||||
if (last_valid->canvas_layer)
|
||||
return last_valid->canvas_layer->get_transform() * xform;
|
||||
if (canvas_layer)
|
||||
return canvas_layer->get_transform() * get_global_transform();
|
||||
else if (is_inside_tree())
|
||||
return get_viewport()->get_canvas_transform() * xform;
|
||||
|
||||
return xform;
|
||||
return get_viewport()->get_canvas_transform() * get_global_transform();
|
||||
else
|
||||
return get_global_transform();
|
||||
}
|
||||
|
||||
Transform2D CanvasItem::get_global_transform() const {
|
||||
|
|
|
@ -139,6 +139,8 @@ class CanvasItem : public Node {
|
|||
|
||||
GDCLASS(CanvasItem, Node);
|
||||
|
||||
friend class CanvasLayer;
|
||||
|
||||
public:
|
||||
enum BlendMode {
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ void CollisionObject2D::_notification(int p_what) {
|
|||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
|
||||
Transform2D global_transform = get_global_transform();
|
||||
Transform2D global_transform = get_global_transform_with_canvas();
|
||||
|
||||
if (area)
|
||||
Physics2DServer::get_singleton()->area_set_transform(rid, global_transform);
|
||||
|
@ -64,7 +64,7 @@ void CollisionObject2D::_notification(int p_what) {
|
|||
} break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
Transform2D global_transform = get_global_transform();
|
||||
Transform2D global_transform = get_global_transform_with_canvas();
|
||||
|
||||
if (only_update_transform_changes && global_transform == last_transform) {
|
||||
return;
|
||||
|
|
|
@ -35,19 +35,6 @@
|
|||
#include "engine.h"
|
||||
#include "math_funcs.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
void PhysicsBody2D::_notification(int p_what) {
|
||||
|
||||
/*
|
||||
switch(p_what) {
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
||||
Physics2DServer::get_singleton()->body_set_state(get_rid(),Physics2DServer::BODY_STATE_TRANSFORM,get_global_transform());
|
||||
|
||||
} break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void PhysicsBody2D::_set_layers(uint32_t p_mask) {
|
||||
|
||||
|
@ -436,7 +423,7 @@ bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia,
|
|||
Physics2DServer::MotionResult *r = NULL;
|
||||
if (p_result.is_valid())
|
||||
r = p_result->get_result_ptr();
|
||||
return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r);
|
||||
return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform_with_canvas(), p_motion, p_infinite_inertia, p_margin, r);
|
||||
}
|
||||
|
||||
void RigidBody2D::_direct_state_changed(Object *p_state) {
|
||||
|
@ -449,7 +436,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
|
|||
|
||||
set_block_transform_notify(true); // don't want notify (would feedback loop)
|
||||
if (mode != MODE_KINEMATIC)
|
||||
set_global_transform(state->get_transform());
|
||||
set_global_transform(get_canvas_transform().affine_inverse() * state->get_transform());
|
||||
linear_velocity = state->get_linear_velocity();
|
||||
angular_velocity = state->get_angular_velocity();
|
||||
if (sleeping != state->is_sleeping()) {
|
||||
|
@ -1144,7 +1131,7 @@ bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision
|
|||
|
||||
Physics2DServer::SeparationResult sep_res[8]; //max 8 rays
|
||||
|
||||
Transform2D gt = get_global_transform();
|
||||
Transform2D gt = get_global_transform_with_canvas();
|
||||
|
||||
Vector2 recover;
|
||||
int hits = Physics2DServer::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin);
|
||||
|
@ -1158,7 +1145,7 @@ bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision
|
|||
}
|
||||
|
||||
gt.elements[2] += recover;
|
||||
set_global_transform(gt);
|
||||
set_global_transform(get_canvas_transform().affine_inverse() * gt);
|
||||
|
||||
if (deepest != -1) {
|
||||
r_collision.collider = sep_res[deepest].collider_id;
|
||||
|
@ -1179,7 +1166,7 @@ bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision
|
|||
|
||||
bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) {
|
||||
|
||||
Transform2D gt = get_global_transform();
|
||||
Transform2D gt = get_global_transform_with_canvas();
|
||||
Physics2DServer::MotionResult result;
|
||||
bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, margin, &result, p_exclude_raycast_shapes);
|
||||
|
||||
|
@ -1198,7 +1185,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_
|
|||
|
||||
if (!p_test_only) {
|
||||
gt.elements[2] += result.motion;
|
||||
set_global_transform(gt);
|
||||
set_global_transform(get_canvas_transform().affine_inverse() * gt);
|
||||
}
|
||||
|
||||
return colliding;
|
||||
|
@ -1272,9 +1259,9 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
|
|||
|
||||
if (p_stop_on_slope) {
|
||||
if (Vector2() == lv_n + p_floor_direction) {
|
||||
Transform2D gt = get_global_transform();
|
||||
Transform2D gt = get_global_transform_with_canvas();
|
||||
gt.elements[2] -= collision.travel;
|
||||
set_global_transform(gt);
|
||||
set_global_transform(get_canvas_transform().affine_inverse() * gt);
|
||||
return Vector2();
|
||||
}
|
||||
}
|
||||
|
@ -1323,7 +1310,7 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci
|
|||
}
|
||||
|
||||
Collision col;
|
||||
Transform2D gt = get_global_transform();
|
||||
Transform2D gt = get_global_transform_with_canvas();
|
||||
|
||||
if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
|
||||
gt.elements[2] += col.travel;
|
||||
|
@ -1332,7 +1319,7 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci
|
|||
on_floor_body = col.collider_rid;
|
||||
floor_velocity = col.collider_vel;
|
||||
}
|
||||
set_global_transform(gt);
|
||||
set_global_transform(get_canvas_transform().affine_inverse() * gt);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1429,22 +1416,22 @@ void KinematicBody2D::_direct_state_changed(Object *p_state) {
|
|||
|
||||
last_valid_transform = state->get_transform();
|
||||
set_notify_local_transform(false);
|
||||
set_global_transform(last_valid_transform);
|
||||
set_global_transform(get_canvas_transform().affine_inverse() * last_valid_transform);
|
||||
set_notify_local_transform(true);
|
||||
}
|
||||
|
||||
void KinematicBody2D::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
last_valid_transform = get_global_transform();
|
||||
last_valid_transform = get_global_transform_with_canvas();
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
|
||||
//used by sync to physics, send the new transform to the physics
|
||||
Transform2D new_transform = get_global_transform();
|
||||
Transform2D new_transform = get_global_transform_with_canvas();
|
||||
Physics2DServer::get_singleton()->body_set_state(get_rid(), Physics2DServer::BODY_STATE_TRANSFORM, new_transform);
|
||||
//but then revert changes
|
||||
set_notify_local_transform(false);
|
||||
set_global_transform(last_valid_transform);
|
||||
set_global_transform(get_canvas_transform().affine_inverse() * last_valid_transform);
|
||||
set_notify_local_transform(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,6 @@ class PhysicsBody2D : public CollisionObject2D {
|
|||
uint32_t _get_layers() const;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
PhysicsBody2D(Physics2DServer::BodyMode p_mode);
|
||||
|
||||
static void _bind_methods();
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
/*************************************************************************/
|
||||
|
||||
#include "canvas_layer.h"
|
||||
#include "scene/2d/canvas_item.h"
|
||||
#include "viewport.h"
|
||||
|
||||
void CanvasLayer::set_layer(int p_xform) {
|
||||
|
@ -62,6 +63,24 @@ void CanvasLayer::_update_xform() {
|
|||
transform.set_origin(ofs);
|
||||
if (viewport.is_valid())
|
||||
VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform);
|
||||
|
||||
if (!is_inside_tree())
|
||||
return;
|
||||
|
||||
_notify_xform(this);
|
||||
}
|
||||
|
||||
void CanvasLayer::_notify_xform(Node *p_node) {
|
||||
|
||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||
|
||||
CanvasItem *ci = Object::cast_to<CanvasItem>(p_node->get_child(i));
|
||||
if (ci) {
|
||||
ci->_notify_transform(ci);
|
||||
} else {
|
||||
_notify_xform(p_node->get_child(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasLayer::_update_locrotscale() {
|
||||
|
|
|
@ -56,6 +56,7 @@ class CanvasLayer : public Node {
|
|||
int sort_index;
|
||||
|
||||
void _update_xform();
|
||||
void _notify_xform(Node *p_node);
|
||||
void _update_locrotscale();
|
||||
|
||||
protected:
|
||||
|
|
Loading…
Reference in New Issue