private static void LoadTranslationPresets() { var presets = Resources.LoadAll <Preset>(resourceTranslationPath); var translations = Resources.LoadAll <PumkinsTranslation>(resourceTranslationPath); foreach (var p in presets) { var mods = p.PropertyModifications; string langName = mods.FirstOrDefault(m => m.propertyPath == "languageName").value; string author = mods.FirstOrDefault(m => m.propertyPath == "author").value; if (Helpers.StringIsNullOrWhiteSpace(langName) || Helpers.StringIsNullOrWhiteSpace(author)) { PumkinsAvatarTools.Log(Strings.Log.invalidTranslation, LogType.Error, p.name); continue; } var tr = translations.FirstOrDefault(t => t.author == author && t.languageName == langName); if (tr == default) { tr = ScriptableObjectUtility.CreateAndSaveAsset <PumkinsTranslation>("language_" + langName, translationPath); } if (p.CanBeAppliedTo(tr)) { p.ApplyTo(tr); } else { PumkinsAvatarTools.Log(Strings.Log.cantApplyPreset, LogType.Error); } } }
/// <summary> /// Destroys ParticleSystem in object /// </summary> /// <param name="destroyInChildrenToo">Whether to destroy particle systems in children as well</param> internal static void DestroyParticleSystems(GameObject from, bool destroyInChildrenToo = true) { var sysList = new List <ParticleSystem>(); if (destroyInChildrenToo) { sysList.AddRange(from.GetComponentsInChildren <ParticleSystem>(true)); } else { sysList.AddRange(from.GetComponents <ParticleSystem>()); } foreach (var p in sysList) { var rend = p.GetComponent <ParticleSystemRenderer>(); if (rend != null) { GameObject.DestroyImmediate(rend); } PumkinsAvatarTools.Log(Strings.Log.removeAttempt + " - " + Strings.Log.success, LogType.Log, p.ToString(), from.name); GameObject.DestroyImmediate(p); } }
/// <summary> /// Sets all materials on the renderers to copies using fallback shaders /// </summary> /// <param name="renders"></param> internal void SetFallbacks(Renderer[] renders) { foreach (var r in renders) { var serial = new SerializedObject(r); var materials = serial.FindProperty("m_Materials"); for (int i = 0; i < r.sharedMaterials.Length; i++) { var oldMat = r.sharedMaterials[i]; if (AssetDatabaseHelpers.IsBuiltInAsset(oldMat)) { continue; } var newMat = cache.GetCachedCopy(oldMat, out bool _); var fallback = MaterialManager.CreateFallbackMaterial(newMat, Color.white); var mat = materials.GetArrayElementAtIndex(i); mat.objectReferenceValue = newMat; } serial.ApplyModifiedProperties(); AssetDatabase.SaveAssets(); PumkinsAvatarTools.Log($"Set fallback materials for <b>{r.gameObject.name}</b>"); } }
/// <summary> /// TODO: Replace with one that reads only the needed lines /// </summary> static bool ReplacePresetGUIDTemp(string filePath, string newGUID) { filePath = Helpers.AbsolutePathToLocalAssetsPath(filePath); if (Helpers.StringIsNullOrWhiteSpace(filePath) || Helpers.StringIsNullOrWhiteSpace(newGUID)) { PumkinsAvatarTools.LogVerbose($"Filepath ({filePath}) or GUID ({newGUID}) is empty", LogType.Warning); return(false); } else if (!File.Exists(filePath)) { PumkinsAvatarTools.Log($"File {filePath} doesn't exist. Can't fix preset references", LogType.Warning); return(false); } var lines = File.ReadAllLines(filePath); for (int i = 0; i < lines.Length; i++) { var line = lines[i]; if (!line.Contains("m_Script")) { continue; } lines[i] = Helpers.ReplaceGUIDInLine(line, newGUID, out bool replaced); if (replaced) { File.WriteAllLines(filePath, lines); return(true); } break; } return(false); }
/// <summary> /// Destroy all components of type in object and it's children /// </summary> internal static void DestroyAllComponentsOfType(GameObject obj, Type type, bool ignoreRoot, bool useIgnoreList) { Transform oldParent = obj.transform.parent; obj.transform.parent = null; try { string log = ""; Component[] comps = obj.transform.GetComponentsInChildren(type, true); if (comps != null && comps.Length > 0) { for (int i = 0; i < comps.Length; i++) { if ((ignoreRoot && comps[i].transform.parent == null) || (useIgnoreList && Helpers.ShouldIgnoreObject(comps[i].transform, PumkinsAvatarTools.Settings._copierIgnoreArray, PumkinsAvatarTools.Settings.bCopier_ignoreArray_includeChildren))) { continue; } log = Strings.Log.removeAttempt + " - "; string name = comps[i].name; if (!PrefabUtility.IsPartOfPrefabInstance(comps[i])) { try { Helpers.DestroyAppropriate(comps[i]); log += Strings.Log.success; PumkinsAvatarTools.Log(log, LogType.Log, type.Name, name); } catch (Exception e) { log += Strings.Log.failed + " - " + e.Message; PumkinsAvatarTools.Log(log, LogType.Exception, type.Name, name); } } else { PumkinsAvatarTools.Log(Strings.Log.cantBeDestroyedPartOfPrefab, LogType.Warning, name, type.Name); } } } } finally { obj.transform.parent = oldParent; } }
public override bool ApplyPreset(GameObject avatar) { if (!avatar || renderers == null) { PumkinsAvatarTools.Log(Strings.Warning.invalidPreset, LogType.Warning, name); return(false); } for (int i = 0; i < renderers.Count; i++) { if (renderers[i] == null) { continue; } var t = avatar.transform.Find(renderers[i].rendererPath); if (t) { var render = t.GetComponent <SkinnedMeshRenderer>(); if (render) { for (int j = 0; j < renderers[i].blendshapes.Count; j++) { int index = render.sharedMesh.GetBlendShapeIndex(renderers[i].blendshapes[j].name); if (index == -1) { foreach (string name in renderers[i].blendshapes[j].otherNames) { index = render.sharedMesh.GetBlendShapeIndex(name); if (index != -1) { break; } } } if (index == -1) { continue; } float weight = renderers[i].blendshapes[j].weight; render.SetBlendShapeWeight(index, weight); } } } } return(true); }
/// <summary> /// Destroys all Missing Script components on avatar /// </summary> internal static void DestroyMissingScripts(GameObject avatar) { #if UNITY_2018 if (EditorApplication.isPlaying) { PumkinsAvatarTools.Log("Can't remove missing scripts in play mode, it causes crashes", LogType.Warning); return; } #endif var ts = avatar.GetComponentsInChildren <Transform>(true); foreach (var t in ts) { if (Helpers.DestroyMissingScriptsInGameObject(t.gameObject)) { PumkinsAvatarTools.Log(Strings.Log.hasMissingScriptDestroying, LogType.Log, Helpers.GetTransformPath(t, avatar.transform)); } } }
/// <summary> /// Destroys GameObjects in object and all children, if it has no children and if it's not a bone /// </summary> internal static void DestroyEmptyGameObjects(GameObject from) { var obj = from.GetComponentsInChildren <Transform>(true); var renders = from.GetComponentsInChildren <SkinnedMeshRenderer>(true); var bones = new HashSet <Transform>(); foreach (var r in renders) { foreach (var b in r.bones) { bones.Add(b); } } foreach (var t in obj.OrderBy(o => o.childCount)) { if (t != null && t != t.root && t.GetComponents <Component>().Length == 1 && !bones.Contains(t)) { int c = t.childCount; for (int i = 0; i < t.childCount; i++) { var n = t.GetChild(i); if (!bones.Contains(n)) { c--; } } if (c <= 0 && (t.name.ToLower() != (t.parent.name.ToLower() + "_end"))) { if (PrefabUtility.GetPrefabInstanceStatus(t) == PrefabInstanceStatus.NotAPrefab || PrefabUtility.GetPrefabInstanceStatus(t) == PrefabInstanceStatus.Disconnected) { PumkinsAvatarTools.Log(Strings.Log.hasNoComponentsOrChildrenDestroying, LogType.Log, t.name); GameObject.DestroyImmediate(t.gameObject); } else { PumkinsAvatarTools.Log(Strings.Log.cantBeDestroyedPartOfPrefab, LogType.Warning, t.name, "GameObject"); } } } } }
/// <summary> /// Assigns back the original materials to the renderers /// </summary> /// <param name="renders"></param> internal void RevertFallbacks(Renderer[] renders) { foreach (var r in renders) { var serial = new SerializedObject(r); var materials = serial.FindProperty("m_Materials"); for (int i = 0; i < r.sharedMaterials.Length; i++) { var newMat = cache.GetOriginalMaterialFromCached(r.sharedMaterials[i]); if (!newMat) { PumkinsAvatarTools.Log($"Can't find original material for material <b>slot {i}</b> on <b>{r.gameObject.name}</b>", LogType.Warning); continue; } var mat = materials.GetArrayElementAtIndex(i); mat.objectReferenceValue = newMat; } PumkinsAvatarTools.Log($"Restored materials for <b>{r.gameObject.name}</b>"); serial.ApplyModifiedProperties(); } }
/// <summary> /// Sets hardcoded TPose. /// </summary> public static void SetTPoseHardcoded(GameObject avatar) { Undo.RegisterFullObjectHierarchyUndo(avatar, "Set TPose"); var anim = avatar.GetComponent <Animator>(); if (anim && anim.avatar && anim.avatar.isHuman) { Vector3 pos = avatar.transform.position; Quaternion rot = avatar.transform.rotation; avatar.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); var humanPoseHandler = new HumanPoseHandler(anim.avatar, avatar.transform); var humanPose = new HumanPose(); humanPoseHandler.GetHumanPose(ref humanPose); //A long time ago CATS used to export avatars with a Armature scale of 100. This caused issues applying poses. //For now we'll just hardcode search for "Armature". //TODO: Find a better way to get the armature and check if it's scale could cause issues when tposing Transform armature = avatar.transform.Find("Armature"); if (!(armature && armature.localScale == Vector3.one)) { if (humanPose.bodyPosition.y < 1 && !Mathf.Approximately(humanPose.bodyPosition.y, 1)) { humanPose.bodyPosition.y = 1; PumkinsAvatarTools.LogVerbose(Strings.PoseEditor.bodyPositionYTooSmall, LogType.Warning, humanPose.bodyPosition.y.ToString()); } } #region Hardcoded TPose Values humanPose.muscles[0] = -6.830189E-07f; humanPose.muscles[1] = 4.268869E-08f; humanPose.muscles[2] = 4.268868E-08f; humanPose.muscles[3] = -8.537737E-08f; humanPose.muscles[4] = 0f; humanPose.muscles[5] = 0f; humanPose.muscles[6] = 0f; humanPose.muscles[7] = 0f; humanPose.muscles[8] = 0f; humanPose.muscles[9] = 4.268868E-08f; humanPose.muscles[10] = -8.537737E-08f; humanPose.muscles[11] = 4.268868E-08f; humanPose.muscles[12] = 3.415095E-07f; humanPose.muscles[13] = 0f; humanPose.muscles[14] = 0f; humanPose.muscles[15] = 0f; humanPose.muscles[16] = 0f; humanPose.muscles[17] = 0f; humanPose.muscles[18] = 0f; humanPose.muscles[19] = 0f; humanPose.muscles[20] = 0f; humanPose.muscles[21] = 0.5994893f; humanPose.muscles[22] = 0.004985309f; humanPose.muscles[23] = 0.00297395f; humanPose.muscles[24] = 0.9989594f; humanPose.muscles[25] = -0.02284526f; humanPose.muscles[26] = -3.449878E-05f; humanPose.muscles[27] = -0.0015229f; humanPose.muscles[28] = -4.781132E-07f; humanPose.muscles[29] = 0.599489f; humanPose.muscles[30] = 0.004985378f; humanPose.muscles[31] = 0.002974245f; humanPose.muscles[32] = 0.9989589f; humanPose.muscles[33] = -0.02284535f; humanPose.muscles[34] = -3.548912E-05f; humanPose.muscles[35] = -0.001522672f; humanPose.muscles[36] = -1.024528E-07f; humanPose.muscles[37] = -2.429621E-07f; humanPose.muscles[38] = 1.549688E-07f; humanPose.muscles[39] = 0.3847253f; humanPose.muscles[40] = 0.310061f; humanPose.muscles[41] = -0.103543f; humanPose.muscles[42] = 0.9925866f; humanPose.muscles[43] = 0.159403f; humanPose.muscles[44] = -0.01539368f; humanPose.muscles[45] = 0.01405432f; humanPose.muscles[46] = 5.680533E-08f; humanPose.muscles[47] = 2.701393E-07f; humanPose.muscles[48] = 0.3847259f; humanPose.muscles[49] = 0.3100605f; humanPose.muscles[50] = -0.1035404f; humanPose.muscles[51] = 0.9925874f; humanPose.muscles[52] = 0.1593992f; humanPose.muscles[53] = -0.01539393f; humanPose.muscles[54] = 0.01405326f; humanPose.muscles[55] = -0.7706841f; humanPose.muscles[56] = 0.423209f; humanPose.muscles[57] = 0.6456643f; humanPose.muscles[58] = 0.6362566f; humanPose.muscles[59] = 0.6677276f; humanPose.muscles[60] = -0.4597229f; humanPose.muscles[61] = 0.811684f; humanPose.muscles[62] = 0.8116837f; humanPose.muscles[63] = 0.6683907f; humanPose.muscles[64] = -0.5737826f; humanPose.muscles[65] = 0.8116839f; humanPose.muscles[66] = 0.8116843f; humanPose.muscles[67] = 0.6670681f; humanPose.muscles[68] = -0.6459302f; humanPose.muscles[69] = 0.8116837f; humanPose.muscles[70] = 0.8116839f; humanPose.muscles[71] = 0.666789f; humanPose.muscles[72] = -0.4676594f; humanPose.muscles[73] = 0.811684f; humanPose.muscles[74] = 0.8116839f; humanPose.muscles[75] = -0.7706831f; humanPose.muscles[76] = 0.4232127f; humanPose.muscles[77] = 0.6456538f; humanPose.muscles[78] = 0.6362569f; humanPose.muscles[79] = 0.6678051f; humanPose.muscles[80] = -0.4589976f; humanPose.muscles[81] = 0.8116843f; humanPose.muscles[82] = 0.8116842f; humanPose.muscles[83] = 0.668391f; humanPose.muscles[84] = -0.5737844f; humanPose.muscles[85] = 0.811684f; humanPose.muscles[86] = 0.8116837f; humanPose.muscles[87] = 0.6669571f; humanPose.muscles[88] = -0.6492739f; humanPose.muscles[89] = 0.8116841f; humanPose.muscles[90] = 0.8116843f; humanPose.muscles[91] = 0.6667888f; humanPose.muscles[92] = -0.4676568f; humanPose.muscles[93] = 0.8116842f; humanPose.muscles[94] = 0.8116836f; #endregion humanPoseHandler.SetHumanPose(ref humanPose); avatar.transform.SetPositionAndRotation(pos, rot); PumkinsAvatarTools.OnPoseWasChanged(PumkinsAvatarTools.PoseChangeType.Reset); } else { PumkinsAvatarTools.Log(Strings.Log.cantSetPoseNonHumanoid, LogType.Warning, "TPose"); } }
void OnGUI() { try { PumkinsCameraPreset newPreset = (PumkinsCameraPreset)preset; if (!newPreset) //Not sure I like this part { newPreset = (PumkinsCameraPreset)AssignOrCreatePreset <PumkinsCameraPreset>(null); preset = newPreset; } Rect r = GUILayoutUtility.GetAspectRect(1.3f); EditorGUI.DrawTextureTransparent(r, PumkinsAvatarTools.SelectedCamRT, ScaleMode.ScaleToFit); scroll = EditorGUILayout.BeginScrollView(scroll); { if (newPreset) { newPreset.name = EditorGUILayout.TextField(Strings.Presets.presetName, newPreset.name); EditorGUILayout.Space(); PumkinsAvatarTools.DrawAvatarSelectionWithButtonGUI(false, false); Helpers.DrawGUILine(); PumkinsAvatarTools.SelectedCamera = (Camera)EditorGUILayout.ObjectField(Strings.Presets.camera, PumkinsAvatarTools.SelectedCamera, typeof(Camera), true); EditorGUILayout.Space(); newPreset.offsetMode = (PumkinsCameraPreset.CameraOffsetMode)EditorGUILayout.EnumPopup(Strings.Presets.offsetMode, newPreset.offsetMode); if (newPreset.offsetMode == PumkinsCameraPreset.CameraOffsetMode.Transform) { EditorGUI.BeginDisabledGroup(!PumkinsAvatarTools.SelectedAvatar); { referenceTransform = EditorGUILayout.ObjectField(Strings.Presets.transform, referenceTransform, typeof(Transform), true) as Transform; if (referenceTransform && !referenceTransform.IsChildOf(PumkinsAvatarTools.SelectedAvatar.transform)) { PumkinsAvatarTools.Log(Strings.Presets.transformDoesntBelongToAvatar, LogType.Warning, referenceTransform.name, PumkinsAvatarTools.SelectedAvatar.name); referenceTransform = null; } } } EditorGUILayout.Space(); Helpers.DrawGUILine(); PumkinsAvatarTools.Instance.DrawOverlayGUI(); Helpers.DrawGUILine(); PumkinsAvatarTools.Instance.DrawBackgroundGUI(); Helpers.DrawGUILine(); PumkinsAvatarTools.Instance.DrawCameraControlButtons(); } EditorGUILayout.EndScrollView(); Helpers.DrawGUILine(); if (!editingExistingPreset) { EditorGUI.BeginDisabledGroup(!PumkinsAvatarTools.SelectedCamera || string.IsNullOrEmpty(newPreset.name) || !PumkinsAvatarTools.SelectedAvatar); { _overwriteFile = GUILayout.Toggle(_overwriteFile, Strings.Presets.overwriteFile); EditorGUI.BeginDisabledGroup(newPreset.offsetMode == PumkinsCameraPreset.CameraOffsetMode.Transform && referenceTransform == null); { if (GUILayout.Button(Strings.Buttons.savePreset, Styles.BigButton)) { #if (VRC_SDK_VRCSDK3 || VRC_SDK_VRCSDK2) && !UDON if (newPreset.offsetMode == PumkinsCameraPreset.CameraOffsetMode.Viewpoint && (Avatar.GetComponent <VRC_AvatarDescriptor>() == null)) { PumkinsAvatarTools.Log(Strings.Log.descriptorIsMissingCantGetViewpoint, LogType.Warning); } else #endif if (newPreset.offsetMode == PumkinsCameraPreset.CameraOffsetMode.Transform) { EditorApplication.delayCall += () => { newPreset.SavePreset(referenceTransform.gameObject, PumkinsAvatarTools.SelectedCamera, _overwriteFile); Close(); }; } else { EditorApplication.delayCall += () => { newPreset.SavePreset(PumkinsAvatarTools.SelectedAvatar, PumkinsAvatarTools.SelectedCamera, _overwriteFile); Close(); }; } } EditorGUILayout.Space(); } EditorGUI.EndDisabledGroup(); } EditorGUI.EndDisabledGroup(); } } } catch { if (this) { Close(); } } }
/// <summary> /// Applies preset to selected camera /// </summary> public override bool ApplyPreset(GameObject avatar) { Camera cam = PumkinsAvatarTools.SelectedCamera; if (!cam || !avatar) { return(false); } Undo.RegisterFullObjectHierarchyUndo(cam.gameObject, "Apply Camera Preset"); Transform dummy = null; try { if (offsetMode == CameraOffsetMode.Viewpoint) { dummy = new GameObject("Dummy").transform; var desc = avatar.GetComponent <VRC_AvatarDescriptor>(); if (desc) { dummy.localPosition = desc.transform.position + desc.ViewPosition; cam.transform.localPosition = positionOffset + dummy.transform.localPosition; cam.transform.localEulerAngles = rotationAnglesOffset + dummy.transform.localEulerAngles; } else { PumkinsAvatarTools.Log(Strings.Log.descriptorIsMissingCantGetViewpoint); } } else { Transform t = avatar.transform.Find(transformPath); dummy = new GameObject("Dummy").transform; if (t) { Transform oldCamParent = cam.transform.parent; cam.transform.parent = dummy; cam.transform.localPosition = positionOffset; cam.transform.localEulerAngles = rotationAnglesOffset; dummy.SetPositionAndRotation(t.position, t.rotation); cam.transform.parent = oldCamParent; } } } catch (Exception e) { Debug.LogError(e.Message); if (dummy) { Helpers.DestroyAppropriate(dummy.gameObject); } return(false); } finally { if (dummy) { Helpers.DestroyAppropriate(dummy.gameObject); } } PumkinsAvatarTools.Instance.bThumbnails_use_camera_overlay = useOverlay; if (useOverlay) { PumkinsAvatarTools.Instance.SetOverlayToImageFromPath(overlayImagePath); } PumkinsAvatarTools.Instance.bThumbnails_use_camera_background = useBackground; if (useBackground) { PumkinsAvatarTools.Instance.cameraBackgroundType = backgroundType; switch (backgroundType) { case PumkinsAvatarTools.CameraBackgroundOverrideType.Color: PumkinsAvatarTools.Instance.SetCameraBackgroundToColor(backgroundColor); break; case PumkinsAvatarTools.CameraBackgroundOverrideType.Image: PumkinsAvatarTools.Instance.cameraBackgroundImageTint = backgroundImageTint; PumkinsAvatarTools.Instance.SetBackgroundToImageFromPath(backgroundImagePath); break; case PumkinsAvatarTools.CameraBackgroundOverrideType.Skybox: PumkinsAvatarTools.Instance.SetCameraBackgroundToSkybox(backgroundMaterial); break; default: break; } } PumkinsAvatarTools.Instance.RefreshBackgroundOverrideType(); return(true); }
public override bool ApplyPreset(GameObject avatar) { if (!avatar) { return(false); } Undo.RegisterFullObjectHierarchyUndo(avatar, "Apply Pose"); PumkinsAvatarTools.ResetPose(avatar); if (presetMode == PosePresetMode.HumanPose) { Animator anim = avatar.GetComponent <Animator>(); if (anim && anim.avatar && anim.avatar.isHuman) { Vector3 pos = avatar.transform.position; Quaternion rot = avatar.transform.rotation; avatar.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity); var humanPoseHandler = new HumanPoseHandler(anim.avatar, avatar.transform); var humanPose = new HumanPose(); humanPoseHandler.GetHumanPose(ref humanPose); humanPose.muscles = muscles; if (PumkinsAvatarTools.Settings.posePresetTryFixSinking) { if (humanPose.bodyPosition.y < 1 && !Mathf.Approximately(humanPose.bodyPosition.y, 0)) { PumkinsAvatarTools.Log(Strings.PoseEditor.bodyPositionYTooSmall, LogType.Warning, humanPose.bodyPosition.y.ToString()); humanPose.bodyPosition.y = 1; } } if (PumkinsAvatarTools.Settings.posePresetApplyBodyPosition) { humanPose.bodyPosition = bodyPosition; } if (PumkinsAvatarTools.Settings.posePresetApplyBodyRotation) { humanPose.bodyRotation = bodyRotation; } humanPoseHandler.SetHumanPose(ref humanPose); avatar.transform.SetPositionAndRotation(pos, rot); PumkinsPoseEditor.OnPoseWasChanged(PumkinsPoseEditor.PoseChangeType.Reset); return(true); } else { PumkinsAvatarTools.Log(Strings.Log.cantSetPoseNonHumanoid, LogType.Error, name); return(false); } } else { if (!avatar) { return(false); } for (int i = 0; i < transformPaths.Count; i++) { var t = avatar.transform.Find(transformPaths[i]); if (t != null) { t.localEulerAngles = transformRotations[i]; } } return(true); } }
private void DrawMainGUI() { if (!PumkinsAvatarTools.SelectedAvatar || !PumkinsAvatarTools.SelectedAvatarIsHuman) { EditorGUILayout.LabelField(Strings.PoseEditor.selectHumanoidAvatar, Styles.HelpBox_OneLine); Helpers.DrawGUILine(); return; } DrawPoseFromAnimationGUI(); //Draw the toolbar then get the muscle ranges based on it's selection toolbarSelection = GUILayout.Toolbar(toolbarSelection, new string[] { "Body", "Head", "Arms", "Legs", "Fingers" }); EditorGUILayout.Space(); scroll = GUILayout.BeginScrollView(scroll); { List <Vector2Int> muscleRanges = new List <Vector2Int>(); switch (toolbarSelection) { case 0: muscleRanges.Add(PumkinsMuscleDefinitions.bodyRange); break; case 1: muscleRanges.Add(PumkinsMuscleDefinitions.headRange); break; case 2: muscleRanges.Add(PumkinsMuscleDefinitions.leftArmRange); muscleRanges.Add(PumkinsMuscleDefinitions.rightArmRange); break; case 3: muscleRanges.Add(PumkinsMuscleDefinitions.leftLegRange); muscleRanges.Add(PumkinsMuscleDefinitions.rightLegRange); break; case 4: muscleRanges.Add(PumkinsMuscleDefinitions.leftFingersRange); muscleRanges.Add(PumkinsMuscleDefinitions.rightFingersRange); break; default: muscleRanges.Add(new Vector2Int(0, HumanTrait.MuscleCount)); break; } //Draw sliders for the muscle ranges and apply the changes if they've changed EditorGUI.BeginChangeCheck(); { for (int i = 0; i < muscleRanges.Count; i++) { Vector2Int range = muscleRanges[i]; for (int j = range.x; j < range.y; j++) { avatarPose.muscles[j] = EditorGUILayout.Slider(new GUIContent(HumanTrait.MuscleName[j]), avatarPose.muscles[j], -sliderRange, sliderRange); } if (i != muscleRanges.Count - 1) { EditorGUILayout.Space(); } } } if (EditorGUI.EndChangeCheck()) { if (PumkinsAvatarTools.SelectedAvatar) { if (PumkinsAvatarTools.Instance.posePresetTryFixSinking && avatarPose.bodyPosition.y > 0 && avatarPose.bodyPosition.y <= 0.01f) { PumkinsAvatarTools.Log(Strings.PoseEditor.bodyPositionYTooSmall, LogType.Warning, avatarPose.bodyPosition.y.ToString()); avatarPose.bodyPosition.y = 1; } Undo.RegisterCompleteObjectUndo(PumkinsAvatarTools.SelectedAvatar, "Pose Editor: Set pose from sliders"); avatarPoseHandler.SetHumanPose(ref avatarPose); } } Helpers.DrawGUILine(); PumkinsAvatarTools.Instance.posePresetApplyBodyPosition = GUILayout.Toggle(PumkinsAvatarTools.Instance.posePresetApplyBodyPosition, Strings.Thumbnails.applyBodyPosition); PumkinsAvatarTools.Instance.posePresetApplyBodyRotation = GUILayout.Toggle(PumkinsAvatarTools.Instance.posePresetApplyBodyRotation, Strings.Thumbnails.applyBodyRotation); EditorGUILayout.Space(); PumkinsAvatarTools.Instance.posePresetTryFixSinking = GUILayout.Toggle(PumkinsAvatarTools.Instance.posePresetTryFixSinking, Strings.Thumbnails.tryFixPoseSinking); PumkinsAvatarTools.Instance.DrawPresetGUI <PumkinsPosePreset>(); } GUILayout.EndScrollView(); }