update CCK to 3.10, fixing unity 2021 crash :)

This commit is contained in:
Crispy 2024-08-03 22:24:42 +02:00
parent 48a978fa2a
commit d11e0fb3a9
492 changed files with 2165204 additions and 437687 deletions

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 98b32b335c98486aacec87ab6497ba21
timeCreated: 1702781645

View file

@ -0,0 +1,154 @@
using System;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace ABI.CCK.Scripts.Editor.AssetProcessing
{
/*
public class CCK_AssetPostProcessor
{
#region Configuration
private const string KEY_PREFIX = "ABI.CCK.AssetPostProcessor.";
private static bool AutoHumanoid => EditorPrefs.GetBool("ABI_CCK_AssetPostProcessor_AutoHumanoid", false);
private static bool AutoReadWrite => EditorPrefs.GetBool("ABI_CCK_AssetPostProcessor_AutoReadWrite", false);
private static bool AutoBlendShapeNormals => EditorPrefs.GetBool("ABI_CCK_AssetPostProcessor_AutoBlendshapeNormals", false);
private static bool AutoTextureStreaming => EditorPrefs.GetBool("ABI_CCK_AssetPostProcessor_AutoTextureStreaming", false);
#endregion
private static bool _isProcessingModel;
private static ModelImporter _modelImporter;
private static PropertyInfo _legacyBlendShapeImporter;
private static PropertyInfo legacyBlendShapeImporter
{
get
{
if(_legacyBlendShapeImporter != null)
return _legacyBlendShapeImporter;
Type modelImporterType = typeof(ModelImporter);
_legacyBlendShapeImporter = modelImporterType.GetProperty(
"legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes",
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public
);
return _legacyBlendShapeImporter;
}
}
#region Asset Post Processing Events
private void OnPreprocessModel()
{
_isProcessingModel = false;
_modelImporter = assetImporter as ModelImporter;
if (_modelImporter == null)
return;
// Check if we have already processed this model
if (!ShouldProcessAsset(_modelImporter.assetPath, out string assetKey))
return;
_isProcessingModel = true;
SessionState.SetBool(assetKey, true);
SetModelImporterSettings(_modelImporter);
}
private void OnPostprocessMeshHierarchy(GameObject root)
{
if (!_isProcessingModel)
return;
if (!AutoHumanoid)
return;
// Check if the model should be humanoid
var childTransforms = root.GetComponentsInChildren<Transform>();
// Check if the model has enough bones to be humanoid
if (childTransforms.Length < HumanTrait.RequiredBoneCount)
return;
// Check if the model has enough *potential* humanoid bones to be humanoid
int potentialHumanBoneCount = childTransforms.Count(childTransform =>
childTransform.name.IndexOf("armature", StringComparison.OrdinalIgnoreCase) >= 0 ||
childTransform.name.IndexOf("hip", StringComparison.OrdinalIgnoreCase) >= 0 ||
childTransform.name.IndexOf("hand", StringComparison.OrdinalIgnoreCase) >= 0 ||
childTransform.name.IndexOf("head", StringComparison.OrdinalIgnoreCase) >= 0);
// IKSystem will still filter it if it doesn't have enough bones
// VRIK requires hips to head, arms, and either both legs or neither leg.
if (potentialHumanBoneCount < 3)
return;
_modelImporter.animationType = ModelImporterAnimationType.Human;
}
private void OnPreprocessTexture()
{
TextureImporter textureImporter = assetImporter as TextureImporter;
if (textureImporter == null)
return;
if (!ShouldProcessAsset(textureImporter.assetPath, out string assetKey))
return;
SessionState.SetBool(assetKey, true);
SetTextureImporterSettings(textureImporter);
}
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
foreach (string deletedAsset in deletedAssets)
{
string assetKey = KEY_PREFIX + AssetDatabase.AssetPathToGUID(deletedAsset);
SessionState.EraseBool(assetKey); // Remove the asset from the list of processed assets, so it can be processed again if re-imported
CCK_AutoCleanupProcessor.OnProcessDeletedAsset(deletedAsset);
}
}
#endregion
#region Private Methods
private static bool ShouldProcessAsset(string assetPath, out string assetKey)
{
assetKey = KEY_PREFIX + AssetDatabase.AssetPathToGUID(assetPath);
return !SessionState.GetBool(assetKey, false);
}
// TODO: Is there anything else we need to set?
private static void SetModelImporterSettings(ModelImporter modelImporter)
{
if (AutoReadWrite)
modelImporter.isReadable = true;
if (AutoBlendShapeNormals)
modelImporter.importBlendShapeNormals = ModelImporterNormals.Import;
//if(modelImporter.importBlendShapeNormals != ModelImporterNormals.Calculate)
legacyBlendShapeImporter.SetValue(modelImporter, true);
}
private static void SetTextureImporterSettings(TextureImporter textureImporter)
{
if (AutoTextureStreaming)
textureImporter.streamingMipmaps = true;
}
#endregion
}
*/
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 983fdec8b2554916a318d13c3cc189a5
timeCreated: 1702781676

View file

@ -0,0 +1,59 @@
using UnityEditor;
namespace ABI.CCK.Scripts.Editor.AssetProcessing
{
/// <summary>
/// Cleans up scripting symbols that were added by the CCK when the CCK is deleted.
/// This is done to prevent Third Party scripts from spewing compile errors when doing a fresh import or uninstall.
/// </summary>
public static class CCK_AutoCleanupProcessor
{
private const string CCK_ROOT_FOLDER = "Assets/ABI.CCK";
// All scripting symbols that can be added by the CCK
private static readonly string[] CCK_SCRIPTING_SYMBOLS =
{
"CVR_CCK_EXISTS",
// third party addons
"CCK_ADDIN_TRANSLATABLE_TMP",
"CCK_ADDIN_HIGHLIGHT_PLUS",
"CCK_ADDIN_MAGICACLOTHSUPPORT"
};
internal static void OnProcessDeletedAsset(string deletedAsset)
{
if (deletedAsset == CCK_ROOT_FOLDER)
OnCCKLikelyDeleted();
}
private static void OnCCKLikelyDeleted()
{
// Remove for BuildTargetGroups
var selectedBuildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup; // just in case somehow user is on unsupported build target group
var buildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.Android, selectedBuildTargetGroup };
foreach (BuildTargetGroup buildTargetGroup in buildTargetGroups)
{
var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);
foreach (var scriptingSymbol in CCK_SCRIPTING_SYMBOLS)
if (defines.Contains(scriptingSymbol)) // remove all CCK scripting symbols
defines = defines.Replace(scriptingSymbol, "");
PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, defines);
}
// Remove for NamedBuildTarget ???
// var buildTargets = new[] { NamedBuildTarget.Standalone, NamedBuildTarget.Android };
// foreach (NamedBuildTarget buildTarget in buildTargets)
// {
// var defines = PlayerSettings.GetScriptingDefineSymbols(buildTarget);
//
// foreach (var scriptingSymbol in CCK_SCRIPTING_SYMBOLS)
// if (defines.Contains(scriptingSymbol)) // remove all CCK scripting symbols
// defines = defines.Replace(scriptingSymbol, "");
//
// PlayerSettings.SetScriptingDefineSymbols(buildTarget, defines);
// }
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a1f6a40517314d64bed4c4d97905ccdc
timeCreated: 1703188866

View file

@ -1,257 +1,266 @@
using System;
using System.Collections.Generic;
using ABI.CCK.Components;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using AnimatorController = UnityEditor.Animations.AnimatorController;
using AnimatorControllerParameter = UnityEngine.AnimatorControllerParameter;
using AnimatorControllerParameterType = UnityEngine.AnimatorControllerParameterType;
[CustomEditor(typeof(ABI.CCK.Components.AnimatorDriver))]
public class CCK_AnimatorDriverEditor : UnityEditor.Editor
[CustomEditor(typeof(AnimatorDriver))]
public class CCK_AnimatorDriverEditor : Editor
{
private AnimatorDriver _animatorDriver;
private ReorderableList _onEnterList;
private ReorderableList _onExitList;
private List<string> animatorParamNames = new List<string>();
private List<string> animatorParamNamesDisplay = new List<string>();
private List<AnimatorDriverTask.ParameterType> animatorParamTypes = new List<AnimatorDriverTask.ParameterType>();
private readonly List<string> _animatorParamNames = new List<string>();
private readonly List<AnimatorDriverTask.ParameterType> _animatorParamTypes = new List<AnimatorDriverTask.ParameterType>();
public override void OnInspectorGUI()
private bool _showLocalOnlyHelp;
private bool _isInPlayMode;
#region Unity Events
private void OnEnable()
{
if (_animatorDriver == null) _animatorDriver = (AnimatorDriver) target;
if (target == null) return;
_animatorDriver = (AnimatorDriver)target;
animatorParamNames.Clear();
animatorParamNamesDisplay.Clear();
animatorParamTypes.Clear();
animatorParamNames.Add("- None -");
animatorParamNamesDisplay.Add("- None -");
animatorParamTypes.Add(AnimatorDriverTask.ParameterType.None);
_isInPlayMode = Application.isPlaying;
_animatorParamNames.Clear();
_animatorParamTypes.Clear();
// TODO: add parameter type display in parameter dropdown
var behaviorContext = AnimatorController.FindStateMachineBehaviourContext(_animatorDriver);
if (behaviorContext.Length > 0)
{
var controller = behaviorContext[0].animatorController;
foreach (var parameter in controller.parameters)
AnimatorController controller = behaviorContext[0].animatorController;
foreach (AnimatorControllerParameter parameter in controller.parameters)
{
switch (parameter.type)
{
case AnimatorControllerParameterType.Bool:
animatorParamNames.Add($"{parameter.name}");
animatorParamNamesDisplay.Add($"{parameter.name} (Bool)");
animatorParamTypes.Add(AnimatorDriverTask.ParameterType.Bool);
_animatorParamNames.Add($"{parameter.name}");
_animatorParamTypes.Add(AnimatorDriverTask.ParameterType.Bool);
break;
case AnimatorControllerParameterType.Float:
animatorParamNames.Add($"{parameter.name}");
animatorParamNamesDisplay.Add($"{parameter.name} (Float)");
animatorParamTypes.Add(AnimatorDriverTask.ParameterType.Float);
_animatorParamNames.Add($"{parameter.name}");
_animatorParamTypes.Add(AnimatorDriverTask.ParameterType.Float);
break;
case AnimatorControllerParameterType.Int:
animatorParamNames.Add($"{parameter.name}");
animatorParamNamesDisplay.Add($"{parameter.name} (Int)");
animatorParamTypes.Add(AnimatorDriverTask.ParameterType.Int);
_animatorParamNames.Add($"{parameter.name}");
_animatorParamTypes.Add(AnimatorDriverTask.ParameterType.Int);
break;
case AnimatorControllerParameterType.Trigger:
animatorParamNames.Add($"{parameter.name}");
animatorParamNamesDisplay.Add($"{parameter.name} (Trigger)");
animatorParamTypes.Add(AnimatorDriverTask.ParameterType.Trigger);
_animatorParamNames.Add($"{parameter.name}");
_animatorParamTypes.Add(AnimatorDriverTask.ParameterType.Trigger);
break;
}
}
}
if (_onEnterList == null)
{
_onEnterList = new ReorderableList(_animatorDriver.EnterTasks, typeof(AnimatorDriverTask),
true, true, true, true);
_onEnterList.drawHeaderCallback = OnDrawHeaderTaskEnter;
_onEnterList.drawElementCallback = OnDrawElementTaskEnter;
_onEnterList.elementHeightCallback = OnHeightElementTaskEnter;
true, true, !_isInPlayMode, !_isInPlayMode)
{
drawHeaderCallback = OnDrawHeaderTaskEnter,
drawElementCallback = OnDrawElementTaskEnter,
elementHeightCallback = OnHeightElementTaskEnter
};
}
_onEnterList.DoLayoutList();
if (_onExitList == null)
{
_onExitList = new ReorderableList(_animatorDriver.ExitTasks, typeof(AnimatorDriverTask),
true, true, true, true);
_onExitList.drawHeaderCallback = OnDrawHeaderTaskExit;
_onExitList.drawElementCallback = OnDrawElementTaskExit;
_onExitList.elementHeightCallback = OnHeightElementTaskExit;
true, true, !_isInPlayMode, !_isInPlayMode)
{
drawHeaderCallback = OnDrawHeaderTaskExit,
drawElementCallback = OnDrawElementTaskExit,
elementHeightCallback = OnHeightElementTaskExit
};
}
}
public override void OnInspectorGUI()
{
if (_animatorDriver == null)
return;
EditorGUI.BeginChangeCheck();
using (new EditorGUILayout.VerticalScope(new GUIStyle() { padding = new RectOffset(10, 10, 10, 10) }))
{
DrawLocalOnlyToggle();
DrawTaskLists();
}
if (EditorGUI.EndChangeCheck())
EditorUtility.SetDirty(_animatorDriver);
}
#endregion
#region GUI Drawing
private void DrawLocalOnlyToggle()
{
using (new EditorGUILayout.HorizontalScope())
{
_animatorDriver.localOnly = EditorGUILayout.Toggle("Local Only", _animatorDriver.localOnly);
if (GUILayout.Button("?", GUILayout.Width(25)))
_showLocalOnlyHelp = !_showLocalOnlyHelp;
GUILayout.Space(5);
}
if (_showLocalOnlyHelp)
{
// TODO: Add to LocalizationProvider
EditorGUILayout.HelpBox("When 'Local Only' is enabled, the animator driver is executed locally and not for remote users.", MessageType.Info);
EditorGUILayout.Space(5);
EditorGUILayout.HelpBox("Avatars: Only the wearer.\nSpawnables: Only the prop's owner.\nWorlds: This option is ignored.", MessageType.Info);
}
EditorGUILayout.Space();
}
private void DrawTaskLists()
{
EditorGUILayout.Space();
_onEnterList.DoLayoutList();
EditorGUILayout.Space();
_onExitList.DoLayoutList();
}
#endregion
#region ReorderableList Drawing
private void OnDrawHeaderTaskEnter(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "On Enter State");
Rect labelRect = new Rect(rect.x, rect.y, rect.width - 35, EditorGUIUtility.singleLineHeight);
GUI.Label(labelRect, "On Enter Tasks");
EditorGUIExtensions.UtilityMenu(rect, _onEnterList,
appendAdditionalMenuItems: (menuBuilder, list) => {
AppendComponentMenu(menuBuilder, list, true);
});
}
private void OnDrawElementTaskEnter(Rect rect, int index, bool isactive, bool isfocused)
{
if (index > _animatorDriver.EnterTasks.Count) return;
if (index >= _animatorDriver.EnterTasks.Count) return;
AnimatorDriverTask element = _animatorDriver.EnterTasks[index];
RenderTask(rect, element);
using (new EditorGUI.DisabledScope(_isInPlayMode))
RenderTask(rect, element);
}
private float OnHeightElementTaskEnter(int index)
{
int length = 3;
const int length = 3;
if (index >= _animatorDriver.EnterTasks.Count)
return 1.25f * length * EditorGUIUtility.singleLineHeight;
if (index > _animatorDriver.EnterTasks.Count) return 1.25f * length * EditorGUIUtility.singleLineHeight;
AnimatorDriverTask task = _animatorDriver.EnterTasks[index];
return (length + TaskHeight(task)) * 1.25f * EditorGUIUtility.singleLineHeight;
}
private void OnDrawHeaderTaskExit(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "On Exit State");
Rect labelRect = new Rect(rect.x, rect.y, rect.width - 35, EditorGUIUtility.singleLineHeight);
GUI.Label(labelRect, "On Exit Tasks");
EditorGUIExtensions.UtilityMenu(rect, _onExitList,
appendAdditionalMenuItems: (menuBuilder, list) => {
AppendComponentMenu(menuBuilder, list, false);
});
}
private void OnDrawElementTaskExit(Rect rect, int index, bool isactive, bool isfocused)
{
if (index > _animatorDriver.ExitTasks.Count) return;
if (index >= _animatorDriver.ExitTasks.Count) return;
AnimatorDriverTask element = _animatorDriver.ExitTasks[index];
RenderTask(rect, element);
using (new EditorGUI.DisabledScope(_isInPlayMode))
RenderTask(rect, element);
}
private float OnHeightElementTaskExit(int index)
{
int length = 3;
const int length = 3;
if (index >= _animatorDriver.ExitTasks.Count)
return 1.25f * length * EditorGUIUtility.singleLineHeight;
if (index > _animatorDriver.ExitTasks.Count) return 1.25f * length * EditorGUIUtility.singleLineHeight;
AnimatorDriverTask task = _animatorDriver.ExitTasks[index];
return (length + TaskHeight(task)) * 1.25f * EditorGUIUtility.singleLineHeight;
}
#endregion
#region AnimatorDriverTask Drawing
private int TaskHeight(AnimatorDriverTask task)
{
int length = 0;
switch (task.aType)
{
case AnimatorDriverTask.SourceType.Static:
case AnimatorDriverTask.SourceType.Parameter:
length += 1;
break;
case AnimatorDriverTask.SourceType.Random:
length += 2;
break;
}
if (task.op != AnimatorDriverTask.Operator.Set)
{
int length = 2;
if (task.aType == AnimatorDriverTask.SourceType.Random)
length += 1;
switch (task.bType)
{
case AnimatorDriverTask.SourceType.Static:
case AnimatorDriverTask.SourceType.Parameter:
length += 1;
break;
case AnimatorDriverTask.SourceType.Random:
length += 2;
break;
}
}
length += 1;
if (task.op == AnimatorDriverTask.Operator.Set)
return length;
length += task.bType == AnimatorDriverTask.SourceType.Random ? 3 : 2;
return length;
}
private void RenderTask(Rect rect, AnimatorDriverTask task)
{
string formulaDisplay = "";
Rect _rect = new Rect(rect.x, rect.y + 2, rect.width, EditorGUIUtility.singleLineHeight);
Rect _rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
float spacing = EditorGUIUtility.singleLineHeight * 1.25f;
float originalLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 100;
int parameterIndex = Math.Max(animatorParamNames.FindIndex(m => m == task.targetName), 0);
EditorGUI.LabelField(_rect, "Parameter");
_rect.x += 100;
_rect.width = rect.width - 100;
int selectedIndex = EditorGUI.Popup(_rect, parameterIndex, animatorParamNamesDisplay.ToArray());
task.targetType = animatorParamTypes[selectedIndex];
task.targetName = animatorParamNames[selectedIndex];
task.targetName = EditorGUIExtensions.AdvancedDropdownInput(_rect, task.targetName, _animatorParamNames,
"Parameter", "No Parameters");
_rect.y += spacing;
var formulaDisplay = $"{task.targetName} = ";
int parameterIndex = Math.Max(_animatorParamNames.FindIndex(m => m == task.targetName), 0);
if (_animatorParamNames.Count != 0 && _animatorParamTypes.Count >= parameterIndex)
task.targetType = _animatorParamTypes[parameterIndex];
task.op = (AnimatorDriverTask.Operator)EditorGUI.EnumPopup(_rect, "Operation", task.op);
_rect.y += spacing;
formulaDisplay = $"{task.targetName} = ";
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Operation");
_rect.x += 100;
_rect.width = rect.width - 100;
task.op = (AnimatorDriverTask.Operator) EditorGUI.EnumPopup(_rect, task.op);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "A Type");
_rect.x += 100;
_rect.width = rect.width - 100;
task.aType = (AnimatorDriverTask.SourceType) EditorGUI.EnumPopup(_rect, task.aType);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
task.aType = (AnimatorDriverTask.SourceType)EditorGUI.EnumPopup(_rect, "A Type", task.aType);
_rect.y += spacing;
switch (task.aType)
{
case AnimatorDriverTask.SourceType.Static:
EditorGUI.LabelField(_rect, "A Value");
_rect.x += 100;
_rect.width = rect.width - 100;
task.aValue = EditorGUI.FloatField(_rect, task.aValue);
task.aValue = EditorGUI.FloatField(_rect, "A Value", task.aValue);
_rect.y += spacing;
formulaDisplay += $"{task.aValue} ";
break;
case AnimatorDriverTask.SourceType.Parameter:
parameterIndex = Math.Max(animatorParamNames.FindIndex(m => m == task.aName), 0);
EditorGUI.LabelField(_rect, "Parameter A");
_rect.x += 100;
_rect.width = rect.width - 100;
selectedIndex = EditorGUI.Popup(_rect, parameterIndex, animatorParamNamesDisplay.ToArray());
task.aParamType = animatorParamTypes[selectedIndex];
task.aName = animatorParamNames[selectedIndex];
task.aName = EditorGUIExtensions.AdvancedDropdownInput(_rect, task.aName, _animatorParamNames,
"Parameter A", "No Parameters");
_rect.y += spacing;
parameterIndex = Math.Max(_animatorParamNames.FindIndex(m => m == task.aName), 0);
task.aParamType = _animatorParamTypes[parameterIndex];
formulaDisplay += $"{task.aName} ";
break;
case AnimatorDriverTask.SourceType.Random:
EditorGUI.LabelField(_rect, "A Min");
_rect.x += 100;
_rect.width = rect.width - 100;
task.aValue = EditorGUI.FloatField(_rect, task.aValue);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "A Max");
_rect.x += 100;
_rect.width = rect.width - 100;
task.aMax = Convert.ToSingle(EditorGUI.TextField(_rect, task.aMax.ToString()));
task.aValue = EditorGUI.FloatField(_rect, "A Min", task.aValue);
_rect.y += spacing;
task.aMax = EditorGUI.FloatField(_rect, "A Max", task.aMax);
_rect.y += spacing;
formulaDisplay += $"Rand({task.aValue}, {task.aMax}) ";
break;
}
if (task.op != AnimatorDriverTask.Operator.Set)
{
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
switch (task.op)
{
case AnimatorDriverTask.Operator.Addition:
@ -295,59 +304,81 @@ public class CCK_AnimatorDriverEditor : UnityEditor.Editor
break;
}
EditorGUI.LabelField(_rect, "B Type");
_rect.x += 100;
_rect.width = rect.width - 100;
task.bType = (AnimatorDriverTask.SourceType) EditorGUI.EnumPopup(_rect, task.bType);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
task.bType = (AnimatorDriverTask.SourceType) EditorGUI.EnumPopup(_rect, "B Type", task.bType);
_rect.y += spacing;
switch (task.bType)
{
case AnimatorDriverTask.SourceType.Static:
EditorGUI.LabelField(_rect, "B Value");
_rect.x += 100;
_rect.width = rect.width - 100;
task.bValue = EditorGUI.FloatField(_rect, task.bValue);
task.bValue = EditorGUI.FloatField(_rect, "B Value", task.bValue);
_rect.y += spacing;
formulaDisplay += $"{task.bValue} ";
break;
case AnimatorDriverTask.SourceType.Parameter:
parameterIndex = Math.Max(animatorParamNames.FindIndex(m => m == task.bName), 0);
EditorGUI.LabelField(_rect, "Parameter B");
_rect.x += 100;
_rect.width = rect.width - 100;
selectedIndex = EditorGUI.Popup(_rect, parameterIndex, animatorParamNamesDisplay.ToArray());
task.bParamType = animatorParamTypes[selectedIndex];
task.bName = animatorParamNames[selectedIndex];
task.bName = EditorGUIExtensions.AdvancedDropdownInput(_rect, task.bName, _animatorParamNames,
"Parameter B", "No Parameters");
_rect.y += spacing;
parameterIndex = Math.Max(_animatorParamNames.FindIndex(m => m == task.bName), 0);
task.bParamType = _animatorParamTypes[parameterIndex];
formulaDisplay += $"{task.bName} ";
break;
case AnimatorDriverTask.SourceType.Random:
EditorGUI.LabelField(_rect, "B Min");
_rect.x += 100;
_rect.width = rect.width - 100;
task.bValue = EditorGUI.FloatField(_rect, task.bValue);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "B Max");
_rect.x += 100;
_rect.width = rect.width - 100;
task.bMax = Convert.ToSingle(EditorGUI.TextField(_rect, task.bMax.ToString()));
task.bValue = EditorGUI.FloatField(_rect, "B Min", task.bValue);
_rect.y += spacing;
task.bMax = EditorGUI.FloatField(_rect, "B Max", task.bMax);
_rect.y += spacing;
formulaDisplay += $"Rand({task.bValue}, {task.bMax}) ";
break;
}
}
EditorGUI.LabelField(_rect, task.targetName == "" ? "No Parameter" : formulaDisplay,
new GUIStyle(GUI.skin.label) { fontStyle = FontStyle.Bold });
var boldtext = new GUIStyle (GUI.skin.label);
boldtext.fontStyle = FontStyle.Bold;
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, task.targetName == "- None -"?"Parameter = A":formulaDisplay, boldtext);
EditorGUIUtility.labelWidth = originalLabelWidth;
}
#endregion
#region Utility
private void AppendComponentMenu(GenericMenuBuilder genericMenuBuilder, ReorderableList list, bool isEnterList)
{
bool hasSelectedTask = list.index != -1;
bool hasTasks = list.count > 0;
if (isEnterList)
{
genericMenuBuilder.AddMenuItem("To Exit Task", hasTasks && hasSelectedTask, () => ConvertSelectedTask(list, _animatorDriver.EnterTasks, _animatorDriver.ExitTasks));
genericMenuBuilder.AddMenuItem("All to Exit Task", hasTasks, ConvertAllTasksToExit);
}
else
{
genericMenuBuilder.AddMenuItem("To Enter Task", hasTasks && hasSelectedTask, () => ConvertSelectedTask(list, _animatorDriver.ExitTasks, _animatorDriver.EnterTasks));
genericMenuBuilder.AddMenuItem("All to Enter Task", hasTasks, ConvertAllTasksToEnter);
}
}
private void ConvertAllTasksToEnter()
{
_animatorDriver.EnterTasks.AddRange(_animatorDriver.ExitTasks);
_animatorDriver.ExitTasks.Clear();
}
private void ConvertAllTasksToExit()
{
_animatorDriver.ExitTasks.AddRange(_animatorDriver.EnterTasks);
_animatorDriver.EnterTasks.Clear();
}
private void ConvertSelectedTask(ReorderableList list, List<AnimatorDriverTask> fromTasks, List<AnimatorDriverTask> toTasks)
{
if (list.index == -1 || list.index >= fromTasks.Count) return;
AnimatorDriverTask selectedTask = fromTasks[list.index];
fromTasks.RemoveAt(list.index);
toTasks.Add(selectedTask);
}
#endregion
}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a6cfbda11115dfa408061903c1760818
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,57 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using ABI.CCK.Scripts;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEngine;
namespace ABI.CCK.Components
{
[CanEditMultipleObjects]
[CustomEditor(typeof(BodyControl))]
public partial class CCK_BodyControlEditor : Editor
{
#region Variables
private BodyControl _bodyControl;
#endregion
#region Serialized Properties
private SerializedProperty m_EnterTasksProp;
private SerializedProperty m_ExitTasksProp;
#endregion
#region Unity Events
private void OnEnable()
{
if (target == null) return;
_bodyControl = (BodyControl)target;
m_EnterTasksProp = serializedObject.FindProperty(nameof(BodyControl.EnterTasks));
m_ExitTasksProp = serializedObject.FindProperty(nameof(BodyControl.ExitTasks));
Initialize_TaskLists();
}
public override void OnInspectorGUI()
{
if (_bodyControl == null)
return;
serializedObject.Update();
Draw_Tasks();
serializedObject.ApplyModifiedProperties();
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,357 @@
#if UNITY_EDITOR
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using ABI.CCK.Scripts.Editor;
using ABI.CCK.Scripts.Editor.Tools;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
namespace ABI.CCK.Components
{
public partial class CCK_BodyControlEditor
{
private ReorderableList _onEnterList;
private ReorderableList _onExitList;
private int _selectedEnterEntry = -1;
private int _selectedExitEntry = -1;
private bool _isInPlayMode;
private void Initialize_TaskLists()
{
_isInPlayMode = Application.isPlaying;
_onEnterList ??= new ReorderableList(serializedObject, m_EnterTasksProp,
true, true, !_isInPlayMode, !_isInPlayMode)
{
drawHeaderCallback = OnDrawHeaderTaskEnter,
drawElementCallback = OnDrawElementTaskEnter,
elementHeightCallback = OnHeightElementTaskEnter,
onAddCallback = OnAddElement,
onMouseUpCallback = OnMouseUpEnter,
//multiSelect = true, // TODO: Can we implement changing multiple tasks at once?
list = _bodyControl.EnterTasks,
index = -1
};
_onExitList ??= new ReorderableList(serializedObject, m_ExitTasksProp,
true, true, !_isInPlayMode, !_isInPlayMode)
{
drawHeaderCallback = OnDrawHeaderTaskExit,
drawElementCallback = OnDrawElementTaskExit,
elementHeightCallback = OnHeightElementTaskExit,
onAddCallback = OnAddElement,
onMouseUpCallback = OnMouseUpExit,
list = _bodyControl.ExitTasks,
index = -1
};
}
private void Draw_Tasks()
{
using (new EditorGUILayout.VerticalScope(new GUIStyle() { padding = new RectOffset(10, 10, 10, 10) }))
{
EditorGUILayout.Space();
_onEnterList.displayAdd = CanAddTarget(_onEnterList.list as IEnumerable<BodyControlTask>);
_onEnterList.DoLayoutList();
EditorGUILayout.Space();
_onExitList.displayAdd = CanAddTarget(_onExitList.list as IEnumerable<BodyControlTask>);
_onExitList.DoLayoutList();
}
}
#region ReorderableList Callbacks
// Enter Tasks
private void OnDrawHeaderTaskEnter(Rect rect)
{
Rect labelRect = new Rect(rect.x, rect.y, rect.width - 35, EditorGUIUtility.singleLineHeight);
GUI.Label(labelRect, "On Enter Tasks");
EditorGUIExtensions.UtilityMenu(rect, _onEnterList, m_EnterTasksProp,
appendAdditionalMenuItems: (menuBuilder, list) => {
AppendUtilityMenu(menuBuilder, _onEnterList, true);
});
}
private void OnDrawElementTaskEnter(Rect rect, int index, bool isactive, bool isfocused)
{
if (index >= _bodyControl.EnterTasks.Count) return;
SerializedProperty taskProperty = _onEnterList.serializedProperty.GetArrayElementAtIndex(index);
if (taskProperty == null || index >= _onEnterList.serializedProperty.arraySize)
return;
using (new EditorGUI.DisabledScope(_isInPlayMode))
RenderTask(rect, _onEnterList, taskProperty);
}
private float OnHeightElementTaskEnter(int index)
{
float lineHeight = EditorGUIUtility.singleLineHeight * 1.25f;
if (index < 0 || index >= _bodyControl.EnterTasks.Count)
return lineHeight;
BodyControlTask task = _bodyControl.EnterTasks[index];
return TaskLines(task) * lineHeight;
}
private void OnMouseUpEnter(ReorderableList list)
{
if (list.index != _selectedEnterEntry)
{
_selectedEnterEntry = list.index;
}
else
{
if (list.index == -1)
return;
list.Deselect(_selectedEnterEntry);
list.index = _selectedEnterEntry = -1;
Repaint();
}
}
// Exit Tasks
private void OnDrawHeaderTaskExit(Rect rect)
{
Rect labelRect = new Rect(rect.x, rect.y, rect.width - 35, EditorGUIUtility.singleLineHeight);
GUI.Label(labelRect, "On Exit Tasks");
EditorGUIExtensions.UtilityMenu(rect, _onExitList, m_ExitTasksProp,
appendAdditionalMenuItems: (menuBuilder, list) => {
AppendUtilityMenu(menuBuilder, _onExitList, false);
});
}
private void OnDrawElementTaskExit(Rect rect, int index, bool isactive, bool isfocused)
{
if (index >= _bodyControl.ExitTasks.Count) return;
SerializedProperty taskProperty = _onExitList.serializedProperty.GetArrayElementAtIndex(index);
if (taskProperty == null || index >= _onExitList.serializedProperty.arraySize)
return;
using (new EditorGUI.DisabledScope(_isInPlayMode))
RenderTask(rect, _onExitList, taskProperty);
}
private float OnHeightElementTaskExit(int index)
{
float lineHeight = EditorGUIUtility.singleLineHeight * 1.25f;
if (index < 0 || index >= _bodyControl.ExitTasks.Count)
return lineHeight;
BodyControlTask task = _bodyControl.ExitTasks[index];
return TaskLines(task) * lineHeight;
}
private void OnMouseUpExit(ReorderableList list)
{
if (list.index != _selectedExitEntry)
{
_selectedExitEntry = list.index;
}
else
{
if (list.index == -1)
return;
list.Deselect(_selectedExitEntry);
list.index = _selectedExitEntry = -1;
Repaint();
}
}
// Shared
private void OnAddElement(ReorderableList list)
{
int targetIndex = list.count;
list.serializedProperty.InsertArrayElementAtIndex(targetIndex);
// list.list is the direct list of tasks
int nextTarget = 0; // get the first target that isn't already in use
while (list.list.Cast<BodyControlTask>().Any(task => task.target == (BodyControlTask.BodyMask)nextTarget))
nextTarget++;
list.serializedProperty.GetArrayElementAtIndex(targetIndex).FindPropertyRelative(nameof(BodyControlTask.target)).intValue = nextTarget;
// select it
list.index = targetIndex;
}
#endregion
#region BodyControlTask Drawing
private int TaskLines(BodyControlTask task)
{
int length = 1;
if (task.isBlend)
length += 2;
return length;
}
private void RenderTask(Rect rect, ReorderableList list, SerializedProperty taskProperty)
{
rect = new Rect(rect.x, rect.y + 2, rect.width, EditorGUIUtility.singleLineHeight);
float spacing = EditorGUIUtility.singleLineHeight * 1.25f;
float originalLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 100;
SerializedProperty targetProp = taskProperty.FindPropertyRelative(nameof(BodyControlTask.target));
SerializedProperty targetWeightProp = taskProperty.FindPropertyRelative(nameof(BodyControlTask.targetWeight));
SerializedProperty transitionDurationProp = taskProperty.FindPropertyRelative(nameof(BodyControlTask.transitionDuration));
SerializedProperty isBlendProp = taskProperty.FindPropertyRelative(nameof(BodyControlTask.isBlend));
// Draw setting type dropdowns
EditorGUILayout.BeginHorizontal();
Rect position = rect;
float halfWidth = (position.width) / 2 - 2;
// Target Dropdown
// display popup of targets that are not already in use in the list
var availableTargets = GetAvailableTargets(list.list as IEnumerable<BodyControlTask>, targetProp);
int selectedIndex = EditorGUI.Popup(new Rect(position.x, position.y, halfWidth, position.height), availableTargets.IndexOf((BodyControlTask.BodyMask)targetProp.intValue), availableTargets.Select(t => t.ToString()).ToArray());
if (selectedIndex >= 0) targetProp.intValue = (int)availableTargets[selectedIndex];
// Type Dropdown
int selectedOption = isBlendProp.boolValue switch
{
true => 2,
_ => targetWeightProp.floatValue switch
{
0f => 1, // On
1f => 0, // Off
_ => 2 // Blend
}
};
selectedOption =
EditorGUI.Popup(new Rect(position.x + halfWidth + 4, position.y, halfWidth, position.height),
selectedOption, new [] { "Enabled", "Disabled" /*, "Blend" */ });
isBlendProp.boolValue = selectedOption == 2;
targetWeightProp.floatValue = selectedOption switch
{
0 => 1f, // On
1 => 0f, // Off
_ => targetWeightProp.floatValue // Blend
};
EditorGUILayout.EndHorizontal();
if (selectedOption == 2)
{
rect.y += spacing;
EditorGUI.PropertyField(rect, targetWeightProp);
rect.y += spacing;
EditorGUI.PropertyField(rect, transitionDurationProp, new GUIContent("Transition (s)"));
}
EditorGUIUtility.labelWidth = originalLabelWidth;
}
private static bool CanAddTarget(IEnumerable<BodyControlTask> tasks)
{
var allTargets = Enum.GetValues(typeof(BodyControlTask.BodyMask)).Cast<BodyControlTask.BodyMask>().ToList();
var usedTargets = tasks.Select(task => task.target).Distinct().ToList();
return allTargets.Except(usedTargets).Any();
}
private static List<BodyControlTask.BodyMask> GetAvailableTargets(IEnumerable<BodyControlTask> tasks, SerializedProperty targetProp)
{
var allTargets = Enum.GetValues(typeof(BodyControlTask.BodyMask)).Cast<BodyControlTask.BodyMask>().ToList();
var usedTargets = tasks.Select(task => task.target).Distinct().ToList();
var availableTargets = allTargets.Where(target => !usedTargets.Contains(target)).ToList();
if (targetProp.intValue >= 0 && !availableTargets.Contains((BodyControlTask.BodyMask)targetProp.intValue))
availableTargets.Add((BodyControlTask.BodyMask)targetProp.intValue);
return availableTargets;
}
#endregion
#region Utility
private void AppendUtilityMenu(GenericMenuBuilder genericMenuBuilder, ReorderableList list, bool isEnterList)
{
bool hasSelectedTask = list.index != -1;
bool hasTasks = list.count > 0;
genericMenuBuilder.AddMenuItem("Set All Enabled", hasTasks, () => SetAllTasksState(list, 1f));
genericMenuBuilder.AddMenuItem("Set All Disabled", hasTasks, () => SetAllTasksState(list, 0f));
genericMenuBuilder.AddSeparator();
string moveToOtherListLabel = isEnterList ? "To Exit Task" : "To Enter Task";
genericMenuBuilder.AddMenuItem(moveToOtherListLabel, hasTasks && hasSelectedTask,
() => ConvertSelectedTask(list, isEnterList ? _bodyControl.EnterTasks : _bodyControl.ExitTasks,
isEnterList ? _bodyControl.ExitTasks : _bodyControl.EnterTasks));
string convertAllLabel = isEnterList ? "All to Exit Task" : "All to Enter Task";
genericMenuBuilder.AddMenuItem(convertAllLabel, hasTasks,
() => ConvertAllTasks(isEnterList ? _bodyControl.EnterTasks : _bodyControl.ExitTasks,
isEnterList ? _bodyControl.ExitTasks : _bodyControl.EnterTasks));
}
private void ConvertAllTasks(List<BodyControlTask> fromTasks, List<BodyControlTask> toTasks)
{
foreach (BodyControlTask task in fromTasks)
{
BodyControlTask existingTask = toTasks.FirstOrDefault(t => t.target == task.target);
if (existingTask != null)
{
existingTask.targetWeight = task.targetWeight;
}
else
{
toTasks.Add(task);
}
}
fromTasks.Clear();
}
private void ConvertSelectedTask(ReorderableList list, List<BodyControlTask> fromTasks, List<BodyControlTask> toTasks)
{
if (list.index == -1 || list.index >= fromTasks.Count)
return;
BodyControlTask selectedTask = fromTasks[list.index];
BodyControlTask existingTask = toTasks.FirstOrDefault(t => t.target == selectedTask.target);
if (existingTask != null)
{
existingTask.targetWeight = selectedTask.targetWeight;
}
else
{
toTasks.Add(selectedTask);
}
fromTasks.RemoveAt(list.index);
}
private void SetAllTasksState(ReorderableList list, float stateValue)
{
IList tasks = list.list;
foreach (BodyControlTask task in tasks) task.targetWeight = stateValue;
}
#endregion
}
}
#endif

View file

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

View file

@ -2,58 +2,38 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.Xml.XPath;
using ABI.CCK.Components;
using ABI.CCK.Scripts.Runtime;
using Abi.Newtonsoft.Json;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
namespace ABI.CCK.Scripts.Editor
{
[InitializeOnLoad]
public class CCK_BuildManagerWindow : EditorWindow
{
public static string Version = "3.5 RELEASE";
public static int BuildID = 98;
private const string CCKVersion = "3.5 RELEASE (Build 98)";
private string[] SupportedUnityVersions = new[]
{
"2019.4.0f1", "2019.4.1f1", "2019.4.2f1", "2019.4.3f1", "2019.4.4f1", "2019.4.5f1", "2019.4.6f1",
"2019.4.7f1", "2019.4.8f1", "2019.4.9f1", "2019.4.10f1", "2019.4.11f1", "2019.4.12f1",
"2019.4.13f1", "2019.4.14f1", "2019.4.15f1", "2019.4.16f1", "2019.4.17f1", "2019.4.18f1",
"2019.4.19f1", "2019.4.20f1", "2019.4.21f1", "2019.4.22f1", "2019.4.23f1", "2019.4.24f1",
"2019.4.25f1", "2019.4.26f1", "2019.4.27f1", "2019.4.28f1", "2019.4.29f1", "2019.4.30f1",
"2019.4.31f1",
"2021.3.1f1", "2021.3.2f1", "2021.3.3f1", "2021.3.4f1", "2021.3.5f1", "2021.3.6f1", "2021.3.7f1",
"2021.3.8f1", "2021.3.9f1", "2021.3.10f1", "2021.3.11f1", "2021.3.12f1", "2021.3.13f1", "2021.3.14f1",
"2021.3.15f1", "2021.3.16f1", "2021.3.17f1", "2021.3.18f1", "2021.3.19f1", "2021.3.20f1", "2021.3.21f1",
"2021.3.22f1", "2021.3.23f1", "2021.3.24f1"
};
string _username;
string _key;
private string _username;
private string _key;
public Texture2D abiLogo;
private bool _attemptingToLogin;
private bool _loggedIn;
private bool _hasAttemptedToLogin;
private bool _allowedToUpload;
//private bool _allowedToUpload;
private string _apiUserRank;
private string _apiCreatorRank;
Vector2 scrollPosAvatar;
Vector2 scrollPosSpawnable;
Vector2 scrollPosWorld;
//private string _apiCreatorRank;
private Vector2 scrollPosAvatar;
private Vector2 scrollPosSpawnable;
private int _tab;
private Vector2 _scroll;
@ -79,20 +59,20 @@ namespace ABI.CCK.Scripts.Editor
}
}
[MenuItem("Alpha Blend Interactive/Control Panel (Builder and Settings)", false, 200)]
static void Init()
[MenuItem("Alpha Blend Interactive/Control Panel", false, 200)]
private static void Init()
{
CCK_BuildManagerWindow window = (CCK_BuildManagerWindow)GetWindow(typeof(CCK_BuildManagerWindow), false, $"CCK :: Control Panel");
window.Show();
}
void OnDisable()
private void OnDisable()
{
EditorApplication.update -= EditorUpdate;
EditorApplication.playModeStateChanged -= OnEditorStateUpdated;
}
void OnEnable()
private void OnEnable()
{
abiLogo = (Texture2D) AssetDatabase.LoadAssetAtPath("Assets/ABI.CCK/GUIAssets/abibig.png", typeof(Texture2D));
@ -103,15 +83,15 @@ namespace ABI.CCK.Scripts.Editor
_username = EditorPrefs.GetString("m_ABI_Username");
_key = EditorPrefs.GetString("m_ABI_Key");
Login();
_ = Login();
}
void OnEditorStateUpdated(PlayModeStateChange state)
private void OnEditorStateUpdated(PlayModeStateChange state)
{
if (state == PlayModeStateChange.EnteredEditMode)
{
EditorPrefs.SetBool("m_ABI_isBuilding", false);
EditorPrefs.SetString("m_ABI_TempVersion", Version);
EditorPrefs.SetString("m_ABI_TempVersion", CVRCommon.CCK_VERSION);
string[] filePaths = Directory.GetFiles(Application.dataPath + "/ABI.CCK/Resources/Cache/", "*.prefab");
foreach (string filePath in filePaths)
@ -172,12 +152,15 @@ namespace ABI.CCK.Scripts.Editor
if (File.Exists(Application.dataPath + "/ABI.CCK/Resources/Cache/_CVRWorld.prefab"))up.asset = Resources.Load<GameObject>("Cache/_CVRWorld").GetComponent<CVRAssetInfo>();
}
}
void OnGUI()
private void OnGUI()
{
var centeredStyle = GUI.skin.GetStyle("Label");
centeredStyle.alignment = TextAnchor.UpperCenter;
GUIStyle centeredStyle = new GUIStyle(GUI.skin.label)
{
alignment = TextAnchor.MiddleCenter,
fixedHeight = 70, // Fixes size when Android
};
GUILayout.Label(abiLogo, centeredStyle);
EditorGUILayout.BeginVertical();
@ -220,7 +203,7 @@ namespace ABI.CCK.Scripts.Editor
if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_LOGIN_BUTTON")))
{
Login();
_ = Login();
}
if (_hasAttemptedToLogin && !_loggedIn)
@ -235,7 +218,7 @@ namespace ABI.CCK.Scripts.Editor
EditorGUILayout.Space();
EditorGUILayout.LabelField(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_INFOTEXT_AUTHENTICATED_AS"), _username);
EditorGUILayout.LabelField(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_INFOTEXT_USER_RANK"), _apiUserRank);
EditorGUILayout.LabelField("CCK version ", CCKVersion);
EditorGUILayout.LabelField("CCK version ", CVRCommon.CCK_VERSION_FULL);
EditorGUILayout.Space();
if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_LOGOUT_BUTTON"))){
bool logout = EditorUtility.DisplayDialog(
@ -248,10 +231,34 @@ namespace ABI.CCK.Scripts.Editor
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_INFOTEXT_DOCUMENTATION"), MessageType.Info);
if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_HEADING_DOCUMENTATION"))) Application.OpenURL("https://docs.abinteractive.net");
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_WARNING_FEEDBACK"), MessageType.Info);
if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_HEADING_FEEDBACK"))) Application.OpenURL("https://hub.abinteractive.net/feedback");
if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_HEADING_FEEDBACK"))) Application.OpenURL("https://feedback.abinteractive.net/");
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_WARNING_FOLDERPATH"), MessageType.Warning);
EditorGUILayout.Space();
EditorGUILayout.LabelField(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_HEADING_FOUNDCONTENT"), EditorStyles.boldLabel);
// Check if using a supported Unity version
if (!SupportedUnityVersions.Contains(Application.unityVersion))
{
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_WORLDS_ERROR_UNITY_UNSUPPORTED"), MessageType.Error);
return;
}
// Check if OpenXR is needed
#if PLATFORM_ANDROID
if (!ABI.CCK.Dependencies.OpenXR.OpenXR_Configurator.IsImported())
{
EditorGUILayout.HelpBox("OpenXR needs to be imported prior to uploading Android content!", MessageType.Error);
if (GUILayout.Button("Import OpenXR")) ABI.CCK.Dependencies.OpenXR.OpenXR_Configurator.RunConfiguration();
return;
}
if (!ABI.CCK.Dependencies.OpenXR.OpenXR_Configurator.IsConfigured())
{
EditorGUILayout.HelpBox("OpenXR needs to be configured prior to uploading Android content!", MessageType.Error);
if (GUILayout.Button("Configure OpenXR")) ABI.CCK.Dependencies.OpenXR.OpenXR_Configurator.RunConfiguration();
return;
}
#endif
List<CVRAvatar> avatars = new List<CVRAvatar>();
List<CVRSpawnable> spawnables = new List<CVRSpawnable>();
List<CVRWorld> worlds = new List<CVRWorld>();
@ -270,8 +277,8 @@ namespace ABI.CCK.Scripts.Editor
{
if (a.gameObject.activeInHierarchy) avatars.Add(a);
}
if (worlds.Count <= 0 && avatars.Count > 0 && SupportedUnityVersions.Contains(Application.unityVersion))
if (worlds.Count <= 0 && avatars.Count > 0)
{
if (avatars.Count <= 0) EditorGUILayout.LabelField(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_UPLOADER_NO_AVATARS_FOUND"));
else
@ -293,7 +300,7 @@ namespace ABI.CCK.Scripts.Editor
}
}
}
if (worlds.Count <= 0 && spawnables.Count > 0 && SupportedUnityVersions.Contains(Application.unityVersion))
if (worlds.Count <= 0 && spawnables.Count > 0)
{
if (spawnables.Count <= 0) EditorGUILayout.LabelField(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_UPLOADER_NO_SPAWNABLES_FOUND"));
else
@ -315,7 +322,7 @@ namespace ABI.CCK.Scripts.Editor
}
}
}
if (avatars.Count <= 0 && worlds.Count == 1 && SupportedUnityVersions.Contains(Application.unityVersion))
if (avatars.Count <= 0 && worlds.Count == 1)
{
int errors = 0;
int overallMissingScripts = 0;
@ -337,31 +344,28 @@ namespace ABI.CCK.Scripts.Editor
if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_UPLOAD_WORLD_BUTTON")) && errors <= 0)
{
CCK_BuildUtility.BuildAndUploadMapAsset(EditorSceneManager.GetActiveScene(), worlds[0].gameObject);
_ = CCK_BuildUtility.BuildAndUploadMapAsset(EditorSceneManager.GetActiveScene(), worlds[0].gameObject);
}
if (overallMissingScripts > 0) if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_UTIL_REMOVE_MISSING_SCRIPTS_BUTTON"))) CCK_Tools.CleanMissingScripts(CCK_Tools.SearchType.Scene , true, null);
}
if (avatars.Count <= 0 && worlds.Count > 1 && SupportedUnityVersions.Contains(Application.unityVersion))
if (avatars.Count <= 0 && worlds.Count > 1)
{
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_WORLDS_ERROR_MULTIPLE_CVR_WORLD"), MessageType.Error);
}
if (avatars.Count > 0 && worlds.Count > 0 && SupportedUnityVersions.Contains(Application.unityVersion))
if (avatars.Count > 0 && worlds.Count > 0)
{
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_WORLDS_ERROR_WORLD_CONTAINS_AVATAR"), MessageType.Error);
}
if (avatars.Count <= 0 && worlds.Count <= 0 && SupportedUnityVersions.Contains(Application.unityVersion))
if (avatars.Count <= 0 && worlds.Count <= 0)
{
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_WORLDS_ERROR_NO_CONTENT"), MessageType.Info);
}
if (!SupportedUnityVersions.Contains(Application.unityVersion))
{
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_WORLDS_ERROR_UNITY_UNSUPPORTED"), MessageType.Error);
}
}
void Tab_Settings()
private void Tab_Settings()
{
EditorGUILayout.LabelField(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_SETTINGS_HEADER"), EditorStyles.boldLabel);
EditorGUILayout.LabelField("CCK version ", CVRCommon.CCK_VERSION);
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
@ -398,11 +402,10 @@ namespace ABI.CCK.Scripts.Editor
EditorGUILayout.EndHorizontal();
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_SETTINGS_HINT_CCK_LANGUAGE"), MessageType.Info);
EditorGUILayout.Space();
}
void OnGUIAvatar(CVRAvatar avatar)
private void OnGUIAvatar(CVRAvatar avatar)
{
GameObject avatarObject = avatar.gameObject;
GUI.enabled = true;
@ -462,12 +465,12 @@ namespace ABI.CCK.Scripts.Editor
if (avatar.viewPosition.y <= 0.5f) EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_AVATAR_INFO_SMALL"), MessageType.Info);
if (avatar.viewPosition.y > 3f) EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_AVATAR_INFO_HUGE"), MessageType.Info);
if (errors <= 0) if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_AVATAR_UPLOAD_BUTTON"))) CCK_BuildUtility.BuildAndUploadAvatar(avatarObject);
if (errors <= 0) if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_AVATAR_UPLOAD_BUTTON"))) _ = CCK_BuildUtility.BuildAndUploadAvatar(avatarObject);
if (overallMissingScripts > 0) if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_UTIL_REMOVE_MISSING_SCRIPTS_BUTTON"))) CCK_Tools.CleanMissingScripts(CCK_Tools.SearchType.Selection ,true,avatarObject);
}
void OnGUISpawnable(CVRSpawnable s)
private void OnGUISpawnable(CVRSpawnable s)
{
GameObject spawnableObject = s.gameObject;
GUI.enabled = true;
@ -512,7 +515,7 @@ namespace ABI.CCK.Scripts.Editor
if (overallSkinnedMeshRenderer >= 5 && overallSkinnedMeshRenderer <= 10) EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_PROPS_INFO_SKINNED_MESH_RENDERERS").Replace("{X}", overallSkinnedMeshRenderer.ToString()), MessageType.Info);
if (overallUniqueMaterials >= 10 && overallUniqueMaterials <= 20) EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_PROPS_INFO_MATERIALS").Replace("{X}", overallUniqueMaterials.ToString()), MessageType.Info);
if (errors <= 0 && overallMissingScripts <= 0) if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_PROPS_UPLOAD_BUTTON"))) CCK_BuildUtility.BuildAndUploadSpawnable(spawnableObject);
if (errors <= 0 && overallMissingScripts <= 0) if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_PROPS_UPLOAD_BUTTON"))) _ = CCK_BuildUtility.BuildAndUploadSpawnable(spawnableObject);
if (overallMissingScripts > 0) if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_BUILDPANEL_UTIL_REMOVE_MISSING_SCRIPTS_BUTTON"))) CCK_Tools.CleanMissingScripts(CCK_Tools.SearchType.Selection ,true, spawnableObject);
}

View file

@ -0,0 +1,19 @@
using UnityEditor;
namespace ABI.CCK.Scripts.Editor
{
public static class CCK_BuildTargetSwitch
{
[MenuItem("Alpha Blend Interactive/Utilities/Switch Target Platform/PC Windows", false, 250)]
public static void SwitchToPC()
{
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64);
}
[MenuItem("Alpha Blend Interactive/Utilities/Switch Target Platform/Android Standalone", false, 250)]
public static void SwitchToAndroid()
{
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android);
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5d6069e9dc8048d29ad54a3057a898be
timeCreated: 1701950588

View file

@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using ABI.CCK.Components;
using UnityEditor;
@ -8,221 +9,160 @@ using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.XR;
using Object = UnityEngine.Object;
using Random = System.Random;
namespace ABI.CCK.Scripts.Editor
{
public class CCK_BuildUtility
{
#region Variables
public static PreAvatarBundleEvent PreAvatarBundleEvent = new PreAvatarBundleEvent();
public static PrePropBundleEvent PrePropBundleEvent = new PrePropBundleEvent();
public static string upload_id = "";
public static PreWorldBundleEvent PreWorldBundleEvent = new PreWorldBundleEvent();
public static string upload_id = "";
#endregion
#region Avatar Upload
public static async Task BuildAndUploadAvatar(GameObject avatarObject)
{
//GameObject avatarCopy = null;
var origInfo = avatarObject.GetComponent<CVRAssetInfo>();
ClearLog();
EnforceVRSetting();
/*try
{
avatarCopy = GameObject.Instantiate(avatarObject);
PrefabUtility.UnpackPrefabInstance(avatarCopy, PrefabUnpackMode.Completely, InteractionMode.UserAction);
Debug.Log("[CCK:BuildUtility] To prevent problems, the prefab has been unpacked. Your game object is no longer linked to the prefab instance.");
}
catch
{
Debug.Log("[CCK:BuildUtility] Object is not a prefab. No need to unpack.");
}*/
//CVRAssetInfo info = avatarCopy.GetComponent<CVRAssetInfo>();
if (string.IsNullOrEmpty(origInfo.objectId))
{
#if UNITY_EDITOR
APIConnection.Initialize(EditorPrefs.GetString("m_ABI_Username"), EditorPrefs.GetString("m_ABI_Key"));
#endif
APIConnection.BaseResponse<APIConnection.GenerateResponse> response = await APIConnection.MakeRequest<APIConnection.GenerateResponse>("cck/generate/avatar", put: true);
if (response != null && response.Data != null)
{
origInfo.objectId = response.Data.Id.ToString();
}
else
{
Debug.LogError($"[CCK:BuildUtility] New Guid could not be generated");
}
}
Random rnd = new Random();
origInfo.randomNum = rnd.Next(11111111, 99999999).ToString();
CVRAssetInfo assetInfo = avatarObject.GetComponent<CVRAssetInfo>();
EditorUtility.SetDirty(origInfo);
try
await InitializeAPIAndSetObjectId(assetInfo, "cck/generate/avatar");
SetAssetInfoDirty(assetInfo);
GameObject instantiatedAvatar = InstantiateAndUnpackPrefab(avatarObject);
if (!HandlePreBuildEvent(PreAvatarBundleEvent.Invoke, instantiatedAvatar))
{
PrefabUtility.ApplyPrefabInstance(avatarObject, InteractionMode.UserAction);
}
catch
{
Debug.Log("[CCK:BuildUtility] Object is not a prefab. No need to Apply To Instance.");
Object.DestroyImmediate(instantiatedAvatar);
return;
}
PreAvatarBundleEvent.Invoke(avatarObject);
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
CCK_Tools.CleanEditorOnlyGameObjects(instantiatedAvatar);
EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());
if (!Application.unityVersion.Contains("2021"))
PrefabUtility.SaveAsPrefabAsset(avatarObject, "Assets/ABI.CCK/Resources/Cache/_CVRAvatar.prefab");
else
PrefabUtility.SaveAsPrefabAsset(avatarObject, $"Assets/ABI.CCK/Resources/Cache/CVRAvatar_{origInfo.objectId}_{origInfo.randomNum}.prefab");
//GameObject.DestroyImmediate(avatarCopy);
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());
PrefabUtility.SaveAsPrefabAsset(instantiatedAvatar,
!Application.unityVersion.Contains("2021")
? "Assets/ABI.CCK/Resources/Cache/_CVRAvatar.prefab"
: $"Assets/ABI.CCK/Resources/Cache/CVRAvatar_{assetInfo.objectId}_{assetInfo.randomNum}.prefab");
AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
if (!Application.unityVersion.Contains("2021"))
assetBundleBuild.assetNames = new[] {"Assets/ABI.CCK/Resources/Cache/_CVRAvatar.prefab"};
else
assetBundleBuild.assetNames = new[] {$"Assets/ABI.CCK/Resources/Cache/CVRAvatar_{origInfo.objectId}_{origInfo.randomNum}.prefab"};
assetBundleBuild.assetNames = !Application.unityVersion.Contains("2021")
? new[] { "Assets/ABI.CCK/Resources/Cache/_CVRAvatar.prefab" }
: new[]
{
$"Assets/ABI.CCK/Resources/Cache/CVRAvatar_{assetInfo.objectId}_{assetInfo.randomNum}.prefab"
};
upload_id = origInfo.objectId;
upload_id = assetInfo.objectId;
EditorPrefs.SetString("m_ABI_uploadId", upload_id);
EditorPrefs.SetString("m_ABI_uploadRand", origInfo.randomNum);
EditorPrefs.SetString("m_ABI_uploadRand", assetInfo.randomNum);
assetBundleBuild.assetBundleName = $"cvravatar_{origInfo.objectId}_{origInfo.randomNum}.cvravatar";
assetBundleBuild.assetBundleName = $"cvravatar_{assetInfo.objectId}_{assetInfo.randomNum}.cvravatar";
BuildPipeline.BuildAssetBundles(Application.persistentDataPath, new[] {assetBundleBuild},
BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);
AssetDatabase.Refresh();
Object.DestroyImmediate(instantiatedAvatar);
if (!File.Exists($"{Application.persistentDataPath}/cvravatar_{assetInfo.objectId}_{assetInfo.randomNum}.cvravatar"))
{
Debug.LogError("Error during bundling\nThere has been an error during the bundling process. Please check your console for errors.");
EditorUtility.DisplayDialog("Error during bundling", "There has been an error during the bundling process. Please check your console for errors.", "OK");
return;
}
AssetDatabase.Refresh();
EditorPrefs.SetBool("m_ABI_isBuilding", true);
EditorApplication.isPlaying = true;
}
public static async Task BuildAndUploadSpawnable(GameObject s)
#endregion
#region Spawnable Upload
public static async Task BuildAndUploadSpawnable(GameObject spawnableObject)
{
GameObject sCopy = null;
var origInfo = s.GetComponent<CVRAssetInfo>();
var spawnable = s.GetComponent<CVRSpawnable>();
ClearLog();
EnforceVRSetting();
CVRAssetInfo assetInfo = spawnableObject.GetComponent<CVRAssetInfo>();
CVRSpawnable spawnable = spawnableObject.GetComponent<CVRSpawnable>();
spawnable.spawnableType = CVRSpawnable.SpawnableType.StandaloneSpawnable;
EditorUtility.SetDirty(spawnable);
if (string.IsNullOrEmpty(origInfo.objectId))
{
#if UNITY_EDITOR
APIConnection.Initialize(EditorPrefs.GetString("m_ABI_Username"), EditorPrefs.GetString("m_ABI_Key"));
#endif
APIConnection.BaseResponse<APIConnection.GenerateResponse> response = await APIConnection.MakeRequest<APIConnection.GenerateResponse>("cck/generate/spawnable", put: true);
await InitializeAPIAndSetObjectId(assetInfo, "cck/generate/spawnable");
SetAssetInfoDirty(assetInfo);
if (response != null && response.Data != null)
{
origInfo.objectId = response.Data.Id.ToString();
}
else
{
Debug.LogError($"[CCK:BuildUtility] New Guid could not be generated");
}
}
Random rnd = new Random();
origInfo.randomNum = rnd.Next(11111111, 99999999).ToString();
EditorUtility.SetDirty(origInfo);
PrePropBundleEvent.Invoke(s);
try
GameObject instantiatedSpawnable = InstantiateAndUnpackPrefab(spawnableObject);
if (!HandlePreBuildEvent(PrePropBundleEvent.Invoke, instantiatedSpawnable))
{
sCopy = GameObject.Instantiate(s);
PrefabUtility.UnpackPrefabInstance(sCopy, PrefabUnpackMode.Completely, InteractionMode.UserAction);
Debug.Log("[CCK:BuildUtility] To prevent problems, the prefab has been unpacked. Your game object is no longer linked to the prefab instance.");
}
catch
{
Debug.Log("[CCK:BuildUtility] Object is not a prefab. No need to unpack.");
Object.DestroyImmediate(instantiatedSpawnable);
return;
}
CCK_Tools.CleanEditorOnlyGameObjects(instantiatedSpawnable);
CVRAssetInfo info = sCopy.GetComponent<CVRAssetInfo>();
try
{
PrefabUtility.ApplyPrefabInstance(s, InteractionMode.UserAction);
}
catch
{
Debug.Log("[CCK:BuildUtility] Object is not a prefab. No need to Apply To Instance.");
}
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());
if (!Application.unityVersion.Contains("2021"))
PrefabUtility.SaveAsPrefabAsset(sCopy, "Assets/ABI.CCK/Resources/Cache/_CVRSpawnable.prefab");
else
PrefabUtility.SaveAsPrefabAsset(sCopy, $"Assets/ABI.CCK/Resources/Cache/CVRSpawnable_{origInfo.objectId}_{origInfo.randomNum}.prefab");
GameObject.DestroyImmediate(sCopy);
EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());
PrefabUtility.SaveAsPrefabAsset(instantiatedSpawnable,
!Application.unityVersion.Contains("2021")
? "Assets/ABI.CCK/Resources/Cache/_CVRSpawnable.prefab"
: $"Assets/ABI.CCK/Resources/Cache/CVRSpawnable_{assetInfo.objectId}_{assetInfo.randomNum}.prefab");
AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
assetBundleBuild.assetNames = !Application.unityVersion.Contains("2021")
? new[] { "Assets/ABI.CCK/Resources/Cache/_CVRSpawnable.prefab" }
: new[]
{
$"Assets/ABI.CCK/Resources/Cache/CVRSpawnable_{assetInfo.objectId}_{assetInfo.randomNum}.prefab"
};
if (!Application.unityVersion.Contains("2021"))
assetBundleBuild.assetNames = new[] {"Assets/ABI.CCK/Resources/Cache/_CVRSpawnable.prefab"};
else
assetBundleBuild.assetNames = new[] {$"Assets/ABI.CCK/Resources/Cache/CVRSpawnable_{origInfo.objectId}_{origInfo.randomNum}.prefab"};
upload_id = origInfo.objectId;
upload_id = assetInfo.objectId;
EditorPrefs.SetString("m_ABI_uploadId", upload_id);
EditorPrefs.SetString("m_ABI_uploadRand", origInfo.randomNum);
EditorPrefs.SetString("m_ABI_uploadRand", assetInfo.randomNum);
assetBundleBuild.assetBundleName = $"cvrspawnable_{origInfo.objectId}_{origInfo.randomNum}.cvrprop";
assetBundleBuild.assetBundleName = $"cvrspawnable_{assetInfo.objectId}_{assetInfo.randomNum}.cvrprop";
BuildPipeline.BuildAssetBundles(Application.persistentDataPath, new[] {assetBundleBuild},
BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);
AssetDatabase.Refresh();
Object.DestroyImmediate(instantiatedSpawnable);
if (!File.Exists($"{Application.persistentDataPath}/cvrspawnable_{assetInfo.objectId}_{assetInfo.randomNum}.cvrprop"))
{
Debug.LogError("Error during bundling\nThere has been an error during the bundling process. Please check your console for errors.");
EditorUtility.DisplayDialog("Error during bundling", "There has been an error during the bundling process. Please check your console for errors.", "OK");
return;
}
AssetDatabase.Refresh();
EditorPrefs.SetBool("m_ABI_isBuilding", true);
EditorApplication.isPlaying = true;
}
#endregion
#region World Upload
public static async Task BuildAndUploadMapAsset(Scene scene, GameObject descriptor)
{
ClearLog();
EnforceVRSetting();
SetupNetworkUUIDs();
CVRAssetInfo info = descriptor.GetComponent<CVRAssetInfo>();
CVRAssetInfo assetInfo = descriptor.GetComponent<CVRAssetInfo>();
if (string.IsNullOrEmpty(info.objectId))
{
#if UNITY_EDITOR
APIConnection.Initialize(EditorPrefs.GetString("m_ABI_Username"), EditorPrefs.GetString("m_ABI_Key"));
#endif
APIConnection.BaseResponse<APIConnection.GenerateResponse> response = await APIConnection.MakeRequest<APIConnection.GenerateResponse>("cck/generate/world", put: true);
await InitializeAPIAndSetObjectId(assetInfo, "cck/generate/world");
SetAssetInfoDirty(assetInfo);
if (response != null && response.Data != null)
{
info.objectId = response.Data.Id.ToString();
EditorUtility.SetDirty(info);
}
else
{
Debug.LogError($"[CCK:BuildUtility] New Guid could not be generated");
}
}
EditorSceneManager.MarkSceneDirty(scene);
EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene());
if (!HandlePreBuildEvent(PreWorldBundleEvent.Invoke, scene))
return;
PrefabUtility.SaveAsPrefabAsset(descriptor, "Assets/ABI.CCK/Resources/Cache/_CVRWorld.prefab");
@ -233,13 +173,90 @@ namespace ABI.CCK.Scripts.Editor
BuildPipeline.BuildAssetBundles(Application.persistentDataPath, new[] {assetBundleBuild},
BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);
AssetDatabase.Refresh();
if (!File.Exists($"{Application.persistentDataPath}/bundle.cvrworld"))
{
Debug.LogError("Error during bundling\nThere has been an error during the bundling process. Please check your console for errors.");
EditorUtility.DisplayDialog("Error during bundling", "There has been an error during the bundling process. Please check your console for errors.", "OK");
return;
}
AssetDatabase.Refresh();
EditorPrefs.SetBool("m_ABI_isBuilding", true);
EditorApplication.isPlaying = true;
}
public static void SetupNetworkUUIDs()
#endregion
#region Private Methods
private static async Task InitializeAPIAndSetObjectId(CVRAssetInfo assetInfo, string apiEndpoint)
{
if (string.IsNullOrEmpty(assetInfo.objectId))
{
#if UNITY_EDITOR
APIConnection.Initialize(EditorPrefs.GetString("m_ABI_Username"), EditorPrefs.GetString("m_ABI_Key"));
#endif
APIConnection.BaseResponse<APIConnection.GenerateResponse> response = await APIConnection.MakeRequest<APIConnection.GenerateResponse>(apiEndpoint, put: true);
if (response != null && response.Data != null)
assetInfo.objectId = response.Data.Id.ToString();
else
Debug.LogError($"[CCK:BuildUtility] New Guid could not be generated");
}
Random rnd = new Random();
assetInfo.randomNum = rnd.Next(11111111, 99999999).ToString();
}
private static void SetAssetInfoDirty(Component assetInfo)
{
EditorUtility.SetDirty(assetInfo);
EditorSceneManager.MarkSceneDirty(assetInfo.gameObject.scene);
EditorSceneManager.SaveScene(assetInfo.gameObject.scene);
}
private static GameObject InstantiateAndUnpackPrefab(GameObject original)
{
GameObject instantiated = Object.Instantiate(original);
if (PrefabUtility.IsPartOfNonAssetPrefabInstance(instantiated) && PrefabUtility.IsOutermostPrefabInstanceRoot(instantiated))
PrefabUtility.UnpackPrefabInstance(instantiated, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
// Why would you do this?
if (instantiated.CompareTag("EditorOnly"))
instantiated.tag = "Untagged";
return instantiated;
}
private static bool HandlePreBuildEvent(Action<GameObject> preBuildEvent, GameObject instantiatedObject)
{
try
{
preBuildEvent.Invoke(instantiatedObject);
return true;
}
catch (Exception ex)
{
Debug.LogError($"[CCK:BuildUtility] Error occurred during PreBuildEvent: {ex.Message}");
return false;
}
}
private static bool HandlePreBuildEvent(Action<Scene> preBuildEvent, Scene scene)
{
try
{
preBuildEvent.Invoke(scene);
return true;
}
catch (Exception ex)
{
Debug.LogError($"[CCK:BuildUtility] Error occurred during PreBuildEvent: {ex.Message}");
return false;
}
}
private static void SetupNetworkUUIDs()
{
CVRInteractable[] interactables = Resources.FindObjectsOfTypeAll<CVRInteractable>();
CVRObjectSync[] objectSyncs = Resources.FindObjectsOfTypeAll<CVRObjectSync>();
@ -360,17 +377,41 @@ namespace ABI.CCK.Scripts.Editor
newserializedObject.ApplyModifiedProperties();
}
}
}
[System.Serializable]
public class PreAvatarBundleEvent : UnityEvent<GameObject>
{
private static void ClearLog()
{
var assembly = Assembly.GetAssembly(typeof(UnityEditor.Editor));
var type = assembly.GetType("UnityEditor.LogEntries");
var method = type.GetMethod("Clear");
method.Invoke(new object(), null);
}
private static void EnforceVRSetting()
{
#if UNITY_2021_1_OR_NEWER
PlayerSettings.virtualRealitySupported = true;
PlayerSettings.stereoRenderingPath = StereoRenderingPath.Instancing;
XRSettings.enabled = false;
#else
PlayerSettings.virtualRealitySupported = true;
PlayerSettings.SetVirtualRealitySDKs(BuildTargetGroup.Standalone, new string[] { "None", "Oculus", "OpenVR", "MockHMD" });
PlayerSettings.stereoRenderingPath = StereoRenderingPath.SinglePass;
#endif
}
#endregion
}
#region PreBundleEvents
[Serializable]
public class PreAvatarBundleEvent : UnityEvent<GameObject> { }
[System.Serializable]
public class PrePropBundleEvent : UnityEvent<GameObject>
{
}
}
[Serializable]
public class PrePropBundleEvent : UnityEvent<GameObject> { }
[Serializable]
public class PreWorldBundleEvent : UnityEvent<Scene> { }
#endregion
}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: feba207f658e6754bbd61863a923e46b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,81 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using ABI.CCK.Scripts;
using UnityEditor;
// TODO: Rename parent folder to CCK_CVRAdvancedAvatarSettingsTriggerEditor
// I fucked up and forgot the Editor postfix, its driving me mad.
// We cannot fix it without requiring clean reimport of the CCK, so it should wait for huge refactor?
namespace ABI.CCK.Components
{
[CanEditMultipleObjects]
[CustomEditor(typeof(CVRAdvancedAvatarSettingsTrigger))]
public partial class CCK_CVRAdvancedAvatarSettingsTriggerEditor : Editor
{
#region EditorGUI Foldouts
private static bool _guiAreaConfigurationFoldout = true;
private static bool _guiInteractionFilterFoldout = true;
private static bool _guiAllowedFilterFoldout;
private static bool _guiTriggerSettingsFoldout;
#endregion
private CVRAdvancedAvatarSettingsTrigger _trigger;
private List<string> _avatarParameterNames;
#region Unity Events
private void OnEnable()
{
if (target == null) return;
_trigger = (CVRAdvancedAvatarSettingsTrigger)target;
CVRAvatar avatar = _trigger.GetComponentInParent<CVRAvatar>();
if (avatar != null && avatar.overrides != null)
_avatarParameterNames = CVRCommon.GetParametersFromControllerAsString(avatar.overrides, CVRCommon.NonCoreFilter);
else
_avatarParameterNames = new List<string>();
}
public override void OnInspectorGUI()
{
if (_trigger == null)
return;
serializedObject.Update();
Draw_TriggerMode();
Draw_AreaSettings();
Draw_FilterSettings();
if (!_trigger.useAdvancedTrigger)
{
Draw_SimpleTasks();
}
else
{
Draw_AllowedFilterSettings();
Draw_AdvancedTasks();
}
serializedObject.ApplyModifiedProperties();
}
#endregion
#region Drawing Methods
private void Draw_TriggerMode()
{
int newSelectedIndex = EditorGUILayout.Popup("Trigger Mode", _trigger.useAdvancedTrigger ? 1 : 0,
new[] { "Simple", "Advanced" });
_trigger.useAdvancedTrigger = (newSelectedIndex == 1);
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,386 @@
#if UNITY_EDITOR
using System.Linq;
using ABI.CCK.Scripts;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAdvancedAvatarSettingsTriggerEditor
{
// Allow
private ReorderableList _allowedTypesList;
private ReorderableList _allowedPointersList;
// Tasks
private ReorderableList _onEnterList;
private ReorderableList _onExitList;
private ReorderableList _onStayList;
private void Draw_AllowedFilterSettings()
{
using (new FoldoutScope(ref _guiAllowedFilterFoldout, "Allowed Filter"))
{
if (!_guiAllowedFilterFoldout) return;
DrawAllowedFilterSettings();
}
}
private void Draw_AdvancedTasks()
{
using (new FoldoutScope(ref _guiTriggerSettingsFoldout, "Trigger Tasks"))
{
if (!_guiTriggerSettingsFoldout) return;
DrawAdvancedTasks();
}
}
#region Drawing Methods
private void DrawAllowedFilterSettings()
{
if (_allowedPointersList == null)
{
_allowedPointersList = new ReorderableList(serializedObject,
serializedObject.FindProperty("allowedPointer"), false, true, true, false)
{
drawHeaderCallback = OnDrawHeaderAllowedPointers,
drawElementCallback = OnDrawElementAllowedPointers,
elementHeightCallback = OnElementHeight,
onChangedCallback = OnChanged
};
}
if (_allowedTypesList == null)
{
_allowedTypesList = new ReorderableList(serializedObject,
serializedObject.FindProperty("allowedTypes"), false, true, true, false)
{
drawHeaderCallback = OnDrawHeaderAllowedTypes,
drawElementCallback = OnDrawElementAllowedTypes,
elementHeightCallback = OnElementHeight,
onChangedCallback = OnChanged
};
}
int newSelectedIndex;
int currentMode = (_allowedPointersList.count > 0) ? 1 : 0;
using (new EditorGUI.IndentLevelScope())
newSelectedIndex = EditorGUILayout.Popup("Allow Filter Mode", currentMode, new[] { "Type", "Reference" });
// This is so jank... Why are they one or the other???
if (newSelectedIndex != currentMode) {
if (newSelectedIndex == 0) {
_allowedPointersList.serializedProperty.arraySize = 0;
} else {
_allowedPointersList.serializedProperty.arraySize = 1;
_allowedPointersList.serializedProperty.GetArrayElementAtIndex(0).objectReferenceValue = null;
}
}
Separator();
if (newSelectedIndex == 0) {
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ADVAVTR_TRIGGER_ALLOWED_TYPES_HELPBOX"), MessageType.Info);
_allowedTypesList.DoLayoutList();
} else {
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ADVAVTR_TRIGGER_ALLOWED_POINTERS_HELPBOX"), MessageType.Info);
_allowedPointersList.DoLayoutList();
}
}
private void DrawAdvancedTasks()
{
if (_onEnterList == null)
{
_onEnterList = new ReorderableList(_trigger.enterTasks,
typeof(CVRAdvancedAvatarSettingsTriggerTask),
false, true, true, true)
{
drawHeaderCallback = OnDrawHeaderEnter,
drawElementCallback = OnDrawElementEnter,
elementHeightCallback = OnHeightElementEnter,
onChangedCallback = OnChangedEnter
};
}
if (_onExitList == null)
{
_onExitList = new ReorderableList(_trigger.exitTasks, typeof(CVRAdvancedAvatarSettingsTriggerTask),
false, true, true, true)
{
drawHeaderCallback = OnDrawHeaderExit,
drawElementCallback = OnDrawElementExit,
elementHeightCallback = OnHeightElementExit,
onChangedCallback = OnChangedExit
};
}
if (_onStayList == null)
{
_onStayList = new ReorderableList(_trigger.stayTasks,
typeof(CVRAdvancedAvatarSettingsTriggerTaskStay),
false, true, true, true)
{
drawHeaderCallback = OnDrawHeaderStay,
drawElementCallback = OnDrawElementStay,
elementHeightCallback = OnHeightElementStay,
onChangedCallback = OnChangedStay
};
}
_onEnterList.DoLayoutList();
EditorGUILayout.Space();
_onExitList.DoLayoutList();
EditorGUILayout.Space();
_onStayList.DoLayoutList();
EditorGUILayout.Space();
if (_trigger.stayTasks.Count > 0)
{
_trigger.sampleDirection = (CVRAdvancedAvatarSettingsTrigger.SampleDirection)
EditorGUILayout.EnumPopup("Sample Direction", _trigger.sampleDirection);
}
}
#endregion
#region ReorderableList AllowLists
private void OnDrawHeaderAllowedTypes(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "Allowed Types");
}
private void OnDrawHeaderAllowedPointers(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "Allowed Pointers");
}
private float OnElementHeight(int index)
{
return 4 + EditorGUIUtility.singleLineHeight;
}
private void OnChanged(ReorderableList list)
{
EditorUtility.SetDirty(_trigger);
}
private void OnDrawElementAllowedTypes(Rect rect, int index, bool isActive, bool isFocused)
{
if (index >= _allowedTypesList.serializedProperty.arraySize) return;
SerializedProperty element = _allowedTypesList.serializedProperty.GetArrayElementAtIndex(index);
GUIContent buttonContent = CVRCommon.DefaultPointerTypes.Contains(element.stringValue)
? EditorGUIExtensions.GetCachedIconContent("Favorite")
: EditorGUIExtensions.GetCachedIconContent("d_editicon.sml");
var newValue = EditorGUIExtensions.AdvancedDropdownInput(
new Rect(rect.x, rect.y + 2, rect.width - 20, EditorGUIUtility.singleLineHeight), element.stringValue,
CVRCommon.DefaultPointerTypes, "Default Pointer Types", buttonContent);
if (newValue != element.stringValue)
{
element.stringValue = newValue;
_allowedTypesList.serializedProperty.serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(target);
}
if (GUI.Button(new Rect(rect.x + rect.width - 18, rect.y + 2, 18, EditorGUIUtility.singleLineHeight), "X"))
{
_allowedTypesList.serializedProperty.DeleteArrayElementAtIndex(index);
_allowedTypesList.serializedProperty.serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(_trigger);
}
}
private void OnDrawElementAllowedPointers(Rect rect, int index, bool isActive, bool isFocused)
{
if (index >= _allowedPointersList.serializedProperty.arraySize) return;
SerializedProperty element = _allowedPointersList.serializedProperty.GetArrayElementAtIndex(index);
EditorGUI.ObjectField(new Rect(rect.x, rect.y + 2, rect.width - 20, EditorGUIUtility.singleLineHeight),
element, typeof(CVRPointer), GUIContent.none);
if (GUI.Button(new Rect(rect.x + rect.width - 18, rect.y + 2, 18, EditorGUIUtility.singleLineHeight), "X"))
{
_allowedPointersList.serializedProperty.DeleteArrayElementAtIndex(index);
_allowedPointersList.serializedProperty.serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(_trigger);
}
}
#endregion
#region ReorderableList OnEnterTasks
private void OnDrawHeaderEnter(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "On Enter Trigger");
EditorGUIExtensions.UtilityMenu(_rect, _onEnterList);
}
private void OnDrawElementEnter(Rect rect, int index, bool isactive, bool isfocused)
{
if (index >= _trigger.enterTasks.Count) return;
CVRAdvancedAvatarSettingsTriggerTask enterTask = _trigger.enterTasks[index];
Rect _rect = new Rect(rect.x, rect.y + 2, rect.width, EditorGUIUtility.singleLineHeight);
float spacing = EditorGUIUtility.singleLineHeight * 1.25f;
float originalLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 100;
enterTask.settingName = EditorGUIExtensions.AdvancedDropdownInput(_rect, enterTask.settingName, _avatarParameterNames,
"Setting Name", "No Parameters");
_rect.y += spacing;
enterTask.settingValue = EditorGUI.FloatField(_rect, "Setting Value", enterTask.settingValue);
_rect.y += spacing;
enterTask.delay = EditorGUI.FloatField(_rect, "Delay", enterTask.delay);
_rect.y += spacing;
enterTask.holdTime = EditorGUI.FloatField(_rect,"Hold Time", enterTask.holdTime);
_rect.y += spacing;
enterTask.updateMethod =
(CVRAdvancedAvatarSettingsTriggerTask.UpdateMethod)EditorGUI.EnumPopup(_rect, "Update Method", enterTask.updateMethod);
EditorGUIUtility.labelWidth = originalLabelWidth;
}
private float OnHeightElementEnter(int index)
{
return EditorGUIUtility.singleLineHeight * 6.25f;
}
private void OnChangedEnter(ReorderableList list)
{
EditorUtility.SetDirty(_trigger);
}
#endregion
#region ReorderableList OnExitTasks
private void OnDrawHeaderExit(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "On Exit Trigger");
EditorGUIExtensions.UtilityMenu(_rect, _onExitList);
}
private void OnDrawElementExit(Rect rect, int index, bool isactive, bool isfocused)
{
if (index >= _trigger.exitTasks.Count) return;
CVRAdvancedAvatarSettingsTriggerTask exitTask = _trigger.exitTasks[index];
Rect _rect = new Rect(rect.x, rect.y + 2, rect.width, EditorGUIUtility.singleLineHeight);
float spacing = EditorGUIUtility.singleLineHeight * 1.25f;
float originalLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 100;
exitTask.settingName = EditorGUIExtensions.AdvancedDropdownInput(_rect, exitTask.settingName, _avatarParameterNames,
"Setting Name", "No Parameters");
_rect.y += spacing;
exitTask.settingValue = EditorGUI.FloatField(_rect, "Setting Value", exitTask.settingValue);
_rect.y += spacing;
exitTask.delay = EditorGUI.FloatField(_rect, "Delay", exitTask.delay);
_rect.y += spacing;
exitTask.updateMethod =
(CVRAdvancedAvatarSettingsTriggerTask.UpdateMethod)EditorGUI.EnumPopup(_rect, "Update Method", exitTask.updateMethod);
EditorGUIUtility.labelWidth = originalLabelWidth;
}
private float OnHeightElementExit(int index)
{
return EditorGUIUtility.singleLineHeight * 5f;
}
private void OnChangedExit(ReorderableList list)
{
EditorUtility.SetDirty(_trigger);
}
#endregion
#region ReorderableList OnStayTasks
private void OnDrawHeaderStay(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "On Stay Trigger");
EditorGUIExtensions.UtilityMenu(_rect, _onStayList);
}
private void OnDrawElementStay(Rect rect, int index, bool isactive, bool isfocused)
{
if (index >= _trigger.stayTasks.Count) return;
CVRAdvancedAvatarSettingsTriggerTaskStay stayTask = _trigger.stayTasks[index];
Rect _rect = new Rect(rect.x, rect.y + 2, rect.width, EditorGUIUtility.singleLineHeight);
float spacing = EditorGUIUtility.singleLineHeight * 1.25f;
float originalLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 100;
stayTask.settingName = EditorGUIExtensions.AdvancedDropdownInput(_rect, stayTask.settingName, _avatarParameterNames,
"Setting Name", "No Parameters");
_rect.y += spacing;
stayTask.updateMethod =
(CVRAdvancedAvatarSettingsTriggerTaskStay.UpdateMethod)EditorGUI.EnumPopup(_rect,
"Update Method", stayTask.updateMethod);
_rect.y += spacing;
if (stayTask.updateMethod == CVRAdvancedAvatarSettingsTriggerTaskStay.UpdateMethod.SetFromPosition ||
stayTask.updateMethod == CVRAdvancedAvatarSettingsTriggerTaskStay.UpdateMethod.SetFromDistance)
{
stayTask.minValue = EditorGUI.FloatField(_rect, "Min Value", stayTask.minValue);
_rect.y += spacing;
stayTask.maxValue = EditorGUI.FloatField(_rect, "Max Value", stayTask.maxValue);
_rect.y += spacing;
}
else
{
stayTask.minValue = EditorGUI.FloatField(_rect, "Change per sec", stayTask.minValue);
_rect.y += spacing;
}
EditorGUIUtility.labelWidth = originalLabelWidth;
}
private float OnHeightElementStay(int index)
{
if (index >= _trigger.stayTasks.Count) return EditorGUIUtility.singleLineHeight * 3.75f;
CVRAdvancedAvatarSettingsTriggerTaskStay stayTask = _trigger.stayTasks[index];
if (stayTask.updateMethod == CVRAdvancedAvatarSettingsTriggerTaskStay.UpdateMethod.SetFromPosition ||
stayTask.updateMethod == CVRAdvancedAvatarSettingsTriggerTaskStay.UpdateMethod.SetFromDistance)
return EditorGUIUtility.singleLineHeight * 5f;
return EditorGUIUtility.singleLineHeight * 3.75f;
}
private void OnChangedStay(ReorderableList list)
{
EditorUtility.SetDirty(_trigger);
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,29 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAdvancedAvatarSettingsTriggerEditor
{
private void Draw_AreaSettings()
{
using (new FoldoutScope(ref _guiAreaConfigurationFoldout, "Area Configuration"))
{
if (!_guiAreaConfigurationFoldout) return;
using (new EditorGUI.IndentLevelScope())
DrawAreaSettings();
}
}
private void DrawAreaSettings()
{
GUILayout.BeginVertical();
EditorGUILayout.PropertyField(serializedObject.FindProperty("areaSize"), new GUIContent("Area Size"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("areaOffset"), new GUIContent("Area Offset"));
GUILayout.EndVertical();
}
}
}
#endif

View file

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

View file

@ -0,0 +1,31 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAdvancedAvatarSettingsTriggerEditor
{
private void Draw_FilterSettings()
{
using (new FoldoutScope(ref _guiInteractionFilterFoldout, "Interaction Filter"))
{
if (!_guiInteractionFilterFoldout) return;
using (new EditorGUI.IndentLevelScope())
DrawFilterSettings();
}
}
private void DrawFilterSettings()
{
GUILayout.BeginVertical();
EditorGUILayout.PropertyField(serializedObject.FindProperty("isLocalInteractable"), new GUIContent("Local Interaction"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("isNetworkInteractable"), new GUIContent("Network Interaction"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("allowParticleInteraction"), new GUIContent("Particle Interaction"));
//EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ADVAVTR_TRIGGER_PARTICLE_HELPBOX"), MessageType.Info);
GUILayout.EndVertical();
}
}
}
#endif

View file

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

View file

@ -0,0 +1,37 @@
#if UNITY_EDITOR
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAdvancedAvatarSettingsTriggerEditor
{
private void Draw_SimpleTasks()
{
using (new FoldoutScope(ref _guiTriggerSettingsFoldout, "Trigger Settings"))
{
if (!_guiTriggerSettingsFoldout) return;
using (new EditorGUI.IndentLevelScope())
DrawSimpleTasks();
}
}
private void DrawSimpleTasks()
{
GUILayout.BeginVertical();
string newName = EditorGUIExtensions.AdvancedDropdownInput(EditorGUILayout.GetControlRect(),
_trigger.settingName, _avatarParameterNames,
"Setting Name", "No Parameters");
if (newName != _trigger.settingName)
serializedObject.FindProperty("settingName").stringValue = newName;
EditorGUILayout.PropertyField(serializedObject.FindProperty("settingValue"), new GUIContent("Setting Value"));
GUILayout.EndVertical();
}
}
}
#endif

View file

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

View file

@ -1,395 +1 @@
using System.Collections.Generic;
using System.Linq;
using ABI.CCK.Components;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using AnimatorController = UnityEditor.Animations.AnimatorController;
using AnimatorControllerParameterType = UnityEngine.AnimatorControllerParameterType;
namespace ABI.CCK.Scripts.Editor
{
[CustomEditor(typeof(CVRAdvancedAvatarSettingsTrigger))]
public class CCK_CVRAdvancedAvatarSettingsTriggerEditor : UnityEditor.Editor
{
private CVRAdvancedAvatarSettingsTrigger trigger;
private AnimatorController animator;
private CVRAdvancedAvatarSettingsTriggerTask enterEntity;
private CVRAdvancedAvatarSettingsTriggerTask exitEntity;
private CVRAdvancedAvatarSettingsTriggerTaskStay stayEntity;
private ReorderableList _onEnterList;
private ReorderableList _onExitList;
private ReorderableList _onStayList;
private List<string> animatorParameters;
public override void OnInspectorGUI()
{
trigger = (CVRAdvancedAvatarSettingsTrigger) target;
var avatar = trigger.GetComponentInParent<CVRAvatar>();
animator = null;
animatorParameters = new List<string>();
animatorParameters.Add("-none-");
if (avatar != null && avatar.overrides != null && avatar.overrides.runtimeAnimatorController != null)
{
animator = (AnimatorController) avatar.overrides.runtimeAnimatorController;
foreach (var parameter in animator.parameters)
{
if ((parameter.type == AnimatorControllerParameterType.Float ||
parameter.type == AnimatorControllerParameterType.Bool ||
parameter.type == AnimatorControllerParameterType.Int)
&& parameter.name.Length > 0 &&
!CCK_CVRAvatarEditor.coreParameters.Contains(parameter.name) && parameter.name.Substring(0, 1) != "#")
{
animatorParameters.Add(parameter.name);
}
}
}
var triggers = trigger.GetComponents<CVRAdvancedAvatarSettingsTrigger>();
if (triggers.Length > 1)
{
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ADVAVTR_TRIGGER_MULTIPLE_TRIGGER_HELPBOX"), MessageType.Error);
}
trigger.areaSize = EditorGUILayout.Vector3Field("Area Size", trigger.areaSize);
trigger.areaOffset = EditorGUILayout.Vector3Field("Area Offset", trigger.areaOffset);
if (!trigger.useAdvancedTrigger)
{
if (animator == null)
{
trigger.settingName = EditorGUILayout.TextField("Setting Name", trigger.settingName);
}
else
{
var animatorParams = animatorParameters.ToArray();
var index = animatorParameters.FindIndex(match => match == trigger.settingName);
index = Mathf.Max(EditorGUILayout.Popup("Setting Name", index, animatorParams), 0);
trigger.settingName = animatorParams[index];
}
trigger.settingValue = EditorGUILayout.FloatField("Setting Value", trigger.settingValue);
trigger.useAdvancedTrigger = EditorGUILayout.Toggle("Enabled Advanced Mode", trigger.useAdvancedTrigger);
}
else
{
trigger.useAdvancedTrigger = EditorGUILayout.Toggle("Enabled Advanced Mode", trigger.useAdvancedTrigger);
var list = serializedObject.FindProperty("allowedPointer");
EditorGUILayout.PropertyField(list, new GUIContent("Allowed Pointers"), true);
serializedObject.ApplyModifiedProperties();
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ADVAVTR_TRIGGER_ALLOWED_POINTERS_HELPBOX"), MessageType.Info);
trigger.isNetworkInteractable = EditorGUILayout.Toggle("Network Interactable", trigger.isNetworkInteractable);
list = serializedObject.FindProperty("allowedTypes");
EditorGUILayout.PropertyField(list, new GUIContent("Allowed Types"), true);
serializedObject.ApplyModifiedProperties();
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ADVAVTR_TRIGGER_ALLOWED_TYPES_HELPBOX"), MessageType.Info);
trigger.allowParticleInteraction = EditorGUILayout.Toggle("Enabled Particle Interaction", trigger.allowParticleInteraction);
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ADVAVTR_TRIGGER_PARTICLE_HELPBOX"), MessageType.Info);
if (_onEnterList == null)
{
_onEnterList = new ReorderableList(trigger.enterTasks, typeof(CVRAdvancedAvatarSettingsTriggerTask),
false, true, true, true);
_onEnterList.drawHeaderCallback = OnDrawHeaderEnter;
_onEnterList.drawElementCallback = OnDrawElementEnter;
_onEnterList.elementHeightCallback = OnHeightElementEnter;
_onEnterList.onAddCallback = OnAddEnter;
_onEnterList.onChangedCallback = OnChangedEnter;
}
_onEnterList.DoLayoutList();
if (_onExitList == null)
{
_onExitList = new ReorderableList(trigger.exitTasks, typeof(CVRAdvancedAvatarSettingsTriggerTask),
false, true, true, true);
_onExitList.drawHeaderCallback = OnDrawHeaderExit;
_onExitList.drawElementCallback = OnDrawElementExit;
_onExitList.elementHeightCallback = OnHeightElementExit;
_onExitList.onAddCallback = OnAddExit;
_onExitList.onChangedCallback = OnChangedExit;
}
_onExitList.DoLayoutList();
if (_onStayList == null)
{
_onStayList = new ReorderableList(trigger.stayTasks, typeof(CVRAdvancedAvatarSettingsTriggerTaskStay),
false, true, true, true);
_onStayList.drawHeaderCallback = OnDrawHeaderStay;
_onStayList.drawElementCallback = OnDrawElementStay;
_onStayList.elementHeightCallback = OnHeightElementStay;
_onStayList.onAddCallback = OnAddStay;
_onStayList.onChangedCallback = OnChangedStay;
}
_onStayList.DoLayoutList();
if (trigger.stayTasks.Count > 0)
{
trigger.sampleDirection = (CVRAdvancedAvatarSettingsTrigger.SampleDirection)
EditorGUILayout.EnumPopup("Sample Direction", trigger.sampleDirection);
}
}
}
private void OnDrawHeaderEnter(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "On Enter Trigger");
}
private void OnDrawElementEnter(Rect rect, int index, bool isactive, bool isfocused)
{
if (index > trigger.enterTasks.Count) return;
enterEntity = trigger.enterTasks[index];
Rect _rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Setting Name");
_rect.x += 100;
_rect.width = rect.width - 100;
if (animator == null)
{
enterEntity.settingName = EditorGUI.TextField(_rect, enterEntity.settingName);
}
else
{
_rect.y += 1;
var animatorParams = animatorParameters.ToArray();
var selected = animatorParameters.FindIndex(match => match == enterEntity.settingName);
selected = Mathf.Max(EditorGUI.Popup(_rect, selected, animatorParams), 0);
enterEntity.settingName = animatorParams[selected];
}
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Setting Value");
_rect.x += 100;
_rect.width = rect.width - 100;
enterEntity.settingValue = EditorGUI.FloatField(_rect, enterEntity.settingValue);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Delay");
_rect.x += 100;
_rect.width = rect.width - 100;
enterEntity.delay = EditorGUI.FloatField(_rect, enterEntity.delay);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Hold Time");
_rect.x += 100;
_rect.width = rect.width - 100;
enterEntity.holdTime = EditorGUI.FloatField(_rect, enterEntity.holdTime);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Update Method");
_rect.x += 100;
_rect.width = rect.width - 100;
enterEntity.updateMethod = (CVRAdvancedAvatarSettingsTriggerTask.UpdateMethod) EditorGUI.EnumPopup(_rect, enterEntity.updateMethod);
}
private float OnHeightElementEnter(int index)
{
return EditorGUIUtility.singleLineHeight * 6.25f;
}
private void OnAddEnter(ReorderableList list)
{
trigger.enterTasks.Add(new CVRAdvancedAvatarSettingsTriggerTask());
Repaint();
}
private void OnChangedEnter(ReorderableList list)
{
//EditorUtility.SetDirty(target);
}
private void OnDrawHeaderExit(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "On Exit Trigger");
}
private void OnDrawElementExit(Rect rect, int index, bool isactive, bool isfocused)
{
if (index > trigger.exitTasks.Count) return;
exitEntity = trigger.exitTasks[index];
Rect _rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Setting Name");
_rect.x += 100;
_rect.width = rect.width - 100;
if (animator == null)
{
exitEntity.settingName = EditorGUI.TextField(_rect, exitEntity.settingName);
}
else
{
_rect.y += 1;
var animatorParams = animatorParameters.ToArray();
var selected = animatorParameters.FindIndex(match => match == exitEntity.settingName);
selected = Mathf.Max(EditorGUI.Popup(_rect, selected, animatorParams), 0);
exitEntity.settingName = animatorParams[selected];
}
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Setting Value");
_rect.x += 100;
_rect.width = rect.width - 100;
exitEntity.settingValue = EditorGUI.FloatField(_rect, exitEntity.settingValue);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Delay");
_rect.x += 100;
_rect.width = rect.width - 100;
exitEntity.delay = EditorGUI.FloatField(_rect, exitEntity.delay);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Update Method");
_rect.x += 100;
_rect.width = rect.width - 100;
exitEntity.updateMethod = (CVRAdvancedAvatarSettingsTriggerTask.UpdateMethod) EditorGUI.EnumPopup(_rect, exitEntity.updateMethod);
}
private float OnHeightElementExit(int index)
{
return EditorGUIUtility.singleLineHeight * 5f;
}
private void OnAddExit(ReorderableList list)
{
trigger.exitTasks.Add(new CVRAdvancedAvatarSettingsTriggerTask());
Repaint();
}
private void OnChangedExit(ReorderableList list)
{
//EditorUtility.SetDirty(target);
}
private void OnDrawHeaderStay(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "On Stay Trigger");
}
private void OnDrawElementStay(Rect rect, int index, bool isactive, bool isfocused)
{
if (index > trigger.stayTasks.Count) return;
stayEntity = trigger.stayTasks[index];
Rect _rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Setting Name");
_rect.x += 100;
_rect.width = rect.width - 100;
if (animator == null)
{
stayEntity.settingName = EditorGUI.TextField(_rect, stayEntity.settingName);
}
else
{
_rect.y += 1;
var animatorParams = animatorParameters.ToArray();
var selected = animatorParameters.FindIndex(match => match == stayEntity.settingName);
selected = Mathf.Max(EditorGUI.Popup(_rect, selected, animatorParams), 0);
stayEntity.settingName = animatorParams[selected];
}
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Update Method");
_rect.x += 100;
_rect.width = rect.width - 100;
stayEntity.updateMethod = (CVRAdvancedAvatarSettingsTriggerTaskStay.UpdateMethod) EditorGUI.EnumPopup(_rect, stayEntity.updateMethod);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
if (stayEntity.updateMethod == CVRAdvancedAvatarSettingsTriggerTaskStay.UpdateMethod.SetFromPosition)
{
EditorGUI.LabelField(_rect, "Min Value");
_rect.x += 100;
_rect.width = rect.width - 100;
stayEntity.minValue = EditorGUI.FloatField(_rect, stayEntity.minValue);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Max Value");
_rect.x += 100;
_rect.width = rect.width - 100;
stayEntity.maxValue = EditorGUI.FloatField(_rect, stayEntity.maxValue);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
}
else
{
EditorGUI.LabelField(_rect, "Change per sec");
_rect.x += 100;
_rect.width = rect.width - 100;
stayEntity.minValue = EditorGUI.FloatField(_rect, stayEntity.minValue);
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
}
}
private float OnHeightElementStay(int index)
{
if (index > trigger.stayTasks.Count) return EditorGUIUtility.singleLineHeight * 3.75f;
stayEntity = trigger.stayTasks[index];
if (stayEntity.updateMethod == CVRAdvancedAvatarSettingsTriggerTaskStay.UpdateMethod.SetFromPosition)
return EditorGUIUtility.singleLineHeight * 5f;
return EditorGUIUtility.singleLineHeight * 3.75f;
}
private void OnAddStay(ReorderableList list)
{
trigger.stayTasks.Add(new CVRAdvancedAvatarSettingsTriggerTaskStay());
Repaint();
}
private void OnChangedStay(ReorderableList list)
{
//EditorUtility.SetDirty(target);
}
}
}
// delete me one day as well the third

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ece7ec86c2882f94d8796905f37fbae5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,68 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
[CanEditMultipleObjects]
[CustomEditor(typeof(CVRAdvancedAvatarSettingsTriggerHelper))]
public class CCK_CVRAdvancedAvatarSettingsTriggerHelperEditor : Editor
{
private CVRAdvancedAvatarSettingsTriggerHelper _triggerHelper;
private SerializedProperty m_TriggersProp;
#region Unity Events
private void OnEnable()
{
if (target == null) return;
_triggerHelper = (CVRAdvancedAvatarSettingsTriggerHelper)target;
//m_TriggersProp = serializedObject.FindProperty(nameof(CVRAdvancedAvatarSettingsTriggerHelper.triggers));
}
public override void OnInspectorGUI()
{
if (_triggerHelper == null)
return;
serializedObject.Update();
// helpbox stating this component is deprecated
EditorGUILayout.HelpBox("This component is deprecated. Similar functionality may be achieved using the new Animator Driver StateBehaviour.", MessageType.Warning);
//Draw_Info();
//Draw_HelperTriggers();
serializedObject.ApplyModifiedProperties();
}
#endregion
#region Drawing Methods
private void Draw_Info()
{
EditorGUILayout.HelpBox("For use with Animation Events. Allows you to call OnEnter, OnExit, and OnStay on any trigger in this list.", MessageType.Info);
}
private void Draw_HelperTriggers()
{
using (new LabelScope("Trigger References"))
DrawHelperTriggers();
}
private void DrawHelperTriggers()
{
GUILayout.BeginVertical();
//Separator();
using (new EditorGUI.IndentLevelScope()) EditorGUILayout.PropertyField(m_TriggersProp, new GUIContent("Triggers"));
GUILayout.EndVertical();
}
#endregion
}
}
#endif

View file

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

View file

@ -1,302 +1,288 @@
using System.Collections.Generic;
using ABI.CCK.Components;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using AnimatorController = UnityEditor.Animations.AnimatorController;
using AnimatorControllerParameterType = UnityEngine.AnimatorControllerParameterType;
// delete this file when we nuke the moon
namespace ABI.CCK.Scripts.Editor
{
[CustomEditor(typeof(ABI.CCK.Components.CVRAnimatorDriver))]
public class CCK_CVRAnimatorDriverEditor : UnityEditor.Editor
{
private CVRAnimatorDriver _driver;
private ReorderableList reorderableList;
private List<string> animatorParamNameList = new List<string>();
private List<AnimatorControllerParameterType> animatorParamTypeList = new List<AnimatorControllerParameterType>();
private Dictionary<AnimatorControllerParameterType, int> typeList = new Dictionary<AnimatorControllerParameterType, int>()
{
{AnimatorControllerParameterType.Float, 0},
{AnimatorControllerParameterType.Int, 1},
{AnimatorControllerParameterType.Bool, 2},
{AnimatorControllerParameterType.Trigger, 3}
};
private void InitializeList()
{
reorderableList = new ReorderableList(_driver.animators, typeof(Animator),
false, true, true, true);
reorderableList.drawHeaderCallback = OnDrawHeader;
reorderableList.drawElementCallback = OnDrawElement;
reorderableList.elementHeightCallback = OnHeightElement;
reorderableList.onAddCallback = OnAdd;
reorderableList.onChangedCallback = OnChanged;
reorderableList.onRemoveCallback = OnRemove;
}
private void OnRemove(ReorderableList list)
{
_driver.animators.RemoveAt(list.index);
_driver.animatorParameters.RemoveAt(list.index);
_driver.animatorParameterType.RemoveAt(list.index);
Repaint();
}
private void OnChanged(ReorderableList list)
{
//EditorUtility.SetDirty(target);
}
private void OnAdd(ReorderableList list)
{
if (_driver.animators.Count >= 16) return;
_driver.animators.Add(null);
_driver.animatorParameters.Add(null);
_driver.animatorParameterType.Add(0);
Repaint();
}
private float OnHeightElement(int index)
{
return EditorGUIUtility.singleLineHeight * 3 * 1.25f;
}
private void OnDrawElement(Rect rect, int index, bool isactive, bool isfocused)
{
if (index > _driver.animators.Count) return;
rect.y += 2;
rect.x += 12;
rect.width -= 12;
Rect _rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Animator");
_rect.x += 100;
_rect.width = rect.width - 100;
EditorGUI.BeginChangeCheck();
var animator = (Animator) EditorGUI.ObjectField(_rect, _driver.animators[index], typeof(Animator), true);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "Animator Driver Animator changed");
EditorUtility.SetDirty(_driver);
_driver.animators[index] = animator;
}
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Parameter");
_rect.x += 100;
_rect.width = rect.width - 100;
animatorParamNameList.Clear();
animatorParamTypeList.Clear();
animatorParamNameList.Add("-none-");
animatorParamTypeList.Add(AnimatorControllerParameterType.Bool);
var oldIndex = 0;
var i = 1;
if (_driver.animators[index] != null && _driver.animators[index].runtimeAnimatorController != null)
{
var runtimeController = _driver.animators[index].runtimeAnimatorController;
UnityEngine.AnimatorControllerParameter[] parameters = null;
if (runtimeController is AnimatorController animatorController)
{
parameters = animatorController.parameters;
}
else if (runtimeController is AnimatorOverrideController overrideController &&
overrideController.runtimeAnimatorController is AnimatorController baseController)
{
parameters = baseController.parameters;
}
if (parameters != null)
{
foreach (var parameter in parameters)
{
animatorParamNameList.Add(parameter.name);
animatorParamTypeList.Add(parameter.type);
if (_driver.animatorParameters[index] == parameter.name)
{
oldIndex = i;
}
i++;
}
}
}
EditorGUI.BeginChangeCheck();
var parameterIndex = EditorGUI.Popup(_rect, oldIndex, animatorParamNameList.ToArray());
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "Animator Driver Parameter changed");
EditorUtility.SetDirty(_driver);
_driver.animatorParameters[index] = animatorParamNameList[parameterIndex];
_driver.animatorParameterType[index] = typeList[animatorParamTypeList[parameterIndex]];
}
rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
_rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(_rect, "Value");
_rect.x += 100;
_rect.width = rect.width - 100;
EditorGUI.BeginChangeCheck();
var value = EditorGUI.FloatField(_rect, GetAnimatorParameterValue(index));
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "Animator Driver Value changed");
EditorUtility.SetDirty(_driver);
SetAnimatorParameterValue(index, value);
}
}
private void OnDrawHeader(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "Animator Parameters");
}
public override void OnInspectorGUI()
{
if (_driver == null) _driver = (CVRAnimatorDriver) target;
EditorGUILayout.Space();
if (reorderableList == null) InitializeList();
reorderableList.DoLayoutList();
}
public float GetAnimatorParameterValue(int index)
{
switch (index)
{
case 0:
return _driver.animatorParameter01;
break;
case 1:
return _driver.animatorParameter02;
break;
case 2:
return _driver.animatorParameter03;
break;
case 3:
return _driver.animatorParameter04;
break;
case 4:
return _driver.animatorParameter05;
break;
case 5:
return _driver.animatorParameter06;
break;
case 6:
return _driver.animatorParameter07;
break;
case 7:
return _driver.animatorParameter08;
break;
case 8:
return _driver.animatorParameter09;
break;
case 9:
return _driver.animatorParameter10;
break;
case 10:
return _driver.animatorParameter11;
break;
case 11:
return _driver.animatorParameter12;
break;
case 12:
return _driver.animatorParameter13;
break;
case 13:
return _driver.animatorParameter14;
break;
case 14:
return _driver.animatorParameter15;
break;
default:
return _driver.animatorParameter16;
break;
}
}
public void SetAnimatorParameterValue(int index, float value)
{
switch (index)
{
case 0:
_driver.animatorParameter01 = value;
break;
case 1:
_driver.animatorParameter02 = value;
break;
case 2:
_driver.animatorParameter03 = value;
break;
case 3:
_driver.animatorParameter04 = value;
break;
case 4:
_driver.animatorParameter05 = value;
break;
case 5:
_driver.animatorParameter06 = value;
break;
case 6:
_driver.animatorParameter07 = value;
break;
case 7:
_driver.animatorParameter08 = value;
break;
case 8:
_driver.animatorParameter09 = value;
break;
case 9:
_driver.animatorParameter10 = value;
break;
case 10:
_driver.animatorParameter11 = value;
break;
case 11:
_driver.animatorParameter12 = value;
break;
case 12:
_driver.animatorParameter13 = value;
break;
case 13:
_driver.animatorParameter14 = value;
break;
case 14:
_driver.animatorParameter15 = value;
break;
default:
_driver.animatorParameter16 = value;
break;
}
}
}
}
// using System.Collections.Generic;
// using ABI.CCK.Components;
// using ABI.CCK.Scripts.Editor;
// using UnityEditor;
// using UnityEditorInternal;
// using UnityEngine;
// using AnimatorController = UnityEditor.Animations.AnimatorController;
// using AnimatorControllerParameterType = UnityEngine.AnimatorControllerParameterType;
//
// namespace ABI.CCK.Scripts.Editor
// {
// [CustomEditor(typeof(ABI.CCK.Components.CVRAnimatorDriver))]
// public class CCK_CVRAnimatorDriverEditor : UnityEditor.Editor
// {
// private CVRAnimatorDriver _driver;
//
// private ReorderableList reorderableList;
//
// private List<string> animatorParamNameList = new List<string>();
// private List<AnimatorControllerParameterType> animatorParamTypeList = new List<AnimatorControllerParameterType>();
//
// private Dictionary<AnimatorControllerParameterType, int> typeList = new Dictionary<AnimatorControllerParameterType, int>()
// {
// {AnimatorControllerParameterType.Float, 0},
// {AnimatorControllerParameterType.Int, 1},
// {AnimatorControllerParameterType.Bool, 2},
// {AnimatorControllerParameterType.Trigger, 3}
// };
//
// private void InitializeList()
// {
// reorderableList = new ReorderableList(_driver.animators, typeof(Animator),
// false, true, true, true);
// reorderableList.drawHeaderCallback = OnDrawHeader;
// reorderableList.drawElementCallback = OnDrawElement;
// reorderableList.elementHeightCallback = OnHeightElement;
// reorderableList.onAddCallback = OnAdd;
// reorderableList.onChangedCallback = OnChanged;
// reorderableList.onRemoveCallback = OnRemove;
// }
//
// private void OnRemove(ReorderableList list)
// {
// _driver.animators.RemoveAt(list.index);
// _driver.animatorParameters.RemoveAt(list.index);
// _driver.animatorParameterType.RemoveAt(list.index);
// Repaint();
// }
//
// private void OnChanged(ReorderableList list)
// {
// //EditorUtility.SetDirty(target);
// }
//
// private void OnAdd(ReorderableList list)
// {
// if (_driver.animators.Count >= 16) return;
// _driver.animators.Add(null);
// _driver.animatorParameters.Add(null);
// _driver.animatorParameterType.Add(0);
// Repaint();
// }
//
// private float OnHeightElement(int index)
// {
// return EditorGUIUtility.singleLineHeight * 3 * 1.25f;
// }
//
// private void OnDrawElement(Rect rect, int index, bool isactive, bool isfocused)
// {
// if (index > _driver.animators.Count) return;
//
// rect.y += 2;
// rect.x += 12;
// rect.width -= 12;
// Rect _rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
//
// EditorGUI.LabelField(_rect, "Animator");
//
// _rect.x += 100;
// _rect.width = rect.width - 100;
//
// EditorGUI.BeginChangeCheck();
//
// var animator = (Animator) EditorGUI.ObjectField(_rect, _driver.animators[index], typeof(Animator), true);
//
// if (EditorGUI.EndChangeCheck())
// {
// Undo.RecordObject(target, "Animator Driver Animator changed");
// EditorUtility.SetDirty(_driver);
// _driver.animators[index] = animator;
// }
//
// rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
// _rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
//
// EditorGUI.LabelField(_rect, "Parameter");
//
// _rect.x += 100;
// _rect.width = rect.width - 100;
//
// animatorParamNameList.Clear();
// animatorParamTypeList.Clear();
//
// animatorParamNameList.Add("-none-");
// animatorParamTypeList.Add(AnimatorControllerParameterType.Bool);
//
// var oldIndex = 0;
// var i = 1;
//
// if (_driver.animators[index] != null && _driver.animators[index].runtimeAnimatorController != null)
// {
// var runtimeController = _driver.animators[index].runtimeAnimatorController;
// UnityEngine.AnimatorControllerParameter[] parameters = null;
//
// if (runtimeController is AnimatorController animatorController)
// {
// parameters = animatorController.parameters;
// }
// else if (runtimeController is AnimatorOverrideController overrideController &&
// overrideController.runtimeAnimatorController is AnimatorController baseController)
// {
// parameters = baseController.parameters;
// }
//
// if (parameters != null)
// {
// foreach (var parameter in parameters)
// {
// animatorParamNameList.Add(parameter.name);
// animatorParamTypeList.Add(parameter.type);
//
// if (_driver.animatorParameters[index] == parameter.name)
// {
// oldIndex = i;
// }
//
// i++;
// }
// }
// }
//
// EditorGUI.BeginChangeCheck();
//
// var parameterIndex = EditorGUI.Popup(_rect, oldIndex, animatorParamNameList.ToArray());
//
// if (EditorGUI.EndChangeCheck())
// {
// Undo.RecordObject(target, "Animator Driver Parameter changed");
// EditorUtility.SetDirty(_driver);
// _driver.animatorParameters[index] = animatorParamNameList[parameterIndex];
// _driver.animatorParameterType[index] = typeList[animatorParamTypeList[parameterIndex]];
// }
//
// rect.y += EditorGUIUtility.singleLineHeight * 1.25f;
// _rect = new Rect(rect.x, rect.y, 100, EditorGUIUtility.singleLineHeight);
//
// EditorGUI.LabelField(_rect, "Value");
//
// _rect.x += 100;
// _rect.width = rect.width - 100;
//
// EditorGUI.BeginChangeCheck();
//
// var value = EditorGUI.FloatField(_rect, GetAnimatorParameterValue(index));
//
// if (EditorGUI.EndChangeCheck())
// {
// Undo.RecordObject(target, "Animator Driver Value changed");
// EditorUtility.SetDirty(_driver);
// SetAnimatorParameterValue(index, value);
// }
// }
//
// private void OnDrawHeader(Rect rect)
// {
// Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
// GUI.Label(_rect, "Animator Parameters");
// EditorGUIExtensions.UtilityMenu(rect, reorderableList);
// }
//
// public override void OnInspectorGUI()
// {
// if (_driver == null) _driver = (CVRAnimatorDriver) target;
//
// EditorGUILayout.Space();
//
// if (reorderableList == null) InitializeList();
// reorderableList.DoLayoutList();
// }
//
// public float GetAnimatorParameterValue(int index)
// {
// switch (index)
// {
// case 0:
// return _driver.animatorParameter01;
// case 1:
// return _driver.animatorParameter02;
// case 2:
// return _driver.animatorParameter03;
// case 3:
// return _driver.animatorParameter04;
// case 4:
// return _driver.animatorParameter05;
// case 5:
// return _driver.animatorParameter06;
// case 6:
// return _driver.animatorParameter07;
// case 7:
// return _driver.animatorParameter08;
// case 8:
// return _driver.animatorParameter09;
// case 9:
// return _driver.animatorParameter10;
// case 10:
// return _driver.animatorParameter11;
// case 11:
// return _driver.animatorParameter12;
// case 12:
// return _driver.animatorParameter13;
// case 13:
// return _driver.animatorParameter14;
// case 14:
// return _driver.animatorParameter15;
// default:
// return _driver.animatorParameter16;
// }
// }
//
// public void SetAnimatorParameterValue(int index, float value)
// {
// switch (index)
// {
// case 0:
// _driver.animatorParameter01 = value;
// break;
// case 1:
// _driver.animatorParameter02 = value;
// break;
// case 2:
// _driver.animatorParameter03 = value;
// break;
// case 3:
// _driver.animatorParameter04 = value;
// break;
// case 4:
// _driver.animatorParameter05 = value;
// break;
// case 5:
// _driver.animatorParameter06 = value;
// break;
// case 6:
// _driver.animatorParameter07 = value;
// break;
// case 7:
// _driver.animatorParameter08 = value;
// break;
// case 8:
// _driver.animatorParameter09 = value;
// break;
// case 9:
// _driver.animatorParameter10 = value;
// break;
// case 10:
// _driver.animatorParameter11 = value;
// break;
// case 11:
// _driver.animatorParameter12 = value;
// break;
// case 12:
// _driver.animatorParameter13 = value;
// break;
// case 13:
// _driver.animatorParameter14 = value;
// break;
// case 14:
// _driver.animatorParameter15 = value;
// break;
// default:
// _driver.animatorParameter16 = value;
// break;
// }
// }
// }
// }

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 503166a9d64c4b4182595e10d6ce963d
timeCreated: 1703219388

View file

@ -0,0 +1,58 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEditor;
namespace ABI.CCK.Components
{
[CanEditMultipleObjects]
[CustomEditor(typeof(CVRAnimatorDriver))]
public partial class CCK_CVRAnimatorDriverEditor : Editor
{
#region Private Variables
private CVRAnimatorDriver _driver;
#endregion
#region Serialized Properties
private readonly List<SerializedProperty> m_ParameterValuesPropList = new();
private SerializedProperty m_AnimatorsProp;
private SerializedProperty m_AnimatorParametersProp;
private SerializedProperty m_AnimatorParameterTypeProp;
#endregion
#region Unity Events
private void OnEnable()
{
if (target == null) return;
_driver = (CVRAnimatorDriver)target;
for (int i = 0; i < 16; i++)
m_ParameterValuesPropList.Add(serializedObject.FindProperty(
i < 9 ? $"animatorParameter0{i + 1}" : $"animatorParameter1{i - 9}"
));
m_AnimatorsProp = serializedObject.FindProperty(nameof(CVRAnimatorDriver.animators));
m_AnimatorParametersProp = serializedObject.FindProperty(nameof(CVRAnimatorDriver.animatorParameters));
m_AnimatorParameterTypeProp = serializedObject.FindProperty(nameof(CVRAnimatorDriver.animatorParameterType));
}
public override void OnInspectorGUI()
{
if (_driver == null)
return;
serializedObject.Update();
DrawEntries();
serializedObject.ApplyModifiedProperties();
}
#endregion
}
}
#endif

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f0ca9029fe954673924df7306b41f85f
timeCreated: 1703219398

View file

@ -0,0 +1,146 @@
#if UNITY_EDITOR
using System;
using ABI.CCK.Scripts;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using AnimatorControllerParameter = UnityEngine.AnimatorControllerParameter;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAnimatorDriverEditor
{
private ReorderableList _driverEntriesList;
private int _selectedDriverEntry = -1;
private void InitializeDriverEntriesList()
{
if (_driverEntriesList != null)
return;
_driverEntriesList ??= new ReorderableList(serializedObject, m_AnimatorsProp,
true, true, true, true)
{
drawHeaderCallback = OnDrawHeaderDriverEntry,
onMouseUpCallback = OnMouseUpDriverEntry,
drawElementCallback = OnDrawElementDriverEntry,
elementHeightCallback = OnHeightElementDriverEntry,
onChangedCallback = OnChangedDriverEntry,
onReorderCallbackWithDetails = OnReorderWithDetailsDriverEntry,
//list = _driver.animators,
index = -1
};
}
private void DrawEntries()
{
InitializeDriverEntriesList();
_driverEntriesList.displayAdd = _driverEntriesList.count < 16;
_driverEntriesList.DoLayoutList();
}
#region ReorderableListDrawing Driver Entries
private void OnDrawHeaderDriverEntry(Rect rect)
{
Rect labelRect = new Rect(rect.x, rect.y, rect.width - 35, EditorGUIUtility.singleLineHeight);
GUI.Label(labelRect, $"Animator Driver Entries ({_driverEntriesList.count} / 16)");
// our list being made from multiple array properties, the UtilityMenu cannot handle it
//EditorGUIExtensions.UtilityMenu(rect, _driverEntriesList, m_AnimatorsProp);
}
private void OnMouseUpDriverEntry(ReorderableList list)
{
if (list.index != _selectedDriverEntry)
{
_selectedDriverEntry = list.index;
}
else
{
if (list.index == -1)
return;
list.Deselect(_selectedDriverEntry);
list.index = _selectedDriverEntry = -1;
Repaint();
}
}
private void OnDrawElementDriverEntry(Rect rect, int index, bool isActive, bool isFocused)
{
if (index >= _driverEntriesList.count) return;
SerializedProperty driverEntry = _driverEntriesList.serializedProperty.GetArrayElementAtIndex(index);
if (driverEntry == null || index >= _driverEntriesList.serializedProperty.arraySize)
return;
rect = new Rect(rect.x, rect.y + 2, rect.width, EditorGUIUtility.singleLineHeight);
float spacing = EditorGUIUtility.singleLineHeight * 1.25f;
float originalLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 100;
SerializedProperty parameterValueProp = m_ParameterValuesPropList[index];
SerializedProperty parameterNameProp = m_AnimatorParametersProp.GetArrayElementAtIndex(index);
SerializedProperty parameterTypeProp = m_AnimatorParameterTypeProp.GetArrayElementAtIndex(index);
if (parameterValueProp == null || parameterNameProp == null || parameterTypeProp == null)
return;
EditorGUI.PropertyField(rect, driverEntry, new GUIContent("Animator"));
rect.y += spacing;
//EditorGUI.PropertyField(rect, parameterNameProp, new GUIContent("Parameter"));
parameterNameProp.stringValue = EditorGUIExtensions.AdvancedDropdownInput(rect,
parameterNameProp.stringValue,
CVRCommon.GetParametersFromAnimatorAsString((Animator)driverEntry.objectReferenceValue), // has null check
"Parameter", "No Parameters");
rect.y += spacing;
EditorGUI.PropertyField(rect, parameterValueProp, new GUIContent("Value"));
rect.y += spacing;
EditorGUIUtility.labelWidth = originalLabelWidth;
}
private float OnHeightElementDriverEntry(int index)
{
const float lineModifier = 1.25f;
const float baseHeight = 3f;
return baseHeight * lineModifier * EditorGUIUtility.singleLineHeight;
}
private void OnChangedDriverEntry(ReorderableList list)
{
EditorUtility.SetDirty(target);
serializedObject.ApplyModifiedProperties();
}
private void OnReorderWithDetailsDriverEntry(ReorderableList list, int oldIndex, int newIndex)
{
if (oldIndex < 0 || newIndex < 0 || oldIndex >= m_AnimatorsProp.arraySize || newIndex >= m_AnimatorsProp.arraySize)
return;
// m_AnimatorsProp is our base property for the reorderable list, so we don't need to move it
// when moving an element, we have to consider the between properties as well -_-
if (oldIndex < newIndex) // moving up (we dragged the element down)
for (int i = oldIndex; i < newIndex; i++) SwapParameterValuesPropList(i, i + 1);
else // moving down (we dragged the element up)
for (int i = oldIndex; i > newIndex; i--) SwapParameterValuesPropList(i, i - 1);
EditorUtility.SetDirty(target);
serializedObject.ApplyModifiedProperties();
return;
void SwapParameterValuesPropList(int index1, int index2)
{
m_AnimatorParametersProp.MoveArrayElement(index1, index2);
m_AnimatorParameterTypeProp.MoveArrayElement(index1, index2);
(m_ParameterValuesPropList[index1], m_ParameterValuesPropList[index2])
= (m_ParameterValuesPropList[index2], m_ParameterValuesPropList[index1]);
}
}
#endregion
}
}
#endif

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 62d32b85d371449ca067a5fc0688522d
timeCreated: 1703220016

View file

@ -1,66 +1,92 @@
using System;
using ABI.CCK.Components;
using UnityEditor;
using UnityEngine;
namespace ABI.CCK.Scripts.Editor
{
[CustomEditor(typeof(ABI.CCK.Components.CVRAssetInfo))]
[CanEditMultipleObjects]
[CustomEditor(typeof(CVRAssetInfo))]
public class CCK_CVRAssetInfoEditor : UnityEditor.Editor
{
private CVRAssetInfo _info;
private string _newGuid;
private SerializedProperty _objectIdProperty;
private string _newGUID;
#region Unity Events
private void OnEnable()
{
if (target == null)
return;
_objectIdProperty = serializedObject.FindProperty("objectId");
}
public override void OnInspectorGUI()
{
if (_info == null) _info = (CVRAssetInfo)target;
serializedObject.Update();
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_HEADER_INFORMATION"), MessageType.Info);
DrawHeaderInfo();
if (!string.IsNullOrEmpty(_info.objectId))
{
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_GUID_LABEL") + _info.objectId, MessageType.Info);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_DETACH_BUTTON")))
{
bool detach = EditorUtility.DisplayDialog(
CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_DETACH_BUTTON_DIALOG_TITLE"),
CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_DETACH_BUTTON_DIALOG_BODY"),
CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_DETACH_BUTTON_DIALOG_ACCEPT"),
CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_DETACH_BUTTON_DIALOG_DENY"));
if (detach) DetachGuid();
}
if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_COPY_BUTTON")))
{
if (!string.IsNullOrEmpty(_info.objectId))
{
GUIUtility.systemCopyBuffer = _info.objectId;
}
}
EditorGUILayout.EndHorizontal();
}
if (!string.IsNullOrEmpty(_objectIdProperty.stringValue))
DrawDetachGUID();
else
{
_newGuid = EditorGUILayout.TextField(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_ATTACH_LABEL"), _newGuid);
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_ATTACH_INFO"), MessageType.Warning);
if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_ATTACH_BUTTON"))) ReattachGuid(_newGuid);
}
DrawAttachGUID();
serializedObject.ApplyModifiedProperties();
}
private void DetachGuid()
#endregion
#region GUI Drawing
private void DrawHeaderInfo()
{
if (!string.IsNullOrEmpty(_info.objectId)) _info.objectId = string.Empty;
}
private void ReattachGuid(string Guid)
{
_info.objectId = Guid;
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_HEADER_INFORMATION"), MessageType.Info);
}
private void DrawDetachGUID()
{
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_GUID_LABEL") + _objectIdProperty.stringValue, MessageType.Info);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_DETACH_BUTTON")))
{
bool shouldDetach = EditorUtility.DisplayDialog(
CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_DETACH_BUTTON_DIALOG_TITLE"),
CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_DETACH_BUTTON_DIALOG_BODY"),
CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_DETACH_BUTTON_DIALOG_ACCEPT"),
CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_DETACH_BUTTON_DIALOG_DENY"));
if (shouldDetach)
{
_newGUID = _objectIdProperty.stringValue;
_objectIdProperty.stringValue = string.Empty;
}
}
if (GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_COPY_BUTTON")))
{
if (!string.IsNullOrEmpty(_objectIdProperty.stringValue))
GUIUtility.systemCopyBuffer = _objectIdProperty.stringValue;
}
EditorGUILayout.EndHorizontal();
}
private void DrawAttachGUID()
{
_newGUID = EditorGUILayout.TextField(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_ATTACH_LABEL"), _newGUID);
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_ATTACH_INFO"), MessageType.Warning);
if (!GUILayout.Button(CCKLocalizationProvider.GetLocalizedText("ABI_UI_ASSET_INFO_ATTACH_BUTTON")))
return;
if (System.Guid.TryParse(_newGUID, out _))
_objectIdProperty.stringValue = _newGUID;
}
#endregion
}
}
}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ce0296e1d6745c5468b89206222b3308
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,63 @@
#if UNITY_EDITOR
using UnityEditor;
// I likely overcomplicated this GUI. I'm not sure if I'll keep it this way or not.
namespace ABI.CCK.Components
{
[CanEditMultipleObjects]
[CustomEditor(typeof(CVRAudioDriver))]
public partial class CCK_CVRAudioDriverEditor : Editor
{
#region EditorGUI Foldouts
private static bool _guiAudioSettingsPlaybackFoldout;
private static bool _guiAudioSettingsAudioSourceFoldout;
#endregion
#region Private Variables
private CVRAudioDriver _audio;
#endregion
#region Serialized Properties
private SerializedProperty m_AudioSourceProp;
private SerializedProperty m_AudioClipsProp;
private SerializedProperty m_SelectedAudioClipProp;
private SerializedProperty m_PlayOnSwitchProp;
#endregion
#region Unity Events
private void OnEnable()
{
if (target == null) return;
_audio = (CVRAudioDriver)target;
m_AudioSourceProp = serializedObject.FindProperty(nameof(CVRAudioDriver.audioSource));
m_AudioClipsProp = serializedObject.FindProperty(nameof(CVRAudioDriver.audioClips));
m_SelectedAudioClipProp = serializedObject.FindProperty(nameof(CVRAudioDriver.selectedAudioClip));
m_PlayOnSwitchProp = serializedObject.FindProperty(nameof(CVRAudioDriver.playOnSwitch));
}
public override void OnInspectorGUI()
{
if (_audio == null)
return;
serializedObject.Update();
Draw_DriverSettings();
serializedObject.ApplyModifiedProperties();
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,54 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAudioDriverEditor
{
private void Draw_DriverSettings()
{
using (new LabelScope("Driver Settings"))
{
using (new EditorGUI.IndentLevelScope())
DrawDriverSettings();
}
}
private void DrawDriverSettings()
{
GUILayout.BeginVertical();
DrawPlaybackSettings();
EditorGUILayout.Space();
DrawAudioSources();
GUILayout.EndVertical();
}
#region Drawing Methods
private void DrawPlaybackSettings()
{
if (!InnerFoldout(ref _guiAudioSettingsPlaybackFoldout, "Playback"))
return;
EditorGUILayout.PropertyField(m_PlayOnSwitchProp, new GUIContent("Play On Switch"));
EditorGUILayout.PropertyField(m_SelectedAudioClipProp, new GUIContent("Selected Audio Clip"));
}
private void DrawAudioSources()
{
if (!InnerFoldout(ref _guiAudioSettingsAudioSourceFoldout, "Audio"))
return;
EditorGUILayout.PropertyField(m_AudioSourceProp, new GUIContent("Audio Source"));
EditorGUILayout.PropertyField(m_AudioClipsProp, new GUIContent("Audio Clips"), true);
}
#endregion
}
}
#endif

View file

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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0c8f7cf20a254f842b408a613966ab0f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 77bf502e56374ff8ba1488a070dc2435
timeCreated: 1709423065

View file

@ -0,0 +1,82 @@
#if UNITY_EDITOR
using ABI.CCK.Scripts;
using UnityEditor;
using UnityEngine;
using AnimatorController = UnityEditor.Animations.AnimatorController;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
// store so we can also know when an undo/redo happened
private RuntimeAnimatorController _lastBaseController;
private RuntimeAnimatorController _lastOverrideController;
private void DrawAutogenControllerFields()
{
RuntimeAnimatorController tempBaseController = EditorGUILayout.ObjectField(
"Base Controller",
m_baseControllerProp.objectReferenceValue,
typeof(RuntimeAnimatorController),
false) as RuntimeAnimatorController;
if (tempBaseController is not AnimatorOverrideController
&& tempBaseController != m_baseControllerProp.objectReferenceValue)
m_baseControllerProp.objectReferenceValue = tempBaseController;
EditorGUILayout.HelpBox(
"This is the Base Controller that is extended for the creation of your Advanced Avatar Settings. " +
"If you do not want to extend a specific Animator Controller, make sure that the Default Avatar Animator " +
"From the Directory 'ABI.CCK/Animations' is used here.", MessageType.Info);
RuntimeAnimatorController tempOverrideController = EditorGUILayout.ObjectField(
"Override Controller",
m_baseOverrideControllerProp.objectReferenceValue,
typeof(RuntimeAnimatorController),
false) as RuntimeAnimatorController;
if (tempOverrideController is not AnimatorController
&& tempOverrideController != m_baseOverrideControllerProp.objectReferenceValue)
m_baseOverrideControllerProp.objectReferenceValue = tempOverrideController;
EditorGUILayout.HelpBox(
"You can put your previous Override Controller here in order to put your overrides in " +
"the newly created Override Controller.", MessageType.Info);
if (_lastBaseController == m_baseControllerProp.objectReferenceValue
&& _lastOverrideController == m_baseOverrideControllerProp.objectReferenceValue)
return;
// change detected (undo/redo, inspector change, etc.)
_lastBaseController = m_baseControllerProp.objectReferenceValue as RuntimeAnimatorController;
_lastOverrideController = m_baseOverrideControllerProp.objectReferenceValue as RuntimeAnimatorController;
serializedObject.ApplyModifiedProperties(); // update backing fields
UpdateSyncUsageAndBaseParameters(); // update the sync usage and base parameters
}
private void DrawCreateControllerButton()
{
if (_syncedBitsTuple.Item2 <= CVRCommon.AVATAR_BIT_LIMIT)
{
if (GUILayout.Button("Create Controller"))
CreateAASController();
}
else
{
using (new EditorGUI.DisabledScope(true))
GUILayout.Button("Create Controller");
EditorGUILayout.HelpBox(
"Cannot create controller. You are over the Synced Bit Limit!", MessageType.Warning);
GUILayout.Space(5);
}
if (_avatar.avatarSettings.overrides == null ||
_avatar.avatarSettings.overrides == _avatar.overrides) return;
if (GUILayout.Button("Attach created Override to Avatar"))
m_OverridesProp.objectReferenceValue = _avatar.avatarSettings.overrides;
}
}
}
#endif

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d6aa02cac0694cab9ba81de900bdf4c6
timeCreated: 1714267882

View file

@ -0,0 +1,318 @@
#if UNITY_EDITOR
using System.Text.RegularExpressions;
using ABI.CCK.Scripts;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using AnimatorController = UnityEditor.Animations.AnimatorController;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
#region ReorderableListDrawing AAS
private void OnMouseUpAAS(ReorderableList list)
{
if (list.index != _selectedAdvSetting)
{
_selectedAdvSetting = list.index;
}
else
{
if (list.index == -1)
return;
list.Deselect(_selectedAdvSetting);
list.index = _selectedAdvSetting = -1;
Repaint();
}
}
private void OnChangedAAS(ReorderableList list)
{
EditorUtility.SetDirty(_avatar);
serializedObject.ApplyModifiedProperties();
}
private void OnReorderedAAS(ReorderableList list)
{
// this is a bandaid fix for the reorderable list not updating the nested reorderable list
foreach (CVRAdvancedSettingsEntry aasEntry in _advSettingsList.list)
{
CVRAdvancesAvatarSettingBase setting = aasEntry.setting;
switch (setting)
{
case CVRAdvancesAvatarSettingGameObjectToggle toggle:
toggle.reorderableList = null; // needs recreation
break;
case CVRAdvancedAvatarSettingMaterialColor color:
color.reorderableList = null; // needs recreation
break;
case CVRAdvancesAvatarSettingSlider slider:
slider.reorderableList = null; // needs recreation
break;
case CVRAdvancesAvatarSettingGameObjectDropdown dropdown:
dropdown.reorderableList = null; // needs recreation
break;
}
}
}
private void OnDrawHeaderAAS(Rect rect)
{
Rect labelRect = new(rect.x, rect.y, rect.width - 35, EditorGUIUtility.singleLineHeight);
GUI.Label(labelRect, $"Inputs ({_advSettingsList.count})");
EditorGUIExtensions.UtilityMenu(rect, _advSettingsList, m_settingEntriesProp, AppendUtilityMenu);
}
private float OnHeightElementAAS(int index)
{
float height = EditorGUIUtility.singleLineHeight * 1.25f;
if (index < 0 || index >= _avatar.avatarSettings.settings.Count)
return height;
CVRAdvancedSettingsEntry advSettingEntry = _avatar.avatarSettings.settings[index];
if (advSettingEntry.isCollapsed)
return height;
float lines = 5f; // 4 lines for the basic settings + 1 for the autogen foldout
switch (advSettingEntry.setting)
{
case CVRAdvancesAvatarSettingGameObjectToggle toggle:
if (advSettingEntry.isAutogenCollapsed) break;
if (toggle.useAnimationClip)
{
lines += 3f;
break;
}
lines += 3.5f; // reorderable list header & footer + space after
lines += toggle.gameObjectTargets.Count == 0 ? 1f : toggle.gameObjectTargets.Count * 1.09f;
break;
case CVRAdvancedAvatarSettingMaterialColor color:
if (advSettingEntry.isAutogenCollapsed) break;
lines += 2.5f; // reorderable list header & footer + space after
lines += color.materialColorTargets.Count == 0 ? 1f : color.materialColorTargets.Count * 1.09f;
break;
case CVRAdvancesAvatarSettingSlider slider:
if (advSettingEntry.isAutogenCollapsed) break;
if (slider.useAnimationClip)
{
lines += 3f;
break;
}
lines += 3.5f; // reorderable list header & footer + space after
lines += slider.materialPropertyTargets.Count == 0 ? 2f : slider.materialPropertyTargets.Count * 2.09f;
break;
case CVRAdvancesAvatarSettingJoystick2D or CVRAdvancesAvatarSettingJoystick3D:
lines += 3.5f; // no fancy autogen stuff but has min/max
break;
case CVRAdvancesAvatarSettingInputSingle or CVRAdvancesAvatarSettingInputVector2 or CVRAdvancesAvatarSettingInputVector3:
lines += 1.5f; // no fancy autogen stuff
break;
case CVRAdvancesAvatarSettingGameObjectDropdown dropdown:
lines += 2f; // reorderable list header & footer, but one less due to autogen foldout
lines += dropdown.options.Count == 0 ? 1f : dropdown.options.Count * 1.09f;
foreach (CVRAdvancedSettingsDropDownEntry dropDownEntry in dropdown.options)
{
if (dropDownEntry.isAutogenCollapsed)
continue;
lines += 1f; // use animation toggle
if (dropDownEntry.useAnimationClip)
{
lines += 1f; // one animation field
continue;
}
lines += 2.5f; // reorderable list header & footer + space after
lines += dropDownEntry.gameObjectTargets.Count == 0 ? 1f : dropDownEntry.gameObjectTargets.Count * 1.09f;
}
break;
}
return lines * height;
}
private void OnDrawElementAAS(Rect rect, int index, bool isActive, bool isFocused)
{
if (index >= _advSettingsList.count) return;
CVRAdvancedSettingsEntry advSettingEntry = (CVRAdvancedSettingsEntry)_advSettingsList.list[index];
SerializedProperty advSettingEntryProp = m_settingEntriesProp.GetArrayElementAtIndex(index);
if (advSettingEntryProp == null || index >= m_settingEntriesProp.arraySize)
return;
DrawAdvSettingEntry(rect, advSettingEntry, advSettingEntryProp);
}
#endregion
#region Drawing Methods
private void DrawAdvSettingEntry(Rect rect, CVRAdvancedSettingsEntry advSettingEntry, SerializedProperty advSettingEntryProp)
{
// boilerplate
rect = new Rect(rect.x, rect.y + 2, rect.width, EditorGUIUtility.singleLineHeight);
float spacing = EditorGUIUtility.singleLineHeight * 1.25f;
float originalLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 120;
SerializedProperty nameProp = advSettingEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsEntry.name));
SerializedProperty machineNameProp = advSettingEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsEntry.machineName));
SerializedProperty entryType = advSettingEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsEntry.type));
SerializedProperty isCollapsed = advSettingEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsEntry.isCollapsed));
SerializedProperty unlinkNameFromMachine = advSettingEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsEntry.unlinkNameFromMachineName));
Texture2D autoIcon = (unlinkNameFromMachine.boolValue
? EditorGUIUtility.Load("d_Linked")
: EditorGUIUtility.Load("d_Unlinked")) as Texture2D;
GUIContent autoButtonContent = new(autoIcon, "Unlink/Link Name to Machine");
EditorGUILayout.BeginHorizontal();
Rect positionFull = rect;
var remainingWidth = positionFull.width - EditorGUIUtility.labelWidth - 20f;
isCollapsed.boolValue = !EditorGUI.Foldout(
new Rect(positionFull.x + 10, positionFull.y, EditorGUIUtility.labelWidth - 20f, positionFull.height),
!isCollapsed.boolValue, "Name", true);
if (GUI.Button(new Rect(positionFull.x + EditorGUIUtility.labelWidth + 2f, positionFull.y, 20f,
positionFull.height), autoButtonContent, GUIStyle.none))
unlinkNameFromMachine.boolValue = !unlinkNameFromMachine.boolValue;
string oldName = nameProp.stringValue;
EditorGUI.PropertyField(
new Rect(positionFull.x + EditorGUIUtility.labelWidth + 24f, positionFull.y, remainingWidth,
positionFull.height), nameProp, GUIContent.none);
if (oldName != nameProp.stringValue &&
!unlinkNameFromMachine.boolValue) // update machine name if not unlinked
machineNameProp.stringValue = Regex.Replace(nameProp.stringValue, @"[^a-zA-Z0-9/\-_#]", "");
EditorGUILayout.EndHorizontal();
if (isCollapsed.boolValue)
{
// TODO: Draw collapsed version
EditorGUIUtility.labelWidth = originalLabelWidth;
return;
}
rect.y += spacing;
if (unlinkNameFromMachine.boolValue)
{
// search dropdown for machine name
machineNameProp.stringValue = EditorGUIExtensions.AdvancedDropdownInput(
rect,
machineNameProp.stringValue,
_baseControllerParams,
"Parameter",
"No Parameters"
);
}
else
{
//EditorGUI.LabelField(rect, "Parameter", machineNameProp.stringValue);
GUI.enabled = false;
EditorGUI.TextField(rect, "Parameter", machineNameProp.stringValue); // i like the border
GUI.enabled = true;
}
rect.y += spacing;
// setting type dropdowns
EditorGUILayout.BeginHorizontal();
Rect position = rect;
float halfWidth = (position.width - EditorGUIUtility.labelWidth) / 2 - 2;
// Setting Type
var oldType = entryType.enumValueIndex;
EditorGUI.PropertyField(
new Rect(position.x, position.y, EditorGUIUtility.labelWidth + halfWidth, position.height), entryType,
new GUIContent("Setting Type"));
// get the property for the specific setting type
SerializedProperty advSettingProp = entryType.enumValueIndex switch
{
(int)CVRAdvancedSettingsEntry.SettingsType.Color => advSettingEntryProp.FindPropertyRelative(
nameof(CVRAdvancedSettingsEntry.materialColorSettings)),
(int)CVRAdvancedSettingsEntry.SettingsType.Dropdown => advSettingEntryProp.FindPropertyRelative(
nameof(CVRAdvancedSettingsEntry.dropDownSettings)),
(int)CVRAdvancedSettingsEntry.SettingsType.Slider => advSettingEntryProp.FindPropertyRelative(
nameof(CVRAdvancedSettingsEntry.sliderSettings)),
(int)CVRAdvancedSettingsEntry.SettingsType.Joystick2D => advSettingEntryProp.FindPropertyRelative(
nameof(CVRAdvancedSettingsEntry.joystick2DSetting)),
(int)CVRAdvancedSettingsEntry.SettingsType.Joystick3D => advSettingEntryProp.FindPropertyRelative(
nameof(CVRAdvancedSettingsEntry.joystick3DSetting)),
(int)CVRAdvancedSettingsEntry.SettingsType.InputSingle => advSettingEntryProp.FindPropertyRelative(
nameof(CVRAdvancedSettingsEntry.inputSingleSettings)),
(int)CVRAdvancedSettingsEntry.SettingsType.InputVector2 => advSettingEntryProp.FindPropertyRelative(
nameof(CVRAdvancedSettingsEntry.inputVector2Settings)),
(int)CVRAdvancedSettingsEntry.SettingsType.InputVector3 => advSettingEntryProp.FindPropertyRelative(
nameof(CVRAdvancedSettingsEntry.inputVector3Settings)),
_ => advSettingEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsEntry.toggleSettings))
};
// part of the setting base for whatever reason, so gotta get it after above
SerializedProperty usedType = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingBase.usedType));
if (oldType != entryType.enumValueIndex)
{
usedType.intValue = (int)CVRAdvancedAvatarSettings.GetDefaultType((CVRAdvancedSettingsEntry.SettingsType)entryType.enumValueIndex);
serializedObject.ApplyModifiedProperties(); // apply the change
}
// used-type dropdown (filtered by setting type)
usedType.intValue = (int)EnumFilter.FilteredEnumPopup(
new Rect(position.x + EditorGUIUtility.labelWidth + halfWidth + 4, position.y, halfWidth,
position.height),
(CVRAdvancesAvatarSettingBase.ParameterType)usedType.intValue,
CVRAdvancedAvatarSettings.GetSupportedTypes(
(CVRAdvancedSettingsEntry.SettingsType)entryType.enumValueIndex)
);
EditorGUILayout.EndHorizontal();
// draw default value by type
rect.y += spacing;
switch ((CVRAdvancedSettingsEntry.SettingsType)entryType.enumValueIndex)
{
default:
case CVRAdvancedSettingsEntry.SettingsType.Toggle:
DrawToggleInternal(rect, spacing, advSettingEntry, advSettingProp);
break;
case CVRAdvancedSettingsEntry.SettingsType.Dropdown:
DrawDropdownInternal(rect, spacing, advSettingEntry, advSettingProp);
break;
case CVRAdvancedSettingsEntry.SettingsType.Color:
DrawColorInternal(rect, spacing, advSettingEntry, advSettingProp);
break;
case CVRAdvancedSettingsEntry.SettingsType.Slider:
DrawSliderInternal(rect, spacing, advSettingEntry, advSettingProp);
break;
case CVRAdvancedSettingsEntry.SettingsType.Joystick2D:
DrawJoystick2DInternal(rect, spacing, advSettingEntry, advSettingProp);
break;
case CVRAdvancedSettingsEntry.SettingsType.Joystick3D:
DrawJoystick3DInternal(rect, spacing, advSettingEntry, advSettingProp);
break;
case CVRAdvancedSettingsEntry.SettingsType.InputSingle:
DrawInputSingleInternal(rect, spacing, advSettingEntry, advSettingProp);
break;
case CVRAdvancedSettingsEntry.SettingsType.InputVector2:
DrawInputVector2Internal(rect, spacing, advSettingEntry, advSettingProp);
break;
case CVRAdvancedSettingsEntry.SettingsType.InputVector3:
DrawInputVector3Internal(rect, spacing, advSettingEntry, advSettingProp);
break;
}
EditorGUIUtility.labelWidth = originalLabelWidth;
}
#endregion
}
}
#endif

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6118c371302943b6bb8a740c62dd0a97
timeCreated: 1714268283

View file

@ -0,0 +1,245 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using ABI.CCK.Scripts;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.Rendering;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
private void DrawColorInternal(
Rect rect,
float spacing,
CVRAdvancedSettingsEntry advSettingEntry,
SerializedProperty advSettingProp)
{
CVRAdvancedAvatarSettingMaterialColor colorSetting = (CVRAdvancedAvatarSettingMaterialColor)advSettingEntry.setting;
SerializedProperty defaultValueProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancedAvatarSettingMaterialColor.defaultValue));
EditorGUI.PropertyField(rect, defaultValueProp, new GUIContent("Default Color"));
rect.y += spacing;
// foldout
advSettingEntry.isAutogenCollapsed = !EditorGUI.Foldout(rect, !advSettingEntry.isAutogenCollapsed, "Autogeneration Options", true, s_BoldFoldoutStyle);
if (advSettingEntry.isAutogenCollapsed)
return;
// autogen stuff
rect.y += spacing;
SerializedProperty materialColorTargets = advSettingProp.FindPropertyRelative(nameof(CVRAdvancedAvatarSettingMaterialColor.materialColorTargets));
// Material Color Targets List
if (colorSetting.reorderableList == null // recreate list if null or stale
|| colorSetting.reorderableList.serializedProperty.serializedObject != serializedObject)
{
colorSetting.reorderableList = new ReorderableList(serializedObject, materialColorTargets,
true, true, true, true)
{
list = colorSetting.materialColorTargets,
};
colorSetting.reorderableList.drawElementCallback = (innerRect, innerIndex, _, _) =>
{
innerRect = new Rect(innerRect.x, innerRect.y + 2, innerRect.width, EditorGUIUtility.singleLineHeight);
SerializedProperty colorEntry = colorSetting.reorderableList.serializedProperty.GetArrayElementAtIndex(innerIndex);
const float elementSpacing = 5;
const float infoIconWidth = 20;
float innerRectHalfWidth = innerRect.width * 0.5f;
// GameObject Field
innerRect.width = innerRectHalfWidth;
SerializedProperty materialColorProp = colorEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialColor.gameObject));
EditorGUI.PropertyField(innerRect, materialColorProp, GUIContent.none);
string tooltipPath = "No Target";
var propertyList = new Dictionary<string, string>();
if (materialColorProp.objectReferenceValue != null)
{
Transform avatarTransform = _avatar.transform;
Transform targetTransform = ((GameObject)materialColorProp.objectReferenceValue).transform;
if (!targetTransform.IsChildOf(avatarTransform))
{
materialColorProp.objectReferenceValue = null; // invalid
}
else
{
MeshRenderer meshRenderer = targetTransform.GetComponent<MeshRenderer>();
SkinnedMeshRenderer skinnedMeshRenderer = targetTransform.GetComponent<SkinnedMeshRenderer>();
ParticleSystemRenderer particleRenderer = targetTransform.GetComponent<ParticleSystemRenderer>();
LineRenderer lineRenderer =targetTransform.GetComponent<LineRenderer>();
TrailRenderer trailRenderer = targetTransform.GetComponent<TrailRenderer>();
bool rendererFound = meshRenderer || skinnedMeshRenderer || particleRenderer ||
lineRenderer || trailRenderer;
if (rendererFound)
{
#region Populate Property List
if (meshRenderer != null)
{
foreach (Material material in meshRenderer.sharedMaterials)
{
if (material == null) continue;
Shader shader = material.shader;
for (var j = 0; j < shader.GetPropertyCount(); j++)
{
if (shader.GetPropertyType(j) != ShaderPropertyType.Color) continue;
var propertyKey = "MeshRenderer: " + shader.GetPropertyDescription(j) +
"(" + shader.GetPropertyName(j) + ")";
if (!propertyList.ContainsKey(propertyKey))
propertyList.Add(propertyKey, "MSR:" + shader.GetPropertyName(j));
}
}
}
if (skinnedMeshRenderer != null)
{
foreach (Material material in skinnedMeshRenderer.sharedMaterials)
{
if (material == null) continue;
Shader shader = material.shader;
for (var j = 0; j < shader.GetPropertyCount(); j++)
{
if (shader.GetPropertyType(j) != ShaderPropertyType.Color) continue;
var propertyKey = "SkinnedMeshRenderer: " +
shader.GetPropertyDescription(j) + "(" +
shader.GetPropertyName(j) + ")";
if (!propertyList.ContainsKey(propertyKey))
propertyList.Add(propertyKey, "SMR:" + shader.GetPropertyName(j));
}
}
}
if (particleRenderer != null)
{
foreach (Material material in particleRenderer.sharedMaterials)
{
if (material == null) continue;
Shader shader = material.shader;
for (var j = 0; j < shader.GetPropertyCount(); j++)
{
if (shader.GetPropertyType(j) != ShaderPropertyType.Color) continue;
var propertyKey = "ParticleRenderer: " + shader.GetPropertyDescription(j) +
"(" + shader.GetPropertyName(j) + ")";
if (!propertyList.ContainsKey(propertyKey))
propertyList.Add(propertyKey, "PTR:" + shader.GetPropertyName(j));
}
}
}
if (lineRenderer != null)
{
foreach (Material material in lineRenderer.sharedMaterials)
{
if (material == null) continue;
Shader shader = material.shader;
for (var j = 0; j < shader.GetPropertyCount(); j++)
{
if (shader.GetPropertyType(j) != ShaderPropertyType.Color) continue;
var propertyKey = "LineRenderer: " + shader.GetPropertyDescription(j) +
"(" + shader.GetPropertyName(j) + ")";
if (!propertyList.ContainsKey(propertyKey))
propertyList.Add(propertyKey, "LNR:" + shader.GetPropertyName(j));
}
}
}
if (trailRenderer != null)
{
foreach (Material material in trailRenderer.sharedMaterials)
{
if (material == null) continue;
Shader shader = material.shader;
for (var j = 0; j < shader.GetPropertyCount(); j++)
{
if (shader.GetPropertyType(j) != ShaderPropertyType.Color) continue;
var propertyKey = "TrailRenderer: " + shader.GetPropertyDescription(j) +
"(" + shader.GetPropertyName(j) + ")";
if (!propertyList.ContainsKey(propertyKey))
propertyList.Add(propertyKey, "TLR:" + shader.GetPropertyName(j));
}
}
}
#endregion
}
else
{
materialColorProp.objectReferenceValue = null; // invalid
}
SerializedProperty materialColorPathProp = colorEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialColor.treePath));
materialColorPathProp.stringValue = AnimationUtility.CalculateTransformPath(targetTransform, avatarTransform);
tooltipPath = $"Path: {avatarTransform.name}/{materialColorPathProp.stringValue}";
}
}
// Property Dropdown
innerRect.x += innerRectHalfWidth + elementSpacing;
innerRect.width -= 2*infoIconWidth - 2*elementSpacing; // left/right padding
SerializedProperty propNameProp = colorEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialColor.propertyName));
SerializedProperty propTypeIdProp = colorEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialColor.propertyTypeIdentifier));
// not valid as a serialized property?
//SerializedProperty propTypeProp = toggleEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialColor.propertyType));
//var propNames = propertyList.Keys.ToArray();
var propDescs = propertyList.Values.ToArray();
string currentItem = propNameProp.stringValue.Length > 0
? propTypeIdProp.stringValue + ":" + propNameProp.stringValue
: CVRCommon.NONE_OR_EMPTY;
// search dropdown for material properties
int selected = EditorGUIExtensions.CustomPopup(
innerRect,
Array.IndexOf(propDescs, currentItem),
propDescs,
"No Properties"
);
// name: _Color
// typeid: SMR
// type: SkinnedMeshRenderer
if (selected >= 0)
{
currentItem = propDescs[selected];
propNameProp.stringValue = currentItem[4..];
propTypeIdProp.stringValue = currentItem[..3];
serializedObject.ApplyModifiedProperties();
// propType is not a valid serialized property
// so autogen will need to handle this
}
// Path Info
innerRect.x += innerRect.width + elementSpacing;
innerRect.width = infoIconWidth;
EditorGUI.LabelField(innerRect, new GUIContent(EditorGUIUtility.IconContent("d_animationanimated").image, tooltipPath));
};
colorSetting.reorderableList.elementHeight = EditorGUIUtility.singleLineHeight + 4f;
colorSetting.reorderableList.drawHeaderCallback = (headerRect) =>
{
Rect labelRect = new(headerRect.x, headerRect.y, headerRect.width - 35, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(labelRect, $"Color Targets ({materialColorTargets.arraySize})");
labelRect.x += 35; // not sure why this is needed, nested lists are weird
EditorGUIExtensions.UtilityMenu(labelRect, colorSetting.reorderableList, materialColorTargets);
};
}
colorSetting.reorderableList.DoList(rect);
}
}
}
#endif

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d0297c5beb0a41ea8108dcbda5dd6bc0
timeCreated: 1709424213

View file

@ -0,0 +1,202 @@
#if UNITY_EDITOR
using ABI.CCK.Scripts;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
void DrawDropdownInternal(
Rect rect,
float spacing,
CVRAdvancedSettingsEntry advSettingEntry,
SerializedProperty advSettingProp)
{
CVRAdvancesAvatarSettingGameObjectDropdown dropdownSetting = (CVRAdvancesAvatarSettingGameObjectDropdown)advSettingEntry.setting;
SerializedProperty defaultValueProp =
advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingGameObjectDropdown
.defaultValue));
int selectedValue = defaultValueProp.intValue; // default value is index of the dropdown options
selectedValue = EditorGUI.Popup(rect, "Default Value", selectedValue, dropdownSetting.optionNames);
defaultValueProp.intValue = selectedValue;
rect.y += spacing;
// foldout
// advSettingEntry.isAutogenCollapsed = !EditorGUI.Foldout(rect, !advSettingEntry.isAutogenCollapsed,
// "Autogeneration Options", true, s_BoldFoldoutStyle);
// if (advSettingEntry.isAutogenCollapsed)
// return;
// autogen stuff
//rect.y += spacing;
SerializedProperty dropdownOptionsProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingGameObjectDropdown.options));
// GameObject Targets List
if (dropdownSetting.reorderableList == null // recreate list if null or stale
|| dropdownSetting.reorderableList.serializedProperty.serializedObject != serializedObject)
{
dropdownSetting.reorderableList = new ReorderableList(serializedObject, dropdownOptionsProp,
true, true, true, true)
{
list = dropdownSetting.options,
};
dropdownSetting.reorderableList.drawElementCallback = (innerRect, innerIndex, _, _) =>
{
if (innerIndex < 0 || innerIndex >= dropdownSetting.options.Count)
return;
innerRect = new Rect(innerRect.x, innerRect.y + 2, innerRect.width, EditorGUIUtility.singleLineHeight);
SerializedProperty dropdownEntryProp = dropdownSetting.reorderableList.serializedProperty.GetArrayElementAtIndex(innerIndex);
CVRAdvancedSettingsDropDownEntry dropDownEntry = dropdownSetting.options[innerIndex];
const float elementSpacing = 10;
float innerRectHalfWidth = innerRect.width * 0.5f;
Rect splitRect = new(innerRect);
// Autogen Dropdown (i have no fucking idea how to make this look good... im sorry)
splitRect.x += elementSpacing;
splitRect.width = innerRectHalfWidth;
dropDownEntry.isAutogenCollapsed = !EditorGUI.Foldout(splitRect,
!dropDownEntry.isAutogenCollapsed, $"Element Name ({innerIndex})", true/*, s_BoldFoldoutStyle*/);
// Name Field
splitRect.x += innerRectHalfWidth;
splitRect.width -= elementSpacing; // left/right padding
SerializedProperty nameProp = dropdownEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsDropDownEntry.name));
EditorGUI.PropertyField(splitRect, nameProp, GUIContent.none);
if (dropDownEntry.isAutogenCollapsed)
return;
// autogen stuff
innerRect.y += spacing;
#region Internal Drawing - Dropdown Inner-Autogen
SerializedProperty useAnimationProp = dropdownEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsDropDownEntry.useAnimationClip));
SerializedProperty animationClipProp = dropdownEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsDropDownEntry.animationClip));
useAnimationProp.boolValue = EditorGUI.Toggle(innerRect, "Use Animation Clip", useAnimationProp.boolValue);
innerRect.y += spacing;
// Animation Clip Field
if (useAnimationProp.boolValue)
{
EditorGUI.PropertyField(new Rect(innerRect.x, innerRect.y, innerRect.width, EditorGUIUtility.singleLineHeight), animationClipProp);
return;
}
#region Internal Drawing - Dropdown Inner-Autogen-GameObjectTargets
SerializedProperty gameObjectTargetsProp = dropdownEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsDropDownEntry.gameObjectTargets));
// GameObject Targets List
if (dropDownEntry.reorderableList == null // recreate list if null or stale
|| dropDownEntry.reorderableList.serializedProperty.serializedObject != serializedObject
|| dropDownEntry.reorderableList.serializedProperty != gameObjectTargetsProp)
{
dropDownEntry.reorderableList = new ReorderableList(serializedObject, gameObjectTargetsProp,
true, true, true, true)
{
list = dropDownEntry.gameObjectTargets,
};
dropDownEntry.reorderableList.drawElementCallback = (innerInnerRect, innerInnerIndex, _, _) =>
{
innerInnerRect = new Rect(innerInnerRect.x, innerInnerRect.y + 2, innerInnerRect.width, EditorGUIUtility.singleLineHeight);
SerializedProperty toggleEntryProp = dropDownEntry.reorderableList.serializedProperty.GetArrayElementAtIndex(innerInnerIndex);
const float innerElementSpacing = 5;
const float infoIconWidth = 20;
// GameObject Field
innerInnerRect.width = innerInnerRect.width * 0.5f;
SerializedProperty gameObjectProp = toggleEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryGameObject.gameObject));
EditorGUI.PropertyField(innerInnerRect, gameObjectProp, GUIContent.none);
string tooltipPath = "No Target";
if (gameObjectProp.objectReferenceValue != null)
{
Transform avatarTransform = _avatar.transform;
Transform targetTransform = ((GameObject)gameObjectProp.objectReferenceValue).transform;
if (!targetTransform.IsChildOf(avatarTransform))
{
gameObjectProp.objectReferenceValue = null;
}
else
{
SerializedProperty gameObjectPathProp = toggleEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryGameObject.treePath));
gameObjectPathProp.stringValue = AnimationUtility.CalculateTransformPath(targetTransform, avatarTransform);
tooltipPath = $"Path: {avatarTransform.name}/{gameObjectPathProp.stringValue}";
}
}
// OnState Field
innerInnerRect.x += innerRectHalfWidth + innerElementSpacing;
innerInnerRect.width -= 2*infoIconWidth - 2*innerElementSpacing; // left/right padding
SerializedProperty onStateProp = toggleEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryGameObject.onState));
onStateProp.boolValue = EditorGUI.Popup(innerInnerRect, onStateProp.boolValue ? 1 : 0, BoolAsStringDisplayOptions) == 1;
// Path Info
innerInnerRect.x += innerInnerRect.width + innerElementSpacing;
innerInnerRect.width = infoIconWidth;
EditorGUI.LabelField(innerInnerRect, new GUIContent(EditorGUIUtility.IconContent("d_animationanimated").image, tooltipPath));
};
dropDownEntry.reorderableList.elementHeight = EditorGUIUtility.singleLineHeight + 4f;
dropDownEntry.reorderableList.drawHeaderCallback = (headerRect) =>
{
Rect labelRect = new(headerRect.x, headerRect.y, headerRect.width - 35, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(labelRect, $"GameObject Targets ({gameObjectTargetsProp.arraySize})");
labelRect.x += 35; // not sure why this is needed, nested lists are weird
EditorGUIExtensions.UtilityMenu(labelRect, dropDownEntry.reorderableList, gameObjectTargetsProp);
};
}
dropDownEntry.reorderableList.DoList(innerRect);
#endregion
#endregion
};
dropdownSetting.reorderableList.elementHeight = EditorGUIUtility.singleLineHeight + 4f;
dropdownSetting.reorderableList.elementHeightCallback = (innerIndex) =>
{
float height = EditorGUIUtility.singleLineHeight * 1.25f;
if (innerIndex < 0 || innerIndex >= dropdownSetting.options.Count)
return height;
CVRAdvancedSettingsDropDownEntry dropdownEntry = dropdownSetting.options[innerIndex];
if (dropdownEntry.isAutogenCollapsed) return height;
float lines = 1f; // use animation toggle
if (dropdownEntry.useAnimationClip)
{
lines += 2f; // both animation fields
return lines * height;
}
lines += 3.5f; // reorderable list header & footer + space after
lines += dropdownEntry.gameObjectTargets.Count == 0 ? 1f : dropdownEntry.gameObjectTargets.Count * 1.09f;
return lines * height;
};
dropdownSetting.reorderableList.drawHeaderCallback = (headerRect) =>
{
Rect labelRect = new(headerRect.x, headerRect.y, headerRect.width - 35, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(labelRect, $"Dropdown Options ({dropdownOptionsProp.arraySize})");
labelRect.x += 35; // not sure why this is needed, nested lists are weird
EditorGUIExtensions.UtilityMenu(labelRect, dropdownSetting.reorderableList, dropdownOptionsProp);
};
}
dropdownSetting.reorderableList.DoList(rect);
}
}
}
#endif

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4e1f511a5d874fd9b5bc9c8a1728066e
timeCreated: 1709424050

View file

@ -0,0 +1,62 @@
#if UNITY_EDITOR
using ABI.CCK.Scripts;
using UnityEditor;
using UnityEngine;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
void DrawInputSingleInternal(
Rect rect,
float spacing,
CVRAdvancedSettingsEntry advSettingEntry,
SerializedProperty advSettingProp)
{
SerializedProperty defaultValueProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingInputSingle.defaultValue));
EditorGUI.PropertyField(rect, defaultValueProp, new GUIContent("Default Value"));
rect.y += spacing;
rect.height *= 2.5f;
EditorGUI.HelpBox(rect, "This Settings does not provide a Setup Utility. " +
"But it will create the necessary Animator Layers, Parameters and Animations. " +
"So you can edit them to your liking after the controller is created.",
MessageType.Info);
}
void DrawInputVector2Internal(
Rect rect,
float spacing,
CVRAdvancedSettingsEntry advSettingEntry,
SerializedProperty advSettingProp)
{
SerializedProperty defaultValueProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingInputVector2.defaultValue));
EditorGUI.PropertyField(rect, defaultValueProp, new GUIContent("Default Value"));
rect.y += spacing;
rect.height *= 2.5f;
EditorGUI.HelpBox(rect, "This Settings does not provide a Setup Utility. " +
"But it will create the necessary Animator Layers, Parameters and Animations. " +
"So you can edit them to your liking after the controller is created.",
MessageType.Info);
}
void DrawInputVector3Internal(
Rect rect,
float spacing,
CVRAdvancedSettingsEntry advSettingEntry,
SerializedProperty advSettingProp)
{
SerializedProperty defaultValueProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingInputVector3.defaultValue));
EditorGUI.PropertyField(rect, defaultValueProp, new GUIContent("Default Value"));
rect.y += spacing;
rect.height *= 2.5f;
EditorGUI.HelpBox(rect, "This Settings does not provide a Setup Utility. " +
"But it will create the necessary Animator Layers, Parameters and Animations. " +
"So you can edit them to your liking after the controller is created.",
MessageType.Info);
}
}
}
#endif

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fd5428143ca147de8f8649f82edbce3b
timeCreated: 1709424338

View file

@ -0,0 +1,61 @@
#if UNITY_EDITOR
using ABI.CCK.Scripts;
using UnityEditor;
using UnityEngine;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
private void DrawJoystick2DInternal(
Rect rect,
float spacing,
CVRAdvancedSettingsEntry advSettingEntry,
SerializedProperty advSettingProp)
{
SerializedProperty defaultValueProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingJoystick2D.defaultValue));
EditorGUI.PropertyField(rect, defaultValueProp, new GUIContent("Default Value"));
rect.y += spacing;
// min/max
SerializedProperty minProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingJoystick2D.rangeMin));
SerializedProperty maxProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingJoystick2D.rangeMax));
EditorGUI.PropertyField(rect, minProp, new GUIContent("Min Value"));
rect.y += spacing;
EditorGUI.PropertyField(rect, maxProp, new GUIContent("Max Value"));
rect.y += spacing;
rect.height *= 2.5f;
EditorGUI.HelpBox(rect, "This Settings does not provide a Setup Utility. " +
"But it will create the necessary Animator Layers, Parameters and Animations. " +
"So you can edit them to your liking after the controller is created.",
MessageType.Info);
}
private void DrawJoystick3DInternal(
Rect rect,
float spacing,
CVRAdvancedSettingsEntry advSettingEntry,
SerializedProperty advSettingProp)
{
SerializedProperty defaultValueProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingJoystick3D.defaultValue));
EditorGUI.PropertyField(rect, defaultValueProp, new GUIContent("Default Value"));
rect.y += spacing;
// min/max
SerializedProperty minProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingJoystick3D.rangeMin));
SerializedProperty maxProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingJoystick3D.rangeMax));
EditorGUI.PropertyField(rect, minProp, new GUIContent("Min Value"));
rect.y += spacing;
EditorGUI.PropertyField(rect, maxProp, new GUIContent("Max Value"));
rect.y += spacing;
rect.height *= 2.5f;
EditorGUI.HelpBox(rect, "This Settings does not provide a Setup Utility. " +
"But it will create the necessary Animator Layers, Parameters and Animations. " +
"So you can edit them to your liking after the controller is created.",
MessageType.Info);
}
}
}
#endif

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 877f1862df6d493fb7547361ef50ce65
timeCreated: 1709424273

View file

@ -0,0 +1,275 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using ABI.CCK.Scripts;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.Rendering;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
private void DrawSliderInternal(
Rect rect,
float spacing,
CVRAdvancedSettingsEntry advSettingEntry,
SerializedProperty advSettingProp)
{
CVRAdvancesAvatarSettingSlider sliderSetting = (CVRAdvancesAvatarSettingSlider)advSettingEntry.setting;
// min/max is not yet exposed, but is in the client
SerializedProperty defaultValueProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingSlider.defaultValue));
defaultValueProp.floatValue = EditorGUI.Slider(rect, "Default Value", defaultValueProp.floatValue, 0f, 1f);
rect.y += spacing;
// foldout
advSettingEntry.isAutogenCollapsed = !EditorGUI.Foldout(rect, !advSettingEntry.isAutogenCollapsed, "Autogeneration Options", true, s_BoldFoldoutStyle);
if (advSettingEntry.isAutogenCollapsed)
return;
// autogen stuff
rect.y += spacing;
SerializedProperty useAnimationProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingSlider.useAnimationClip));
SerializedProperty minAnimationClipProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingSlider.minAnimationClip));
SerializedProperty maxAnimationClipProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingSlider.maxAnimationClip));
useAnimationProp.boolValue = EditorGUI.Toggle(rect, "Use Animation Clip", useAnimationProp.boolValue);
rect.y += spacing;
// Animation Clip Fields
if (useAnimationProp.boolValue)
{
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), minAnimationClipProp);
rect.y += spacing;
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), maxAnimationClipProp);
return;
}
SerializedProperty materialPropertyTargets = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingSlider.materialPropertyTargets));
// Slider Float/Range Targets List
if (sliderSetting.reorderableList == null // recreate list if null or stale
|| sliderSetting.reorderableList.serializedProperty.serializedObject != serializedObject)
{
sliderSetting.reorderableList = new ReorderableList(serializedObject, materialPropertyTargets,
true, true, true, true)
{
list = sliderSetting.materialPropertyTargets,
};
sliderSetting.reorderableList.drawElementCallback = (innerRect, innerIndex, _, _) =>
{
innerRect = new Rect(innerRect.x, innerRect.y + 2, innerRect.width, EditorGUIUtility.singleLineHeight);
Rect innerRectButBelow = new Rect(innerRect.x, innerRect.y + 2, innerRect.width, EditorGUIUtility.singleLineHeight);
SerializedProperty colorEntry = sliderSetting.reorderableList.serializedProperty.GetArrayElementAtIndex(innerIndex);
const float elementSpacing = 5;
const float infoIconWidth = 20;
float innerRectHalfWidth = innerRect.width * 0.5f;
// GameObject Field
innerRect.width = innerRectHalfWidth;
SerializedProperty materialColorProp = colorEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialProperty.gameObject));
EditorGUI.PropertyField(innerRect, materialColorProp, GUIContent.none);
string tooltipPath = "No Target";
var propertyList = new Dictionary<string, string>();
if (materialColorProp.objectReferenceValue != null)
{
Transform avatarTransform = _avatar.transform;
Transform targetTransform = ((GameObject)materialColorProp.objectReferenceValue).transform;
if (!targetTransform.IsChildOf(avatarTransform))
{
materialColorProp.objectReferenceValue = null; // invalid
}
else
{
MeshRenderer meshRenderer = targetTransform.GetComponent<MeshRenderer>();
SkinnedMeshRenderer skinnedMeshRenderer = targetTransform.GetComponent<SkinnedMeshRenderer>();
ParticleSystemRenderer particleRenderer = targetTransform.GetComponent<ParticleSystemRenderer>();
LineRenderer lineRenderer =targetTransform.GetComponent<LineRenderer>();
TrailRenderer trailRenderer = targetTransform.GetComponent<TrailRenderer>();
bool rendererFound = meshRenderer || skinnedMeshRenderer || particleRenderer ||
lineRenderer || trailRenderer;
if (rendererFound)
{
#region Populate Property List
if (meshRenderer != null)
{
foreach (Material material in meshRenderer.sharedMaterials)
{
if (material == null) continue;
Shader shader = material.shader;
for (var j = 0; j < shader.GetPropertyCount(); j++)
{
if (shader.GetPropertyType(j) != ShaderPropertyType.Float
&& shader.GetPropertyType(j) != ShaderPropertyType.Range) continue;
var propertyKey = "MeshRenderer: " + shader.GetPropertyDescription(j) +
"(" + shader.GetPropertyName(j) + ")";
if (!propertyList.ContainsKey(propertyKey))
propertyList.Add(propertyKey, "MSR:" + shader.GetPropertyName(j));
}
}
}
if (skinnedMeshRenderer != null)
{
foreach (Material material in skinnedMeshRenderer.sharedMaterials)
{
if (material == null) continue;
Shader shader = material.shader;
for (var j = 0; j < shader.GetPropertyCount(); j++)
{
if (shader.GetPropertyType(j) != ShaderPropertyType.Float
&& shader.GetPropertyType(j) != ShaderPropertyType.Range) continue;
var propertyKey = "SkinnedMeshRenderer: " +
shader.GetPropertyDescription(j) + "(" +
shader.GetPropertyName(j) + ")";
if (!propertyList.ContainsKey(propertyKey))
propertyList.Add(propertyKey, "SMR:" + shader.GetPropertyName(j));
}
}
}
if (particleRenderer != null)
{
foreach (Material material in particleRenderer.sharedMaterials)
{
if (material == null) continue;
Shader shader = material.shader;
for (var j = 0; j < shader.GetPropertyCount(); j++)
{
if (shader.GetPropertyType(j) != ShaderPropertyType.Float
&& shader.GetPropertyType(j) != ShaderPropertyType.Range) continue;
var propertyKey = "ParticleRenderer: " + shader.GetPropertyDescription(j) +
"(" + shader.GetPropertyName(j) + ")";
if (!propertyList.ContainsKey(propertyKey))
propertyList.Add(propertyKey, "PTR:" + shader.GetPropertyName(j));
}
}
}
if (lineRenderer != null)
{
foreach (Material material in lineRenderer.sharedMaterials)
{
if (material == null) continue;
Shader shader = material.shader;
for (var j = 0; j < shader.GetPropertyCount(); j++)
{
if (shader.GetPropertyType(j) != ShaderPropertyType.Float
&& shader.GetPropertyType(j) != ShaderPropertyType.Range) continue;
var propertyKey = "LineRenderer: " + shader.GetPropertyDescription(j) +
"(" + shader.GetPropertyName(j) + ")";
if (!propertyList.ContainsKey(propertyKey))
propertyList.Add(propertyKey, "LNR:" + shader.GetPropertyName(j));
}
}
}
if (trailRenderer != null)
{
foreach (Material material in trailRenderer.sharedMaterials)
{
if (material == null) continue;
Shader shader = material.shader;
for (var j = 0; j < shader.GetPropertyCount(); j++)
{
if (shader.GetPropertyType(j) != ShaderPropertyType.Float
&& shader.GetPropertyType(j) != ShaderPropertyType.Range) continue;
var propertyKey = "TrailRenderer: " + shader.GetPropertyDescription(j) +
"(" + shader.GetPropertyName(j) + ")";
if (!propertyList.ContainsKey(propertyKey))
propertyList.Add(propertyKey, "TLR:" + shader.GetPropertyName(j));
}
}
}
#endregion
}
else
{
materialColorProp.objectReferenceValue = null; // invalid
}
SerializedProperty materialColorPathProp = colorEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialProperty.treePath));
materialColorPathProp.stringValue = AnimationUtility.CalculateTransformPath(targetTransform, avatarTransform);
tooltipPath = $"Path: {avatarTransform.name}/{materialColorPathProp.stringValue}";
}
}
// Property Dropdown
innerRect.x += innerRectHalfWidth + elementSpacing;
innerRect.width -= 2*infoIconWidth - 2*elementSpacing; // left/right padding
SerializedProperty propNameProp = colorEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialProperty.propertyName));
SerializedProperty propTypeIdProp = colorEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialProperty.propertyTypeIdentifier));
SerializedProperty minValueProp = colorEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialProperty.minValue));
SerializedProperty maxValueProp = colorEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialProperty.maxValue));
// not valid as a serialized property?
//SerializedProperty propTypeProp = toggleEntry.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryMaterialColor.propertyType));
//var propNames = propertyList.Keys.ToArray();
var propDescs = propertyList.Values.ToArray();
string currentItem = propNameProp.stringValue.Length > 0
? propTypeIdProp.stringValue + ":" + propNameProp.stringValue
: CVRCommon.NONE_OR_EMPTY;
// search dropdown for material properties
int selected = EditorGUIExtensions.CustomPopup(
innerRect,
Array.IndexOf(propDescs, currentItem),
propDescs,
"No Properties"
);
// name: _Color
// typeid: SMR
// type: SkinnedMeshRenderer
if (selected >= 0)
{
currentItem = propDescs[selected];
propNameProp.stringValue = currentItem[4..];
propTypeIdProp.stringValue = currentItem[..3];
serializedObject.ApplyModifiedProperties();
// propType is not a valid serialized property
// so autogen will need to handle this
}
// Path Info
innerRect.x += innerRect.width + elementSpacing;
innerRect.width = infoIconWidth;
EditorGUI.LabelField(innerRect, new GUIContent(EditorGUIUtility.IconContent("d_animationanimated").image, tooltipPath));
innerRectButBelow.y += EditorGUIUtility.singleLineHeight + 4f;
innerRectButBelow.width = innerRectHalfWidth;
minValueProp.floatValue = EditorGUI.FloatField(innerRectButBelow, "Min Value", minValueProp.floatValue);
innerRectButBelow.x += innerRectHalfWidth + elementSpacing;
maxValueProp.floatValue = EditorGUI.FloatField(innerRectButBelow, "Max Value", maxValueProp.floatValue);
};
sliderSetting.reorderableList.elementHeight = (EditorGUIUtility.singleLineHeight + 4f) * 2f;
sliderSetting.reorderableList.drawHeaderCallback = (headerRect) =>
{
Rect labelRect = new(headerRect.x, headerRect.y, headerRect.width - 35, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(labelRect, $"Slider Targets ({materialPropertyTargets.arraySize})");
labelRect.x += 35; // not sure why this is needed, nested lists are weird
EditorGUIExtensions.UtilityMenu(labelRect, sliderSetting.reorderableList, materialPropertyTargets);
};
}
sliderSetting.reorderableList.DoList(rect);
}
}
}
#endif

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d42afa81de944f8b96dd614d64b9e485
timeCreated: 1709424234

View file

@ -0,0 +1,118 @@
#if UNITY_EDITOR
using ABI.CCK.Scripts;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
private void DrawToggleInternal(
Rect rect,
float spacing,
CVRAdvancedSettingsEntry advSettingEntry,
SerializedProperty advSettingProp)
{
CVRAdvancesAvatarSettingGameObjectToggle toggleSetting = advSettingEntry.setting as CVRAdvancesAvatarSettingGameObjectToggle;
SerializedProperty defaultValueProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingGameObjectToggle.defaultValue));
defaultValueProp.boolValue = EditorGUI.Popup(rect, "Default Value", defaultValueProp.boolValue ? 1 : 0, BoolAsStringDisplayOptions) == 1;
rect.y += spacing;
// foldout
advSettingEntry.isAutogenCollapsed = !EditorGUI.Foldout(rect, !advSettingEntry.isAutogenCollapsed, "Autogeneration Options", true, s_BoldFoldoutStyle);
if (advSettingEntry.isAutogenCollapsed)
return;
// autogen stuff
rect.y += spacing;
SerializedProperty useAnimationProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingGameObjectToggle.useAnimationClip));
SerializedProperty animationClipProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingGameObjectToggle.animationClip));
SerializedProperty animationNameProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingGameObjectToggle.offAnimationClip));
useAnimationProp.boolValue = EditorGUI.Toggle(rect, "Use Animation Clip", useAnimationProp.boolValue);
rect.y += spacing;
// Animation Clip Fields
if (useAnimationProp.boolValue)
{
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), animationClipProp);
rect.y += spacing;
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), animationNameProp);
return;
}
SerializedProperty gameObjectTargetsProp = advSettingProp.FindPropertyRelative(nameof(CVRAdvancesAvatarSettingGameObjectToggle.gameObjectTargets));
// GameObject Targets List
if (toggleSetting!.reorderableList == null // recreate list if null
|| toggleSetting.reorderableList.serializedProperty.serializedObject != serializedObject) // stale
{
toggleSetting.reorderableList = new ReorderableList(serializedObject, gameObjectTargetsProp,
true, true, true, true)
{
list = toggleSetting.gameObjectTargets,
};
toggleSetting.reorderableList.drawElementCallback = (innerRect, innerIndex, _, _) =>
{
innerRect = new Rect(innerRect.x, innerRect.y + 2, innerRect.width, EditorGUIUtility.singleLineHeight);
SerializedProperty toggleEntryProp = toggleSetting.reorderableList.serializedProperty.GetArrayElementAtIndex(innerIndex);
const float elementSpacing = 5;
const float infoIconWidth = 20;
float innerRectHalfWidth = innerRect.width * 0.5f;
// GameObject Field
innerRect.width = innerRectHalfWidth;
SerializedProperty gameObjectProp = toggleEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryGameObject.gameObject));
EditorGUI.PropertyField(innerRect, gameObjectProp, GUIContent.none);
string tooltipPath = "No Target";
if (gameObjectProp.objectReferenceValue != null)
{
Transform avatarTransform = _avatar.transform;
Transform targetTransform = ((GameObject)gameObjectProp.objectReferenceValue).transform;
if (!targetTransform.IsChildOf(avatarTransform))
{
gameObjectProp.objectReferenceValue = null;
}
else
{
SerializedProperty gameObjectPathProp = toggleEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryGameObject.treePath));
gameObjectPathProp.stringValue = AnimationUtility.CalculateTransformPath(targetTransform, avatarTransform);
tooltipPath = $"Path: {avatarTransform.name}/{gameObjectPathProp.stringValue}";
}
}
// OnState Field
innerRect.x += innerRectHalfWidth + elementSpacing;
innerRect.width -= 2*infoIconWidth - 2*elementSpacing; // left/right padding
SerializedProperty onStateProp = toggleEntryProp.FindPropertyRelative(nameof(CVRAdvancedSettingsTargetEntryGameObject.onState));
onStateProp.boolValue = EditorGUI.Popup(innerRect, onStateProp.boolValue ? 1 : 0, BoolAsStringDisplayOptions) == 1;
// Path Info
innerRect.x += innerRect.width + elementSpacing;
innerRect.width = infoIconWidth;
EditorGUI.LabelField(innerRect, new GUIContent(EditorGUIUtility.IconContent("d_animationanimated").image, tooltipPath));
};
toggleSetting.reorderableList.elementHeight = EditorGUIUtility.singleLineHeight + 4f;
toggleSetting.reorderableList.drawHeaderCallback = (headerRect) =>
{
Rect labelRect = new(headerRect.x, headerRect.y, headerRect.width - 35, EditorGUIUtility.singleLineHeight);
EditorGUI.LabelField(labelRect, $"GameObject Targets ({gameObjectTargetsProp.arraySize})");
labelRect.x += 35; // not sure why this is needed, nested lists are weird
EditorGUIExtensions.UtilityMenu(labelRect, toggleSetting.reorderableList, gameObjectTargetsProp);
};
}
toggleSetting.reorderableList.DoList(rect);
}
}
}
#endif

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: df6671fcd41141df877371502a7eb664
timeCreated: 1709423125

View file

