public IEnumerable <ValidateResult> Validate(VRCAvatarDescriptor avatar) { var humanoidBoneNames = Enum.GetNames(typeof(HumanBodyBones)) .SelectMany(n => new string[] { n, ToContainSpace(n) }) .Distinct() .ToArray(); var playableLayers = VRCAvatarUtility.GetBaseAnimationLayers(avatar); if (!playableLayers.Any()) { yield break; } foreach (var playableLayer in playableLayers) { if (playableLayer.type == VRCAvatarDescriptor.AnimLayerType.FX) { continue; } var animatorController = playableLayer.animatorController as AnimatorController; if (animatorController is null) { continue; } foreach (var state in animatorController.layers.SelectMany(l => l.stateMachine.states)) { var clip = state.state.motion as AnimationClip; if (clip is null) { continue; } foreach (var binding in AnimationUtility.GetCurveBindings(clip)) { // Transformを操作するもの以外が含まれているか検出 if (binding.type != typeof(Transform) && !(binding.type == typeof(Animator) && humanoidBoneNames.Any(n => binding.propertyName.StartsWith(n)))) { yield return(new ValidateResult( clip, ValidateResult.ValidateResultType.Error, $"{clip.name} have key changed other than Transform")); } } } } }
public IEnumerable <ValidateResult> Validate(VRCAvatarDescriptor avatar) { var exParamsAsset = VRCAvatarUtility.GetExpressionParametersAsset(avatar); if (exParamsAsset is null) { yield break; } var exParams = exParamsAsset.parameters.Where(p => !string.IsNullOrEmpty(p.name)).ToArray(); if (!exParams.Any()) { yield break; } var parameterlist = VRCAvatarUtility.GetParameters(avatar.baseAnimationLayers.Select(l => l.animatorController as AnimatorController)); bool found = false; foreach (var exParam in exParams) { var exParamName = exParam.name; var exParamType = exParam.valueType == VRCExpressionParameters.ValueType.Float ? AnimatorControllerParameterType.Float : AnimatorControllerParameterType.Int; found = false; foreach (var param in parameterlist) { if (exParamName == param.name && exParamType == param.type) { found = true; break; } } if (!found) { yield return(new ValidateResult( exParamsAsset, ValidateResult.ValidateResultType.Error, $"{exParamName} is not found in AnimatorControllers")); } } }
public IEnumerable <ValidateResult> Validate(VRCAvatarDescriptor avatar) { var animationClips = VRCAvatarUtility.GetAnimationClips(avatar); foreach (var animationClip in animationClips) { foreach (var binding in AnimationUtility.GetCurveBindings(animationClip)) { if (!avatar.transform.Find(binding.path)) { yield return(new ValidateResult( animationClip, ValidateResult.ValidateResultType.Warning, $"`{animationClip.name}` have missing path. ({binding.path})")); } } } }
public IEnumerable <ValidateResult> Validate(VRCAvatarDescriptor avatar) { var controllers = VRCAvatarUtility.GetControllers(avatar); foreach (var controller in controllers) { // 一番上のLayerは内部的にweight0であっても強制的に1になるので調べない for (int i = 1; i < controller.layers.Length; i++) { var layer = controller.layers[i]; if (layer.defaultWeight == 0) { yield return(new ValidateResult( controller, ValidateResult.ValidateResultType.Warning, $"`{layer.name}` Layer in {controller.name} is weight 0.")); } } } }