using UnityEngine; using MalbersAnimations.Scriptables; using MalbersAnimations.Events; using System; #if UNITY_EDITOR using UnityEditor; #endif namespace MalbersAnimations.Controller { [AddComponentMenu("Malbers/Interaction/Pickable")] public class Pickable : MonoBehaviour, ICollectable { // public enum CollectType { Collectable, Hold, OneUse } //For different types of collectable items? FOR ANOTHER UPDATE public bool Align = true; public bool AlignPos = true; public float AlignTime = 0.15f; public float AlignDistance = 1f; public FloatReference PickDelay = new FloatReference(0); public FloatReference DropDelay = new FloatReference(0); public FloatReference coolDown = new FloatReference(0f); public BoolReference m_Collectable = new BoolReference(false); public BoolReference m_ByAnimation = new BoolReference(false); public BoolReference m_DestroyOnPick = new BoolReference(false); [Tooltip("Unparent the Pickable, so it does not have any Transform parents.")] public BoolReference SceneRoot = new BoolReference(true); public FloatReference m_Value = new FloatReference(1f); //Not done yet public BoolReference m_AutoPick = new BoolReference(false); //Not done yet public IntReference m_ID = new IntReference(); //Not done yet /// Who Did the Picking public GameObject Picker { get; set; } public BoolEvent OnFocused = new BoolEvent(); public GameObjectEvent OnPicked = new GameObjectEvent(); public GameObjectEvent OnPrePicked = new GameObjectEvent(); public GameObjectEvent OnDropped = new GameObjectEvent(); public GameObjectEvent OnPreDropped = new GameObjectEvent(); [SerializeField] private Rigidbody rb; [RequiredField] public Collider m_collider; private float currentPickTime; /// Is this Object being picked public bool IsPicked { get; set; } /// Current value of the Item public float Value { get => m_Value.Value; set => m_Value.Value = value; } /// The Item will be autopicked if the Picker is focusing it public bool AutoPick { get => m_AutoPick.Value; set => m_AutoPick.Value = value; } public bool Collectable { get => m_Collectable.Value; set => m_Collectable.Value = value; } public Rigidbody RigidBody => rb; /// The Pick Up Drop Logic will be called via animator events/messages public bool ByAnimation { get => m_ByAnimation.Value; set => m_ByAnimation.Value = value; } public bool DestroyOnPick { get => m_DestroyOnPick.Value; set => m_DestroyOnPick.Value = value; } public bool InCoolDown => !MTools.ElapsedTime(CurrentPickTime, coolDown); public int ID { get => m_ID.Value; set => m_ID.Value = value; } private bool focused; public bool Focused { get => focused; set => OnFocused.Invoke(focused = value); } /// Game Time the Pickable was Picked public float CurrentPickTime { get => currentPickTime; set => currentPickTime = value; } private void OnDisable() { Focused = false; } private void Awake() { rb = GetComponent(); CurrentPickTime = -coolDown; if (SceneRoot.Value) transform.parent = null; } public virtual void Pick() { if (RigidBody) { RigidBody.useGravity = false; RigidBody.velocity = Vector3.zero; RigidBody.collisionDetectionMode = CollisionDetectionMode.Discrete; RigidBody.isKinematic = true; } m_collider.enabled = false; IsPicked = true; OnPicked.Invoke(Picker); CurrentPickTime = Time.time; } public virtual void Drop() { IsPicked = false; if (RigidBody) { RigidBody.useGravity = true; RigidBody.isKinematic = false; RigidBody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; } m_collider.enabled = true; var localScale = transform.localScale; transform.parent = null; transform.localScale = localScale; OnDropped.Invoke(Picker); Picker = null; //Reset who did the picking CurrentPickTime = Time.time; } [HideInInspector] public int EditorTabs = 0; #if UNITY_EDITOR private void OnDrawGizmosSelected() { UnityEditor.Handles.color = Color.yellow; UnityEditor.Handles.DrawWireDisc(transform.position, transform.up, AlignDistance); } private void Reset() { m_collider = GetComponent(); rb = GetComponent(); var EInteract = MTools.GetInstance("Interact UI"); if (EInteract) { UnityEditor.Events.UnityEventTools.AddObjectPersistentListener(OnFocused, EInteract.Invoke, transform); UnityEditor.Events.UnityEventTools.AddPersistentListener(OnFocused, EInteract.Invoke); UnityEditor.Events.UnityEventTools.AddBoolPersistentListener(OnPicked, EInteract.Invoke, false); } } #endif } //INSPECTOR #if UNITY_EDITOR [CustomEditor(typeof(Pickable)), CanEditMultipleObjects] public class PickableEditor : Editor { private SerializedProperty // PickAnimations, PickUpMode, PickUpAbility, DropMode, DropAbility,DropAnimations, Align, AlignTime, AlignDistance, AlignPos, EditorTabs, m_AutoPick, DropDelay, PickDelay, rb, CoolDown, SceneRoot, OnFocused, OnPrePicked, OnPicked, OnDropped, OnPreDropped, /*ShowEvents, */FloatID, IntID, m_collider, m_Collectable, m_ByAnimation, m_DestroyOnPick; private Pickable m; protected string[] Tabs1 = new string[] { "General", "Events" }; private void OnEnable() { m = (Pickable)target; EditorTabs = serializedObject.FindProperty("EditorTabs"); SceneRoot = serializedObject.FindProperty("SceneRoot"); rb = serializedObject.FindProperty("rb"); PickDelay = serializedObject.FindProperty("PickDelay"); DropDelay = serializedObject.FindProperty("DropDelay"); m_Collectable = serializedObject.FindProperty("m_Collectable"); m_ByAnimation = serializedObject.FindProperty("m_ByAnimation"); m_DestroyOnPick = serializedObject.FindProperty("m_DestroyOnPick"); Align = serializedObject.FindProperty("Align"); AlignTime = serializedObject.FindProperty("AlignTime"); AlignDistance = serializedObject.FindProperty("AlignDistance"); OnFocused = serializedObject.FindProperty("OnFocused"); OnPicked = serializedObject.FindProperty("OnPicked"); OnPrePicked = serializedObject.FindProperty("OnPrePicked"); OnDropped = serializedObject.FindProperty("OnDropped"); OnPreDropped = serializedObject.FindProperty("OnPreDropped"); //ShowEvents = serializedObject.FindProperty("ShowEvents"); FloatID = serializedObject.FindProperty("m_Value"); IntID = serializedObject.FindProperty("m_ID"); m_collider = serializedObject.FindProperty("m_collider"); AlignPos = serializedObject.FindProperty("AlignPos"); //Collectable = serializedObject.FindProperty("Collectable"); m_AutoPick = serializedObject.FindProperty("m_AutoPick"); CoolDown = serializedObject.FindProperty("coolDown"); } public override void OnInspectorGUI() { serializedObject.Update(); MalbersEditor.DrawDescription("Pickable - Collectable object"); EditorGUILayout.BeginVertical(MTools.StyleGray); { EditorTabs.intValue = GUILayout.Toolbar(EditorTabs.intValue, Tabs1); EditorGUILayout.BeginVertical(EditorStyles.helpBox); { if (Application.isPlaying) { EditorGUI.BeginDisabledGroup(true); EditorGUILayout.ToggleLeft("Is Picked", m.IsPicked); EditorGUI.EndDisabledGroup(); } if (EditorTabs.intValue == 0) DrawGeneral(); else DrawEvents(); } EditorGUILayout.EndVertical(); } EditorGUILayout.EndVertical(); serializedObject.ApplyModifiedProperties(); } private void DrawEvents() { EditorGUILayout.PropertyField(OnFocused); if (m.PickDelay > 0 || m.m_ByAnimation.Value) EditorGUILayout.PropertyField(OnPrePicked, new GUIContent("On Pre-Picked By")); EditorGUILayout.PropertyField(OnPicked, new GUIContent("On Picked By")); if (m.DropDelay > 0 || m.m_ByAnimation.Value) EditorGUILayout.PropertyField(OnPreDropped, new GUIContent("On Pre-Dropped By")); EditorGUILayout.PropertyField(OnDropped, new GUIContent("On Dropped By")); } private void DrawGeneral() { m_AutoPick.isExpanded = MalbersEditor.Foldout(m_AutoPick.isExpanded, "Pickable Item"); if (m_AutoPick.isExpanded) { EditorGUILayout.PropertyField(IntID, new GUIContent("ID", "Int value the Pickable Item can store. This ID is used by the Picker component to Identify each Pickable Object")); EditorGUILayout.PropertyField(FloatID, new GUIContent("Float Value", "Float value the Pickable Item can store.. that it can be use for anything")); EditorGUILayout.PropertyField(m_AutoPick, new GUIContent("Auto", "The Item will be Picked Automatically")); EditorGUILayout.PropertyField(m_ByAnimation, new GUIContent("Use Animation", "The Item will Pre-Picked/Dropped by the Picker Animator." + " Pick-Drop Logic is called by Animation Event or Animator Message Behaviour.\nUse the Methods: TryPickUpDrop(); TryPickUp(); TryDrop();")); EditorGUILayout.PropertyField(SceneRoot); EditorGUILayout.PropertyField(m_Collectable, new GUIContent("Collectable", "The Item will Picked by the Pickable and it will be stored")); if (m.Collectable) EditorGUILayout.PropertyField(m_DestroyOnPick, new GUIContent("Destroy Collectable", "The Item will be destroyed after is picked")); } //EditorGUILayout.EndVertical(); // EditorGUILayout.BeginVertical(EditorStyles.helpBox); { m_collider.isExpanded = MalbersEditor.Foldout(m_collider.isExpanded, "References"); if (m_collider.isExpanded) { EditorGUILayout.PropertyField(m_collider); EditorGUILayout.PropertyField(rb, new GUIContent("Rigid Body")); } } //EditorGUILayout.EndVertical(); // EditorGUILayout.BeginVertical(EditorStyles.helpBox); { CoolDown.isExpanded = MalbersEditor.Foldout(CoolDown.isExpanded, "Delays"); if (CoolDown.isExpanded) { EditorGUILayout.PropertyField(CoolDown); EditorGUILayout.PropertyField(PickDelay, new GUIContent("Pick Delay", "Delay time after Calling the Pick Action")); EditorGUILayout.PropertyField(DropDelay, new GUIContent("Drop Delay", "Delay time after Calling the Drop Action")); } } // EditorGUILayout.EndVertical(); // EditorGUILayout.BeginVertical(EditorStyles.helpBox); { Align.isExpanded = MalbersEditor.Foldout(Align.isExpanded, "Alignment"); if (Align.isExpanded) { EditorGUILayout.PropertyField(Align, new GUIContent("Align On Pick", "Align the character to the Item")); if (Align.boolValue) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(AlignPos, new GUIContent("Align Pos", "align the Position")); EditorGUIUtility.labelWidth = 60; EditorGUILayout.PropertyField(AlignDistance, new GUIContent("Distance", "Distance to move the Animal towards the Item"), GUILayout.MinWidth(50)); EditorGUIUtility.labelWidth = 0; EditorGUILayout.EndHorizontal(); EditorGUILayout.PropertyField(AlignTime, new GUIContent("Time", "Time required to do the alignment")); } } } // EditorGUILayout.EndVertical(); } } #endif }