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); } } } }