update CCK to 3.10, fixing unity 2021 crash :)
This commit is contained in:
parent
48a978fa2a
commit
d11e0fb3a9
492 changed files with 2165204 additions and 437687 deletions
3
Assets/ABI.CCK/Scripts/Editor/AssetProcessing.meta
Executable file
3
Assets/ABI.CCK/Scripts/Editor/AssetProcessing.meta
Executable file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 98b32b335c98486aacec87ab6497ba21
|
||||
timeCreated: 1702781645
|
154
Assets/ABI.CCK/Scripts/Editor/AssetProcessing/CCK_AssetPostProcessor.cs
Executable file
154
Assets/ABI.CCK/Scripts/Editor/AssetProcessing/CCK_AssetPostProcessor.cs
Executable 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
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 983fdec8b2554916a318d13c3cc189a5
|
||||
timeCreated: 1702781676
|
59
Assets/ABI.CCK/Scripts/Editor/AssetProcessing/CCK_AutoCleanupProcessor.cs
Executable file
59
Assets/ABI.CCK/Scripts/Editor/AssetProcessing/CCK_AutoCleanupProcessor.cs
Executable 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);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a1f6a40517314d64bed4c4d97905ccdc
|
||||
timeCreated: 1703188866
|
|
@ -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
|
||||
}
|
8
Assets/ABI.CCK/Scripts/Editor/CCK_BodyControlEditor.meta
Executable file
8
Assets/ABI.CCK/Scripts/Editor/CCK_BodyControlEditor.meta
Executable file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a6cfbda11115dfa408061903c1760818
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
57
Assets/ABI.CCK/Scripts/Editor/CCK_BodyControlEditor/CCK_BodyControlEditor.cs
Executable file
57
Assets/ABI.CCK/Scripts/Editor/CCK_BodyControlEditor/CCK_BodyControlEditor.cs
Executable 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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0f8ef1acbc515f14a95ab5d052d380aa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5dcbab43e1f6d26409fe31f9bd79ca2c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
19
Assets/ABI.CCK/Scripts/Editor/CCK_BuildTargetSwitch.cs
Executable file
19
Assets/ABI.CCK/Scripts/Editor/CCK_BuildTargetSwitch.cs
Executable 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);
|
||||
}
|
||||
}
|
||||
}
|
3
Assets/ABI.CCK/Scripts/Editor/CCK_BuildTargetSwitch.cs.meta
Executable file
3
Assets/ABI.CCK/Scripts/Editor/CCK_BuildTargetSwitch.cs.meta
Executable file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5d6069e9dc8048d29ad54a3057a898be
|
||||
timeCreated: 1701950588
|
|
@ -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
|
||||
}
|
8
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAdvancedAvatarSettingsTrigger.meta
Executable file
8
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAdvancedAvatarSettingsTrigger.meta
Executable file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: feba207f658e6754bbd61863a923e46b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dc36bd391a0b38a41bb6c78e7989b06e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8cbe29d1da65cc9439ac330896c6705f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f74f233979f38e7409b25a0065034d17
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d5e33caf6454aca468b953399704087c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ed63a9ccfec553d429394fb89e1cee41
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ece7ec86c2882f94d8796905f37fbae5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 20a4a948606a9b847bc99b59a6ecedf9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
3
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAnimatorDriverEditor.meta
Executable file
3
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAnimatorDriverEditor.meta
Executable file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 503166a9d64c4b4182595e10d6ce963d
|
||||
timeCreated: 1703219388
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f0ca9029fe954673924df7306b41f85f
|
||||
timeCreated: 1703219398
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 62d32b85d371449ca067a5fc0688522d
|
||||
timeCreated: 1703220016
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
8
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAudioDriverEditor.meta
Executable file
8
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAudioDriverEditor.meta
Executable file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ce0296e1d6745c5468b89206222b3308
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: adf3d613d523bbd499c6f4ba881065b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -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
8
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAvatarEditor.meta
Executable file
8
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAvatarEditor.meta
Executable file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0c8f7cf20a254f842b408a613966ab0f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 77bf502e56374ff8ba1488a070dc2435
|
||||
timeCreated: 1709423065
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d6aa02cac0694cab9ba81de900bdf4c6
|
||||
timeCreated: 1714267882
|
|
@ -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
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6118c371302943b6bb8a740c62dd0a97
|
||||
timeCreated: 1714268283
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d0297c5beb0a41ea8108dcbda5dd6bc0
|
||||
timeCreated: 1709424213
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4e1f511a5d874fd9b5bc9c8a1728066e
|
||||
timeCreated: 1709424050
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fd5428143ca147de8f8649f82edbce3b
|
||||
timeCreated: 1709424338
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 877f1862df6d493fb7547361ef50ce65
|
||||
timeCreated: 1709424273
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d42afa81de944f8b96dd614d64b9e485
|
||||
timeCreated: 1709424234
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: df6671fcd41141df877371502a7eb664
|
||||
timeCreated: 1709423125
|
490
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAvatarEditor/CCK_CVRAvatarEditor.cs
Executable file
490
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAvatarEditor/CCK_CVRAvatarEditor.cs
Executable 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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f674ceaf9f32b8b49a43756c6b8c534f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a1a0903b37ddaac4cadea63af36bb2f0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 90200356b5f9ddb4da77d79cc62408e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0b03a9525ffb3cf45b0da9f97cddb018
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d00535e95d2832841a9af39be34acf6a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
391
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAvatarEditor/CCK_CVRAvatarEditorEyeLook.cs
Executable file
391
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAvatarEditor/CCK_CVRAvatarEditorEyeLook.cs
Executable 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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0b75520004bec7345b51aa98559b122c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d7c23f289e852114f8795da96ecaae1c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f1fc531404a36bc428e4f04d465d6595
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a2a799dec0d33114199d9bba008748fa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
3
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAvatarPickupMarkerEditor.meta
Executable file
3
Assets/ABI.CCK/Scripts/Editor/CCK_CVRAvatarPickupMarkerEditor.meta
Executable file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 638a719a6ebd4b3b873a4dc695158d88
|
||||
timeCreated: 1713330383
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 910705e8706c47ff92262eaf15ea711a
|
||||
timeCreated: 1713330411
|
8
Assets/ABI.CCK/Scripts/Editor/CCK_CVRBaseLuaBehaviourEditor.meta
Executable file
8
Assets/ABI.CCK/Scripts/Editor/CCK_CVRBaseLuaBehaviourEditor.meta
Executable file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bc729a864bf245944904601886a4131e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5efc2461fe2c34a4995284eab5c86e21
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 53e02df5678c8bd4695568fa966d3a37
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e38ea6ae063fa384fb87bff48c26d590
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/ABI.CCK/Scripts/Editor/CCK_CVRCameraHelperEditor.meta
Executable file
8
Assets/ABI.CCK/Scripts/Editor/CCK_CVRCameraHelperEditor.meta
Executable file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d526df5faaa409d4a9e3e7e4a9449e20
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 62a5cb12ce47ac24c8feeece7cd8c3ee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ad8ddcdf1a622954f8c4c751d42aa592
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 568a1ae7b6a604345a673aedc2d1cfef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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 ");
|
||||
|
|
3
Assets/ABI.CCK/Scripts/Editor/CCK_CVRFluidVolumeEditor.meta
Executable file
3
Assets/ABI.CCK/Scripts/Editor/CCK_CVRFluidVolumeEditor.meta
Executable file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a658175bce634ded88659d06fac6e21e
|
||||
timeCreated: 1699270791
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue