瀏覽代碼

FTI - Add `multimesh_instances_reset_physics_interpolation()`

lawnjelly 1 月之前
父節點
當前提交
8bf24dcc44

+ 7 - 0
doc/classes/MultiMesh.xml

@@ -56,6 +56,13 @@
 				This allows you to move instances instantaneously, and should usually be used when initially placing an instance such as a bullet to prevent graphical glitches.
 			</description>
 		</method>
+		<method name="reset_instances_physics_interpolation">
+			<return type="void" />
+			<description>
+				When using [i]physics interpolation[/i], this function allows you to prevent interpolation for all instances in the current physics tick.
+				This allows you to move all instances instantaneously, and should usually be used when initially placing instances to prevent graphical glitches.
+			</description>
+		</method>
 		<method name="set_as_bulk_array">
 			<return type="void" />
 			<argument index="0" name="array" type="PoolRealArray" />

+ 8 - 0
doc/classes/VisualServer.xml

@@ -2244,6 +2244,14 @@
 				Sets the [Transform2D] for this instance. For use when multimesh is used in 2D. Equivalent to [method MultiMesh.set_instance_transform_2d].
 			</description>
 		</method>
+		<method name="multimesh_instances_reset_physics_interpolation">
+			<return type="void" />
+			<argument index="0" name="multimesh" type="RID" />
+			<description>
+				Prevents physics interpolation for all instances during the current physics tick.
+				This is useful when moving all instances to new locations, to give instantaneous changes rather than interpolation from the previous locations.
+			</description>
+		</method>
 		<method name="multimesh_set_as_bulk_array">
 			<return type="void" />
 			<argument index="0" name="multimesh" type="RID" />

+ 5 - 0
scene/resources/multimesh.cpp

@@ -230,6 +230,10 @@ void MultiMesh::reset_instance_physics_interpolation(int p_instance) {
 	VisualServer::get_singleton()->multimesh_instance_reset_physics_interpolation(multimesh, p_instance);
 }
 
+void MultiMesh::reset_instances_physics_interpolation() {
+	VisualServer::get_singleton()->multimesh_instances_reset_physics_interpolation(multimesh);
+}
+
 void MultiMesh::set_instance_transform(int p_instance, const Transform &p_transform) {
 	VisualServer::get_singleton()->multimesh_instance_set_transform(multimesh, p_instance, p_transform);
 }
@@ -332,6 +336,7 @@ void MultiMesh::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_instance_custom_data", "instance", "custom_data"), &MultiMesh::set_instance_custom_data);
 	ClassDB::bind_method(D_METHOD("get_instance_custom_data", "instance"), &MultiMesh::get_instance_custom_data);
 	ClassDB::bind_method(D_METHOD("reset_instance_physics_interpolation", "instance"), &MultiMesh::reset_instance_physics_interpolation);
+	ClassDB::bind_method(D_METHOD("reset_instances_physics_interpolation"), &MultiMesh::reset_instances_physics_interpolation);
 	ClassDB::bind_method(D_METHOD("set_as_bulk_array", "array"), &MultiMesh::set_as_bulk_array);
 	ClassDB::bind_method(D_METHOD("set_as_bulk_array_interpolated", "array_current", "array_previous"), &MultiMesh::set_as_bulk_array_interpolated);
 	ClassDB::bind_method(D_METHOD("get_aabb"), &MultiMesh::get_aabb);

+ 1 - 0
scene/resources/multimesh.h

@@ -120,6 +120,7 @@ public:
 	Color get_instance_custom_data(int p_instance) const;
 
 	void reset_instance_physics_interpolation(int p_instance);
+	void reset_instances_physics_interpolation();
 
 	void set_as_bulk_array(const PoolVector<float> &p_array);
 	void set_as_bulk_array_interpolated(const PoolVector<float> &p_array_curr, const PoolVector<float> &p_array_prev);

+ 14 - 0
servers/visual/rasterizer.cpp

@@ -490,6 +490,20 @@ void RasterizerStorage::multimesh_instance_reset_physics_interpolation(RID p_mul
 	}
 }
 
