using UnityEngine; using UnityEditor; namespace Interactions { [CustomEditor(typeof(InteractableBase), true)] public class InteractableEditor : UnityEditor.Editor { SerializedProperty isOneTimeProp; SerializedProperty cooldownProp; SerializedProperty characterToInteractProp; SerializedProperty interactionStartedProp; SerializedProperty interactionInterruptedProp; SerializedProperty characterArrivedProp; SerializedProperty interactionCompleteProp; private bool showBaseSettings = true; private bool showEvents = false; private void OnEnable() { isOneTimeProp = serializedObject.FindProperty("isOneTime"); cooldownProp = serializedObject.FindProperty("cooldown"); characterToInteractProp = serializedObject.FindProperty("characterToInteract"); interactionStartedProp = serializedObject.FindProperty("interactionStarted"); interactionInterruptedProp = serializedObject.FindProperty("interactionInterrupted"); characterArrivedProp = serializedObject.FindProperty("characterArrived"); interactionCompleteProp = serializedObject.FindProperty("interactionComplete"); } public override void OnInspectorGUI() { serializedObject.Update(); // Draw child-specific properties first (anything not part of base class) DrawPropertiesExcluding(serializedObject, "m_Script", "isOneTime", "cooldown", "characterToInteract", "interactionStarted", "interactionInterrupted", "characterArrived", "interactionComplete"); // Base Interaction Settings (Collapsible) EditorGUILayout.Space(10); showBaseSettings = EditorGUILayout.Foldout(showBaseSettings, "Base Interaction Settings", true, EditorStyles.foldoutHeader); if (showBaseSettings) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(isOneTimeProp); EditorGUILayout.PropertyField(cooldownProp); EditorGUILayout.PropertyField(characterToInteractProp); // Character Move Targets (sub-section) EditorGUILayout.Space(5); EditorGUILayout.LabelField("Character Move Targets", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Add Trafalgar Target")) { CreateMoveTarget(CharacterToInteract.Trafalgar); } if (GUILayout.Button("Add Pulver Target")) { CreateMoveTarget(CharacterToInteract.Pulver); } EditorGUILayout.EndHorizontal(); // Add a button for creating a "Both" target if (GUILayout.Button("Add Both Characters Target")) { CreateMoveTarget(CharacterToInteract.Both); } // Display character target counts InteractableBase interactable = (InteractableBase)target; CharacterMoveToTarget[] moveTargets = interactable.GetComponentsInChildren(); int trafalgarTargets = 0; int pulverTargets = 0; int bothTargets = 0; foreach (var target in moveTargets) { if (target.characterType == CharacterToInteract.Trafalgar) trafalgarTargets++; else if (target.characterType == CharacterToInteract.Pulver) pulverTargets++; else if (target.characterType == CharacterToInteract.Both) bothTargets++; } EditorGUILayout.LabelField($"Trafalgar Targets: {trafalgarTargets}, Pulver Targets: {pulverTargets}, Both Targets: {bothTargets}"); if (trafalgarTargets > 1 || pulverTargets > 1 || bothTargets > 1 || (bothTargets > 0 && (trafalgarTargets > 0 || pulverTargets > 0))) { EditorGUILayout.HelpBox("Warning: Multiple move targets found that may conflict. Priority order: Both > Character-specific targets.", MessageType.Warning); } EditorGUI.indentLevel--; } // Interaction Events (Collapsible) EditorGUILayout.Space(10); showEvents = EditorGUILayout.Foldout(showEvents, "Interaction Events", true, EditorStyles.foldoutHeader); if (showEvents) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(interactionStartedProp); EditorGUILayout.PropertyField(interactionInterruptedProp); EditorGUILayout.PropertyField(characterArrivedProp); EditorGUILayout.PropertyField(interactionCompleteProp); EditorGUI.indentLevel--; } serializedObject.ApplyModifiedProperties(); } private void CreateMoveTarget(CharacterToInteract characterType) { InteractableBase interactable = (InteractableBase)target; // Create a new GameObject GameObject targetObj = new GameObject($"{characterType}MoveTarget"); // Set parent targetObj.transform.SetParent(interactable.transform); targetObj.transform.localPosition = Vector3.zero; // Start at the same position as the interactable // Add CharacterMoveToTarget component CharacterMoveToTarget moveTarget = targetObj.AddComponent(); moveTarget.characterType = characterType; // Position it based on character type (offset for better visibility) switch (characterType) { case CharacterToInteract.Trafalgar: moveTarget.positionOffset = new Vector3(1.0f, 0, 0); break; case CharacterToInteract.Pulver: moveTarget.positionOffset = new Vector3(0, 0, 1.0f); break; case CharacterToInteract.Both: moveTarget.positionOffset = new Vector3(0.7f, 0, 0.7f); break; } // Select the newly created object Selection.activeGameObject = targetObj; Undo.RegisterCreatedObjectUndo(targetObj, $"Create {characterType} Move Target"); } } }