@ -0,0 +1,490 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using ABI.CCK.Scripts;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEngine;
namespace ABI.CCK.Components
{
[CanEditMultipleObjects]
[CustomEditor(typeof(CVRAvatar))]
public partial class CCK_CVRAvatarEditor : Editor
{
#region Editor GUI Foldouts
private static bool _guiAvatarSettingsFoldout = true;
private static bool _guiAvatarCustomizationFoldout = true;
private static bool _guiEyeLookSettingsFoldout;
private static bool _guiEyeLookMuscleInfoFoldout;
private static bool _guiEyeBlinkSettingsFoldout;
private static bool _guiLipSyncSettingsFoldout;
private static bool _guiFirstPersonRenderSettingsFoldout;
private static bool _guiAdvancedTaggingFoldout;
private static bool _guiAdvancedSettingsFoldout;
#endregion
#region Private Variables
// Common
private static readonly string[] _visemeNames =
{ "sil", "PP", "FF", "TH", "DD", "kk", "CH", "SS", "nn", "RR", "aa", "E", "ih", "oh", "ou" };
// Avatar
private CVRAvatar _avatar;
private Animator _animator;
// Avatar Info
private bool _isHumanoid;
private List<string> _blendShapeNames;
#endregion
#region Serialized Properties
private SerializedProperty m_ViewPositionProp;
private SerializedProperty m_VoiceParentProp;
private SerializedProperty m_VoicePositionProp;
private SerializedProperty m_OverridesProp;
private SerializedProperty m_BodyMeshProp;
// Eye Movement Settings
private SerializedProperty m_UseEyeMovementProp;
private SerializedProperty m_EyeMovementIntervalProp;
private SerializedProperty m_EyeMovementInfoProp;
private UnityEditorInternal.ReorderableList m_EyeMovementInfoEyesList;
// Eye Blinking Settings
private SerializedProperty m_UseBlinkBlendshapesProp;
private SerializedProperty m_BlinkGapProp;
private SerializedProperty m_BlinkDurationProp;
private SerializedProperty m_BlinkBlendshapeProp;
// Lipsync Settings
private SerializedProperty m_UseVisemeLipsyncProp;
private SerializedProperty m_VisemeModeProp;
private SerializedProperty m_VisemeSmoothingProp;
private SerializedProperty m_VisemeBlendshapesProp;
// First Person Render Settings
private SerializedProperty m_fprSettingsListProp;
// Avatar Advanced Tagging
private SerializedProperty m_advTaggingListProp;
// Avatar Advanced Settings
private SerializedProperty m_avatarSettingsProp;
private SerializedProperty m_settingEntriesProp;
private SerializedProperty m_baseControllerProp;
private SerializedProperty m_baseOverrideControllerProp;
#endregion
#region Unity Events
private void OnEnable()
{
if (target == null) return;
_avatar = (CVRAvatar)target;
_avatar.Reset();
m_ViewPositionProp = serializedObject.FindProperty(nameof(CVRAvatar.viewPosition));
m_VoiceParentProp = serializedObject.FindProperty(nameof(CVRAvatar.voiceParent));
m_VoicePositionProp = serializedObject.FindProperty(nameof(CVRAvatar.voicePosition));
m_OverridesProp = serializedObject.FindProperty(nameof(CVRAvatar.overrides));
m_BodyMeshProp = serializedObject.FindProperty(nameof(CVRAvatar.bodyMesh));
// Eye Movement Settings
m_UseEyeMovementProp = serializedObject.FindProperty(nameof(CVRAvatar.useEyeMovement));
m_EyeMovementIntervalProp = serializedObject.FindProperty(nameof(CVRAvatar.eyeMovementInterval));
m_EyeMovementInfoProp = serializedObject.FindProperty(nameof(CVRAvatar.eyeMovementInfo));
m_EyeMovementInfoEyesList = InitializeEyesReorderableList(m_EyeMovementInfoProp);
// Eye Blinking Settings
m_UseBlinkBlendshapesProp = serializedObject.FindProperty(nameof(CVRAvatar.useBlinkBlendshapes));
m_BlinkGapProp = serializedObject.FindProperty(nameof(CVRAvatar.blinkGap));
m_BlinkDurationProp = serializedObject.FindProperty(nameof(CVRAvatar.blinkDuration));
m_BlinkBlendshapeProp = serializedObject.FindProperty(nameof(CVRAvatar.blinkBlendshape));
// Viseme Settings
m_UseVisemeLipsyncProp = serializedObject.FindProperty(nameof(CVRAvatar.useVisemeLipsync));
m_VisemeModeProp = serializedObject.FindProperty(nameof(CVRAvatar.visemeMode));
m_VisemeSmoothingProp = serializedObject.FindProperty(nameof(CVRAvatar.visemeSmoothing));
m_VisemeBlendshapesProp = serializedObject.FindProperty(nameof(CVRAvatar.visemeBlendshapes));
// First Person Render Settings
m_fprSettingsListProp = serializedObject.FindProperty(nameof(CVRAvatar.fprSettingsList));
// Avatar Advanced Tagging
m_advTaggingListProp = serializedObject.FindProperty(nameof(CVRAvatar.advancedTaggingList));
// Avatar Advanced Settings
m_avatarSettingsProp = serializedObject.FindProperty(nameof(CVRAvatar.avatarSettings));
m_baseControllerProp = m_avatarSettingsProp.FindPropertyRelative(nameof(CVRAdvancedAvatarSettings.baseController));
m_baseOverrideControllerProp = m_avatarSettingsProp.FindPropertyRelative(nameof(CVRAdvancedAvatarSettings.baseOverrideController));
m_settingEntriesProp = m_avatarSettingsProp.FindPropertyRelative(nameof(CVRAdvancedAvatarSettings.settings));
GetBlendshapeNames();
_animator = _avatar.GetComponent<Animator>();
if (_animator != null && _animator.isHuman)
{
_isHumanoid = true;
GetHumanoidEyeMuscleLimits();
}
}
public override void OnInspectorGUI()
{
if (_avatar == null)
return;
serializedObject.Update();
Draw_GeneralAvatarSettings();
Draw_AvatarCustomization();
Draw_EyeLookSettings();
Draw_EyeBlinkSettings();
Draw_LipSyncSettings();
Draw_FPRSettings();
Draw_AdvancedTagging();
Draw_AdvancedSettings();
serializedObject.ApplyModifiedProperties();
}
public void OnSceneGUI()
{
if (_avatar == null)
return;
Transform avatarTransform = _avatar.transform;
Vector3 scale = avatarTransform.localScale;
Vector3 inverseScale = new Vector3(1 / scale.x, 1 / scale.y, 1 / scale.z);
//View Position
GUIStyle style = new GUIStyle();
style.normal.textColor = Color.green;
style.fontSize = 20;
Handles.BeginGUI();
Vector3 pos = avatarTransform.TransformPoint(Vector3.Scale(_avatar.viewPosition, inverseScale));
Vector2 pos2D = HandleUtility.WorldToGUIPoint(pos);
GUI.Label(new Rect(pos2D.x + 20, pos2D.y - 10, 100, 20), "View Position", style);
Handles.EndGUI();
EditorGUI.BeginChangeCheck();
Vector3 viewPos = Handles.PositionHandle(pos, avatarTransform.rotation);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(_avatar, "CVR View Position Change");
_avatar.viewPosition = Vector3.Scale(avatarTransform.InverseTransformPoint(viewPos), scale);
}
//Voice Position
style.normal.textColor = Color.red;
Handles.BeginGUI();
pos = avatarTransform.TransformPoint(Vector3.Scale(_avatar.voicePosition, inverseScale));
pos2D = HandleUtility.WorldToGUIPoint(pos);
GUI.Label(new Rect(pos2D.x + 20, pos2D.y - 10, 100, 20), "Voice Position", style);
Handles.EndGUI();
EditorGUI.BeginChangeCheck();
Vector3 voicePos = Handles.PositionHandle(pos, avatarTransform.rotation);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(_avatar, "CVR Voice Position Change");
_avatar.voicePosition = Vector3.Scale(avatarTransform.InverseTransformPoint(voicePos), scale);
}
}
#endregion
#region BlendshapeDropdowns
private void DrawBlendshape(string label, ref string blendshape)
{
if (_avatar.bodyMesh != null)
{
if (string.IsNullOrEmpty(blendshape))
blendshape = "-none-";
blendshape = EditorGUIExtensions.CustomPopup(
GUILayoutUtility.GetRect(new GUIContent(label), EditorStyles.popup),
label,
blendshape,
_blendShapeNames.ToArray(),
blendshape
);
}
else
{
EditorGUILayout.HelpBox("Avatar does not have a Face Mesh specified.", MessageType.Warning);
}
}
private void DrawBlendshape(string label, SerializedProperty blendshapesProp)
{
if (_avatar.bodyMesh != null)
{
if (!blendshapesProp.isArray)
return;
if (blendshapesProp.arraySize != 1)
blendshapesProp.arraySize = 1;
SerializedProperty blendshapeElementProp = blendshapesProp.GetArrayElementAtIndex(0);
string currentValue = blendshapeElementProp.stringValue;
if (string.IsNullOrEmpty(currentValue))
currentValue = "-none-";
string newValue = EditorGUIExtensions.CustomPopup(
GUILayoutUtility.GetRect(new GUIContent(label), EditorStyles.popup),
label,
currentValue,
_blendShapeNames.ToArray(),
currentValue
);
if (newValue != currentValue)
blendshapeElementProp.stringValue = newValue;
}
else
{
EditorGUILayout.HelpBox("Avatar does not have a Face Mesh specified.",
MessageType.Warning);
}
}
private void DrawBlendshapes(string label, ref string[] blendshapes, IReadOnlyList<string> names = null)
{
if (_avatar.bodyMesh != null)
{
for (var i = 0; i < blendshapes.Length; i++)
{
var currentLabel = names == null ? label + " " + (i + 1) : label + names[i];
if (string.IsNullOrEmpty(blendshapes[i]))
blendshapes[i] = "-none-";
blendshapes[i] = EditorGUIExtensions.CustomPopup(
GUILayoutUtility.GetRect(new GUIContent(currentLabel), EditorStyles.popup),
currentLabel,
blendshapes[i],
_blendShapeNames.ToArray(),
blendshapes[i]);
}
}
else
{
EditorGUILayout.HelpBox("Avatar does not have a Face Mesh specified.",
MessageType.Warning);
}
}
private void DrawBlendshapes(string label, SerializedProperty blendshapesProp, IReadOnlyList<string> names = null)
{
if (_avatar.bodyMesh != null)
{
if (!blendshapesProp.isArray)
return;
if (names != null && blendshapesProp.arraySize != names.Count)
blendshapesProp.arraySize = names.Count;
for (int i = 0; i < blendshapesProp.arraySize; i++)
{
SerializedProperty blendshapeElementProp = blendshapesProp.GetArrayElementAtIndex(i);
var currentLabel = (names == null) ? label + " " + (i + 1) : label + names[i];
string currentValue = blendshapeElementProp.stringValue;
if (string.IsNullOrEmpty(currentValue))
{
currentValue = "-none-";
}
string newValue = EditorGUIExtensions.CustomPopup(
GUILayoutUtility.GetRect(new GUIContent(currentLabel), EditorStyles.popup),
currentLabel,
currentValue,
_blendShapeNames.ToArray(),
currentValue);
if (newValue != currentValue)
blendshapeElementProp.stringValue = newValue;
}
}
else
{
EditorGUILayout.HelpBox("Avatar does not have a Face Mesh specified.",
MessageType.Warning);
}
}
#endregion
#region Private Methods
// this is probably overkill
private void AutoSetViewPosition()
{
if (_animator == null || !_isHumanoid)
return;
Transform leftEye = _animator.GetBoneTransform(HumanBodyBones.LeftEye);
Transform rightEye = _animator.GetBoneTransform(HumanBodyBones.RightEye);
Transform head = _animator.GetBoneTransform(HumanBodyBones.Head);
if (leftEye && rightEye)
{
Undo.RecordObject(_avatar, "CVR View Position Change");
_avatar.viewPosition = RoundNearZero((leftEye.position + rightEye.position) / 2);
return;
}
if (leftEye || rightEye)
{
Undo.RecordObject(_avatar, "CVR View Position Change");
_avatar.viewPosition = ProjectSingleEyePosition(leftEye ? leftEye : rightEye);
return;
}
if (head)
{
string[] leftEyeNames = { "LeftEye", "Left_Eye", "EyeLeft", "Eye_Left" };
string[] rightEyeNames = { "RightEye", "Right_Eye", "EyeRight", "Eye_Right" };
leftEye = FindChildByNameVariants(head, leftEyeNames);
rightEye = FindChildByNameVariants(head, rightEyeNames);
if (leftEye && rightEye)
{
Undo.RecordObject(_avatar, "CVR View Position Change");
_avatar.viewPosition = RoundNearZero((leftEye.position + rightEye.position) / 2);
return;
}
if (leftEye || rightEye)
{
Undo.RecordObject(_avatar, "CVR View Position Change");
_avatar.viewPosition = ProjectSingleEyePosition(leftEye ? leftEye : rightEye);
return;
}
Transform root = _animator.GetBoneTransform(HumanBodyBones.Hips);
float headBoneHeight = Vector3.Distance(root.position, head.position);
Vector3 localOffset = new Vector3(0f, -0.1f * headBoneHeight, 0.1f * headBoneHeight);
Undo.RecordObject(_avatar, "CVR View Position Change");
_avatar.viewPosition = RoundNearZero(head.TransformPoint(localOffset));
return;
}
Debug.LogWarning("Could not find suitable bone for view position. We really tried...");
}
private Vector3 ProjectSingleEyePosition(Transform singleEye)
{
Vector3 eyePosition = singleEye.position;
Transform avatarRoot = _animator.transform;
Vector3 toEyeDirection = (eyePosition - avatarRoot.position).normalized;
float dotForward = Vector3.Dot(toEyeDirection, avatarRoot.forward);
float dotUp = Vector3.Dot(toEyeDirection, avatarRoot.up);
float dotRight = Vector3.Dot(toEyeDirection, avatarRoot.right);
if (Mathf.Abs(dotForward) > Mathf.Abs(dotUp) && Mathf.Abs(dotForward) > Mathf.Abs(dotRight))
return RoundNearZero(eyePosition - Vector3.Project(eyePosition - _animator.transform.position, avatarRoot.forward));
return Mathf.Abs(dotUp) > Mathf.Abs(dotRight) ? RoundNearZero(singleEye.position - Vector3.Project(eyePosition - avatarRoot.position, avatarRoot.up)) : RoundNearZero(singleEye.position - Vector3.Project(eyePosition - avatarRoot.position, avatarRoot.right));
}
private void AutoSetVoicePosition()
{
Transform jaw = _animator.GetBoneTransform(HumanBodyBones.Jaw);
Transform head = _animator.GetBoneTransform(HumanBodyBones.Head);
if (jaw)
{
Undo.RecordObject(_avatar, "CVR Voice Position Change");
_avatar.voicePosition = jaw.position;
}
else if (head)
{
Vector3 localOffset = new Vector3(0f, 0.005f, 0.06f);
Undo.RecordObject(_avatar, "CVR Voice Position Change");
_avatar.voicePosition = head.TransformPoint(localOffset);
}
}
private static Transform FindChildByNameVariants(Transform parent, string[] nameVariants)
{
foreach (string potentialName in nameVariants)
{
Transform child = parent.Find(potentialName);
if (child) return child;
child = parent.Cast<Transform>().FirstOrDefault(t => string.Equals(t.name, potentialName, StringComparison.OrdinalIgnoreCase));
if (child) return child;
}
return null;
}
private static Vector3 RoundNearZero(Vector3 position)
{
const float tolerance = 0.01f;
return new Vector3(
Mathf.Abs(position.x) < tolerance ? 0 : position.x,
Mathf.Abs(position.y) < tolerance ? 0 : position.y,
Mathf.Abs(position.z) < tolerance ? 0 : position.z
);
}
private void GetBlendshapeNames()
{
_blendShapeNames = new List<string> { "-none-" };
if (_avatar.bodyMesh == null) return;
for (var i = 0; i < _avatar.bodyMesh.sharedMesh.blendShapeCount; i++)
_blendShapeNames.Add(_avatar.bodyMesh.sharedMesh.GetBlendShapeName(i));
}
private void AutoSelectVisemeBlendshapes()
{
Undo.RecordObject(_avatar, "CVR Auto Select Visemes");
for (var i = 0; i < _visemeNames.Length; i++)
{
var vPrefix = "v_" + _visemeNames[i];
var visemePrefix = "viseme_" + _visemeNames[i];
foreach (var blendShapeName in _blendShapeNames)
{
if (blendShapeName.IndexOf(vPrefix, StringComparison.OrdinalIgnoreCase) < 0 &&
blendShapeName.IndexOf(visemePrefix, StringComparison.OrdinalIgnoreCase) < 0)
continue;
_avatar.visemeBlendshapes[i] = blendShapeName;
break;
}
}
}
// Failed... Reset is called on component
// but editor doesnt exist yet...
// private void AutoSetup(CVRAvatar avatar)
// {
// if (_avatar != avatar)
// return;
//
// // find face mesh first
// AutoSetViewPosition();
// AutoSetVoicePosition();
// AutoSelectVisemeBlendshapes();
// }
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,265 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using ABI.CCK.Scripts;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using AnimatorController = UnityEditor.Animations.AnimatorController;
using AnimatorControllerParameter = UnityEngine.AnimatorControllerParameter;
using AnimatorControllerParameterType = UnityEngine.AnimatorControllerParameterType;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
private static readonly string[] BoolAsStringDisplayOptions = {"False", "True"};
private ReorderableList _advSettingsList;
private int _selectedAdvSetting = -1;
private (int, int) _syncedBitsTuple; // (Current-Overrides, New-AutoGen)
private int _syncedValues;
private int _syncedBooleans;
private List<string> _baseControllerParams = new();
private void InitializeSettingsListIfNeeded()
{
if (_advSettingsList != null)
return;
if (_avatar.avatarSettings is not { initialized: true })
CreateAvatarSettings(_avatar);
if (_avatar.avatarSettings == null)
return;
UpdateSyncUsageAndBaseParameters();
_advSettingsList = new ReorderableList(serializedObject, m_settingEntriesProp,
true, true, true, true)
{
drawHeaderCallback = OnDrawHeaderAAS,
onMouseUpCallback = OnMouseUpAAS,
drawElementCallback = OnDrawElementAAS,
elementHeightCallback = OnHeightElementAAS,
onChangedCallback = OnChangedAAS,
onReorderCallback = OnReorderedAAS,
list = _avatar.avatarSettings.settings,
index = -1
};
}
private void Draw_AdvancedSettings()
{
using (new ToggleFoldoutScope(ref _guiAdvancedSettingsFoldout, ref _avatar.avatarUsesAdvancedSettings, "Advanced Settings"))
{
if (!_guiAdvancedSettingsFoldout) return;
InitializeSettingsListIfNeeded();
using (new EditorGUI.DisabledGroupScope(!_avatar.avatarUsesAdvancedSettings))
DrawAvatarAdvancedSettings();
}
}
// TODO: Cleanup all of this...
// Decouple AutoGen from GUI
// Add simplified menu entry mode (no AutoGen)
private void DrawAvatarAdvancedSettings()
{
if (_avatar.avatarSettings == null)
return;
DrawAutogenControllerFields();
// display current usage compared to new usage prior to creating the controller
EditorGUIExtensions.MultiProgressBar(
EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight),
_syncedBitsTuple.Item1 / CVRCommon.AVATAR_BIT_LIMIT,
(_syncedBitsTuple.Item2) / CVRCommon.AVATAR_BIT_LIMIT,
$"({_syncedBitsTuple.Item1}, {_syncedBitsTuple.Item2}) of 3200 Synced Bits used"
);
_advSettingsList.DoLayoutList();
DrawCreateControllerButton();
}
#region Private Methods
private void UpdateSyncUsageAndBaseParameters()
{
// get the current usage of synced bits / preview usage of autogen
_syncedBitsTuple = _avatar.GetParameterSyncUsage();
// populate the base controller parameters for existing-generation warning
_baseControllerParams = CVRCommon.GetParametersFromControllerAsString(
_avatar.avatarSettings.baseController, CVRCommon.NonCoreFilter, CVRCommon.NonNullFilter);
}
private void CreateAASController()
{
// ensure everything is up to date
serializedObject.ApplyModifiedProperties();
if (_avatar.avatarSettings.baseController == null)
{
EditorUtility.DisplayDialog("Animator Error",
"The Base Animator was not selected. No new Animator Controller was created.", "OK");
return;
}
if (_avatar.avatarSettings.animator != null)
{
if (!EditorUtility.DisplayDialog("Animator already created",
"There is Animator already created for this avatar.", "Override", "Cancel"))
{
return;
}
}
string pathToCurrentFolder = "Assets/AdvancedSettings.Generated";
if (!AssetDatabase.IsValidFolder(pathToCurrentFolder))
AssetDatabase.CreateFolder("Assets", "AdvancedSettings.Generated");
string folderPath = pathToCurrentFolder + "/" + _avatar.name + "_AAS";
if (!AssetDatabase.IsValidFolder(folderPath))
AssetDatabase.CreateFolder(pathToCurrentFolder, _avatar.name + "_AAS");
string animatorPath = pathToCurrentFolder + "/" + _avatar.name + "_AAS/" + _avatar.name + "_aas.controller";
AssetDatabase.CopyAsset(AssetDatabase.GetAssetPath(_avatar.avatarSettings.baseController.GetInstanceID()),
animatorPath);
_avatar.avatarSettings.animator = AssetDatabase.LoadAssetAtPath<AnimatorController>(animatorPath);
_baseControllerParams.Clear();
if (_avatar.avatarSettings.baseController != null)
{
AnimatorController animator = (AnimatorController)_avatar.avatarSettings.baseController;
foreach (AnimatorControllerParameter parameter in animator.parameters)
{
if (parameter.type == AnimatorControllerParameterType.Float && parameter.name.Length > 0 &&
!CVRCommon.CoreParameters.Contains(parameter.name) && parameter.name.Substring(0, 1) != "#")
{
_baseControllerParams.Add(parameter.name);
}
if (parameter.type == AnimatorControllerParameterType.Int && parameter.name.Length > 0 &&
!CVRCommon.CoreParameters.Contains(parameter.name) && parameter.name.Substring(0, 1) != "#")
{
_baseControllerParams.Add(parameter.name);
}
if (parameter.type == AnimatorControllerParameterType.Bool && parameter.name.Length > 0 &&
!CVRCommon.CoreParameters.Contains(parameter.name) && parameter.name.Substring(0, 1) != "#")
{
_baseControllerParams.Add(parameter.name);
}
}
}
foreach (CVRAdvancedSettingsEntry entry in _avatar.avatarSettings.settings)
{
switch (entry.type)
{
default:
if (_baseControllerParams.Contains(entry.machineName)) continue;
break;
case CVRAdvancedSettingsEntry.SettingsType.Color:
if (_baseControllerParams.Contains(entry.machineName + "-r") ||
_baseControllerParams.Contains(entry.machineName + "-g") ||
_baseControllerParams.Contains(entry.machineName + "-b")) continue;
break;
case CVRAdvancedSettingsEntry.SettingsType.Joystick2D:
case CVRAdvancedSettingsEntry.SettingsType.InputVector2:
if (_baseControllerParams.Contains(entry.machineName + "-x") ||
_baseControllerParams.Contains(entry.machineName + "-y")) continue;
break;
case CVRAdvancedSettingsEntry.SettingsType.Joystick3D:
case CVRAdvancedSettingsEntry.SettingsType.InputVector3:
if (_baseControllerParams.Contains(entry.machineName + "-x") ||
_baseControllerParams.Contains(entry.machineName + "-y") ||
_baseControllerParams.Contains(entry.machineName + "-z")) continue;
break;
}
string fileName = Regex.Replace(entry.machineName, "[^a-zA-Z0-9_]+", "", RegexOptions.Compiled);
entry.setting.SetupAnimator(ref _avatar.avatarSettings.animator, entry.machineName, folderPath, fileName);
}
if (_avatar.avatarSettings.baseOverrideController != null)
{
string overridePath = pathToCurrentFolder + "/" + _avatar.name + "_AAS/" + _avatar.name +
"_aas_overrides.overrideController";
AssetDatabase.CopyAsset(
AssetDatabase.GetAssetPath(_avatar.avatarSettings.baseOverrideController.GetInstanceID()),
overridePath);
_avatar.avatarSettings.overrides = AssetDatabase.LoadAssetAtPath<AnimatorOverrideController>(overridePath);
_avatar.avatarSettings.overrides.runtimeAnimatorController = _avatar.avatarSettings.animator;
}
else
{
_avatar.avatarSettings.overrides = new AnimatorOverrideController(_avatar.avatarSettings.animator);
AssetDatabase.CreateAsset(_avatar.avatarSettings.overrides,
pathToCurrentFolder + "/" + _avatar.name + "_AAS/" + _avatar.name +
"_aas_overrides.overrideController");
}
AssetDatabase.SaveAssets();
}
private static void CreateAvatarSettings(CVRAvatar avatar)
{
string[] guids = AssetDatabase.FindAssets("AvatarAnimator t:animatorController", null);
if (guids.Length < 1)
{
Debug.LogError(
"No Animator controller with the name \"AvatarAnimator\" was found. Please make sure that you CCK is installed properly.");
return;
}
Type projectWindowUtilType = typeof(ProjectWindowUtil);
MethodInfo getActiveFolderPath =
projectWindowUtilType.GetMethod("GetActiveFolderPath", BindingFlags.Static | BindingFlags.NonPublic);
if (getActiveFolderPath != null) getActiveFolderPath.Invoke(null, Array.Empty<object>());
avatar.avatarSettings = new CVRAdvancedAvatarSettings
{
baseController = AssetDatabase.LoadAssetAtPath<AnimatorController>(AssetDatabase.GUIDToAssetPath(guids[0])),
settings = new List<CVRAdvancedSettingsEntry>(),
initialized = true
};
}
#endregion
#region Utility
private void AppendUtilityMenu(GenericMenuBuilder genericMenuBuilder, ReorderableList list)
{
bool hasSettings = _avatar != null &&
_avatar.avatarSettings is { settings: not null };
genericMenuBuilder.AddMenuItem("Collapse All", hasSettings,
() => CollapseAllEntries(_avatar.avatarSettings.settings));
}
private static void CollapseAllEntries(List<CVRAdvancedSettingsEntry> settingsEntries)
{
foreach (CVRAdvancedSettingsEntry advSettingEntry in settingsEntries)
advSettingEntry.isCollapsed = advSettingEntry.isAutogenCollapsed = true;
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,103 @@
#if UNITY_EDITOR
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
private ReorderableList _advTaggingList;
private void Draw_AdvancedTagging()
{
using (new ToggleFoldoutScope(ref _guiAdvancedTaggingFoldout, ref _avatar.enableAdvancedTagging, "Advanced Tagging"))
{
if (!_guiAdvancedTaggingFoldout) return;
InitializeTaggingList();
EditorGUILayout.HelpBox("If you are using the Advanced Tagging System, you do not need to Tag your Avatar appropriately if you mark all affected GameObjects here.", MessageType.Info);
using (new EditorGUI.DisabledGroupScope(!_avatar.enableAdvancedTagging))
_advTaggingList.DoLayoutList();
}
}
#region AvatarAdvancedTagging ReorderableList
private void InitializeTaggingList()
{
_advTaggingList ??= new ReorderableList(serializedObject, m_advTaggingListProp, true, true, true, true)
{
drawHeaderCallback = OnDrawHeaderTagging,
drawElementCallback = OnDrawElementTagging,
elementHeightCallback = OnHeightElementTagging,
onChangedCallback = OnChangedTagging,
list = _avatar.advancedTaggingList // This is a hack to make the Utility Menu work
};
}
private float OnHeightElementTagging(int index)
{
if (index > _avatar.advancedTaggingList.Count) return EditorGUIUtility.singleLineHeight * 2.5f;
return EditorGUIUtility.singleLineHeight *
((_avatar.advancedTaggingList[index].fallbackGameObject != null &&
_avatar.advancedTaggingList[index].fallbackGameObject.activeSelf) ? 5f : 3.75f);
}
private void OnDrawHeaderTagging(Rect rect)
{
Rect _rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
GUI.Label(_rect, "Tagged GameObjects");
EditorGUIExtensions.UtilityMenu(_rect, _advTaggingList);
}
private void OnDrawElementTagging(Rect rect, int index, bool isActive, bool isFocused)
{
if (index >= _advTaggingList.count) return;
SerializedProperty advTaggingProp = _advTaggingList.serializedProperty.GetArrayElementAtIndex(index);
if (advTaggingProp == null || index >= _advTaggingList.serializedProperty.arraySize)
return;
Rect _rect = new (rect.x, rect.y + 2, rect.width, EditorGUIUtility.singleLineHeight);
float spacing = EditorGUIUtility.singleLineHeight * 1.25f;
float originalLabelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 100;
SerializedProperty tagsProp = advTaggingProp.FindPropertyRelative(nameof(CVRAvatarAdvancedTaggingEntry.tags));
EditorGUI.PropertyField(_rect, tagsProp, new GUIContent("Tags"));
_rect.y += spacing;
SerializedProperty gameObjectProp = advTaggingProp.FindPropertyRelative(nameof(CVRAvatarAdvancedTaggingEntry.gameObject));
EditorGUI.PropertyField(_rect, gameObjectProp, new GUIContent("GameObject"));
_rect.y += spacing;
SerializedProperty fallbackGameObjectProp = advTaggingProp.FindPropertyRelative(nameof(CVRAvatarAdvancedTaggingEntry.fallbackGameObject));
EditorGUI.PropertyField(_rect, fallbackGameObjectProp, new GUIContent("Fallback GO"));
_rect.y += spacing;
if (fallbackGameObjectProp.objectReferenceValue != null)
{
GameObject fallbackGO = (GameObject)fallbackGameObjectProp.objectReferenceValue;
if (fallbackGO.activeSelf)
{
EditorGUI.HelpBox(_rect, "The Fallback GameObject needs to be disabled by default!", MessageType.Error);
_rect.y += spacing;
}
}
EditorGUIUtility.labelWidth = originalLabelWidth;
}
private void OnChangedTagging(ReorderableList list)
{
EditorUtility.SetDirty(target);
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,37 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
private void Draw_AvatarCustomization()
{
using (new FoldoutScope(ref _guiAvatarCustomizationFoldout, "Avatar Customization"))
{
if (!_guiAvatarCustomizationFoldout) return;
using (new EditorGUI.IndentLevelScope())
DrawAvatarCustomization();
}
}
#region Drawing Methods
private void DrawAvatarCustomization()
{
EditorGUILayout.PropertyField(m_OverridesProp, new GUIContent("Animation Overrides"));
EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_AVATAR_INFO_OVERRIDE_CONTROLLER"), MessageType.Info);
Object previousBodyMesh = m_BodyMeshProp.objectReferenceValue;
EditorGUILayout.PropertyField(m_BodyMeshProp, new GUIContent("Face Mesh"));
if (m_BodyMeshProp.objectReferenceValue != previousBodyMesh)
GetBlendshapeNames();
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,42 @@
#if UNITY_EDITOR
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
private void Draw_EyeBlinkSettings()
{
using (new FoldoutScope(ref _guiEyeBlinkSettingsFoldout, "Eye Blink Settings"))
{
if (!_guiEyeBlinkSettingsFoldout) return;
using (new EditorGUI.IndentLevelScope())
DrawEyeBlinkSettings();
}
}
#region Drawing Methods
private void DrawEyeBlinkSettings()
{
EditorGUILayout.PropertyField(m_UseBlinkBlendshapesProp, new GUIContent("Use Blink Blendshapes"));
Separator();
EditorGUIExtensions.LimitSliderSidedProp("Blink Gap (Seconds)", m_BlinkGapProp, CVRAvatar.BlinkMinGapLimit, CVRAvatar.BlinkMaxGapLimit);
EditorGUIExtensions.LimitSliderSidedProp("Blink Duration (Seconds)", m_BlinkDurationProp, CVRAvatar.BlinkMinDurationLimit, CVRAvatar.BlinkMaxDurationLimit);
Separator();
DrawBlendshapes("Blink", m_BlinkBlendshapeProp);
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,391 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using ABI.CCK.Scripts;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
// Muscle Limits
private Vector2 _leftEyeUpDown, _leftEyeInOut, _rightEyeUpDown, _rightEyeInOut;
private void Draw_EyeLookSettings()
{
using (new FoldoutScope(ref _guiEyeLookSettingsFoldout, "Eye Look Settings"))
{
if (!_guiEyeLookSettingsFoldout) return;
using (new EditorGUI.IndentLevelScope())
DrawEyeLookSettings();
}
}
#region Drawing Methods
private void DrawEyeLookSettings()
{
EditorGUILayout.PropertyField(m_UseEyeMovementProp, new GUIContent("Use Eye Movement"));
Separator();
EditorGUIExtensions.LimitSliderSidedProp("Switch target interval (Seconds)", m_EyeMovementIntervalProp, CVRAvatar.EyeMovementMinIntervalLimit, CVRAvatar.EyeMovementMaxIntervalLimit);
// Eye movement mode
SerializedProperty typeProp = m_EyeMovementInfoProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfo.type));
EditorGUILayout.PropertyField(typeProp, new GUIContent("Eye Look Mode"));
Separator();
switch (_avatar.eyeMovementInfo.type)
{
default: // legacy avatars likely use Muscle
case CVRAvatar.CVRAvatarEyeLookMode.Muscle:
DrawMuscleEyeSettings();
break;
case CVRAvatar.CVRAvatarEyeLookMode.None:
EditorGUILayout.HelpBox("Eye movement will be completely disabled.", MessageType.Info);
break;
case CVRAvatar.CVRAvatarEyeLookMode.Transform:
m_EyeMovementInfoEyesList.DoLayoutList();
EditorGUILayout.HelpBox("Is Left will dictate the Eye In/Out direction, and used for the " +
"parameter stream (it will pick the first left and right eye available.", MessageType.Info);
break;
case CVRAvatar.CVRAvatarEyeLookMode.Blendshape:
m_EyeMovementInfoEyesList.DoLayoutList();
EditorGUILayout.HelpBox("Is Left will dictate the Eye In/Out direction, and used for the " +
"parameter stream (it will pick the first left and right eye available.", MessageType.Info);
EditorGUILayout.HelpBox("These angle limit values will be used to decide when a blendshape takes the value 100. " +
"For example if you set the eye up limit to 25 degrees, we will set the blendshape to 100 " +
"whenever the eye angle is 25 degrees up (or more).", MessageType.Info);
break;
}
}
private void DrawMuscleEyeSettings()
{
if (!_isHumanoid)
{
EditorGUILayout.HelpBox("Avatar is not configured as humanoid or lacks an Animator component. Muscle eye look mode is not supported!",
MessageType.Error);
return;
}
EditorGUILayout.HelpBox("Using the eye transforms and muscle limits set in the humanoid configuration.",
MessageType.Info);
if (!InnerFoldout(ref _guiEyeLookMuscleInfoFoldout, "Eye Limits"))
return;
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.ObjectField("Left Eye", _animator.GetBoneTransform(HumanBodyBones.LeftEye),
typeof(Transform), true);
EditorGUILayout.ObjectField("Right Eye", _animator.GetBoneTransform(HumanBodyBones.RightEye),
typeof(Transform), true);
EditorGUILayout.LabelField("Left Eye Limits (in degrees)", EditorStyles.boldLabel);
EditorGUIExtensions.LimitSliderSided("Eye Down/Up", ref _leftEyeUpDown, -180f, 180f);
EditorGUIExtensions.LimitSliderSided("Eye In/Out", ref _leftEyeInOut, -180f, 180f);
EditorGUILayout.LabelField("Right Eye Limits (in degrees)", EditorStyles.boldLabel);
EditorGUIExtensions.LimitSliderSided("Eye Down/Up", ref _rightEyeUpDown, -180f, 180f);
EditorGUIExtensions.LimitSliderSided("Eye In/Out", ref _rightEyeInOut, -180f, 180f);
EditorGUI.EndDisabledGroup();
}
private ReorderableList InitializeEyesReorderableList(SerializedProperty eyeMovementInfoProp) {
SerializedProperty eyesListProp = eyeMovementInfoProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfo.eyes));
return new ReorderableList(eyeMovementInfoProp.serializedObject, eyesListProp, true, true, true, true) {
drawHeaderCallback = OnDrawHeaderEyeSettings,
drawElementCallback = OnDrawElementEyeSettings,
elementHeightCallback = OnHeightElementEyeSettings,
onChangedCallback = OnChangedEyeSettings,
onAddCallback = OnAddEyeElement,
onRemoveCallback = OnRemoveEyeElement,
};
}
private void OnAddEyeElement(ReorderableList list)
{
Undo.RecordObject(target, "Add Avatar Custom Eye Element");
serializedObject.Update();
var tempList = _avatar.eyeMovementInfo.eyes == null
? new List<CVRAvatar.EyeMovementInfoEye>()
: new List<CVRAvatar.EyeMovementInfoEye>(_avatar.eyeMovementInfo.eyes);
// Attempt to auto-populate the eye transforms
bool containsOneRightEye = tempList.Exists(e => e is { isLeft: false });
Transform eyeInitialTransform = null;
if (_animator != null && _animator.isHuman)
eyeInitialTransform = _animator.GetBoneTransform(containsOneRightEye ? HumanBodyBones.LeftEye : HumanBodyBones.RightEye);
switch (_avatar.eyeMovementInfo.type)
{
case CVRAvatar.CVRAvatarEyeLookMode.Transform:
tempList.Add(new CVRAvatar.EyeMovementInfoEye() {
isLeft = containsOneRightEye,
eyeTransform = eyeInitialTransform,
eyeSkinnedMeshRenderer = _avatar.bodyMesh,
eyeAngleLimitDown = CVRAvatar.DefaultEyeAngleLimitDown,
eyeAngleLimitUp = CVRAvatar.DefaultEyeAngleLimitUp,
eyeAngleLimitIn = CVRAvatar.DefaultEyeAngleLimitIn,
eyeAngleLimitOut = CVRAvatar.DefaultEyeAngleLimitOut,
});
break;
case CVRAvatar.CVRAvatarEyeLookMode.Blendshape:
tempList.Add(new CVRAvatar.EyeMovementInfoEye() {
isLeft = containsOneRightEye,
eyeTransform = eyeInitialTransform,
eyeSkinnedMeshRenderer = _avatar.bodyMesh,
eyeAngleLimitDown = -CVRAvatar.DefaultUniformAngleLimit,
eyeAngleLimitUp = CVRAvatar.DefaultUniformAngleLimit,
eyeAngleLimitIn = -CVRAvatar.DefaultUniformAngleLimit,
eyeAngleLimitOut = CVRAvatar.DefaultUniformAngleLimit,
});
break;
}
_avatar.eyeMovementInfo.eyes = tempList.ToArray();
serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(target);
}
private void OnRemoveEyeElement(ReorderableList list)
{
var index = list.index;
var eyesProperty = list.serializedProperty;
if (index < 0 || index >= eyesProperty.arraySize) return;
eyesProperty.DeleteArrayElementAtIndex(index);
eyesProperty.serializedObject.ApplyModifiedProperties();
}
private void OnDrawHeaderEyeSettings(Rect rect)
{
Rect labelRect = new Rect(rect.x, rect.y, rect.width - 35, EditorGUIUtility.singleLineHeight);
GUI.Label(labelRect, "Eyes");
}
private void OnChangedEyeSettings(ReorderableList list)
{
EditorUtility.SetDirty(target);
}
private float OnHeightElementEyeSettings(int index)
{
SerializedProperty eyesListProp = m_EyeMovementInfoProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfo.eyes));
float spacing = EditorGUIUtility.singleLineHeight * 1.25f;
if (index >= eyesListProp.arraySize) return spacing;
float heightElement = spacing * 3;
SerializedProperty eyeProp = eyesListProp.GetArrayElementAtIndex(index);
// Handle the missing/wrong transform height
bool skip = false;
SerializedProperty eyeTransformProp = eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeTransform));
if (eyeTransformProp.objectReferenceValue == null || !((Transform)eyeTransformProp.objectReferenceValue).IsChildOf(_avatar.transform)) {
heightElement += spacing * 1;
skip = true;
}
if (skip) return heightElement;
switch (_avatar.eyeMovementInfo.type) {
case CVRAvatar.CVRAvatarEyeLookMode.Transform:
heightElement += spacing * 5;
break;
case CVRAvatar.CVRAvatarEyeLookMode.Blendshape:
// Handle the missing/wrong mesh renderer height
SerializedProperty eyeSkinnedMeshRendererProp = eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeSkinnedMeshRenderer));
if (eyeSkinnedMeshRendererProp.objectReferenceValue == null || !((SkinnedMeshRenderer)eyeSkinnedMeshRendererProp.objectReferenceValue).transform.IsChildOf(_avatar.transform)) {
heightElement += spacing * 2;
break;
}
heightElement += spacing * 12;
break;
}
return heightElement;
}
private void OnDrawElementEyeSettings(Rect rect, int index, bool isActive, bool isFocused) {
SerializedProperty eyesListProp = m_EyeMovementInfoProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfo.eyes));
if (index >= eyesListProp.arraySize) return;
rect = new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight);
float spacing = EditorGUIUtility.singleLineHeight * 1.25f;
SerializedProperty eyeProp = eyesListProp.GetArrayElementAtIndex(index);
EditorGUI.LabelField(rect, $"Eye #{index+1}", EditorStyles.boldLabel);
rect.y += spacing;
SerializedProperty isLeftProp = eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.isLeft));
EditorGUI.PropertyField(rect, isLeftProp);
rect.y += spacing;
switch (_avatar.eyeMovementInfo.type) {
case CVRAvatar.CVRAvatarEyeLookMode.Transform:
DrawTransformEyeSettingsEye(ref rect, spacing, eyeProp);
break;
case CVRAvatar.CVRAvatarEyeLookMode.Blendshape:
DrawBlendshapeEyeSettingsEye(ref rect, spacing, eyeProp);
break;
}
}
private void DrawTransformEyeSettingsEye(ref Rect rect, float spacing, SerializedProperty eyeProp) {
SerializedProperty eyeTransformProp = eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeTransform));
// Display ObjectFields for Transform
eyeTransformProp.objectReferenceValue = EditorGUI.ObjectField(rect, "Eye Transform", eyeTransformProp.objectReferenceValue, typeof(Transform), true);
rect.y += spacing;
if (eyeTransformProp.objectReferenceValue == null) {
EditorGUI.HelpBox(rect, "A Transform is required for Transform and Blenshapes based eye movement!", MessageType.Error);
rect.y += spacing;
return;
}
if (!((Transform)eyeTransformProp.objectReferenceValue).IsChildOf(_avatar.transform)) {
EditorGUI.HelpBox(rect, "The Transform is not inside of the current avatar's Hierarchy!", MessageType.Error);
rect.y += spacing;
return;
}
// Set the angle values
rect.y += spacing;
EditorGUI.LabelField(rect, "Angle Limits (in degrees)", EditorStyles.boldLabel);
rect.y += spacing;
EditorGUIExtensions.LimitSliderSidedFloats(ref rect, spacing, "Eye Down/Up",
eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeAngleLimitDown)),
eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeAngleLimitUp)), -180f, 180f);
EditorGUIExtensions.LimitSliderSidedFloats(ref rect, spacing, "Eye In/Out",
eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeAngleLimitIn)),
eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeAngleLimitOut)), -180f, 180f);
rect.y += spacing;
}
private void DrawBlendshapeEyeSettingsEye(ref Rect rect, float spacing, SerializedProperty eyeProp) {
SerializedProperty eyeTransformProp = eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeTransform));
SerializedProperty eyeSkinnedMeshRendererProp = eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeSkinnedMeshRenderer));
// Display ObjectFields for Transform and SkinnedMeshRenderer
eyeTransformProp.objectReferenceValue = EditorGUI.ObjectField(rect, "Eye Position Transform", eyeTransformProp.objectReferenceValue, typeof(Transform), true);
rect.y += spacing;
if (eyeTransformProp.objectReferenceValue == null) {
EditorGUI.HelpBox(rect, "A Transform is required for Transform and Blenshapes based eye movement!", MessageType.Error);
rect.y += spacing;
return;
}
if (!((Transform)eyeTransformProp.objectReferenceValue).IsChildOf(_avatar.transform)) {
EditorGUI.HelpBox(rect, "The Transform is not inside of the current avatar's Hierarchy!", MessageType.Error);
rect.y += spacing;
return;
}
eyeSkinnedMeshRendererProp.objectReferenceValue = EditorGUI.ObjectField(rect, "Eye Skinned Mesh Renderer", eyeSkinnedMeshRendererProp.objectReferenceValue, typeof(SkinnedMeshRenderer), true);
rect.y += spacing;
if (eyeSkinnedMeshRendererProp.objectReferenceValue == null) {
EditorGUI.HelpBox(rect, "A Skinned Mesh Renderer is required for Blenshapes based eye movement!", MessageType.Error);
rect.y += spacing;
return;
}
if (!((SkinnedMeshRenderer)eyeSkinnedMeshRendererProp.objectReferenceValue).transform.IsChildOf(_avatar.transform)) {
EditorGUI.HelpBox(rect, "The Skinned Mesh Renderer is not inside of the current avatar's Hierarchy!", MessageType.Error);
rect.y += spacing;
return;
}
// Display blendshape selection for each side
rect.y += spacing;
EditorGUI.LabelField(rect, "Blendshapes", EditorStyles.boldLabel);
rect.y += spacing;
DrawBlendShapeSelector(ref rect, spacing, "Look Up", eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeBlendShapeUp)), eyeSkinnedMeshRendererProp.objectReferenceValue as SkinnedMeshRenderer);
DrawBlendShapeSelector(ref rect, spacing, "Look Down", eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeBlendShapeDown)), eyeSkinnedMeshRendererProp.objectReferenceValue as SkinnedMeshRenderer);
DrawBlendShapeSelector(ref rect, spacing, "Look In", eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeBlendShapeIn)), eyeSkinnedMeshRendererProp.objectReferenceValue as SkinnedMeshRenderer);
DrawBlendShapeSelector(ref rect, spacing, "Look Out", eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeBlendShapeOut)), eyeSkinnedMeshRendererProp.objectReferenceValue as SkinnedMeshRenderer);
// Set the angle values
rect.y += spacing;
EditorGUI.LabelField(rect, "Angle Limits (in degrees)", EditorStyles.boldLabel);
rect.y += spacing;
EditorGUIExtensions.LimitSliderSidedFloats(ref rect, spacing, "Eye Down/Up",
eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeAngleLimitDown)),
eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeAngleLimitUp)), -180f, 180f);
EditorGUIExtensions.LimitSliderSidedFloats(ref rect, spacing, "Eye In/Out",
eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeAngleLimitIn)),
eyeProp.FindPropertyRelative(nameof(CVRAvatar.EyeMovementInfoEye.eyeAngleLimitOut)), -180f, 180f);
rect.y += spacing;
}
private void DrawBlendShapeSelector(ref Rect rect, float spacing, string label, SerializedProperty blendShapeProp, SkinnedMeshRenderer skinnedMeshRenderer) {
var blendShapes = new List<string> {"-none-"};
for (int i = 0; i < skinnedMeshRenderer.sharedMesh.blendShapeCount; i++) {
blendShapes.Add(skinnedMeshRenderer.sharedMesh.GetBlendShapeName(i));
}
int currentIndex = blendShapes.IndexOf(blendShapeProp.stringValue);
if (currentIndex == -1) currentIndex = 0; // Default to "-none-"
int selectedIndex = EditorGUI.Popup(rect, label, currentIndex, blendShapes.ToArray());
rect.y += spacing;
blendShapeProp.stringValue = selectedIndex > 0 ? blendShapes[selectedIndex] : "";
}
#endregion
#region Private Methods
private void GetHumanoidEyeMuscleLimits()
{
Vector2 defaultUpDown = new Vector2(-10f, 15f);
Vector2 defaultInOut = new Vector2(-20f, 20f);
foreach (HumanBone humanBone in _animator.avatar.humanDescription.human)
if (humanBone.humanName == HumanBodyBones.LeftEye.ToString())
{
_leftEyeUpDown = humanBone.limit.useDefaultValues
? defaultUpDown
: new Vector2(humanBone.limit.min.z, humanBone.limit.max.z);
_leftEyeInOut = humanBone.limit.useDefaultValues
? defaultInOut
: new Vector2(-humanBone.limit.max.y, -humanBone.limit.min.y);
}
else if (humanBone.humanName == HumanBodyBones.RightEye.ToString())
{
_rightEyeUpDown = humanBone.limit.useDefaultValues
? defaultUpDown
: new Vector2(humanBone.limit.min.z, humanBone.limit.max.z);
_rightEyeInOut = humanBone.limit.useDefaultValues
? defaultInOut
: new Vector2(humanBone.limit.min.y, humanBone.limit.max.y);
}
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,161 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
private ReorderableList _fprSettingsList;
private void InitializeFirstPersonRenderList()
{
if (_fprSettingsList != null)
return;
_fprSettingsList ??= new ReorderableList(serializedObject, m_fprSettingsListProp, true, true, true, true)
{
drawHeaderCallback = OnDrawHeaderFPR,
drawElementCallback = OnDrawElementFPR,
elementHeightCallback = OnHeightElementFPR,
onChangedCallback = OnChangedFPR,
//list = _avatar.fprSettingsList
};
}
private void Draw_FPRSettings()
{
if (!shouldDrawFPRMigrationInfo)
return;
using (new ToggleFoldoutScope(ref _guiFirstPersonRenderSettingsFoldout, ref _avatar.enableCustomFPR, "First Person Render (Deprecated)"))
{
if (!_guiFirstPersonRenderSettingsFoldout) return;
Draw_MigrationInfo();
EditorGUI.BeginDisabledGroup(true);
InitializeFirstPersonRenderList();
_fprSettingsList.DoLayoutList();
EditorGUI.EndDisabledGroup();
}
}
#region ReorderableListDrawing FPR
private void OnDrawHeaderFPR(Rect rect)
{
Rect labelRect = new Rect(rect.x, rect.y, rect.width - 35, EditorGUIUtility.singleLineHeight);
GUI.Label(labelRect, $"FPR Exclusions ({_fprSettingsList.count})");
//EditorGUIExtensions.UtilityMenu(rect, _fprSettingsList);
}
private void OnChangedFPR(ReorderableList list)
{
EditorUtility.SetDirty(target);
}
private float OnHeightElementFPR(int index)
{
return EditorGUIUtility.singleLineHeight * 1.25f;
}
private void OnDrawElementFPR(Rect rect, int index, bool isActive, bool isFocused)
{
if (index >= _fprSettingsList.count) return;
SerializedProperty fprSettingsEntry = _fprSettingsList.serializedProperty.GetArrayElementAtIndex(index);
if (fprSettingsEntry == null || index >= _fprSettingsList.serializedProperty.arraySize)
return;
rect = new Rect(rect.x, rect.y + 2, rect.width, EditorGUIUtility.singleLineHeight);
SerializedProperty visibilityProp = fprSettingsEntry.FindPropertyRelative(nameof(CVRAvatarFPREntry.visibility));
SerializedProperty transformProp = fprSettingsEntry.FindPropertyRelative(nameof(CVRAvatarFPREntry.transform));
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width - 60, rect.height), transformProp, GUIContent.none);
rect.x += rect.width - 55;
rect.width = 55;
string[] popupOptions = { "Hide", "Show" };
int visibilityIndex = visibilityProp.intValue;
visibilityIndex = EditorGUI.Popup(rect, visibilityIndex, popupOptions);
if (visibilityIndex != visibilityProp.intValue)
visibilityProp.intValue = visibilityIndex;
}
#endregion
#region FPRExclusion Migration
private bool shouldDrawFPRMigrationInfo => _avatar.fprSettingsList is { Count: > 0 };
private void Draw_MigrationInfo()
{
EditorGUILayout.HelpBox("This feature has been reworked and moved to the new FPRExclusion component.", MessageType.Warning);
EditorGUILayout.HelpBox("You may migrate your old settings to the new system by clicking the button below. Note: You may need to manually tweak things afterward.", MessageType.Info);
if (GUILayout.Button("Migrate FPR Settings")) MigrateFPRSettings();
if (GUILayout.Button("Remove FPR Settings")) RemoveFPRSettings();
}
private void MigrateFPRSettings()
{
// prompt user
if (!EditorUtility.DisplayDialog("Migrate FPR Settings",
"This process will autogenerate a GameObject named CCK.FPRExclusions on the root of your avatar containing the new components. This cannot be undone.", "Do it", "No thanks"))
return;
// convert FPREntries into FPRExclusion components
var oldFPRSettings = _avatar.fprSettingsList;
// add gameobject to root of avatar
GameObject fprExclusionRoot = new ("CCK.FPRExclusions");
fprExclusionRoot.transform.SetParent(_avatar.transform);
fprExclusionRoot.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
fprExclusionRoot.transform.localScale = Vector3.one;
foreach (CVRAvatarFPREntry entry in oldFPRSettings)
{
if (entry.transform == null) continue; // skip null entries
// create new child object with FPRExclusion component
GameObject newExclusion = new ("[FPR] " + entry.transform.name, typeof(FPRExclusion));
newExclusion.transform.SetParent(fprExclusionRoot.transform);
newExclusion.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
newExclusion.transform.localScale = Vector3.one;
// set target
FPRExclusion fprExclusion = newExclusion.GetComponent<FPRExclusion>();
fprExclusion.target = entry.transform;
fprExclusion.isShown = entry.visibility;
}
// remove old settings
_avatar.fprSettingsList.Clear();
_avatar.fprSettingsList = null;
// ping new object in hierarchy
EditorGUIUtility.PingObject(fprExclusionRoot);
}
private void RemoveFPRSettings()
{
// prompt user
if (!EditorUtility.DisplayDialog("Remove FPR Settings",
"This process will remove all depricated FPR settings from this avatar. This cannot be undone.", "Do it", "No thanks"))
return;
// remove old settings
_avatar.fprSettingsList.Clear();
_avatar.fprSettingsList = null;
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,43 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
private void Draw_GeneralAvatarSettings()
{
using (new FoldoutScope(ref _guiAvatarSettingsFoldout, "General Avatar Settings"))
{
if (!_guiAvatarSettingsFoldout) return;
using (new EditorGUI.IndentLevelScope())
DrawGeneralSettings();
}
}
#region Drawing Methods
private void DrawGeneralSettings()
{
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.PropertyField(m_ViewPositionProp, new GUIContent("View Position"));
if (_isHumanoid && GUILayout.Button("Auto", GUILayout.Width(40))) AutoSetViewPosition();
}
EditorGUILayout.Space();
if (_isHumanoid) EditorGUILayout.PropertyField(m_VoiceParentProp, new GUIContent("Voice Parent"));
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.PropertyField(m_VoicePositionProp, new GUIContent("Voice Position"));
if (_isHumanoid && GUILayout.Button("Auto", GUILayout.Width(40))) AutoSetVoicePosition();
}
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,80 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRAvatarEditor
{
private void Draw_LipSyncSettings()
{
using (new FoldoutScope(ref _guiLipSyncSettingsFoldout, "Lip Sync Settings"))
{
if (!_guiLipSyncSettingsFoldout) return;
using (new EditorGUI.IndentLevelScope())
DrawLipSyncSettings();
}
}
#region Drawing Methods
private void DrawLipSyncSettings()
{
EditorGUILayout.PropertyField(m_UseVisemeLipsyncProp, new GUIContent("Use Lip Sync"));
EditorGUILayout.PropertyField(m_VisemeModeProp, new GUIContent("Lip Sync Mode"));
Separator();
switch (_avatar.visemeMode)
{
default: // not really sure what the default is?
case CVRAvatar.CVRAvatarVisemeMode.Visemes:
{
DrawLipSyncVisemeMode();
break;
}
case CVRAvatar.CVRAvatarVisemeMode.SingleBlendshape:
DrawBlendshape("Single Blendshape: ", m_VisemeBlendshapesProp);
break;
case CVRAvatar.CVRAvatarVisemeMode.JawBone:
DrawLipSyncJawBoneMode();
break;
}
}
private void DrawLipSyncVisemeMode()
{
EditorGUILayout.PropertyField(m_VisemeSmoothingProp, new GUIContent("Viseme Smoothing"), GUILayout.MinWidth(10));
DrawBlendshapes("Viseme: ", m_VisemeBlendshapesProp, _visemeNames);
EditorGUILayout.Space();
if (_avatar.bodyMesh != null && GUILayout.Button("Auto Select Visemes"))
{
m_UseVisemeLipsyncProp.boolValue = true;
AutoSelectVisemeBlendshapes();
}
//EditorGUILayout.HelpBox(CCKLocalizationProvider.GetLocalizedText("ABI_UI_AVATAR_INFO_EYE_VISEMES"), MessageType.Info);
}
private void DrawLipSyncJawBoneMode()
{
if (!_isHumanoid)
{
EditorGUILayout.HelpBox("Avatar is not configured as humanoid or lacks an Animator component. Jaw bone lipsync mode is not supported!",
MessageType.Error);
return;
}
EditorGUILayout.HelpBox("Using the jaw transform set in the humanoid configuration.", MessageType.Info);
using (new EditorGUI.DisabledGroupScope(true))
EditorGUILayout.ObjectField("Jaw", _animator.GetBoneTransform(HumanBodyBones.Jaw), typeof(Transform), true);
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 638a719a6ebd4b3b873a4dc695158d88
timeCreated: 1713330383

View file

@ -0,0 +1,49 @@
using UnityEditor;
namespace ABI.CCK.Components
{
[CanEditMultipleObjects]
[CustomEditor(typeof(CVRAvatarPickupMarker))]
public class CCK_CVRAvatarPickupMarkerEditor : Editor
{
#region Private Variables
private CVRAvatarPickupMarker _pickupMarker;
#endregion
#region Serialized Properties
private SerializedProperty m_AvatarGuidProp;
#endregion
#region Unity Events
private void OnEnable()
{
if (target == null) return;
_pickupMarker = (CVRAvatarPickupMarker)target;
m_AvatarGuidProp = serializedObject.FindProperty(nameof(CVRAvatarPickupMarker.avatarGuid));
}
public override void OnInspectorGUI()
{
if (_pickupMarker == null)
return;
serializedObject.Update();
EditorGUILayout.PropertyField(m_AvatarGuidProp);
if (string.IsNullOrEmpty(m_AvatarGuidProp.stringValue))
EditorGUILayout.HelpBox("GUID is empty", MessageType.Info);
else if (!System.Guid.TryParse(m_AvatarGuidProp.stringValue, out _))
EditorGUILayout.HelpBox("Invalid GUID", MessageType.Warning);
serializedObject.ApplyModifiedProperties();
}
#endregion
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 910705e8706c47ff92262eaf15ea711a
timeCreated: 1713330411

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bc729a864bf245944904601886a4131e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,59 @@
using UnityEditor;
namespace ABI.CCK.Components
{
[CustomEditor(typeof(CVRLuaClientBehaviour))]
public partial class CCK_CVRLuaClientBehaviourEditor : Editor
{
#region Editor GUI Fields
private static bool _guiLuaAssetFoldout = true;
private static bool _guiBoundObjectsFoldout = true;
#endregion
#region Private Variables
private CVRBaseLuaBehaviour _baseLuaBehaviour;
#endregion
#region Serialized Properties
private SerializedProperty m_LocalOnly;
private SerializedProperty m_LuaAsset;
private SerializedProperty m_BoundObjects;
#endregion
public void OnEnable()
{
if (target == null) return;
_baseLuaBehaviour = (CVRLuaClientBehaviour)target;
m_LocalOnly = serializedObject.FindProperty(nameof(CVRLuaClientBehaviour.localOnly));
m_LuaAsset = serializedObject.FindProperty(nameof(CVRLuaClientBehaviour.asset));
m_BoundObjects = serializedObject.FindProperty(nameof(CVRLuaClientBehaviour.boundObjects));
}
public override void OnInspectorGUI()
{
if (_baseLuaBehaviour == null)
return;
EditorGUILayout.HelpBox(
"Lua is an open-source language that you can use to easily add new scripted behaviours to objects in props, avatars, and worlds.",
MessageType.Info);
EditorGUILayout.HelpBox(
"To test scripting in-game you need to use our Scripting Nightly branch. Instruction on how to opt in can be found in our discord server.",
MessageType.Warning);
serializedObject.Update();
Draw_LuaAsset();
Draw_BoundObjects();
serializedObject.ApplyModifiedProperties();
}
}
}

View file

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

View file

@ -0,0 +1,94 @@
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRLuaClientBehaviourEditor
{
private ReorderableList _boundObjectList;
private void Draw_BoundObjects()
{
using (new FoldoutScope(ref _guiBoundObjectsFoldout, "Bound Objects", s_BoldFoldoutStyle))
{
if (!_guiBoundObjectsFoldout) return;
DrawBoundObjects();
}
}
#region Drawing Methods
private void DrawBoundObjects()
{
_boundObjectList ??= new ReorderableList(serializedObject, m_BoundObjects, true, true, false, false)
{
footerHeight = 0f,
elementHeight = EditorGUIUtility.singleLineHeight + 4f,
drawHeaderCallback = rect =>
{
EditorGUI.LabelField(new Rect(rect.x, rect.y, rect.width * 0.5f, rect.height), "Object Names");
EditorGUI.LabelField(
new Rect(rect.x + rect.width * 0.5f, rect.y, rect.width * 0.5f, rect.height),
"Object Values");
},
drawElementCallback = (rect, index, _, _) =>
{
Rect _rect = new (rect.x, rect.y + 2, rect.width, EditorGUIUtility.singleLineHeight);
SerializedProperty element = _boundObjectList.serializedProperty.GetArrayElementAtIndex(index);
var halfWidth = _rect.width * 0.5f;
EditorGUI.PropertyField(
new Rect(_rect.x, _rect.y, halfWidth - 5f, EditorGUIUtility.singleLineHeight),
element.FindPropertyRelative(nameof(CVRBaseLuaBehaviour.BoundObject.name)), GUIContent.none);
EditorGUI.PropertyField(
new Rect(_rect.x + halfWidth, _rect.y, halfWidth, EditorGUIUtility.singleLineHeight),
element.FindPropertyRelative(nameof(CVRBaseLuaBehaviour.BoundObject.boundThing)), GUIContent.none);
}
};;
EditorGUILayout.HelpBox(
"Bound Objects are a way to tell your script about other objects in the scene, and will be accessible via the BoundObjects global (read-only). Careful: Duplicate names will be overwritten by the last duplicate.",
MessageType.Info);
Separator();
DrawBoundObjectButtons();
_boundObjectList.DoLayoutList();
}
private void DrawBoundObjectButtons()
{
EditorGUILayout.BeginHorizontal();
// Add Button
if (GUILayout.Button("Add Bound Object"))
{
m_BoundObjects.InsertArrayElementAtIndex(m_BoundObjects.arraySize);
SerializedProperty newElement =
m_BoundObjects.GetArrayElementAtIndex(m_BoundObjects.arraySize - 1);
newElement.FindPropertyRelative(nameof(CVRBaseLuaBehaviour.BoundObject.name)).stringValue = "";
newElement.FindPropertyRelative(nameof(CVRBaseLuaBehaviour.BoundObject.boundThing)).objectReferenceValue = null;
_boundObjectList.index = m_BoundObjects.arraySize - 1;
}
// Remove Button
EditorGUI.BeginDisabledGroup(m_BoundObjects.arraySize == 0 || _boundObjectList.index < 0);
if (GUILayout.Button("Remove Bound Object"))
{
var removeIndex = _boundObjectList.index;
if (removeIndex >= 0 && removeIndex < m_BoundObjects.arraySize)
{
m_BoundObjects.DeleteArrayElementAtIndex(removeIndex);
_boundObjectList.index--;
}
}
EditorGUI.EndDisabledGroup();
EditorGUILayout.EndHorizontal();
}
#endregion
}
}

View file

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

View file

@ -0,0 +1,113 @@
using System;
using System.Linq;
using ABI.CCK.Components.ScriptableObjects;
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
using Object = UnityEngine.Object;
namespace ABI.CCK.Components
{
public partial class CCK_CVRLuaClientBehaviourEditor
{
private Vector2 _scrollPosition;
private void Draw_LuaAsset()
{
using (new FoldoutScope(ref _guiLuaAssetFoldout, "Lua Script", s_BoldFoldoutStyle))
{
if (!_guiLuaAssetFoldout) return;
using (new EditorGUI.IndentLevelScope())
DrawLuaAsset();
}
}
#region Drawing Methods
private void DrawLuaAsset()
{
if (!DrawScriptAsset())
return;
Separator();
DrawScriptPreview();
}
private bool DrawScriptAsset()
{
DrawLocalOnly();
Object luaAsset = EditorGUILayout.ObjectField("Script Asset:", m_LuaAsset.objectReferenceValue, typeof(CVRLuaScript),
allowSceneObjects: true, null);
if (luaAsset is CVRLuaScript luaScript
&& m_LuaAsset.objectReferenceValue != luaScript)
{
string assetPath = AssetDatabase.GetAssetPath(luaScript);
if (!string.IsNullOrEmpty(assetPath) && assetPath.EndsWith(".lua", StringComparison.OrdinalIgnoreCase))
{
_baseLuaBehaviour.asset = luaScript;
m_LuaAsset.objectReferenceValue = luaScript; // set via serialized property to support undo
}
}
using (new EditorGUI.DisabledScope(true))
EditorGUILayout.LabelField("Script Path:", _baseLuaBehaviour.ScriptPath);
if (m_LuaAsset.objectReferenceValue != null)
return true;
EditorGUILayout.HelpBox(
"No linked file. Please drag your LUA file from your project to the field above.",
MessageType.Error);
return false;
}
private void DrawLocalOnly()
{
if (_baseLuaBehaviour.GetComponentInParent<CVRAvatar>() != null)
{
EditorGUILayout.PropertyField(m_LocalOnly, new GUIContent("Run only for Avatar's Wearer"));
if (!m_LocalOnly.boolValue)
EditorGUILayout.HelpBox("This script will run on every player's machine. When unsure keep it enabled.", MessageType.Warning);
}
else if (_baseLuaBehaviour.GetComponentInParent<CVRSpawnable>() != null)
{
EditorGUILayout.PropertyField(m_LocalOnly, new GUIContent("Run only for Prop's Spawner"));
if (!m_LocalOnly.boolValue)
EditorGUILayout.HelpBox("This script will run on every player's machine. When unsure keep it enabled.", MessageType.Info);
}
}
private void DrawScriptPreview()
{
const float lineHeight = 24;
int lineCount = CountLines(_baseLuaBehaviour.ScriptText);
float scrollViewHeight = Mathf.Min(lineCount * lineHeight, 200);
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, false, false,
GUILayout.Width(EditorGUIUtility.currentViewWidth - 30), GUILayout.Height(scrollViewHeight));
using (new EditorGUI.DisabledScope(true))
{
using (new SetIndentLevelScope(0))
EditorGUILayout.TextArea(_baseLuaBehaviour.ScriptText, GUILayout.ExpandHeight(true));
}
EditorGUILayout.EndScrollView();
}
#endregion
#region Private Methods
private static int CountLines(string text)
{
return string.IsNullOrEmpty(text)
? 0
: 1 + text.Count(c => c == '\n');
}
#endregion
}
}

View file

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

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d526df5faaa409d4a9e3e7e4a9449e20
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,89 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
[CanEditMultipleObjects]
[CustomEditor(typeof(CVRCameraHelper))]
public partial class CCK_CVRCameraHelperEditor : Editor
{
#region EditorGUI Foldouts
private static bool _guiCameraSettingsFoldout = true;
private static bool _guiShaderSettingsFoldout = true;
#endregion
private CVRCameraHelper _cameraHelper;
private CVRAvatar _validAvatar;
private CVRSpawnable _validSpawnable;
private CVRPickupObject _validPickup;
private SerializedProperty m_CamProp;
private SerializedProperty m_SetAsMirroringCamera;
private SerializedProperty m_SelectedShaderProp;
private SerializedProperty m_ReplacementShadersProp;
#region Unity Events
private void OnEnable()
{
if (target == null) return;
_cameraHelper = (CVRCameraHelper)target;
_validAvatar = _cameraHelper.GetComponentInParent<CVRAvatar>();
_validSpawnable = _cameraHelper.GetComponentInParent<CVRSpawnable>();
_validPickup = _cameraHelper.GetComponentInParent<CVRPickupObject>();
m_CamProp = serializedObject.FindProperty(nameof(CVRCameraHelper.cam));
m_SetAsMirroringCamera = serializedObject.FindProperty(nameof(CVRCameraHelper.setAsMirroringCamera));
m_SelectedShaderProp = serializedObject.FindProperty(nameof(CVRCameraHelper.selectedShader));
m_ReplacementShadersProp = serializedObject.FindProperty(nameof(CVRCameraHelper.replacementShaders));
}
public override void OnInspectorGUI()
{
if (_cameraHelper == null)
return;
serializedObject.Update();
Draw_Info();
Draw_AvatarError();
Draw_PropWarning();
Draw_CameraSettings();
Draw_ShaderSettings();
serializedObject.ApplyModifiedProperties();
}
#endregion
#region Drawing Methods
private void Draw_Info()
{
EditorGUILayout.HelpBox("For use with Animation Events. Allows you to call TakeScreenshot to save the Camera Render Texture output. Limited to once per second.", MessageType.Info);
}
private void Draw_AvatarError()
{
if (_validAvatar != null)
EditorGUILayout.HelpBox("CVRCameraHelper is not currently allowed on Avatars!", MessageType.Error);
}
private void Draw_PropWarning()
{
if (_validSpawnable && !_validPickup)
EditorGUILayout.HelpBox("CVRPickupObject is missing in hierarchy. CVRCameraHelper must be held while on a prop for TakeScreenshot to work.", MessageType.Warning);
}
#endregion
}
}
#endif

View file

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

View file

@ -0,0 +1,33 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRCameraHelperEditor
{
private void Draw_CameraSettings()
{
using (new FoldoutScope(ref _guiCameraSettingsFoldout, "Camera Settings"))
{
if (!_guiCameraSettingsFoldout) return;
using (new EditorGUI.IndentLevelScope())
DrawCameraSettings();
}
}
private void DrawCameraSettings()
{
GUILayout.BeginVertical();
EditorGUILayout.PropertyField(m_CamProp, new GUIContent("Camera"));
// This option is not implemented. Leaving in GUI though as it fills the space nicely. :)
EditorGUILayout.PropertyField(m_SetAsMirroringCamera, new GUIContent("Mirroring Camera"));
GUILayout.EndVertical();
}
}
}
#endif

