/// <summary> /// クラスに含まれる処理を適用します。 /// </summary> /// <param name="avatar"></param> /// <param name="swayingParametersConverter"></param> /// <returns></returns> internal static IEnumerable <Converter.Message> Apply( GameObject avatar, Converter.SwayingObjectsConverterSetting swayingObjectsConverterSetting, Converter.SwayingParametersConverter swayingParametersConverter ) { var messages = new List <Converter.Message>(); ConvertMeta(avatar: avatar); ConvertVRMFirstPerson(avatar: avatar); if (DynamicBoneType == null || swayingObjectsConverterSetting == Converter.SwayingObjectsConverterSetting.RemoveSwayingObjects) { return(messages); } IDictionary <VRMSpringBoneColliderGroup, IEnumerable <MonoBehaviour> > dynamicBoneColliderGroups = null; if (swayingObjectsConverterSetting == Converter.SwayingObjectsConverterSetting.ConvertVrmSpringBonesAndVrmSpringBoneColliderGroups) { RemoveUnusedColliderGroups(avatar: avatar); dynamicBoneColliderGroups = ConvertVRMSpringBoneColliderGroups(avatar); } ConvertVRMSpringBones( avatar: avatar, dynamicBoneColliderGroups: dynamicBoneColliderGroups, swayingParametersConverter: swayingParametersConverter ); messages.AddRange(GetMessagesAboutDynamicBoneLimits(avatar: avatar)); return(messages); }
/// <summary> /// クラスに含まれる処理を適用します。 /// </summary> /// <param name="avatar"></param> /// <param name="swayingParametersConverter"></param> /// <returns></returns> internal static IEnumerable <(string, MessageType)> Apply( GameObject avatar, Converter.SwayingObjectsConverterSetting swayingObjectsConverterSetting, Converter.SwayingParametersConverter swayingParametersConverter ) { var messages = new List <(string, MessageType)>(); ConvertMeta(avatar: avatar); ConvertVRMFirstPerson(avatar: avatar); if (DynamicBoneType == null || swayingObjectsConverterSetting == Converter.SwayingObjectsConverterSetting.RemoveSwayingObjects) { return(messages); } IDictionary <VRMSpringBoneColliderGroup, IEnumerable <dynamic> > dynamicBoneColliderGroups = null; if (swayingObjectsConverterSetting == Converter.SwayingObjectsConverterSetting.ConvertVrmSpringBonesAndVrmSpringBoneColliderGroups) { RemoveUnusedColliderGroups(avatar: avatar); dynamicBoneColliderGroups = ConvertVRMSpringBoneColliderGroups(avatar); } ConvertVRMSpringBones( avatar: avatar, dynamicBoneColliderGroups: dynamicBoneColliderGroups, swayingParametersConverter: swayingParametersConverter ); messages.AddRange(VRChatUtility.CalculateDynamicBoneLimitations(prefabInstance: avatar)); return(messages); }
/// <summary> /// 指定された<see cref="VRMSpringBone"/>を基に<see cref="DynamicBone"/>を設定します。 /// </summary> /// <param name="springBone"></param> /// <param name="dynamicBoneColliderGroups">キーに<see cref="VRMSpringBoneColliderGroup"/>、値に対応する<see cref="DynamicBoneCollider"/>のリストを持つジャグ配列。</param> /// <param name="swayingParametersConverter"></param> private static void ConvertVRMSpringBone( VRMSpringBone springBone, IDictionary <VRMSpringBoneColliderGroup, IEnumerable <MonoBehaviour> > dynamicBoneColliderGroups, Converter.SwayingParametersConverter swayingParametersConverter ) { var springBoneParameters = new SpringBoneParameters(stiffnessForce: springBone.m_stiffnessForce, dragForce: springBone.m_dragForce); var boneInfo = new BoneInfo(vrmMeta: springBone.gameObject.GetComponentsInParent <VRMMeta>()[0]); foreach (var transform in springBone.RootBones) { var dynamicBone = springBone.gameObject.AddComponent(DynamicBoneType); DynamicBoneType.GetField("m_Root").SetValue(dynamicBone, transform); DynamicBoneType.GetField("m_Exclusions").SetValue(dynamicBone, new List <Transform>()); DynamicBoneParameters dynamicBoneParameters = null; if (swayingParametersConverter != null) { dynamicBoneParameters = swayingParametersConverter( springBoneParameters: springBoneParameters, boneInfo: boneInfo ); } if (dynamicBoneParameters != null) { DynamicBoneType.GetField("m_Damping").SetValue(dynamicBone, dynamicBoneParameters.Damping); DynamicBoneType.GetField("m_DampingDistrib") .SetValue(dynamicBone, dynamicBoneParameters.DampingDistrib); DynamicBoneType.GetField("m_Elasticity").SetValue(dynamicBone, dynamicBoneParameters.Elasticity); DynamicBoneType.GetField("m_ElasticityDistrib") .SetValue(dynamicBone, dynamicBoneParameters.ElasticityDistrib); DynamicBoneType.GetField("m_Stiffness").SetValue(dynamicBone, dynamicBoneParameters.Stiffness); DynamicBoneType.GetField("m_StiffnessDistrib") .SetValue(dynamicBone, dynamicBoneParameters.StiffnessDistrib); DynamicBoneType.GetField("m_Inert").SetValue(dynamicBone, dynamicBoneParameters.Inert); DynamicBoneType.GetField("m_InertDistrib") .SetValue(dynamicBone, dynamicBoneParameters.InertDistrib); } DynamicBoneType.GetField("m_Gravity") .SetValue(dynamicBone, springBone.m_gravityDir * springBone.m_gravityPower); DynamicBoneType.GetField("m_Radius").SetValue(dynamicBone, springBone.m_hitRadius); if (dynamicBoneColliderGroups != null) { var colliders = Activator.CreateInstance(type: DynamicBoneColliderBaseListType); MethodInfo addMethod = DynamicBoneColliderBaseListType.GetMethod("Add"); foreach (var collider in springBone.ColliderGroups.SelectMany( colliderGroup => dynamicBoneColliderGroups[colliderGroup] )) { addMethod.Invoke(colliders, new[] { collider }); } DynamicBoneType.GetField("m_Colliders").SetValue(dynamicBone, colliders); } } }
/// <summary> /// 子孫の<see cref="VRMSpringBone"/>を基に<see cref="DynamicBone"/>を設定します。 /// </summary> /// <param name="avatar"></param> /// <param name="dynamicBoneColliderGroups">キーに<see cref="VRMSpringBoneColliderGroup"/>、値に対応する<see cref="DynamicBoneCollider"/>のリストを持つジャグ配列。</param> /// <param name="swayingParametersConverter"></param> private static void ConvertVRMSpringBones( GameObject avatar, IDictionary <VRMSpringBoneColliderGroup, IEnumerable <MonoBehaviour> > dynamicBoneColliderGroups, Converter.SwayingParametersConverter swayingParametersConverter ) { foreach (var springBone in avatar.GetComponentsInChildren <VRMSpringBone>()) { ConvertVRMSpringBone(springBone: springBone, dynamicBoneColliderGroups: dynamicBoneColliderGroups, swayingParametersConverter: swayingParametersConverter); } }
/// <summary> /// 指定された<see cref="VRMSpringBone"/>を基に<see cref="DynamicBone"/>を設定します。 /// </summary> /// <param name="springBone"></param> /// <param name="dynamicBoneColliderGroups">キーに<see cref="VRMSpringBoneColliderGroup"/>、値に対応する<see cref="DynamicBoneCollider"/>のリストを持つジャグ配列。</param> /// <param name="swayingParametersConverter"></param> private static void ConvertVRMSpringBone( VRMSpringBone springBone, IDictionary <VRMSpringBoneColliderGroup, IEnumerable <dynamic> > dynamicBoneColliderGroups, Converter.SwayingParametersConverter swayingParametersConverter ) { var springBoneParameters = new SpringBoneParameters() { StiffnessForce = springBone.m_stiffnessForce, DragForce = springBone.m_dragForce, }; var boneInfo = new BoneInfo(vrmMeta: springBone.gameObject.GetComponentsInParent <VRMMeta>()[0]); foreach (var transform in springBone.RootBones) { dynamic dynamicBone = springBone.gameObject.AddComponent(DynamicBoneType); dynamicBone.m_Root = transform; dynamicBone.m_Exclusions = new List <Transform>(); DynamicBoneParameters dynamicBoneParameters = null; if (swayingParametersConverter != null) { dynamicBoneParameters = swayingParametersConverter( springBoneParameters: springBoneParameters, boneInfo: boneInfo ); } if (dynamicBoneParameters != null) { dynamicBone.m_Damping = dynamicBoneParameters.Damping; dynamicBone.m_DampingDistrib = dynamicBoneParameters.DampingDistrib; dynamicBone.m_Elasticity = dynamicBoneParameters.Elasticity; dynamicBone.m_ElasticityDistrib = dynamicBoneParameters.ElasticityDistrib; dynamicBone.m_Stiffness = dynamicBoneParameters.Stiffness; dynamicBone.m_StiffnessDistrib = dynamicBoneParameters.StiffnessDistrib; dynamicBone.m_Inert = dynamicBoneParameters.Inert; dynamicBone.m_InertDistrib = dynamicBoneParameters.InertDistrib; } dynamicBone.m_Gravity = springBone.m_gravityDir * springBone.m_gravityPower; dynamicBone.m_Radius = springBone.m_hitRadius; if (dynamicBoneColliderGroups != null) { dynamic colliders = Activator.CreateInstance(type: DynamicBoneColliderBaseListType); foreach (var collider in springBone.ColliderGroups.SelectMany( colliderGroup => dynamicBoneColliderGroups[colliderGroup] )) { colliders.Add(collider); } dynamicBone.m_Colliders = colliders; } } }
protected override bool DrawWizardGUI() { base.DrawWizardGUI(); isValid = true; if (this.callbackFunctions) { Type callBackFunctions = this.callbackFunctions.GetClass(); this.swayingParametersConverter = Delegate.CreateDelegate( type: typeof(Converter.SwayingParametersConverter), target: callBackFunctions, method: "SwayingParametersConverter", ignoreCase: false, throwOnBindFailure: false ) as Converter.SwayingParametersConverter; this.postConverting = Delegate.CreateDelegate( type: typeof(Wizard.PostConverting), target: callBackFunctions, method: "PostConverting", ignoreCase: false, throwOnBindFailure: false ) as Wizard.PostConverting; } var indentStyle = new GUIStyle() { padding = new RectOffset() { left = Wizard.Indent } }; EditorGUILayout.LabelField( (this.swayingParametersConverter != null ? "☑" : "☐") + " public static DynamicBoneParameters SwayingParametersConverter(SpringBoneParameters, BoneInfo)", indentStyle ); EditorGUILayout.LabelField( (this.postConverting != null ? "☑" : "☐") + " public static void PostConverting(GameObject, VRMMeta)", indentStyle ); #if VRC_SDK_VRCSDK2 || VRC_SDK_VRCSDK3 foreach (var type in Converter.RequiredComponents) { if (!this.avatar.GetComponent(type)) { EditorGUILayout.HelpBox(string.Format(_("Not set “{0}” component."), type), MessageType.Error); isValid = false; } } IEnumerable <string> excludedSpringBoneComments = this.excludedSpringBoneComments.Except(new[] { "" }); if (excludedSpringBoneComments.Count() > 0) { IEnumerable <string> comments = excludedSpringBoneComments.Except( this.GetSpringBonesWithComments(prefab: this.avatar.gameObject, comments: excludedSpringBoneComments) .Select(commentAndSpringBones => commentAndSpringBones.Key) ); if (comments.Count() > 0) { EditorGUILayout.HelpBox(string.Join(separator: "\n• ", value: new[] { _("VRMSpringBones with the below Comments do not exist.") } .Concat(comments).ToArray()), MessageType.Warning); } } if (this.combineMeshes) { IEnumerable <string> notCombineRendererObjectNames = this.notCombineRendererObjectNames.Except(new[] { "" }); if (notCombineRendererObjectNames.Count() > 0) { IEnumerable <string> names = notCombineRendererObjectNames.Except( this.avatar.GetComponentsInChildren <SkinnedMeshRenderer>() .Concat <Component>(this.avatar.GetComponentsInChildren <MeshRenderer>()) .Select(renderer => renderer.name) ); if (names.Count() > 0) { EditorGUILayout.HelpBox(string.Join(separator: "\n• ", value: new[] { _("Renderers on the below name GameObject do not exist.") } .Concat(names).ToArray()), MessageType.Warning); } } } else { EditorGUILayout.HelpBox(_("If you do not “Combine Meshes”," + " and any of VRMBlendShapes references meshes other than the mesh having most shape keys" + " or the mesh is not direct child of the avatar root," + " the avatar will not be converted correctly."), MessageType.Warning); } if (!string.IsNullOrEmpty(this.blendShapeForFingerpoint) && !VRMUtility.GetUserDefinedBlendShapeClip(this.avatar, this.blendShapeForFingerpoint)) { EditorGUILayout.HelpBox(string.Format( _("There is no user-defined VRMBlensShape with the name “{0}”."), this.blendShapeForFingerpoint ), MessageType.Warning); } string version = VRChatUtility.GetSupportedUnityVersion(); if (version != "" && Application.unityVersion != version) { EditorGUILayout.HelpBox(string.Format( _("Unity {0} is running. If you are using a different version than {1}, VRChat SDK might not work correctly. Recommended using Unity downloaded from {2} ."), Application.unityVersion, version, VRChatUtility.DownloadURL ), MessageType.Warning); } if (!isValid || !this.forQuest) { return(true); } AvatarPerformanceStats statistics = new AvatarPerformanceStats(); AvatarPerformance.CalculatePerformanceStats( avatarName: avatar.GetComponent <VRMMeta>().Meta.Title, avatarObject: this.avatar.gameObject, perfStats: statistics ); int currentPolycount = (int)statistics.polyCount; int maxPolycount = VRChatUtility.AvatarPerformanceStatsLevelSets["Quest"].medium.polyCount; if (currentPolycount > maxPolycount) { EditorGUILayout.HelpBox(string.Format( _("The number of polygons is {0}."), currentPolycount ) + string.Format( _("If this value exceeds {0}, the avatar will not shown under the default user setting."), maxPolycount ), MessageType.Error); } #else EditorGUILayout.HelpBox(_("VRChat SDK2 or SDK3 has not been imported."), MessageType.Error); isValid = false; #endif return(true); }