initial upload

This commit is contained in:
tom.hempel
2025-09-21 22:42:26 +02:00
commit d03bcd4ba5
6231 changed files with 351582 additions and 0 deletions

View File

@ -0,0 +1,153 @@
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
{
/// <summary>
/// Editor window for managing Convai NPC components.
/// </summary>
public class ConvaiNPCComponentSettingsWindow : EditorWindow
{
private ConvaiNPC _convaiNPC;
/// <summary>
/// Handles GUI events for the window.
/// </summary>
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();
}
}
/// <summary>
/// Refreshes the component states when the window gains focus.
/// </summary>
private void OnFocus()
{
RefreshComponentStates();
}
/// <summary>
/// Opens the Convai NPC Component Settings window.
/// </summary>
/// <param name="convaiNPC">The Convai NPC to manage.</param>
public static void Open(ConvaiNPC convaiNPC)
{
ConvaiNPCComponentSettingsWindow window = GetWindow<ConvaiNPCComponentSettingsWindow>();
window.titleContent = new GUIContent("Convai NPC Component Settings");
window._convaiNPC = convaiNPC;
window.RefreshComponentStates();
window.Show();
}
/// <summary>
/// Refreshes the states of the components.
/// </summary>
private void RefreshComponentStates()
{
if (_convaiNPC != null)
{
_convaiNPC.IncludeActionsHandler = _convaiNPC.GetComponent<ConvaiActionsHandler>() is not null;
_convaiNPC.LipSync = _convaiNPC.GetComponent<ConvaiLipSync>() is not null;
_convaiNPC.HeadEyeTracking = _convaiNPC.GetComponent<ConvaiHeadTracking>() is not null;
_convaiNPC.EyeBlinking = _convaiNPC.GetComponent<ConvaiBlinkingHandler>() is not null;
_convaiNPC.NarrativeDesignManager = _convaiNPC.GetComponent<NarrativeDesignManager>() is not null;
_convaiNPC.ConvaiGroupNPCController = _convaiNPC.GetComponent<ConvaiGroupNPCController>() is not null;
_convaiNPC.LongTermMemoryController = _convaiNPC.GetComponent<ConvaiLTMController>() is not null;
_convaiNPC.NarrativeDesignKeyController =
_convaiNPC.GetComponent<NarrativeDesignKeyController>() is not null;
_convaiNPC.DynamicInfoController = _convaiNPC.GetComponent<DynamicInfoController>() is not null;
Repaint();
}
}
/// <summary>
/// Applies changes based on the user's selection in the inspector.
/// </summary>
private void ApplyChanges()
{
if (EditorUtility.DisplayDialog("Confirm Apply Changes",
"Do you want to apply the following changes?", "Yes", "No"))
{
ApplyComponent<ConvaiActionsHandler>(_convaiNPC.IncludeActionsHandler);
ApplyComponent<ConvaiLipSync>(_convaiNPC.LipSync);
ApplyComponent<ConvaiHeadTracking>(_convaiNPC.HeadEyeTracking);
ApplyComponent<ConvaiBlinkingHandler>(_convaiNPC.EyeBlinking);
ApplyComponent<NarrativeDesignManager>(_convaiNPC.NarrativeDesignManager);
ApplyComponent<ConvaiGroupNPCController>(_convaiNPC.ConvaiGroupNPCController);
ApplyComponent<ConvaiLTMController>(_convaiNPC.LongTermMemoryController);
ApplyComponent<NarrativeDesignKeyController>(_convaiNPC.NarrativeDesignKeyController);
ApplyComponent<DynamicInfoController>(_convaiNPC.DynamicInfoController);
}
}
/// <summary>
/// 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.
/// </summary>
/// <typeparam name="T">The type of the component.</typeparam>
/// <param name="includeComponent">Whether to include the component.</param>
private void ApplyComponent<T>(bool includeComponent) where T : Component
{
T component = _convaiNPC.GetComponent<T>();
if (includeComponent)
{
if (component == null)
{
component = _convaiNPC.gameObject.AddComponentSafe<T>();
}
}
else if (component != null)
{
DestroyImmediate(component);
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1f84be99651944b69262e8060b8ac451
timeCreated: 1696842374

View File

@ -0,0 +1,107 @@
#if UNITY_EDITOR
using System;
using System.Text;
using Convai.Scripts.Runtime.Core;
using Convai.Scripts.Runtime.LoggerSystem;
using UnityEditor;
using UnityEngine;
namespace Convai.Scripts.Editor.NPC
{
/// <summary>
/// Custom editor for the ConvaiNPC component.
/// Provides functionalities to cache and restore states of all convai scripts whenever a scene is saved.
/// </summary>
[CustomEditor(typeof(ConvaiNPC))]
[HelpURL("https://docs.convai.com/api-docs/plugins-and-integrations/unity-plugin/scripts-overview")]
public class ConvaiNPCEditor : UnityEditor.Editor
{
private ConvaiNPC _convaiNPC;
private void OnEnable()
{
_convaiNPC = (ConvaiNPC)target;
}
/// <summary>
/// Overrides the default inspector GUI to add custom buttons and functionality.
/// </summary>
public override void OnInspectorGUI()
{
DrawDefaultInspector();
GUILayout.BeginHorizontal();
// Add Components button to add necessary components and assign a random color to the character.
if (GUILayout.Button(new GUIContent(
"Add Components",
"Adds necessary components to the NPC and assigns a random color to the character's text"
),
GUILayout.Width(120)
)
) AddComponentsToNPC();
if (GUILayout.Button(new GUIContent(
"Copy Debug",
"Copies the session id and other essential properties to clipboard for easier debugging"
),
GUILayout.Width(120)
)
) CopyToClipboard();
GUILayout.EndHorizontal();
}
private void CopyToClipboard()
{
StringBuilder stringBuilder = new();
stringBuilder.AppendLine($"Endpoint: {_convaiNPC.GetEndPointURL}");
stringBuilder.AppendLine($"Character ID: {_convaiNPC.characterID}");
stringBuilder.AppendLine($"Session ID: {_convaiNPC.sessionID}");
GUIUtility.systemCopyBuffer = stringBuilder.ToString();
}
/// <summary>
/// Adds components to the NPC and assigns a random color to the character's text.
/// </summary>
private void AddComponentsToNPC()
{
try
{
ConvaiNPCComponentSettingsWindow.Open(_convaiNPC);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
catch (Exception ex)
{
ConvaiLogger.Exception($"Unexpected error occurred when applying changes. Error: {ex}", ConvaiLogger.LogCategory.UI);
}
}
}
/// <summary>
/// Provides extension methods for Unity editor components.
/// </summary>
public static class EditorExtensions
{
/// <summary>
/// Adds a component to the GameObject safely, catching any exceptions that occur during the process.
/// </summary>
/// <param name="go">The GameObject to which the component will be added.</param>
/// <typeparam name="T">The type of the component to be added, derived from UnityEngine.Component.</typeparam>
/// <returns>The newly added component, or null if the operation failed.</returns>
public static T AddComponentSafe<T>(this GameObject go) where T : Component
{
try
{
return go.AddComponent<T>();
}
catch (Exception ex)
{
ConvaiLogger.Exception($"Failed to add component of type {typeof(T).Name}, Error: {ex}", ConvaiLogger.LogCategory.UI);
return null;
}
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4f2ab5d11b144b3aa5d8c371ea664c44
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: