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);
    }
Example #2
0
	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;
	}
Example #3
0
 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;
    }
Example #6
0
	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);
        }
Example #10
0
	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);
		}
	 }
	}
Example #11
0
 public PlayableLayerData FindPlayableLayerData(VRCAvatarDescriptor.AnimLayerType type)
 {
     foreach (PlayableLayerData item in data)
     {
         if (item.layer == type)
         {
             return(item);
         }
     }
     return(null);
 }
Example #12
0
	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);
            }
        }
Example #17
0
 public PlayableLayerData(VRCAvatarDescriptor.AnimLayerType type)
 {
     layer = type;
     start = 0;
     end   = 0;
 }
Example #18
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;
 }
Example #21
0
	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

	}