Ver código fonte

Take CanvasLayer transform into account for 2D physics

Fixes #18073.
Pedro J. Estébanez 7 anos atrás
pai
commit
4839e5f6d9

+ 2 - 0
scene/2d/canvas_item.h

@@ -139,6 +139,8 @@ class CanvasItem : public Node {
 
 	GDCLASS(CanvasItem, Node);
 
+	friend class CanvasLayer;
+
 public:
 	enum BlendMode {
 

+ 2 - 2
scene/2d/collision_object_2d.cpp

@@ -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;

+ 14 - 27
scene/2d/physics_body_2d.cpp

@@ -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);
 	}
 }

+ 0 - 1
scene/2d/physics_body_2d.h

@@ -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();

+ 19 - 0
scene/main/canvas_layer.cpp

@@ -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() {

+ 1 - 0
scene/main/canvas_layer.h

@@ -56,6 +56,7 @@ class CanvasLayer : public Node {
 	int sort_index;
 
 	void _update_xform();
+	void _notify_xform(Node *p_node);
 	void _update_locrotscale();
 
 protected: