namespace Tilia.Interactions.Interactables.Interactables.Utility
{
using Tilia.Interactions.Interactables.Interactors.ComponentTags;
using UnityEngine;
using Zinnia.Tracking.Collision;
using Zinnia.Utility;
///
/// A factory for creating an Interactable Object.
///
public class InteractableFactory
{
///
/// The grab action type to be applied to the primary or secondary action.
///
public enum ActionType
{
///
/// No action is performed.
///
None,
///
/// The Interactable will follow the Interactor.
///
Follow,
///
/// The Interactable will swap the primary action to the secondary Interactor.
///
Swap,
///
/// The Interactable will attempt to rotate into the direction of the Interactor.
///
ControlDirection,
///
/// The Interactable will scale in size based on the point difference between the given Interactors.
///
Scale
}
///
/// Whether the given can be converted to an Interactable Object.
///
/// The object to convert.
/// Whether it can be converted.
public virtual bool CanConvert(GameObject objectToConvert)
{
return objectToConvert.GetComponentInParent() == null;
}
///
/// Creates a new Interactable Object in the scene.
///
/// The Interactable Object prefab to create from.
/// The Object to convert into the new Interactable Object.
/// The created Interactable Object.
public virtual GameObject Create(GameObject interactablePrefab, GameObject objectToConvert)
{
if (!CanConvert(objectToConvert))
{
return null;
}
int siblingIndex = objectToConvert.transform.GetSiblingIndex();
interactablePrefab.name += "_" + objectToConvert.name;
interactablePrefab.name = interactablePrefab.name.Replace("(Clone)", "");
InteractableFacade facade = interactablePrefab.GetComponent();
interactablePrefab.transform.SetParent(objectToConvert.transform.parent);
interactablePrefab.transform.localPosition = objectToConvert.transform.localPosition;
interactablePrefab.transform.localRotation = objectToConvert.transform.localRotation;
interactablePrefab.transform.localScale = objectToConvert.transform.localScale;
HideMeshes(facade.Configuration.MeshContainer);
objectToConvert.transform.SetParent(facade.Configuration.MeshContainer.transform);
objectToConvert.transform.localPosition = Vector3.zero;
objectToConvert.transform.localRotation = Quaternion.identity;
objectToConvert.transform.localScale = Vector3.one;
interactablePrefab.transform.SetSiblingIndex(siblingIndex);
return interactablePrefab;
}
///
/// Embeds an Interactable Object as a child of the existing scene GameObject.
///
/// The Interactable Object prefab to create from and embed.
/// The Object to embed the new Interactable Object into.
/// The existing scene GameObject with the embedded newly created Interactable Object.
public virtual GameObject Embed(GameObject interactablePrefab, GameObject embedInto)
{
if (!CanConvert(embedInto))
{
return null;
}
interactablePrefab.transform.SetParent(embedInto.transform);
interactablePrefab.transform.localPosition = Vector3.zero;
interactablePrefab.transform.localRotation = Quaternion.identity;
interactablePrefab.transform.localScale = Vector3.one;
InteractableFacade facade = interactablePrefab.GetComponent();
Object.DestroyImmediate(facade.GetComponent());
Object.DestroyImmediate(facade.GetComponent());
Object.DestroyImmediate(facade.GetComponent());
Object.DestroyImmediate(facade.GetComponent());
embedInto.AddComponent();
embedInto.AddComponent();
facade.Configuration.CollisionNotifier = embedInto.AddComponent();
Rigidbody baseRigidbody = embedInto.GetComponent();
facade.Configuration.CollisionNotifier.CollisionStarted.AddListener(facade.Configuration.AddCollisionExtractor.DoExtract);
facade.Configuration.CollisionNotifier.CollisionStopped.AddListener(facade.Configuration.RemoveCollisionExtractor.DoExtract);
facade.Configuration.ConsumerContainer = embedInto;
facade.Configuration.ConsumerRigidbody = baseRigidbody;
HideMeshes(facade.Configuration.MeshContainer);
facade.Configuration.MeshContainer = embedInto;
return embedInto;
}
///
/// Hides all of the meshes found in the given child hierarchy.
///
/// The container to find the meshes in.
protected virtual void HideMeshes(GameObject container)
{
foreach (Renderer currentMesh in container.GetComponentsInChildren())
{
currentMesh.gameObject.SetActive(false);
}
}
}
}