Sfoglia il codice sorgente

Merge pull request #6090 from WalasPrime/raytrace_force

Added force_raycast_update GDScript method for RayCast[2D]
Rémi Verschelde 9 anni fa
parent
commit
afd86ee240
5 ha cambiato i file con 73 aggiunte e 42 eliminazioni
  1. 14 0
      doc/base/classes.xml
  2. 27 21
      scene/2d/ray_cast_2d.cpp
  3. 3 0
      scene/2d/ray_cast_2d.h
  4. 27 21
      scene/3d/ray_cast.cpp
  5. 2 0
      scene/3d/ray_cast.h

+ 14 - 0
doc/base/classes.xml

@@ -31871,6 +31871,8 @@
 		RayCast can ignore some objects by adding them to the exception list via [code]add_exception[/code], setting proper filtering with layers, or by filtering object types with type masks.
 
 		Only enabled raycasts will be able to query the space and report collisions!
+
+		RayCast calculates intersection every fixed frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between fixed frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast.
 	</description>
 	<methods>
 		<method name="add_exception">
@@ -31891,6 +31893,11 @@
 				Removes all collision exception for this ray.
 			</description>
 		</method>
+		<method name="force_raycast_update">
+			<description>
+				Updates the collision information in case if this object's properties changed during the current frame (for example position, rotation or the cast_point). Note, [code]set_enabled[/code] is not required for this to work.
+			</description>
+		</method>
 		<method name="get_cast_to" qualifiers="const">
 			<return type="Vector3">
 			</return>
@@ -32009,6 +32016,8 @@
 		RayCast2D can ignore some objects by adding them to the exception list via [code]add_exception[/code], setting proper filtering with layers, or by filtering object types with type masks.
 
 		Only enabled raycasts will be able to query the space and report collisions!
+
+		RayCast2D calculates intersection every fixed frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between fixed frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast.
 	</description>
 	<methods>
 		<method name="add_exception">
@@ -32029,6 +32038,11 @@
 				Removes all collision exception for this ray.
 			</description>
 		</method>
+		<method name="force_raycast_update">
+			<description>
+				Updates the collision information in case if this object's properties changed during the current frame (for example position, rotation or the cast_point). Note, [code]set_enabled[/code] is not required for this to work.
+			</description>
+		</method>
 		<method name="get_cast_to" qualifiers="const">
 			<return type="Vector2">
 			</return>

+ 27 - 21
scene/2d/ray_cast_2d.cpp

@@ -187,39 +187,44 @@ void RayCast2D::_notification(int p_what) {
 			if (!enabled)
 				break;
 
+			_update_raycast_state();
 
 
-			Ref<World2D> w2d = get_world_2d();
-			ERR_BREAK( w2d.is_null() );
-
-			Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(w2d->get_space());
-			ERR_BREAK( !dss );
-
-			Matrix32 gt = get_global_transform();
+		} break;
+	}
+}
 
-			Vector2 to = cast_to;
-			if (to==Vector2())
-				to=Vector2(0,0.01);
+void RayCast2D::_update_raycast_state() {
+	Ref<World2D> w2d = get_world_2d();
+	ERR_FAIL_COND( w2d.is_null() );
 
-			Physics2DDirectSpaceState::RayResult rr;
+	Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(w2d->get_space());
+	ERR_FAIL_COND( !dss );
 
-			if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude,layer_mask,type_mask)) {
+	Matrix32 gt = get_global_transform();
 
-				collided=true;
-				against=rr.collider_id;
-				collision_point=rr.position;
-				collision_normal=rr.normal;
-				against_shape=rr.shape;
-			} else {
-				collided=false;
-			}
+	Vector2 to = cast_to;
+	if (to==Vector2())
+		to=Vector2(0,0.01);
 
+	Physics2DDirectSpaceState::RayResult rr;
 
+	if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude,layer_mask,type_mask)) {
 
-		} break;
+		collided=true;
+		against=rr.collider_id;
+		collision_point=rr.position;
+		collision_normal=rr.normal;
+		against_shape=rr.shape;
+	} else {
+		collided=false;
 	}
 }
 