+void RasterizerStorage::multimesh_instances_reset_physics_interpolation(RID p_multimesh) {
+	MMInterpolator *mmi = _multimesh_get_interpolator(p_multimesh);
+	if (mmi && mmi->_data_curr.size()) {
+		// We don't want to invoke COW here, so copy the data directly.
+		ERR_FAIL_COND(mmi->_data_prev.size() != mmi->_data_curr.size());
+		PoolVector<float>::Read read = mmi->_data_curr.read();
+		PoolVector<float>::Write write = mmi->_data_prev.write();
+
+		const float *r = read.ptr();
+		float *w = write.ptr();
+		memcpy(w, r, sizeof(float) * mmi->_data_curr.size());
+	}
+}
+
 void RasterizerStorage::_multimesh_add_to_interpolation_lists(RID p_multimesh, MMInterpolator &r_mmi) {
 	if (!r_mmi.on_interpolate_update_list) {
 		r_mmi.on_interpolate_update_list = true;

+ 1 - 0
servers/visual/rasterizer.h

@@ -368,6 +368,7 @@ public:
 	virtual void multimesh_set_physics_interpolated(RID p_multimesh, bool p_interpolated);
 	virtual void multimesh_set_physics_interpolation_quality(RID p_multimesh, VS::MultimeshPhysicsInterpolationQuality p_quality);
 	virtual void multimesh_instance_reset_physics_interpolation(RID p_multimesh, int p_index);
+	virtual void multimesh_instances_reset_physics_interpolation(RID p_multimesh);
 
 	virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
 	virtual int multimesh_get_visible_instances(RID p_multimesh) const;

+ 1 - 0
servers/visual/visual_server_raster.h

@@ -288,6 +288,7 @@ public:
 	BIND2(multimesh_set_physics_interpolated, RID, bool)
 	BIND2(multimesh_set_physics_interpolation_quality, RID, MultimeshPhysicsInterpolationQuality)
 	BIND2(multimesh_instance_reset_physics_interpolation, RID, int)
+	BIND1(multimesh_instances_reset_physics_interpolation, RID)
 
 	BIND2(multimesh_set_visible_instances, RID, int)
 	BIND1RC(int, multimesh_get_visible_instances, RID)

+ 1 - 0
servers/visual/visual_server_wrap_mt.h

@@ -211,6 +211,7 @@ public:
 	FUNC2(multimesh_set_physics_interpolated, RID, bool)
 	FUNC2(multimesh_set_physics_interpolation_quality, RID, MultimeshPhysicsInterpolationQuality)
 	FUNC2(multimesh_instance_reset_physics_interpolation, RID, int)
+	FUNC1(multimesh_instances_reset_physics_interpolation, RID)
 
 	FUNC2(multimesh_set_visible_instances, RID, int)
 	FUNC1RC(int, multimesh_get_visible_instances, RID)

+ 1 - 0
servers/visual_server.cpp

@@ -1967,6 +1967,7 @@ void VisualServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("multimesh_set_physics_interpolated", "multimesh", "interpolated"), &VisualServer::multimesh_set_physics_interpolated);
 	ClassDB::bind_method(D_METHOD("multimesh_set_physics_interpolation_quality", "multimesh", "quality"), &VisualServer::multimesh_set_physics_interpolation_quality);
 	ClassDB::bind_method(D_METHOD("multimesh_instance_reset_physics_interpolation", "multimesh", "index"), &VisualServer::multimesh_instance_reset_physics_interpolation);
+	ClassDB::bind_method(D_METHOD("multimesh_instances_reset_physics_interpolation", "multimesh"), &VisualServer::multimesh_instances_reset_physics_interpolation);
 #ifndef _3D_DISABLED
 	ClassDB::bind_method(D_METHOD("immediate_create"), &VisualServer::immediate_create);
 	ClassDB::bind_method(D_METHOD("immediate_begin", "immediate", "primitive", "texture"), &VisualServer::immediate_begin, DEFVAL(RID()));

+ 1 - 0
servers/visual_server.h

@@ -395,6 +395,7 @@ public:
 	virtual void multimesh_set_physics_interpolated(RID p_multimesh, bool p_interpolated) = 0;
 	virtual void multimesh_set_physics_interpolation_quality(RID p_multimesh, MultimeshPhysicsInterpolationQuality p_quality) = 0;
 	virtual void multimesh_instance_reset_physics_interpolation(RID p_multimesh, int p_index) = 0;
+	virtual void multimesh_instances_reset_physics_interpolation(RID p_multimesh) = 0;
 
 	virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
 	virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;