private void DoUpgrade()
        {
            var originalName = _target.gameObject.name;
            DynamicDNAConverterController newController = _target.DoUpgrade();

            if (newController != null)
            {
                drawAsLegacy = true;

                EditorGUIUtility.PingObject(newController);
                EditorUtility.DisplayDialog("Upgrade Complete!", "Your SkeletonModifiers and StartingPose (if set) can now be found in the new 'Converter Controller'. The old " + originalName + " has been stored in a 'LegacyDNA' folder", "Got it!");

                //We need to make the new asset the one that ConverterCustomizer is inspecting if it was inspecting the old one
                if (thisDDCC != null)
                {
                    for (int i = 0; i < thisDDCC.availableConverters.Count; i++)
                    {
                        if (thisDDCC.availableConverters[i] is DynamicDNAConverterBehaviour && (thisDDCC.availableConverters[i] as DynamicDNAConverterBehaviour) == _target)
                        {
                            thisDDCC.availableConverters[i] = newController;
                        }
                    }
                    if (thisDDCC.selectedConverter is DynamicDNAConverterBehaviour && (thisDDCC.selectedConverter as DynamicDNAConverterBehaviour) == _target)
                    {
                        thisDDCC.selectedConverter = newController;
                    }
                }
                //otherwise select the new controller so it shows in the inspector
                else
                {
                    Selection.activeObject = newController;
                }
            }
        }
        private void DrawObjectReferenceField(Rect position, SerializedProperty property, GUIContent label)
        {
            Vector2 iconSize = EditorGUIUtility.GetIconSize();

            EditorGUIUtility.SetIconSize(new Vector2(12f, 12f));
            DynamicDNAConverterController converterControllerObject = null;

            if (property.objectReferenceValue != null)
            {
                converterControllerObject = property.objectReferenceValue.GetType() == typeof(DynamicDNAConverterController) ? property.objectReferenceValue as DynamicDNAConverterController : null;
            }

            var dummyFieldStyle = new GUIStyle(EditorStyles.objectField);            //could be objectFieldMiniThumb

            dummyFieldStyle.normal.background = null;

            var labelPos = new Rect(position.xMin, position.yMin, EditorGUIUtility.labelWidth, position.height);
            var fieldPos = new Rect(labelPos.xMax, position.yMin, position.width - labelPos.width, position.height);

            //unfortunately we can use PrefixLabel because it inherits the GUI.content color of the field (which is transparent)
            //the result is the label doesn't highlight- but I think we can live with that!
            EditorGUI.LabelField(labelPos, label);

            var prevContentColor = GUI.contentColor;

            GUI.contentColor = new Color(0, 0, 0, 0);            //hide the content of the field so we can use our own label
            EditorGUI.BeginChangeCheck();
            //We use a converterController field rather than an object field so that the 'dot' button shows ConverterControllers when clicked
            converterControllerObject = (DynamicDNAConverterController)EditorGUI.ObjectField(fieldPos, "", converterControllerObject, typeof(DynamicDNAConverterController), false);
            if (EditorGUI.EndChangeCheck())
            {
                property.objectReferenceValue = converterControllerObject;
            }
            GUI.contentColor = prevContentColor;

            Rect dropRect = fieldPos;

            dropRect.width = dropRect.width - 18f;

            System.Type fieldType = typeof(DynamicDNAConverterController);

            if (property.objectReferenceValue != null)
            {
                fieldType = property.objectReferenceValue.GetType();
            }

            GUIContent typeContent = EditorGUIUtility.ObjectContent(property.objectReferenceValue, fieldType);

            if (property.objectReferenceValue == null)
            {
                typeContent.text  = "None (DNAConverterController/Behaviour)";
                typeContent.image = null;
            }

            GUI.Box(dropRect, typeContent, dummyFieldStyle);
            DoDropArea(dropRect, property);
            EditorGUIUtility.SetIconSize(iconSize);
        }
        private bool Init()
        {
            if (!_initialized)
            {
                bool stylesSet = false;

                if (EditorStyles.helpBox == null || EditorStyles.foldout == null || EditorStyles.label == null)
                {
                    //Dont set any styles
                }
                else
                {
                    //Style for subHeaders
                    _subHeaderStyle        = new GUIStyle(EditorStyles.helpBox);
                    _subHeaderStyle.margin = new RectOffset(_subHeaderStyle.margin.left, _subHeaderStyle.margin.right, _subHeaderStyle.margin.top, 0);

                    //Style for Tips
                    _foldoutTipStyle           = new GUIStyle(EditorStyles.foldout);
                    _foldoutTipStyle.fontStyle = FontStyle.Bold;

                    //Help Icon & style
                    _helpIcon = EditorGUIUtility.FindTexture("_Help");

                    _helpStyle               = new GUIStyle(EditorStyles.label);
                    _helpStyle.fixedHeight   = _helpIcon.height + 4f;
                    _helpStyle.contentOffset = new Vector2(-4f, 0f);

                    //Styles for the Add Converter area
                    var reorderableListDefaults = new ReorderableList.Defaults();
                    _pluginChooserAreaStyle               = new GUIStyle(reorderableListDefaults.boxBackground);
                    _pluginChooserAreaStyle.margin        = new RectOffset(4, 4, 2, 2);
                    _pluginChooserAreaStyle.stretchHeight = false;
                    _pluginChooserAreaStyle.padding       = new RectOffset(8, 8, 4, 8);

                    _pluginsByDNAAreaStyle         = new GUIStyle(EditorStyles.textField);
                    _pluginsByDNAAreaStyle.margin  = new RectOffset(0, 0, 0, 0);
                    _pluginsByDNAAreaStyle.padding = new RectOffset(4, 4, 4, 4);

                    stylesSet = true;
                }

                _initialized = stylesSet;

                _target = target as DynamicDNAConverterController;

                _dnaAsset = _target.DNAAsset;

                InitPlugins();
            }
            return(_initialized);
        }
示例#4
0
        /// <summary>
        /// Replaces all references to this asset in RaceDatas and SlotDataAssets with a reference to the given DynamicDNAConverterController
        /// </summary>
        /// <param name="replacingAsset"></param>
        public void FindAndReplaceUsage(DynamicDNAConverterController replacingAsset)
        {
            if (replacingAsset == null)
            {
                Debug.LogWarning("Could not find and replace usage of the behaviour because nor replacement was supplied");
                return;
            }
            var original = this;

            //In Unity 2018.3+ this asset may be being inspected in its own Prefab scene (rather than via customizer).
            //If that is the case 'this' will be a clone rather than the object that is actually assigned to Races/Slots, so...
#if UNITY_2018_3_OR_NEWER
            var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage(this.gameObject);
            if (prefabStage != null)
            {
                var origGO = (GameObject)AssetDatabase.LoadAssetAtPath(prefabStage.prefabAssetPath, typeof(GameObject));
                if (origGO != null && origGO.GetComponent <DynamicDNAConverterBehaviour>() != null)
                {
                    original = origGO.GetComponent <DynamicDNAConverterBehaviour>();
                }
            }
#endif
            if (original == null)
            {
                Debug.LogWarning("Could not find and replace usage of the behaviour because the original could not be determined");
                return;
            }
            string[] raceGuids     = AssetDatabase.FindAssets("t:RaceData", null);
            string[] slotGuids     = AssetDatabase.FindAssets("t:SlotDataAsset", null);
            string[] rangeGuids    = AssetDatabase.FindAssets("t:DNARangeAsset", null);
            int      updatedRaces  = 0;
            int      updatedSlots  = 0;
            int      updatedRanges = 0;
            //store for found items so we dont gobble memory
            RaceData      foundRace;
            SlotDataAsset foundSlot;
            DNARangeAsset foundDNARange;
            //Find races that need updating
            for (int i = 0; i < raceGuids.Length; i++)
            {
                foundRace = (RaceData)AssetDatabase.LoadAssetAtPath((AssetDatabase.GUIDToAssetPath(raceGuids[i])), typeof(RaceData));
                if (foundRace)
                {
                    if (foundRace.UpgradeFromLegacy(original, replacingAsset))
                    {
                        Debug.Log("RaceData: " + foundRace.raceName + " was updated to use new ConverterController " + replacingAsset.name);
                        EditorUtility.SetDirty(foundRace);
                        updatedRaces++;
                    }
                }
            }
            //Find slots that need Updating
            for (int i = 0; i < slotGuids.Length; i++)
            {
                foundSlot = (SlotDataAsset)AssetDatabase.LoadAssetAtPath((AssetDatabase.GUIDToAssetPath(slotGuids[i])), typeof(SlotDataAsset));
                if (foundSlot)
                {
                    if (foundSlot.UpgradeFromLegacy(original, replacingAsset))
                    {
                        Debug.Log("SlotData: " + foundSlot.slotName + " was updated to use new ConverterController " + replacingAsset.name);
                        EditorUtility.SetDirty(foundSlot);
                        updatedSlots++;
                    }
                }
            }
            //Find DNARangeAssets that need updating
            for (int i = 0; i < rangeGuids.Length; i++)
            {
                foundDNARange = (DNARangeAsset)AssetDatabase.LoadAssetAtPath((AssetDatabase.GUIDToAssetPath(slotGuids[i])), typeof(DNARangeAsset));
                if (foundDNARange)
                {
                    if (foundDNARange.UpgradeFromLegacy(original, replacingAsset))
                    {
                        Debug.Log("DNARangeAsset: " + foundDNARange.name + " was updated to use new ConverterController " + replacingAsset.name);
                        EditorUtility.SetDirty(foundDNARange);
                        updatedRanges++;
                    }
                }
            }
            var processCompleteMessage = updatedRaces + " RaceDatas, " + updatedSlots + " SlotDataAssets, and " + updatedRanges + " DNARangeAssets were updated to use the new controller (" + replacingAsset.name + ")";
            Debug.Log("DynamicDNAConverterBehaviour FindAndReplaceUsage: " + processCompleteMessage);
            UnityEditor.EditorUtility.DisplayDialog("Find and Replace Complete!", processCompleteMessage, "Ok, Great");
        }
