Repository: godotengine/godot
File: modules/jolt_physics/objects/jolt_soft_body_3d.cpp (C++)

Code before:
	if (!in_space()) {
		return false;
	}

	const JoltReadableBody3D body = space->read_body(jolt_id);
	ERR_FAIL_COND_V(body.is_invalid(), false);

	return !body->IsActive();
}

void JoltSoftBody3D::apply_node_impulse(int p_index, const Vector3 &p_impulse) {
	ERR_FAIL_COND_MSG(!in_space(), vformat("Failed to apply impulse for '%s'. Doing so without a physics space is not supported when using Jolt Physics. If this relates to a node, try adding the node to a scene tree first.", to_string()));

	ERR_FAIL_NULL(shared);
	ERR_FAIL_INDEX(p_index, (int)shared->mesh_to_physics.size());
	const size_t physics_index = (size_t)shared->mesh_to_physics[p_index];

	if (pinned_vertices.has(physics_index)) {
		return;
	}

	const float last_step = space->get_last_step();
	if (unlikely(last_step == 0.0f)) {
		return;
	}
	wake_up();

	JoltWritableBody3D body = space->write_body(jolt_id);
	ERR_FAIL_COND(body.is_invalid());

	JPH::SoftBodyMotionProperties &motion_properties = static_cast<JPH::SoftBodyMotionProperties &>(*body->GetMotionPropertiesUnchecked());

	JPH::Array<JPH::SoftBodyVertex> &physics_vertices = motion_properties.GetVertices();
	JPH::SoftBodyVertex &physics_vertex = physics_vertices[physics_index];

	const JPH::Vec3 impulse = to_jolt(p_impulse);
	physics_vertex.mVelocity += impulse * physics_vertex.mInvMass;
}

void JoltSoftBody3D::apply_node_force(int p_index, const Vector3 &p_force) {
	ERR_FAIL_COND_MSG(!in_space(), vformat("Failed to apply force for '%s'. Doing so without a physics space is not supported when using Jolt Physics. If this relates to a node, try adding the node to a scene tree first.", to_string()));

	const float last_step = space->get_last_step();
	const Vector3 impulse = p_force * last_step;
	apply_node_impulse(p_index, impulse);
}

void JoltSoftBody3D::apply_central_impulse(const Vector3 &p_impulse) {
	ERR_FAIL_COND_MSG(!in_space(), vformat("Failed to apply central impulse for '%s'. Doing so without a physics space is not supported when using Jolt Physics. If this relates to a node, try adding the node to a scene tree first.", to_string()));

	ERR_FAIL_NULL(shared);

Review comment (refactor):
I'd say move this `wake_up()` call to the bottom of the method instead.

Normally I try to put these activation calls in "reaction" methods instead, like `_mesh_changed()`, `_mass_changed()`, etc. and then call those instead of `wake_up()`, at the bottom of the method, but the reasons for that are somewhat vague and mostly opinionated, so it's fine if you don't.

Code after:
void JoltSoftBody3D::apply_vertex_force(int p_index, const Vector3 &p_force) {
	ERR_FAIL_COND_MSG(!in_space(), vformat("Failed to apply force to '%s'. Doing so without a physics space is not supported when using Jolt Physics. If this relates to a node, try adding the node to a scene tree first.", to_string()));

	apply_vertex_impulse(p_index, p_force * space->get_last_step());
}

void JoltSoftBody3D::apply_central_impulse(const Vector3 &p_impulse) {
	ERR_FAIL_COND_MSG(!in_space(), vformat("Failed to apply central impulse to '%s'. Doing so without a physics space is not supported when using Jolt Physics. If this relates to a node, try adding the node to a scene tree first.", to_string()));
	ERR_FAIL_NULL(shared);

	JPH::SoftBodyMotionProperties &motion_properties = static_cast<JPH::SoftBodyMotionProperties &>(*jolt_body->GetMotionPropertiesUnchecked());
	JPH::Array<JPH::SoftBodyVertex> &physics_vertices = motion_properties.GetVertices();

	const JPH::Vec3 impulse = to_jolt(p_impulse) / physics_vertices.size();

	for (JPH::SoftBodyVertex &physics_vertex : physics_vertices) {
		if (physics_vertex.mInvMass > 0.0f) {
			physics_vertex.mVelocity += impulse * physics_vertex.mInvMass;
		}
	}

	wake_up();
}

void JoltSoftBody3D::apply_central_force(const Vector3 &p_force) {
	ERR_FAIL_COND_MSG(!in_space(), vformat("Failed to apply central force to '%s'. Doing so without a physics space is not supported when using Jolt Physics. If this relates to a node, try adding the node to a scene tree first.", to_string()));
	ERR_FAIL_NULL(shared);

	JPH::BodyInterface &body_iface = space->get_body_iface();

	body_iface.AddForce(jolt_body->GetID(), to_jolt(p_force), JPH::EActivation::Activate);
}

void JoltSoftBody3D::set_is_sleeping(bool p_enabled) {
	if (!in_space()) {
		return;
	}

	JPH::BodyInterface &body_iface = space->get_body_iface();

	if (p_enabled) {
		body_iface.DeactivateBody(jolt_body->GetID());
	} else {
		body_iface.ActivateBody(jolt_body->GetID());
	}
}

bool JoltSoftBody3D::is_sleep_allowed() const {
	if (!in_space()) {
		return jolt_settings->mAllowSleeping;
	} else {