// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
// SPDX-License-Identifier: MIT

#pragma once

JPH_NAMESPACE_BEGIN

class Body;
class SoftBodyManifold;

/// Return value for the OnSoftBodyContactValidate callback. Determines if the contact will be processed or not.
enum class SoftBodyValidateResult
{
	AcceptContact,														///< Accept this contact
	RejectContact,														///< Reject this contact
};

/// Contact settings for a soft body contact.
/// The values are filled in with their defaults by the system so the callback doesn't need to modify anything, but it can if it wants to.
class SoftBodyContactSettings
{
public:
	float							mInvMassScale1 = 1.0f;				///< Scale factor for the inverse mass of the soft body (0 = infinite mass, 1 = use original mass, 2 = body has half the mass). For the same contact pair, you should strive to keep the value the same over time.
	float							mInvMassScale2 = 1.0f;				///< Scale factor for the inverse mass of the other body (0 = infinite mass, 1 = use original mass, 2 = body has half the mass). For the same contact pair, you should strive to keep the value the same over time.
	float							mInvInertiaScale2 = 1.0f;			///< Scale factor for the inverse inertia of the other body (usually same as mInvMassScale2)
	bool							mIsSensor;							///< If the contact should be treated as a sensor vs body contact (no collision response)
};

/// A listener class that receives collision contact events for soft bodies against rigid bodies.
/// It can be registered with the PhysicsSystem.
class SoftBodyContactListener
{
public:
	/// Ensure virtual destructor
	virtual							~SoftBodyContactListener() = default;

	/// Called whenever the soft body's aabox overlaps with another body's aabox (so receiving this callback doesn't tell if any of the vertices will collide).
	/// This callback can be used to change the behavior of the collision response for all vertices in the soft body or to completely reject the contact.
	/// Note that this callback is called when all bodies are locked, so don't use any locking functions!
	/// @param inSoftBody The soft body that collided. It is safe to access this as the soft body is only updated on the current thread.
	/// @param inOtherBody The other body that collided. Note that accessing the position/orientation/velocity of inOtherBody may result in a race condition as other threads may be modifying the body at the same time.
	/// @param ioSettings The settings for all contact points that are generated by this collision.
	/// @return Whether the contact should be processed or not.
	virtual SoftBodyValidateResult	OnSoftBodyContactValidate([[maybe_unused]] const Body &inSoftBody, [[maybe_unused]] const Body &inOtherBody, [[maybe_unused]] SoftBodyContactSettings &ioSettings) { return SoftBodyValidateResult::AcceptContact; }

	/// Called after all contact points for a soft body have been handled. You only receive one callback per body pair per simulation step and can use inManifold to iterate through all contacts.
	/// Note that this callback is called when all bodies are locked, so don't use any locking functions!
	/// You will receive a single callback for a soft body per simulation step for performance reasons, this callback will apply to all vertices in the soft body.
	/// @param inSoftBody The soft body that collided. It is safe to access this as the soft body is only updated on the current thread.
	/// @param inManifold The manifold that describes the contact surface between the two bodies. Other bodies may be modified by other threads during this callback.
	virtual void					OnSoftBodyContactAdded([[maybe_unused]] const Body &inSoftBody, const SoftBodyManifold &inManifold) { /* Do nothing */ }
};

JPH_NAMESPACE_END