示例#5
0
        /// <summary>
        /// Upgrades a DynamicDNAConverter Prefab to a new ConverterController asset and replaces any usage of the old asset. Stores the original asset in a relative 'Legacy' folder.
        /// </summary>
        /// <returns>Returns the path of the new converterController asset</returns>
        public DynamicDNAConverterController DoUpgrade()
        {
            var DCBPath = AssetDatabase.GetAssetPath(this.gameObject);

            //In Unity 2018.3+ this asset may be being inspected in its own Prefab scene (rather than via customizer).
            //If that is the case we need to get the path differently
#if UNITY_2018_3_OR_NEWER
            var prefabStage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetPrefabStage(this.gameObject);
            if (prefabStage != null)
            {
                DCBPath = prefabStage.prefabAssetPath;
            }
#endif
            if (string.IsNullOrEmpty(DCBPath))
            {
                Debug.LogWarning("Upgrade could not be completed. Could not get asset path for the DNAConverterBehaviour to upgrade");
                return(null);
            }

            var newControllerName = this.name.Replace("DynamicDNAConverterBehaviour", "").Replace("DynamicDNAConverter", "").Replace("DNAConverterBehaviour", "").Replace("ConverterBehaviour", "").Replace("Legacy", "");
            if (_converterController != null)
            {
                Debug.LogWarning("Upgrading " + this.gameObject.name + " failed because it already references a previously converted version. If you need to Upgrade again please inspect this assets 'Legacy Settings' and click 'Revert To Legacy Settings'");
                return(null);
            }

            DynamicDNAConverterController newController = null;
            DynamicDNAPlugin skelModsPlug     = null;
            DynamicDNAPlugin startingPosePlug = null;

            newControllerName += "DNAConverterController";
            var path = DCBPath;
            path = path.Replace("/" + Path.GetFileName(path), "");
            var assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(path + "/" + newControllerName + ".asset");
            newController = DynamicDNAConverterController.CreateDynamicDNAConverterControllerAsset(assetPathAndName, false);
            if (newController == null)
            {
                //bail if the converterController was not created
                Debug.LogWarning("DynamicDNAConverterBehaviour BackupAndUpgrade failed because it was unable to create the new ConverterController.");
                return(null);
            }
            //Add skeletonModifiers
            if (_skeletonModifiers.Count > 0)
            {
                skelModsPlug = newController.AddPlugin(typeof(SkeletonDNAConverterPlugin));
                if (!((SkeletonDNAConverterPlugin)skelModsPlug).ImportSettings(this.gameObject, 0))
                {
                    Debug.LogWarning("Your SkeletonModifiers did not import correctly into the new plugin. Please try importing then manually");
                }
            }
            //Add startingPose
            if (_startingPose != null)
            {
                startingPosePlug = newController.AddPlugin(typeof(BonePoseDNAConverterPlugin));
                if (((BonePoseDNAConverterPlugin)startingPosePlug).ImportSettings(this.gameObject, 0))
                {
                    Debug.LogWarning("Your StartingPose did not import correctly into the new plugin. Please try importing it manually");
                }
            }
            //Import the rest of our data
            newController.ImportConverterBehaviourData(this);

            //Set this last because the backwards compatible public properties get values from it if its set
            _converterController = newController;

            EditorUtility.SetDirty(newController);
            if (skelModsPlug != null)
            {
                EditorUtility.SetDirty(skelModsPlug);
            }
            if (startingPosePlug != null)
            {
                EditorUtility.SetDirty(startingPosePlug);
            }

            //Find and replace the usage of this
            FindAndReplaceUsage(newController);

            //If this asset is not inside a 'LegacyDNA' folder move it inside one
            //We need to keep the old one because downloaded content may still require it
            //The RaceDatas and SlotDataAssets will warn the user if they are using a legacy DynamicDNAConverterBehaviour
            var    DCBFilename     = System.IO.Path.GetFileName(DCBPath);
            string moveAssetResult = "";
#pragma warning disable 0219
            string newDCBPath = DCBPath;
#pragma warning restore
            if (DCBPath.IndexOf("LegacyDNA" + "/" + DCBFilename) == -1)
            {
                var DCBDir = System.IO.Path.GetDirectoryName(DCBPath);
                if (!AssetDatabase.IsValidFolder(DCBDir + "/" + "LegacyDNA"))
                {
                    AssetDatabase.CreateFolder(DCBDir, "LegacyDNA");
                }
                if (DCBFilename.IndexOf("Legacy") == -1)
                {
                    DCBFilename = System.IO.Path.GetFileNameWithoutExtension(DCBPath) + " Legacy" + System.IO.Path.GetExtension(DCBPath);
                }
                moveAssetResult = AssetDatabase.MoveAsset(DCBPath, DCBDir + "/" + "LegacyDNA" + "/" + DCBFilename);
                if (string.IsNullOrEmpty(moveAssetResult))
                {
                    newDCBPath = DCBDir + "/" + "LegacyDNA" + "/" + DCBFilename;
                }
            }
            if (!string.IsNullOrEmpty(moveAssetResult))
            {
                Debug.LogWarning(moveAssetResult);
            }

#if UNITY_2018_3_OR_NEWER
            //If this happenned in a prefab stage (rather than via customizer) it wont save the prefab with the added converterController so
            if (prefabStage != null)
            {
                PrefabUtility.SaveAsPrefabAsset(this.gameObject, newDCBPath);
            }
#endif

            EditorUtility.SetDirty(this.gameObject);
            AssetDatabase.SaveAssets();
            return(_converterController);
        }
示例#6
0
        void OnUpdate()
        {
            if (haveValidContext)
            {
                if (activeBoneIndex != editBoneIndex)
                {
                    activeBoneIndex = BAD_INDEX;
                    mirrorBoneIndex = BAD_INDEX;
                    if (editBoneIndex != BAD_INDEX)
                    {
                        int boneHash = targetPose.poses[editBoneIndex].hash;
                        context.activeTransform = context.activeUMA.skeleton.GetBoneTransform(boneHash);
                        if (context.activeTransform != null)
                        {
                            activeBoneIndex = editBoneIndex;
                        }

                        if (context.mirrorTransform != null)
                        {
                            int mirrorHash = UMASkeleton.StringToHash(context.mirrorTransform.name);
                            for (int i = 0; i < targetPose.poses.Length; i++)
                            {
                                if (targetPose.poses[i].hash == mirrorHash)
                                {
                                    mirrorBoneIndex = i;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        context.activeTransform = null;
                    }
                }
                if (!dynamicDNAConverterMode)
                {
                    context.activeUMA.skeleton.ResetAll();
                    if (context.startingPose != null)
                    {
                        context.startingPose.ApplyPose(context.activeUMA.skeleton, context.startingPoseWeight);
                    }

                    foreach (IDNAConverter id in context.activeUMA.umaRecipe.raceData.dnaConverterList)
                    {
                        if (id is DynamicDNAConverterController)
                        {
                            DynamicDNAConverterController Dcc  = id as DynamicDNAConverterController;
                            List <DynamicDNAPlugin>       LBpp = Dcc.GetPlugins(typeof(BonePoseDNAConverterPlugin));
                            foreach (DynamicDNAPlugin ddp in LBpp)
                            {
                                BonePoseDNAConverterPlugin bc = ddp as BonePoseDNAConverterPlugin;
                                foreach (BonePoseDNAConverterPlugin.BonePoseDNAConverter converter in bc.poseDNAConverters)
                                {
                                    converter.poseToApply.ApplyPose(context.activeUMA.skeleton, converter.startingPoseWeight);
                                }
                            }
                            Dcc.overallModifiers.UpdateCharacter(context.activeUMA, context.activeUMA.skeleton, false);
                        }
                    }

                    if (haveEditTarget)
                    {
                        targetPose.ApplyPose(context.activeUMA.skeleton, 1f);
                    }
                    else
                    {
                        targetPose.ApplyPose(context.activeUMA.skeleton, previewWeight);
                    }
                }
                else
                {
                    //TODO
                    //how do we deal with poses that are not applied? The user will see the character in its current pose and bone positions for that
                    //which makes no sense
                    //also because this will be hooked up to dna, the dna itself might be causing other changes to happen ('overallScale' for example)
                    //So I think the editor for bonePoseConverters, needs to jump in here and ask the user if they want to apply the dna that makes the pose active?
                    //OR
                    //maybe we create a skeleton how it would be IF the pose was applied to it and the user edits those transforms?
                    //If the pose is applied they will see their character change, if its not it might be clearer that is the case
                }
            }
            if (!Application.isPlaying)
            {
                _livePopupEditor = null;
            }
        }
示例#7
0
        private void CreateBonePoseCallback(UMAData umaData)
        {
            UMA.PoseTools.UMABonePose bonePose = CreatePoseAsset("", bonePoseSaveName);
            //I dont think this should have ever overwritten the existing one

            /*if (selectedConverter.startingPose == null)
             * {
             *      bonePose = CreatePoseAsset("", bonePoseSaveName);
             * }
             * else
             * {
             *      bonePose = selectedConverter.startingPose;
             *      bonePose.poses = new UMABonePose.PoseBone[1];
             * }*/

            UMASkeleton skeletonPreDNA  = tempAvatarPreDNA.GetComponent <UMADynamicAvatar>().umaData.skeleton;
            UMASkeleton skeletonPostDNA = tempAvatarPostDNA.GetComponent <UMADynamicAvatar>().umaData.skeleton;

            Transform transformPreDNA;
            Transform transformPostDNA;
            bool      transformDirty;
            int       parentHash;

            foreach (int boneHash in skeletonPreDNA.BoneHashes)
            {
                skeletonPreDNA.TryGetBoneTransform(boneHash, out transformPreDNA, out transformDirty, out parentHash);
                skeletonPostDNA.TryGetBoneTransform(boneHash, out transformPostDNA, out transformDirty, out parentHash);

                if ((transformPreDNA == null) || (transformPostDNA == null))
                {
                    Debug.LogWarning("Bad bone hash in skeleton: " + boneHash);
                    continue;
                }

                if (!LocalTransformsMatch(transformPreDNA, transformPostDNA))
                {
                    bonePose.AddBone(transformPreDNA, transformPostDNA.localPosition, transformPostDNA.localRotation, transformPostDNA.localScale);
                }
            }

            UMAUtils.DestroySceneObject(tempAvatarPreDNA);
            UMAUtils.DestroySceneObject(tempAvatarPostDNA);


            // This can be very helpful for testing

            /*
             * bonePose.ApplyPose(skeletonPreDNA, 1.0f);
             */

            EditorUtility.SetDirty(bonePose);
            AssetDatabase.SaveAssets();

            if (_applyAndResetOnCreateBP)
            {
                DynamicDNAConverterController converterController = (selectedConverter is DynamicDNAConverterController) ? (selectedConverter as DynamicDNAConverterController) : null;
                DynamicDNAConverterBehaviour  converterBehaviour  = (selectedConverter is DynamicDNAConverterBehaviour) ? (selectedConverter as DynamicDNAConverterBehaviour) : null;
                //UMA2.8+ fixDNAPrefabs Removed the converterBehaviour.ConverterController field, it should be directly assigned to the Races/Slots now
                //if (converterBehaviour.ConverterController != null)
                //	converterController = converterBehaviour.ConverterController;
                if (converterController != null)
                {
                    //find the first BonePoseDNAConverterPlugin and add the pose to it
                    var existingBPCPs = converterController.GetPlugins(typeof(BonePoseDNAConverterPlugin));
                    BonePoseDNAConverterPlugin thisBPCP;
                    if (existingBPCPs.Count > 0)
                    {
                        thisBPCP = existingBPCPs[0] as BonePoseDNAConverterPlugin;
                        //Turn off any other starting poses?
                        for (int i = 0; i < existingBPCPs.Count; i++)
                        {
                            for (int bi = 0; bi < (existingBPCPs[i] as BonePoseDNAConverterPlugin).poseDNAConverters.Count; bi++)
                            {
                                (existingBPCPs[i] as BonePoseDNAConverterPlugin).poseDNAConverters[bi].startingPoseWeight = 0f;
                            }
                        }
                    }
                    else
                    {
                        //if there isn't one create it
                        thisBPCP = converterController.AddPlugin(typeof(BonePoseDNAConverterPlugin)) as BonePoseDNAConverterPlugin;
                    }
                    thisBPCP.poseDNAConverters.Add(new BonePoseDNAConverterPlugin.BonePoseDNAConverter(bonePose, 1f));
                    Debug.Log(bonePose.name + " added as a starting pose to " + thisBPCP.name);
                }
                else if (converterBehaviour != null)
                {
                    // Set this asset as the converters pose asset
                    converterBehaviour.startingPose = bonePose;
                    //make sure its fully applied
                    converterBehaviour.startingPoseWeight = 1f;
                }

                // Reset all the DNA values for target Avatar to default
                UMADnaBase[] targetDNA = activeUMA.umaData.GetAllDna();
                foreach (UMADnaBase dnaEntry in targetDNA)
                {
                    for (int i = 0; i < dnaEntry.Values.Length; i++)
                    {
                        dnaEntry.SetValue(i, 0.5f);
                    }
                }

                // Optionally clear the DNA from the base recipe,
                // since it's now included in the new starting pose
                UMARecipeBase baseRaceRecipe = activeUMA.umaData.umaRecipe.GetRace().baseRaceRecipe;
                if (baseRaceRecipe != null)
                {
                    if (EditorUtility.DisplayDialog("Base Recipe Cleanup", "Starting Pose created. Remove DNA from base recipe of active race? Choose 'RemoveDNA' if your intention is to replace modifications made by a recipes starting DNA values with the created pose.", "Remove DNA", "Keep DNA"))
                    {
                        UMAData.UMARecipe baseRecipeData = new UMAData.UMARecipe();
                        baseRaceRecipe.Load(baseRecipeData, activeUMA.context);
                        baseRecipeData.ClearDna();
                        baseRaceRecipe.Save(baseRecipeData, activeUMA.context);
                    }
                }
            }
        }
 public static void CreateDynamicDNAConverterController()
 {
     DynamicDNAConverterController.CreateDynamicDNAConverterControllerAsset();
 }