+void RayCast2D::force_raycast_update() {
+	_update_raycast_state();
+}
+
 void RayCast2D::add_exception_rid(const RID& p_rid) {
 
 	exclude.insert(p_rid);
@@ -265,6 +270,7 @@ void RayCast2D::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_cast_to"),&RayCast2D::get_cast_to);
 
 	ObjectTypeDB::bind_method(_MD("is_colliding"),&RayCast2D::is_colliding);
+	ObjectTypeDB::bind_method(_MD("force_raycast_update"),&RayCast2D::force_raycast_update);
 
 	ObjectTypeDB::bind_method(_MD("get_collider"),&RayCast2D::get_collider);
 	ObjectTypeDB::bind_method(_MD("get_collider_shape"),&RayCast2D::get_collider_shape);

+ 3 - 0
scene/2d/ray_cast_2d.h

@@ -52,6 +52,7 @@ class RayCast2D : public Node2D {
 protected:
 
 	void _notification(int p_what);
+	void _update_raycast_state();
 	static void _bind_methods();
 public:
 
@@ -70,6 +71,8 @@ public:
 	void set_exclude_parent_body(bool p_exclude_parent_body);
 	bool get_exclude_parent_body() const;
 
+	void force_raycast_update();
+
 	bool is_colliding() const;
 	Object *get_collider() const;
 	int get_collider_shape() const;

+ 27 - 21
scene/3d/ray_cast.cpp

@@ -134,39 +134,44 @@ void RayCast::_notification(int p_what) {
 			if (!enabled)
 				break;
 
+			_update_raycast_state();
 
 
-			Ref<World> w3d = get_world();
-			ERR_BREAK( w3d.is_null() );
-
-			PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(w3d->get_space());
-			ERR_BREAK( !dss );
-
-			Transform gt = get_global_transform();
+		} break;
+	}
+}
 
-			Vector3 to = cast_to;
-			if (to==Vector3())
-				to=Vector3(0,0.01,0);
+void RayCast::_update_raycast_state(){
+	Ref<World> w3d = get_world();
+	ERR_FAIL_COND( w3d.is_null() );
 
-			PhysicsDirectSpaceState::RayResult rr;
+	PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(w3d->get_space());
+	ERR_FAIL_COND( !dss );
 
-			if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude, layer_mask, type_mask)) {
+	Transform gt = get_global_transform();
 
-				collided=true;
-				against=rr.collider_id;
-				collision_point=rr.position;
-				collision_normal=rr.normal;
-				against_shape=rr.shape;
-			} else {
-				collided=false;
-			}
+	Vector3 to = cast_to;
+	if (to==Vector3())
+		to=Vector3(0,0.01,0);
 
+	PhysicsDirectSpaceState::RayResult rr;
 
+	if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude, layer_mask, type_mask)) {
 
-		} break;
+		collided=true;
+		against=rr.collider_id;
+		collision_point=rr.position;
+		collision_normal=rr.normal;
+		against_shape=rr.shape;
+	} else {
+		collided=false;
 	}
 }
 
+void RayCast::force_raycast_update() {
+	_update_raycast_state();
+}
+
 void RayCast::add_exception_rid(const RID& p_rid) {
 
 	exclude.insert(p_rid);
@@ -212,6 +217,7 @@ void RayCast::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_cast_to"),&RayCast::get_cast_to);
 
 	ObjectTypeDB::bind_method(_MD("is_colliding"),&RayCast::is_colliding);
+	ObjectTypeDB::bind_method(_MD("force_raycast_update"),&RayCast::force_raycast_update);
 
 	ObjectTypeDB::bind_method(_MD("get_collider"),&RayCast::get_collider);
 	ObjectTypeDB::bind_method(_MD("get_collider_shape"),&RayCast::get_collider_shape);

+ 2 - 0
scene/3d/ray_cast.h

@@ -53,6 +53,7 @@ class RayCast : public Spatial {
 protected:
 
 	void _notification(int p_what);
+	void _update_raycast_state();
 	static void _bind_methods();
 public:
 
@@ -68,6 +69,7 @@ public:
 	void set_type_mask(uint32_t p_mask);
 	uint32_t get_type_mask() const;
 
+	void force_raycast_update();
 	bool is_colliding() const;
 	Object *get_collider() const;
 	int get_collider_shape() const;