string GetAnimLayerButtonName(VRCAvatarDescriptor.AnimLayerType layerType) { string name = null; _animLayerButtonNames.TryGetValue(layerType, out name); if (string.IsNullOrEmpty(name)) { foreach (EditorAnimLayerInfo info in baseAnimLayerTypes) { if (info.type == layerType) { if (_animator && (!_animator.isHuman) && info.label == "Face") { name = "Default BlendShapes"; } else { name = ("Default " + info.label); } _animLayerButtonNames.Add(layerType, name); return(name); } } foreach (EditorAnimLayerInfo info in specialAnimLayerTypes) { if (info.type == layerType) { name = ("Default " + info.label); _animLayerButtonNames.Add(layerType, name); return(name); } } } return(name); }
private Issue ValidateOnlyTransformsMotion(bool onlyTransfroms, VRCAvatarDescriptor.AnimLayerType layerName, Motion motion) { Issue issue = new Issue(); if(!motion) return null; else if(motion is BlendTree) { BlendTree bTree = (BlendTree)motion; bool hadIssue = false; foreach(ChildMotion child in bTree.children) { Issue mIssue = ValidateOnlyTransformsMotion(onlyTransfroms, layerName, child.motion); if(null != mIssue) { issue.Reference.AddRange(mIssue.Reference); hadIssue = true; } } if(hadIssue) return issue; } else if(motion is AnimationClip) { AnimationClip clip = (AnimationClip)motion; foreach(EditorCurveBinding binding in AnimationUtility.GetCurveBindings(clip)) { if(onlyTransfroms != (binding.type == typeof(Transform) || binding.type == typeof(Animator))) { //string issue = onlyTransfroms ? "Transforms" : "Non-Transforms"; //Debug.LogWarning($"[{clip.name}] in {layerName} layer contains {issue}"); issue.Reference.Add(clip); return issue; } } } return null; }
private void Reset() { inventoryAnimLayer = VRCAvatarDescriptor.AnimLayerType.Gesture; basisAnimator = AssetDatabase.LoadAssetAtPath <AnimatorController>("Assets/VRCSDK/Examples3/Animation/Controllers/vrc_AvatarV3HandsLayer.controller"); descriptorGUID = GUID.Generate().ToString(); hideFlags = HideFlags.DontSaveInBuild; }
public static void SetAnimationLayer(this VRCAvatarDescriptor avatar, VRCAvatarDescriptor.AnimLayerType layer, VRCAvatarDescriptor.CustomAnimLayer animation) { switch (layer) { case VRCAvatarDescriptor.AnimLayerType.Base: case VRCAvatarDescriptor.AnimLayerType.Additive: case VRCAvatarDescriptor.AnimLayerType.Gesture: case VRCAvatarDescriptor.AnimLayerType.Action: case VRCAvatarDescriptor.AnimLayerType.FX: var(_, bIndex) = avatar.baseAnimationLayers.Select((w, i) => (Value: w, Index: i)).First(w => w.Value.type == layer); avatar.baseAnimationLayers[bIndex] = animation; break; case VRCAvatarDescriptor.AnimLayerType.SpecialIK: case VRCAvatarDescriptor.AnimLayerType.Sitting: case VRCAvatarDescriptor.AnimLayerType.TPose: case VRCAvatarDescriptor.AnimLayerType.IKPose: var(_, sIndex) = avatar.specialAnimationLayers.Select((w, i) => (Value: w, Index: i)).First(w => w.Value.type == layer); avatar.specialAnimationLayers[sIndex] = animation; break; default: throw new ArgumentOutOfRangeException(nameof(layer), layer, null); } }
void InitAnimLayer(SerializedProperty list, VRCAvatarDescriptor.AnimLayerType type, bool isDefault, int index = -1) { list.InsertArrayElementAtIndex(list.arraySize); var element = list.GetArrayElementAtIndex((index == -1) ? (list.arraySize - 1) : index); element.FindPropertyRelative("type").enumValueIndex = (int)type; element.FindPropertyRelative("isDefault").boolValue = isDefault; }
private void ValidateParameterDriver(VRCAvatarParameterDriver d, VRCAvatarDescriptor.AnimLayerType type, AnimatorControllerLayer layer, AnimatorState state) { drivers.Add(new DriverIssue { driver = d, layerName = layer.name, layerType = type, state = state }); }
bool IsHumanOnlyAnimLayer(VRCAvatarDescriptor.AnimLayerType layerType) { switch (layerType) { case VRCAvatarDescriptor.AnimLayerType.Additive: return(true); case VRCAvatarDescriptor.AnimLayerType.Gesture: return(true); } return(false); }
public static AnimatorController GetPlayableLayer(this VRCAvatarDescriptor avatarDescriptor, VRCAvatarDescriptor.AnimLayerType animLayerType) { var customAnimLayer = avatarDescriptor.baseAnimationLayers?.First(x => x.type == animLayerType); if (customAnimLayer?.animatorController == null) { return(null); } return((AnimatorController)customAnimLayer.Value.animatorController); }
public static bool HasAnimationLayer(this VRCAvatarDescriptor avatar, VRCAvatarDescriptor.AnimLayerType layer) { if (!avatar.customizeAnimationLayers) { return(false); } var anim = avatar.GetAnimationLayer(layer); return(!anim.isDefault && anim.isEnabled && anim.animatorController != null); }
private void ValidateOnlyTransforms(VRCAvatarDescriptor.AnimLayerType layerName, AnimatorController controller) { bool onlyTransfroms = layerName != VRCAvatarDescriptor.AnimLayerType.FX; if(!controller) return; foreach(AnimatorControllerLayer layer in controller.layers) { ValidateOnlyTransforms(onlyTransfroms, layerName, layer.stateMachine.states, layer.name); foreach(ChildAnimatorStateMachine childMachine in layer.stateMachine.stateMachines) { ValidateOnlyTransforms(onlyTransfroms, layerName, childMachine.stateMachine.states, layer.name); } } }
public PlayableLayerData FindPlayableLayerData(VRCAvatarDescriptor.AnimLayerType type) { foreach (PlayableLayerData item in data) { if (item.layer == type) { return(item); } } return(null); }
private void ValidateOnlyTransforms(bool onlyTransfroms, VRCAvatarDescriptor.AnimLayerType layerName, ChildAnimatorState[] states, string animLayerName) { foreach(ChildAnimatorState state in states) { Motion m = state.state.motion; Issue issue = ValidateOnlyTransformsMotion(onlyTransfroms, layerName, m); if(null != issue) { if(onlyTransfroms) { issue.Cause = $"Layer[{animLayerName}]: Motion contains non-Transformations"; issue.Reference.Add(state.state); issues.GetLayer(layerName).Insert(0, issue); } else { issue.Cause = $"Layer[{animLayerName}]: Motion contains Transformations"; issue.Reference.Add(state.state); issues.GetLayer(layerName).Insert(0, issue); } } } }
public static void SetAnimationLayer(this VRCAvatarDescriptor avatar, VRCAvatarDescriptor.AnimLayerType layer, AnimatorController controller) { if (!avatar.customizeAnimationLayers) { avatar.customizeAnimationLayers = true; } var l = avatar.GetAnimationLayer(layer); if (l.isDefault) { l.isDefault = false; } l.animatorController = controller; avatar.SetAnimationLayer(layer, l); }
public static void SetPlayableLayer(this VRCAvatarDescriptor avatarDescriptor, AnimatorController animatorController, VRCAvatarDescriptor.AnimLayerType animLayerType) { var avatarDesctiptorSerializedObject = new SerializedObject(avatarDescriptor); avatarDesctiptorSerializedObject.Update(); var indexOf = ArrayUtility.IndexOf(avatarDescriptor.baseAnimationLayers, avatarDescriptor.baseAnimationLayers.First(x => x.type == animLayerType)); if (indexOf > -1) { avatarDescriptor.baseAnimationLayers[indexOf].isDefault = animatorController == null; avatarDescriptor.baseAnimationLayers[indexOf].animatorController = animatorController; } avatarDescriptor.customizeAnimationLayers = !avatarDescriptor.baseAnimationLayers.All(x => x.isDefault); avatarDesctiptorSerializedObject.ApplyModifiedProperties(); }
public List <Issue> GetLayer(VRCAvatarDescriptor.AnimLayerType layer) { if (VRCAvatarDescriptor.AnimLayerType.Base == layer) { return(BaseLayer); } else if (VRCAvatarDescriptor.AnimLayerType.Additive == layer) { return(AdditiveLayer); } else if (VRCAvatarDescriptor.AnimLayerType.Gesture == layer) { return(GestureLayer); } else if (VRCAvatarDescriptor.AnimLayerType.Action == layer) { return(ActionLayer); } else if (VRCAvatarDescriptor.AnimLayerType.FX == layer) { return(FXLayer); } throw new System.Exception("TEA Manager has a playable layer mapping issue, the VRChat SDK may not be compatible"); }
public static VRCAvatarDescriptor.CustomAnimLayer GetAnimationLayer(this VRCAvatarDescriptor avatar, VRCAvatarDescriptor.AnimLayerType layer) { switch (layer) { case VRCAvatarDescriptor.AnimLayerType.Base: case VRCAvatarDescriptor.AnimLayerType.Additive: case VRCAvatarDescriptor.AnimLayerType.Gesture: case VRCAvatarDescriptor.AnimLayerType.Action: case VRCAvatarDescriptor.AnimLayerType.FX: return(avatar.baseAnimationLayers.First(w => w.type == layer)); case VRCAvatarDescriptor.AnimLayerType.SpecialIK: case VRCAvatarDescriptor.AnimLayerType.Sitting: case VRCAvatarDescriptor.AnimLayerType.TPose: case VRCAvatarDescriptor.AnimLayerType.IKPose: return(avatar.specialAnimationLayers.First(w => w.type == layer)); default: throw new ArgumentOutOfRangeException(nameof(layer), layer, null); } }
public PlayableLayerData(VRCAvatarDescriptor.AnimLayerType type) { layer = type; start = 0; end = 0; }
public PlayableLayerData() { layer = VRCAvatarDescriptor.AnimLayerType.Base; start = 0; end = 0; }
void EnforceAnimLayerSetup(bool isOnEnable = false) { if (_animator) { if (_animator.isHuman) { // human -> add missing base layers from previous non-human setup bool haveAdditive = false; bool haveGesture = false; for (int v = 0; v < _baseAnimLayers.arraySize; v++) { SerializedProperty layer = _baseAnimLayers.GetArrayElementAtIndex(v); SerializedProperty type = layer.FindPropertyRelative("type"); if ((VRCAvatarDescriptor.AnimLayerType)type.enumValueIndex == VRCAvatarDescriptor.AnimLayerType.Additive) { haveAdditive = true; } if ((VRCAvatarDescriptor.AnimLayerType)type.enumValueIndex == VRCAvatarDescriptor.AnimLayerType.Gesture) { haveGesture = true; SetLayerMaskFromController(layer); } } if (!haveAdditive) { InitAnimLayer(_baseAnimLayers, VRCAvatarDescriptor.AnimLayerType.Additive, true, 1); } if (!haveGesture) { InitAnimLayer(_baseAnimLayers, VRCAvatarDescriptor.AnimLayerType.Gesture, true, 2); } } else { // non-human -> remove excess base layers from previous human setup List <int> baseLayersToDelete = new List <int>(); for (int v = 0; v < _baseAnimLayers.arraySize; v++) { SerializedProperty layer = _baseAnimLayers.GetArrayElementAtIndex(v); SerializedProperty type = layer.FindPropertyRelative("type"); VRCAvatarDescriptor.AnimLayerType t = (VRCAvatarDescriptor.AnimLayerType)type.enumValueIndex; if (IsHumanOnlyAnimLayer(t)) { baseLayersToDelete.Add(v); } } if (baseLayersToDelete.Count > 0) { DeleteAnimLayers(_baseAnimLayers, baseLayersToDelete); } } } // reset 'Special' layer buttons to default when left empty for (int v = 0; v < _specialAnimLayers.arraySize; v++) { SerializedProperty layer = _specialAnimLayers.GetArrayElementAtIndex(v); SerializedProperty type = layer.FindPropertyRelative("type"); SerializedProperty isDefault = layer.FindPropertyRelative("isDefault"); SerializedProperty animatorController = layer.FindPropertyRelative("animatorController"); if ((!isDefault.boolValue) && (animatorController.objectReferenceValue == null)) { if (isOnEnable || (GUI.GetNameOfFocusedControl() != GetAnimLayerButtonName((VRCAvatarDescriptor.AnimLayerType)type.enumValueIndex))) { isDefault.boolValue = true; } } } }
public EditorAnimLayerInfo(string label, VRCAvatarDescriptor.AnimLayerType type) { this.label = label; this.type = type; }
private void GetBehaviours(RuntimeAnimatorController runController, AnimatorController controller, TEA_PlayableLayerData layerData, VRCAvatarDescriptor.AnimLayerType type) { AnimatorController runCont = AssetDatabase.LoadAssetAtPath<AnimatorController>(AssetDatabase.GetAssetPath(runController)); int layerC = 0; foreach(AnimatorControllerLayer layer in runCont.layers) { AnimatorControllerLayer copyLayer = controller.layers[layerC]; int stateC = 0; foreach(ChildAnimatorState state in layer.stateMachine.states) { ChildAnimatorState copyState = copyLayer.stateMachine.states[stateC]; int behC = 0; foreach(StateMachineBehaviour beh in state.state.behaviours) { //Debug.Log($"getting avatar[{currentAvatar.name}] copyState[{copyState.state.name}] state[{state.state.name}] behC[{behC}] count[{copyState.state.behaviours.Length}]"); if(beh is VRCPlayableLayerControl) { VRCPlayableLayerControl pc = (VRCPlayableLayerControl)beh; TEA_PlayableLayerControl tc = copyState.state.AddStateMachineBehaviour<TEA_PlayableLayerControl>(); tc.blendDuration = pc.blendDuration; tc.debugString = pc.debugString; tc.goalWeight = pc.goalWeight; tc.layer = pc.layer; tc.state = copyState.state.name; } else if(beh is VRCAvatarParameterDriver) { VRCAvatarParameterDriver vd = (VRCAvatarParameterDriver)beh; TEA_AvatarParameterDriver td = copyState.state.AddStateMachineBehaviour<TEA_AvatarParameterDriver>(); td.name = vd.name; td.debugString = vd.debugString; td.localOnly = vd.localOnly; td.parameters = new List<VRC.SDKBase.VRC_AvatarParameterDriver.Parameter>(); foreach(VRCAvatarParameterDriver.Parameter param in vd.parameters) { td.parameters.Add(new VRCAvatarParameterDriver.Parameter() { chance = param.chance, name = param.name, type = param.type, value = param.value, valueMax = param.valueMax, valueMin = param.valueMin }); td.state = copyState.state.name; //--- validation --- } ValidateParameterDriver((VRCAvatarParameterDriver)beh, type, layer, state.state); } behC++; }//for behavior stateC++; }//for state layerC++; }//for layer }