using Convai.Scripts.Runtime.Core; using Convai.Scripts.Runtime.Features; using Convai.Scripts.Runtime.Features.LongTermMemory; using UnityEditor; using UnityEngine; using ConvaiLipSync = Convai.Scripts.Runtime.Features.LipSync.ConvaiLipSync; namespace Convai.Scripts.Editor.NPC { /// /// Editor window for managing Convai NPC components. /// public class ConvaiNPCComponentSettingsWindow : EditorWindow { private ConvaiNPC _convaiNPC; /// /// Handles GUI events for the window. /// private void OnGUI() { titleContent = new GUIContent("Convai NPC Components"); Vector2 windowSize = new(300, 250); minSize = windowSize; maxSize = windowSize; if (_convaiNPC == null) { EditorGUILayout.LabelField("No ConvaiNPC selected"); return; } EditorGUILayout.BeginVertical(GUI.skin.box); EditorGUIUtility.labelWidth = 200f; // Set a custom label width _convaiNPC.IncludeActionsHandler = EditorGUILayout.Toggle(new GUIContent("NPC Actions", "Decides if Actions Handler is included"), _convaiNPC.IncludeActionsHandler); _convaiNPC.LipSync = EditorGUILayout.Toggle(new GUIContent("Lip Sync", "Decides if Lip Sync is enabled"), _convaiNPC.LipSync); _convaiNPC.HeadEyeTracking = EditorGUILayout.Toggle(new GUIContent("Head & Eye Tracking", "Decides if Head & Eye tracking is enabled"), _convaiNPC.HeadEyeTracking); _convaiNPC.EyeBlinking = EditorGUILayout.Toggle(new GUIContent("Eye Blinking", "Decides if Eye Blinking is enabled"), _convaiNPC.EyeBlinking); _convaiNPC.NarrativeDesignManager = EditorGUILayout.Toggle(new GUIContent("Narrative Design Manager", "Decides if Narrative Design Manager is enabled"), _convaiNPC.NarrativeDesignManager); _convaiNPC.ConvaiGroupNPCController = EditorGUILayout.Toggle(new GUIContent("Group NPC Controller", "Decides if this NPC can be a part of Convai NPC to NPC Conversation"), _convaiNPC.ConvaiGroupNPCController); _convaiNPC.LongTermMemoryController = EditorGUILayout.Toggle(new GUIContent("Long Term Memory", "Component to toggle Long term memory for this character"), _convaiNPC.LongTermMemoryController); _convaiNPC.NarrativeDesignKeyController = EditorGUILayout.Toggle(new GUIContent("Narrative Design Keys", "Adds handler for Narrative Design Keys for this character"), _convaiNPC.NarrativeDesignKeyController); _convaiNPC.DynamicInfoController = EditorGUILayout.Toggle(new GUIContent("Dynamic Info", "Component used to send dynamic info like your game states to the character"), _convaiNPC.DynamicInfoController); EditorGUILayout.EndVertical(); GUILayout.Space(10); if (GUILayout.Button("Apply Changes", GUILayout.Height(40))) { ApplyChanges(); EditorUtility.SetDirty(_convaiNPC); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Close(); } } /// /// Refreshes the component states when the window gains focus. /// private void OnFocus() { RefreshComponentStates(); } /// /// Opens the Convai NPC Component Settings window. /// /// The Convai NPC to manage. public static void Open(ConvaiNPC convaiNPC) { ConvaiNPCComponentSettingsWindow window = GetWindow(); window.titleContent = new GUIContent("Convai NPC Component Settings"); window._convaiNPC = convaiNPC; window.RefreshComponentStates(); window.Show(); } /// /// Refreshes the states of the components. /// private void RefreshComponentStates() { if (_convaiNPC != null) { _convaiNPC.IncludeActionsHandler = _convaiNPC.GetComponent() is not null; _convaiNPC.LipSync = _convaiNPC.GetComponent() is not null; _convaiNPC.HeadEyeTracking = _convaiNPC.GetComponent() is not null; _convaiNPC.EyeBlinking = _convaiNPC.GetComponent() is not null; _convaiNPC.NarrativeDesignManager = _convaiNPC.GetComponent() is not null; _convaiNPC.ConvaiGroupNPCController = _convaiNPC.GetComponent() is not null; _convaiNPC.LongTermMemoryController = _convaiNPC.GetComponent() is not null; _convaiNPC.NarrativeDesignKeyController = _convaiNPC.GetComponent() is not null; _convaiNPC.DynamicInfoController = _convaiNPC.GetComponent() is not null; Repaint(); } } /// /// Applies changes based on the user's selection in the inspector. /// private void ApplyChanges() { if (EditorUtility.DisplayDialog("Confirm Apply Changes", "Do you want to apply the following changes?", "Yes", "No")) { ApplyComponent(_convaiNPC.IncludeActionsHandler); ApplyComponent(_convaiNPC.LipSync); ApplyComponent(_convaiNPC.HeadEyeTracking); ApplyComponent(_convaiNPC.EyeBlinking); ApplyComponent(_convaiNPC.NarrativeDesignManager); ApplyComponent(_convaiNPC.ConvaiGroupNPCController); ApplyComponent(_convaiNPC.LongTermMemoryController); ApplyComponent(_convaiNPC.NarrativeDesignKeyController); ApplyComponent(_convaiNPC.DynamicInfoController); } } /// /// Applies or removes a component based on the specified condition. /// If the component is to be removed, its state is saved. If it's added, its state is restored if previously saved. /// /// The type of the component. /// Whether to include the component. private void ApplyComponent(bool includeComponent) where T : Component { T component = _convaiNPC.GetComponent(); if (includeComponent) { if (component == null) { component = _convaiNPC.gameObject.AddComponentSafe(); } } else if (component != null) { DestroyImmediate(component); } } } }