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 {
|
Transform2D CanvasItem::get_global_transform_with_canvas() const {
|
||||||
|
|
||||||
const CanvasItem *ci = this;
|
if (canvas_layer)
|
||||||
Transform2D xform;
|
return canvas_layer->get_transform() * get_global_transform();
|
||||||
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;
|
|
||||||
else if (is_inside_tree())
|
else if (is_inside_tree())
|
||||||
return get_viewport()->get_canvas_transform() * xform;
|
return get_viewport()->get_canvas_transform() * get_global_transform();
|
||||||
|
else
|
||||||
return xform;
|
return get_global_transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform2D CanvasItem::get_global_transform() const {
|
Transform2D CanvasItem::get_global_transform() const {
|
||||||
|
|
|
@ -139,6 +139,8 @@ class CanvasItem : public Node {
|
||||||
|
|
||||||
GDCLASS(CanvasItem, Node);
|
GDCLASS(CanvasItem, Node);
|
||||||
|
|
||||||
|
friend class CanvasLayer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum BlendMode {
|
enum BlendMode {
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ void CollisionObject2D::_notification(int p_what) {
|
||||||
|
|
||||||
case NOTIFICATION_ENTER_TREE: {
|
case NOTIFICATION_ENTER_TREE: {
|
||||||
|
|
||||||
Transform2D global_transform = get_global_transform();
|
Transform2D global_transform = get_global_transform_with_canvas();
|
||||||
|
|
||||||
if (area)
|
if (area)
|
||||||
Physics2DServer::get_singleton()->area_set_transform(rid, global_transform);
|
Physics2DServer::get_singleton()->area_set_transform(rid, global_transform);
|
||||||
|
@ -64,7 +64,7 @@ void CollisionObject2D::_notification(int p_what) {
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
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) {
|
if (only_update_transform_changes && global_transform == last_transform) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -35,19 +35,6 @@
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "math_funcs.h"
|
#include "math_funcs.h"
|
||||||
#include "scene/scene_string_names.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) {
|
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;
|
Physics2DServer::MotionResult *r = NULL;
|
||||||
if (p_result.is_valid())
|
if (p_result.is_valid())
|
||||||
r = p_result->get_result_ptr();
|
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) {
|
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)
|
set_block_transform_notify(true); // don't want notify (would feedback loop)
|
||||||
if (mode != MODE_KINEMATIC)
|
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();
|
linear_velocity = state->get_linear_velocity();
|
||||||
angular_velocity = state->get_angular_velocity();
|
angular_velocity = state->get_angular_velocity();
|
||||||
if (sleeping != state->is_sleeping()) {
|
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
|
Physics2DServer::SeparationResult sep_res[8]; //max 8 rays
|
||||||
|
|
||||||
Transform2D gt = get_global_transform();
|
Transform2D gt = get_global_transform_with_canvas();
|
||||||
|
|
||||||
Vector2 recover;
|
Vector2 recover;
|
||||||
int hits = Physics2DServer::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin);
|
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;
|
gt.elements[2] += recover;
|
||||||
set_global_transform(gt);
|
set_global_transform(get_canvas_transform().affine_inverse() * gt);
|
||||||
|
|
||||||
if (deepest != -1) {
|
if (deepest != -1) {
|
||||||
r_collision.collider = sep_res[deepest].collider_id;
|
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) {
|
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;
|
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);
|
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) {
|
if (!p_test_only) {
|
||||||
gt.elements[2] += result.motion;
|
gt.elements[2] += result.motion;
|
||||||
set_global_transform(gt);
|
set_global_transform(get_canvas_transform().affine_inverse() * gt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return colliding;
|
return colliding;
|
||||||
|
@ -1272,9 +1259,9 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
|
||||||
|
|
||||||
if (p_stop_on_slope) {
|
if (p_stop_on_slope) {
|
||||||
if (Vector2() == lv_n + p_floor_direction) {
|
if (Vector2() == lv_n + p_floor_direction) {
|
||||||
Transform2D gt = get_global_transform();
|
Transform2D gt = get_global_transform_with_canvas();
|
||||||
gt.elements[2] -= collision.travel;
|
gt.elements[2] -= collision.travel;
|
||||||
set_global_transform(gt);
|
set_global_transform(get_canvas_transform().affine_inverse() * gt);
|
||||||
return Vector2();
|
return Vector2();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1323,7 +1310,7 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci
|
||||||
}
|
}
|
||||||
|
|
||||||
Collision col;
|
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)) {
|
if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
|
||||||
gt.elements[2] += col.travel;
|
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;
|
on_floor_body = col.collider_rid;
|
||||||
floor_velocity = col.collider_vel;
|
floor_velocity = col.collider_vel;
|
||||||
}
|
}
|
||||||
set_global_transform(gt);
|
set_global_transform(get_canvas_transform().affine_inverse() * gt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1429,22 +1416,22 @@ void KinematicBody2D::_direct_state_changed(Object *p_state) {
|
||||||
|
|
||||||
last_valid_transform = state->get_transform();
|
last_valid_transform = state->get_transform();
|
||||||
set_notify_local_transform(false);
|
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);
|
set_notify_local_transform(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KinematicBody2D::_notification(int p_what) {
|
void KinematicBody2D::_notification(int p_what) {
|
||||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
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) {
|
if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
|
||||||
//used by sync to physics, send the new transform to the physics
|
//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);
|
Physics2DServer::get_singleton()->body_set_state(get_rid(), Physics2DServer::BODY_STATE_TRANSFORM, new_transform);
|
||||||
//but then revert changes
|
//but then revert changes
|
||||||
set_notify_local_transform(false);
|
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);
|
set_notify_local_transform(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,6 @@ class PhysicsBody2D : public CollisionObject2D {
|
||||||
uint32_t _get_layers() const;
|
uint32_t _get_layers() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
|
||||||
PhysicsBody2D(Physics2DServer::BodyMode p_mode);
|
PhysicsBody2D(Physics2DServer::BodyMode p_mode);
|
||||||
|
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "canvas_layer.h"
|
#include "canvas_layer.h"
|
||||||
|
#include "scene/2d/canvas_item.h"
|
||||||
#include "viewport.h"
|
#include "viewport.h"
|
||||||
|
|
||||||
void CanvasLayer::set_layer(int p_xform) {
|
void CanvasLayer::set_layer(int p_xform) {
|
||||||
|
@ -62,6 +63,24 @@ void CanvasLayer::_update_xform() {
|
||||||
transform.set_origin(ofs);
|
transform.set_origin(ofs);
|
||||||
if (viewport.is_valid())
|
if (viewport.is_valid())
|
||||||
VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform);
|
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() {
|
void CanvasLayer::_update_locrotscale() {
|
||||||
|
|
|
@ -56,6 +56,7 @@ class CanvasLayer : public Node {
|
||||||
int sort_index;
|
int sort_index;
|
||||||
|
|
||||||
void _update_xform();
|
void _update_xform();
|
||||||
|
void _notify_xform(Node *p_node);
|
||||||
void _update_locrotscale();
|
void _update_locrotscale();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
Loading…
Reference in New Issue