View file

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

View file

@ -0,0 +1,31 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
public partial class CCK_CVRCameraHelperEditor
{
private void Draw_ShaderSettings()
{
using (new FoldoutScope(ref _guiShaderSettingsFoldout, "Shader Settings"))
{
if (!_guiShaderSettingsFoldout) return;
using (new EditorGUI.IndentLevelScope())
DrawShaderSettings();
}
}
private void DrawShaderSettings()
{
GUILayout.BeginVertical();
EditorGUILayout.PropertyField(m_SelectedShaderProp, new GUIContent("Selected Shader"));
EditorGUILayout.PropertyField(m_ReplacementShadersProp, new GUIContent("Replacement Shaders"), true);
GUILayout.EndVertical();
}
}
}
#endif

View file

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

View file

@ -4,56 +4,99 @@ using UnityEngine;
namespace ABI.CCK.Scripts.Editor
{
[CustomEditor(typeof(ABI.CCK.Components.CVRDescription))]
[CustomEditor(typeof(CVRDescription))]
public class CCK_CVRDescriptionEditor : UnityEditor.Editor
{
private CVRDescription _description;
#region Unity Events
private void OnEnable()
{
if (target == null) return;
_description = (CVRDescription)target;
}
public override void OnInspectorGUI()
{
if (_description == null) _description = (CVRDescription) target;
if (_description == null)
return;
EditorGUI.BeginChangeCheck();
if (_description.locked)
{
switch (_description.type)
{
case 0:
EditorGUILayout.HelpBox(_description.description, MessageType.None);
break;
case 1:
EditorGUILayout.HelpBox(_description.description, MessageType.Info);
break;
case 2:
EditorGUILayout.HelpBox(_description.description, MessageType.Warning);
break;
case 3:
EditorGUILayout.HelpBox(_description.description, MessageType.Error);
break;
}
if (!string.IsNullOrEmpty(_description.url))
{
if (GUILayout.Button("Read more about this topic"))
{
Application.OpenURL(_description.url);
}
}
}
DrawLockedDescription();
else
{
EditorGUILayout.LabelField("Description");
_description.description = EditorGUILayout.TextArea(_description.description);
EditorGUILayout.LabelField("Documentation Url");
_description.url = EditorGUILayout.TextField(_description.url);
DrawEditableDescription();
EditorGUILayout.LabelField("Icon Type");
_description.type = EditorGUILayout.Popup(_description.type, new string[] { "None", "Info", "Warning", "Error" });
if (GUILayout.Button("Lock info"))
{
_description.locked = true;
}
}
if (EditorGUI.EndChangeCheck())
EditorUtility.SetDirty(_description);
}
#endregion
#region GUI Drawing
private void DrawLockedDescription()
{
GUIStyle helpBoxStyle = new GUIStyle(EditorStyles.helpBox)
{
padding = new RectOffset(10, 10, 10, 10)
};
GUIStyle descriptionStyle = new GUIStyle(EditorStyles.label)
{
richText = true,
wordWrap = true
};
EditorGUILayout.BeginVertical(helpBoxStyle);
EditorGUILayout.BeginHorizontal();
GUIContent iconContent = GUIContent.none;
switch (_description.type)
{
case 1: // Info
iconContent = EditorGUIUtility.IconContent("console.infoicon");
break;
case 2: // Warning
iconContent = EditorGUIUtility.IconContent("console.warnicon");
break;
case 3: // Error
iconContent = EditorGUIUtility.IconContent("console.erroricon");
break;
}
if (iconContent != GUIContent.none)
{
GUILayout.Label(iconContent, GUILayout.Width(40), GUILayout.Height(40));
GUILayout.Space(10);
}
using (new EditorGUILayout.ScrollViewScope(Vector2.zero, GUILayout.ExpandWidth(true)))
EditorGUILayout.LabelField(_description.description, descriptionStyle);
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
if (!string.IsNullOrEmpty(_description.url) && GUILayout.Button("Read more about this topic"))
Application.OpenURL(_description.url);
}
private void DrawEditableDescription()
{
EditorGUILayout.LabelField("Description:", new GUIStyle(EditorStyles.label));
_description.description = EditorGUILayout.TextArea(_description.description,
new GUIStyle(EditorStyles.textArea) { richText = true },
GUILayout.Height(100));
_description.url = EditorGUILayout.TextField("Documentation Url", _description.url);
_description.type = EditorGUILayout.Popup("Icon Type", _description.type, new[] { "None", "Info", "Warning", "Error" });
if (GUILayout.Button("Lock info"))
_description.locked = true;
}
#endregion
}
}

View file

@ -1,12 +1,13 @@
using System.Collections.Generic;
using System.Linq;
using ABI.CCK.Components;
using ABI.CCK.Scripts.Editor;
using UnityEditor;
using UnityEngine;
namespace ABI.CCK.Scripts.Editor
{
[CustomEditor(typeof(ABI.CCK.Components.CVRFaceTracking))]
[CustomEditor(typeof(CVRFaceTracking))]
public class CCK_CVRFaceTrackingEditor : UnityEditor.Editor
{
private CVRFaceTracking _faceTracking;
@ -16,28 +17,22 @@ namespace ABI.CCK.Scripts.Editor
if (_faceTracking == null) _faceTracking = (CVRFaceTracking) target;
_faceTracking.GetBlendShapeNames();
_faceTracking.UseFacialTracking = EditorGUILayout.Toggle("Enable Facial Tracking", _faceTracking.UseFacialTracking);
_faceTracking.BlendShapeStrength = EditorGUILayout.Slider("Blend Shape Weight", _faceTracking.BlendShapeStrength, 50f, 500f);
_faceTracking.FaceMesh = (SkinnedMeshRenderer)EditorGUILayout.ObjectField("Face Mesh", _faceTracking.FaceMesh, typeof(SkinnedMeshRenderer), true);
for (int i = 0; i < CVRFaceTracking.FaceBlendShapeNames.Length; i++)
{
int current = 0;
for (int j = 0; j < _faceTracking.BlendShapeNames.Count; ++j)
if (_faceTracking.FaceBlendShapes[i] == _faceTracking.BlendShapeNames[j])
current = j;
int viseme = EditorGUILayout.Popup(CVRFaceTracking.FaceBlendShapeNames[i], current, _faceTracking.BlendShapeNames.ToArray());
_faceTracking.FaceBlendShapes[i] = _faceTracking.BlendShapeNames[viseme];
_faceTracking.FaceBlendShapes[i] = EditorGUIExtensions.CustomPopup(
GUILayoutUtility.GetRect(new GUIContent(CVRFaceTracking.FaceBlendShapeNames[i]), EditorStyles.popup),
CVRFaceTracking.FaceBlendShapeNames[i],
_faceTracking.FaceBlendShapes[i],
_faceTracking.BlendShapeNames.ToArray(),
CVRFaceTracking.FaceBlendShapeNames[i]);
}
if (GUILayout.Button("Auto select Blendshapes"))
{
_faceTracking.FindVisemes();
}
_faceTracking.AutoSelectFaceTrackingShapes();
EditorGUILayout.BeginVertical("HelpBox");
EditorGUILayout.LabelField("Face Tracking ");

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a658175bce634ded88659d06fac6e21e
timeCreated: 1699270791

View file

@ -0,0 +1,76 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static ABI.CCK.Scripts.Editor.SharedComponentGUI;
namespace ABI.CCK.Components
{
[CanEditMultipleObjects]
[CustomEditor(typeof(FluidVolume))]
public class CCK_CVRFluidVolumeEditor : Editor
{
private FluidVolume _fluidVolume;
private SerializedProperty m_VolumeTypeProp;
private SerializedProperty m_ExtendProp;
private SerializedProperty m_DepthProp;
private SerializedProperty m_DensityProp;
private SerializedProperty m_PlaceFromCenterProp;
private SerializedProperty m_StreamTypeProp;
private SerializedProperty m_StreamAngleProp;
private SerializedProperty m_StreamStrengthProp;
private SerializedProperty m_SplashParticleSystem;
#region Unity Events
private void OnEnable()
{
if (target == null) return;
_fluidVolume = (FluidVolume) target;
m_VolumeTypeProp = serializedObject.FindProperty(nameof(FluidVolume.volumeType));
m_ExtendProp = serializedObject.FindProperty(nameof(FluidVolume.extend));
m_DepthProp = serializedObject.FindProperty(nameof(FluidVolume.depth));
m_DensityProp = serializedObject.FindProperty(nameof(FluidVolume.density));
m_PlaceFromCenterProp = serializedObject.FindProperty(nameof(FluidVolume.placeFromCenter));
m_StreamTypeProp = serializedObject.FindProperty(nameof(FluidVolume.streamType));
m_StreamAngleProp = serializedObject.FindProperty(nameof(FluidVolume.streamAngle));
m_StreamStrengthProp = serializedObject.FindProperty(nameof(FluidVolume.streamStrength));
m_SplashParticleSystem = serializedObject.FindProperty(nameof(FluidVolume.splashParticleSystem));
}
public override void OnInspectorGUI()
{
if (_fluidVolume == null)
return;
serializedObject.Update();
Draw_Editor();
serializedObject.ApplyModifiedProperties();
}
#endregion
#region Drawing Methods
private void Draw_Editor()
{
EditorGUILayout.PropertyField(m_VolumeTypeProp, new GUIContent("Volume Type"));
EditorGUILayout.PropertyField(m_ExtendProp, new GUIContent("Width/Length"));
EditorGUILayout.PropertyField(m_DepthProp, new GUIContent("Depth"));
if (_fluidVolume.volumeType == FluidVolume.VolumeType.Box)
EditorGUILayout.PropertyField(m_PlaceFromCenterProp, new GUIContent("Place from center"));
EditorGUILayout.Space(15f);
EditorGUILayout.PropertyField(m_StreamTypeProp, new GUIContent("Stream Type"));
EditorGUILayout.PropertyField(m_StreamAngleProp, new GUIContent("Stream Angle"));
EditorGUILayout.PropertyField(m_StreamStrengthProp, new GUIContent("Stream Strength"));
EditorGUILayout.Space(15f);
EditorGUILayout.PropertyField(m_SplashParticleSystem, new GUIContent("Splash Particle System"));
}
#endregion
}
}
#endif

Some files were not shown because too many files have changed in this diff Show more