Exemplo n.º 1
0
        public override void OnInspectorGUI()
        {
            if (warningIcon == null)
            {
                warningIcon                = EditorGUIUtility.FindTexture("console.warnicon.sml");
                warningStyle               = new GUIStyle(EditorStyles.label);
                warningStyle.fixedHeight   = warningIcon.height + 4f;
                warningStyle.contentOffset = new Vector2(0, -2f);
            }
            if (_recipe == null)
            {
                return;
            }

            foreach (IUMARecipePlugin plugin in plugins)
            {
                string label = plugin.GetSectionLabel();
                plugin.foldOut = GUIHelper.FoldoutBar(plugin.foldOut, label);
                if (plugin.foldOut)
                {
                    GUIHelper.BeginVerticalPadded(10, new Color(0.65f, 0.675f, 1f));
                    plugin.OnInspectorGUI(serializedObject);
                    GUIHelper.EndVerticalPadded(10);
                }
            }

            PowerToolsGUI();
            base.OnInspectorGUI();
        }
 public void RandomWardrobeSlotGUI(RandomAvatar ra, RandomWardrobeSlot rws)
 {
     // do random colors
     // show each possible item.
     GUIHelper.FoldoutBar(ref rws.GuiFoldout, rws.WardrobeSlot.name + " (" + rws.WardrobeSlot.wardrobeSlot + ")", out rws.Delete);
     if (rws.GuiFoldout)
     {
         GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.75f, 0.75f));
         rws.Chance = EditorGUILayout.IntSlider("Weighted Chance", rws.Chance, 1, 100);
         if (rws.PossibleColors.Length > 0)
         {
             if (GUILayout.Button("Add Shared Color"))
             {
                 rws.AddColorTable = true;
             }
             foreach (RandomColors rc in rws.Colors)
             {
                 RandomColorsGUI(ra, rws, rc);
             }
         }
         else
         {
             GUILayout.Label("Wardrobe Recipe has no Shared Colors");
         }
         GUIHelper.EndVerticalPadded(10);
     }
 }
Exemplo n.º 3
0
        protected virtual bool DrawIncompatibleSlots(bool ShowHelp)
        {
            bool doUpdate = false;

            DeletedRecipes.Clear();
            UMAWardrobeRecipe uwr = target as UMAWardrobeRecipe;

            if (uwr == null)
            {
                return(false);
            }


            GUILayout.BeginHorizontal(EditorStyles.toolbarButton);
            GUILayout.Space(10);
            showIncompatible = EditorGUILayout.Foldout(showIncompatible, "Incompatible Recipes");
            GUILayout.EndHorizontal();

            if (showIncompatible)
            {
                GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));
                if (GUILayout.Button("Add Incompatible Recipe"))
                {
                    uwr.IncompatibleRecipes.Add(null);
                    doUpdate = true;
                }

                for (int i = 0; i < uwr.IncompatibleRecipes.Count; i++)
                {
                    UMAWardrobeRecipe u = uwr.IncompatibleRecipes[i];
                    GUILayout.BeginHorizontal();
                    uwr.IncompatibleRecipes[i] = (UMAWardrobeRecipe)EditorGUILayout.ObjectField(u, typeof(UMAWardrobeRecipe), false);
                    if (u != uwr.IncompatibleRecipes[i])
                    {
                        doUpdate = true;
                    }
                    if (GUILayout.Button("X", EditorStyles.miniButton, GUILayout.Width(24)))
                    {
                        doUpdate = true;
                        DeletedRecipes.Add(u);
                    }
                    GUILayout.EndHorizontal();
                }

                GUIHelper.EndVerticalPadded(3);
            }

            if (DeletedRecipes.Count > 0)
            {
                uwr.IncompatibleRecipes.Remove(DeletedRecipes[0]);
            }
            if (ShowHelp)
            {
                EditorGUILayout.HelpBox("Incompatible Wardrobe Recipes are recipes that will not work with this specific recipe. It is up to your application to enforce this.", MessageType.Info);
            }
            GUILayout.Space(1);
            return(doUpdate);
        }
Exemplo n.º 4
0
        public override void OnInspectorGUI()
        {
            //base.DrawDefaultInspector();

            serializedObject.Update();
            DrawPropertiesExcluding(serializedObject, _excludeProperties);

            GUILayout.Space(10);
            GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));
            _editorFoldout = EditorGUILayout.Foldout(_editorFoldout, "Editor Tools", true);
            if (_editorFoldout)
            {
                if (GUILayout.Button("Clear DNA Morphs List", GUILayout.MaxWidth(200)))
                {
                    if (EditorUtility.DisplayDialog("Warning", "Are you sure you want to clear the DNA Morphs list?", "Yes", "Cancel"))
                    {
                        ClearDnaMorphs();
                    }
                }
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button(new GUIContent("Extract BlendShape Names", "This will find all the blendshape names in the supplied SlotData->MeshData and add them to the dna morph list. Warning! Will clear existing morphs."), GUILayout.MaxWidth(200)))
                {
                    if (EditorUtility.DisplayDialog("Warning", "This will clear your current dna morph list. Are you sure to proceed?", "Yes", "Cancel"))
                    {
                        ExtractBlendShapeNames();
                    }
                }
                _slotAsset = EditorGUILayout.ObjectField(_slotAsset, typeof(SlotDataAsset), false) as SlotDataAsset;

                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button(new GUIContent("Write to DynamicDNA", "This will write all the dna entry names from the dna morph list to the supplied DynamicUMADnaAsset.  Warning! This will clear the existing Dna Names on the DynamicUMADnaAsset."), GUILayout.MaxWidth(200)))
                {
                    if (EditorUtility.DisplayDialog("Warning", "This will clear your DynamicDnaName list. Are you sure to proceed?", "Yes", "Cancel"))
                    {
                        WriteToDynamicDNA();
                    }
                }
                _dnaAsset = EditorGUILayout.ObjectField(_dnaAsset, typeof(DynamicUMADnaAsset), false) as DynamicUMADnaAsset;
                EditorGUILayout.EndHorizontal();
            }
            GUIHelper.EndVerticalPadded(3);

            GUILayout.Space(10);
            GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));
            _morphsFoldout = EditorGUILayout.Foldout(_morphsFoldout, "Open/Close DNA Morphs", true);

            if (_morphsFoldout)
            {
                _morphList.DoLayoutList();
            }

            GUIHelper.EndVerticalPadded(3);

            serializedObject.ApplyModifiedProperties();
        }
 private void DrawHelp(string[] help)
 {
     GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));
     for (int i = 0; i < help.Length; i++)
     {
         EditorGUILayout.HelpBox(help[i], MessageType.None);
     }
     GUIHelper.EndVerticalPadded(3);
 }
        //draws the coverImages foldout
        protected virtual bool DrawCoverImagesUI(Type TargetType)
        {
            bool doUpdate = false;
            //FieldInfos
            var CoverImagesField = TargetType.GetField("coverImages", BindingFlags.Public | BindingFlags.Instance);
            //field values
            List <Sprite> coverImages = (List <Sprite>)CoverImagesField.GetValue(target);

            //drawUI
            GUILayout.BeginHorizontal(EditorStyles.toolbarButton);
            GUILayout.Space(10);
            coverImagesIsExpanded = EditorGUILayout.Foldout(coverImagesIsExpanded, new GUIContent("Cover Images"));
            GUILayout.EndHorizontal();
            if (coverImagesIsExpanded)
            {
                List <Sprite> prevCoverImages = coverImages;
                GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));
                EditorGUILayout.BeginHorizontal();
                for (int i = 0; i < coverImages.Count; i++)
                {
                    EditorGUI.BeginChangeCheck();
                    var thisImg = EditorGUILayout.ObjectField(coverImages[i], typeof(Sprite), false, GUILayout.Width(75), GUILayout.Height(75));
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (thisImg != coverImages[i])
                        {
                            if (thisImg == null)
                            {
                                coverImages.RemoveAt(i);
                            }
                            else
                            {
                                coverImages[i] = (Sprite)thisImg;
                            }
                            doUpdate = true;
                        }
                    }
                }
                EditorGUILayout.EndHorizontal();
                if (GUILayout.Button("Add"))
                {
                    coverImages.Add(null);
                }
                if (!AreListsEqual <Sprite>(prevCoverImages, coverImages))
                {
                    CoverImagesField.SetValue(target, coverImages);
                }
                GUIHelper.EndVerticalPadded(10);
            }
            GUILayout.Space(-5f);
            return(doUpdate);
        }
        //Draws the plugins in 'By Converter' view
        private void DrawConverters()
        {
            GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));

            if (_target.PluginCount == 0)
            {
                EditorGUILayout.HelpBox("No Converters have been added yet. Use the 'Add' tool below to add some", MessageType.Info);
            }
            _convertersListProp = serializedObject.FindProperty("_plugins");

            _convertersROL = CachedReorderableList.GetListDrawer(_convertersListProp, DrawConverterListHeaderCallback, GetConverterListEntryHeightCallback, DrawConverterListEntryCallback, DrawConverterListFooterCallback);
            _convertersROL.headerHeight = 0f;
            _convertersROL.footerHeight = (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing * 2);
            _convertersROL.DoLayoutList();

            GUIHelper.EndVerticalPadded(3);
        }
        private void DoDragDrop()
        {
            GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.85f, 1f), EditorStyles.helpBox);
            GUILayout.Label("Automatic Drag and Drop processing", EditorStyles.boldLabel);
            Rect dropArea = GUILayoutUtility.GetRect(0.0f, 50.0f, GUILayout.ExpandWidth(true));

            nameAfterMaterial = GUILayout.Toggle(nameAfterMaterial, "Name slot by material");
            Color save = GUI.color;

            GUI.color = Color.white;
            GUI.Box(dropArea, "Drag FBX GameObject or meshes here to generate all slots and overlays for the GameObject");
            relativeFolder = EditorGUILayout.ObjectField("Relative Folder", relativeFolder, typeof(UnityEngine.Object), false) as UnityEngine.Object;
            EnforceFolder(ref relativeFolder);

            DropAreaGUI(dropArea);
            GUI.color = save;
            GUIHelper.EndVerticalPadded(10);
        }
Exemplo n.º 9
0
        public void RandomWardrobeSlotGUI(RandomAvatar ra, RandomWardrobeSlot rws)
        {
            // do random colors
            // show each possible item.
            string name = "<null>";

            if (rws.WardrobeSlot != null)
            {
                name = rws.WardrobeSlot.name;
            }

            GUIHelper.FoldoutBar(ref rws.GuiFoldout, name + " (" + rws.Chance + ")", out rws.Delete);
            if (rws.GuiFoldout)
            {
                GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.75f, 0.75f));
                rws.Chance = EditorGUILayout.IntSlider("Weighted Chance", rws.Chance, 1, 100);
                if (rws.PossibleColors.Length > 0)
                {
                    if (GUILayout.Button("Add Shared Color"))
                    {
                        rws.AddColorTable = true;
                    }
                    RandomColors delme = null;
                    foreach (RandomColors rc in rws.Colors)
                    {
                        if (RandomColorsGUI(ra, rws, rc))
                        {
                            delme = rc;
                        }
                    }
                    if (delme != null)
                    {
                        rws.Colors.Remove(delme);
                        EditorUtility.SetDirty(this.target);
                        AssetDatabase.SaveAssets();
                    }
                }
                else
                {
                    GUILayout.Label("Wardrobe Recipe has no Shared Colors");
                }
                GUIHelper.EndVerticalPadded(10);
            }
        }
        private void DrawOverallModifiers()
        {
            var overallModifiersProp   = serializedObject.FindProperty("_overallModifiers");
            var overallModsFoldoutRect = EditorGUILayout.GetControlRect();

            overallModsFoldoutRect.height = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
            var overallModsLabel = EditorGUI.BeginProperty(overallModsFoldoutRect, new GUIContent(overallModifiersProp.displayName), overallModifiersProp);

            overallModsLabel.text = overallModsLabel.text.ToUpper();
            //TODO Id actually like an import settings thing here now, so that you can import overallModifiers from another converterController or converterBehaviour
            GUIHelper.ToolbarStyleFoldout(overallModsFoldoutRect, overallModsLabel.text.ToUpper(), new string[] { overallModsLabel.tooltip }, ref _overallModifiersExpanded, ref _overallModifiersHelpExpanded);

            if (_overallModifiersExpanded)
            {
                GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));
                GUILayout.Space(5);
                EditorGUILayout.PropertyField(overallModifiersProp);
                GUIHelper.EndVerticalPadded(3);
            }
        }
        private void DrawDNAAssetField()
        {
            var dnaAssetProp        = serializedObject.FindProperty("_dnaAsset");
            var dnaAssetFoldoutRect = EditorGUILayout.GetControlRect();

            dnaAssetFoldoutRect.height = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
            var dnaAssetLabel = EditorGUI.BeginProperty(dnaAssetFoldoutRect, new GUIContent(dnaAssetProp.displayName), dnaAssetProp);

            dnaAssetLabel.text = dnaAssetLabel.text.ToUpper();
            GUIHelper.ToolbarStyleFoldout(dnaAssetFoldoutRect, dnaAssetLabel.text.ToUpper(), new string[] { dnaAssetLabel.tooltip }, ref _dnaAssetExpanded, ref _dnaAssetHelpExpanded);

            if (_dnaAssetExpanded)
            {
                GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));
                GUILayout.Space(5);
                EditorGUI.BeginChangeCheck();
                EditorGUILayout.PropertyField(dnaAssetProp);
                if (EditorGUI.EndChangeCheck())
                {
                    if (dnaAssetProp.objectReferenceValue != null)
                    {
                        _dnaAsset = dnaAssetProp.objectReferenceValue as DynamicUMADnaAsset;
                    }
                    else
                    {
                        _dnaAsset = null;
                    }
                    //TODO in the ConverterBehaviour editor we cleared the DNA on the avatar.umaData (if we are in play mode and inspecting using customizer)
                    //we could probably do with doing the same here

                    /*
                     * //force the Avatar to update its dna and dnaconverter dictionaries
                     *      umaData.umaRecipe.ClearDna();
                     *      umaData.umaRecipe.ClearDNAConverters();
                     */
                }
                GUIHelper.EndVerticalPadded(3);
            }

            EditorGUILayout.Space();
        }
        private void DrawFullHelp()
        {
            GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));

            EditorGUILayout.HelpBox("A DNAEvaluationGraph is an option you can choose in a DNAEvaluator field that many UMA DNA Converters use when interpreting your avatars dna values. Its one of these:", MessageType.None);

            GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));
            EditorGUI.indentLevel++;
            var exampleFieldProp = serializedObject.FindProperty("_exampleField");

            EditorGUILayout.PropertyField(exampleFieldProp);
            EditorGUI.indentLevel--;
            GUIHelper.EndVerticalPadded(3);
            EditorGUILayout.HelpBox("The graph is used to perform math operations on an incoming dna value. UMA comes with a set of DNAEvaluationGraphs built in. But if you need something sepcial you can add it below. Give it a go! If you add a graph in the 'CustomGraphs' area below and then click the dropdown in the field above you will see it is in there as an option. This will be the same for all DNAPlugins that use this field.", MessageType.None);
            EditorGUILayout.HelpBox("For example, below is a DNA called 'DNAValue'. Below that is a DNAEvaluator, using a graph, that will evaluate 'DNAValue'. Try changing the settings in the Evaluator and see how they affect the calculated 'Result' in the last field", MessageType.None);

            GUIHelper.BeginVerticalPadded(5, new Color(0.75f, 0.875f, 1f, 0.3f));
            EditorGUI.indentLevel++;
            var exampleEvaluatorProp = serializedObject.FindProperty("_exampleEvaluator");

            exampleEvaluatorProp.isExpanded = true;
            var exampleDNAProp = serializedObject.FindProperty("_exampleDNAValue");

            EditorGUI.BeginChangeCheck();
            exampleDNAProp.floatValue = EditorGUILayout.Slider(new GUIContent("DNAValue"), exampleDNAProp.floatValue, 0f, 1f);
            EditorGUILayout.Space();
            EditorGUILayout.PropertyField(exampleEvaluatorProp);
            if (EditorGUI.EndChangeCheck())
            {
                serializedObject.ApplyModifiedProperties();
            }
            EditorGUI.BeginDisabledGroup(true);
            EditorGUILayout.FloatField(new GUIContent("Evaluated Result!"), _target.EvaluateDemo());
            EditorGUI.EndDisabledGroup();
            EditorGUI.indentLevel--;
            GUIHelper.EndVerticalPadded(5);

            EditorGUILayout.HelpBox("The Evaluation Graph field itself is a value field rather than a reference field, so once its been set to use a certain graph that graph will not change even if you change the preset that set it. Think of it like Color.red, Color.blue etc, if Unity changed the hues of those colors, any colors that you set using those defaults, would not actually change. So there is no actual need to include this preset library in your project. Its just here to help.", MessageType.None);

            GUIHelper.EndVerticalPadded(3);
        }
Exemplo n.º 13
0
        public override void OnInspectorGUI()
        {
            centeredLabel           = new GUIStyle(GUI.skin.label);
            centeredLabel.fontStyle = FontStyle.Bold;
            centeredLabel.alignment = TextAnchor.MiddleCenter;

            serializedObject.Update();

            EditorGUILayout.LabelField("Basic Configuration", centeredLabel);
            GUIHelper.BeginVerticalPadded();
            EditorGUILayout.PropertyField(fitAtlas);
            EditorGUILayout.PropertyField(SharperFitTextures);
            EditorGUILayout.PropertyField(AtlasOverflowFitMethod);
            EditorGUILayout.PropertyField(FitPercentageDecrease);
            GUIHelper.EndVerticalPadded();
            EditorGUILayout.PropertyField(convertRenderTexture);
            EditorGUILayout.PropertyField(convertMipMaps);
            EditorGUILayout.IntPopup(atlasResolution, atlasLabels, atlasValues);
            EditorGUILayout.PropertyField(defaultOverlayAsset);

            serializedObject.ApplyModifiedProperties();
        }
Exemplo n.º 14
0
        public override void OnInspectorGUI()
        {
            centeredLabel           = new GUIStyle(GUI.skin.label);
            centeredLabel.fontStyle = FontStyle.Bold;
            centeredLabel.alignment = TextAnchor.MiddleCenter;

            serializedObject.Update();

            EditorGUILayout.LabelField("Basic Configuration", centeredLabel);
            GUIHelper.BeginVerticalPadded();
            EditorGUILayout.PropertyField(fitAtlas);
            EditorGUILayout.PropertyField(SharperFitTextures);
            EditorGUILayout.PropertyField(AtlasOverflowFitMethod);
            EditorGUILayout.HelpBox("Note: Atlas Overflow parameters only work with coroutines disabled below.", MessageType.None);
            EditorGUILayout.PropertyField(FitPercentageDecrease);
            GUIHelper.EndVerticalPadded();
            EditorGUILayout.PropertyField(serializedObject.FindProperty("SaveAndRestoreIgnoredItems"));
            EditorGUILayout.PropertyField(convertRenderTexture);
            EditorGUILayout.PropertyField(convertMipMaps);
            EditorGUILayout.IntPopup(atlasResolution, atlasLabels, atlasValues);
            EditorGUILayout.PropertyField(defaultOverlayAsset);

            serializedObject.ApplyModifiedProperties();
        }
        //Maybe eventually we can use the new IMGUI classes once older unity version are no longer supported.
        private void DrawChannelList(SerializedProperty list)
        {
            // EditorGUILayout.PropertyField(list, new GUIContent("Texture Channels", "List of texture channels to be used in this material."));
            channelListExpanded = GUIHelper.FoldoutBar(channelListExpanded, "Texture Channels");
            if (channelListExpanded)
            {
                GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));
                EditorGUILayout.PropertyField(list.FindPropertyRelative("Array.size"));
                if (channelExpanded.Length != list.arraySize)
                {
                    channelExpanded = new bool[list.arraySize];
                }

                for (int i = 0; i < list.arraySize; i++)
                {
                    SerializedProperty channel = list.GetArrayElementAtIndex(i);
                    SerializedProperty materialPropertyName = channel.FindPropertyRelative("materialPropertyName"); //Let's get this eary to be able to use it in the element header.
                                                                                                                    // EditorGUILayout.PropertyField(channel, new GUIContent("Channel " + i + ": " + materialPropertyName.stringValue));
                                                                                                                    // EditorGUILayout.LabelField(new GUIContent("Channel " + i + ": " + materialPropertyName.stringValue),EditorStyles.toolbar);

                    channelExpanded[i] = GUIHelper.FoldoutBar(channelExpanded[i], "Channel " + i + ": " + materialPropertyName.stringValue);
                    if (channelExpanded[i])
                    {
                        GUIHelper.BeginVerticalPadded(10, new Color(0.85f, 0.85f, 0.85f));
                        EditorGUILayout.PropertyField(channel.FindPropertyRelative("channelType"), new GUIContent("Channel Type", "The channel type. Affects the texture atlassing process."));
                        EditorGUILayout.PropertyField(channel.FindPropertyRelative("textureFormat"), new GUIContent("Texture Format", "Format used for the texture in this channel."));

                        if (channel.FindPropertyRelative("textureFormat") != null && i < ((UMAMaterial)target).channels.Length)
                        {
                            RenderTextureFormat format = ((UMAMaterial)target).channels[i].textureFormat;
                            if (!SystemInfo.SupportsRenderTextureFormat(format))
                            {
                                EditorGUILayout.HelpBox("This Texture Format is not supported on this system!", MessageType.Error);
                            }
                        }

                        EditorGUILayout.BeginHorizontal();

                        EditorGUILayout.PropertyField(materialPropertyName, new GUIContent("Material Property Name", "The name of the property this texture corresponds to in the shader used by this material."), GUILayout.MinWidth(300));
                        if (_shaderProperties != null)
                        {
                            int selection = EditorGUILayout.Popup(0, _shaderProperties, GUILayout.MinWidth(100), GUILayout.MaxWidth(200));
                            if (selection > 0)
                            {
                                materialPropertyName.stringValue = _shaderProperties[selection];
                            }
                        }
                        EditorGUILayout.EndHorizontal();

                        SerializedProperty NonShaderProperty = channel.FindPropertyRelative("NonShaderTexture");
                        UMAMaterial        source            = target as UMAMaterial;
                        if (source.material != null)
                        {
                            if (!source.material.HasProperty(materialPropertyName.stringValue) && !NonShaderProperty.boolValue)
                            {
                                EditorGUILayout.HelpBox("This name is not found in the shader! Are you sure it is correct?", MessageType.Warning);
                            }
                        }

                        EditorGUILayout.PropertyField(channel.FindPropertyRelative("ConvertRenderTexture"), new GUIContent("Convert RenderTexture", "Convert the Render Texture to a Texture2D (so it can be compressed)"));
                        SerializedProperty ConvertRenderTextureProperty = channel.FindPropertyRelative("ConvertRenderTexture");
                        if (ConvertRenderTextureProperty.boolValue == true)
                        {
                            EditorGUILayout.PropertyField(channel.FindPropertyRelative("Compression"), new GUIContent("Texture Compression", "Compress the atlas texture to DXT1 or DXT5"));
                        }

                        EditorGUILayout.PropertyField(channel.FindPropertyRelative("DownSample"), new GUIContent("Down Sample", "Decrease size to save texture memory"));
                        EditorGUILayout.PropertyField(channel.FindPropertyRelative("sourceTextureName"), new GUIContent("Source Texture Name", "For use with procedural materials, leave empty otherwise."));

                        EditorGUILayout.PropertyField(NonShaderProperty, new GUIContent("NonShader Texture", "For having a texture get merged by the UMA texture merging process but not used in a shader. E.G. Pixel/UV based ID lookup. The Material Property Name should be empty when this is true."));
                        if (NonShaderProperty.boolValue && !string.IsNullOrEmpty(materialPropertyName.stringValue))
                        {
                            EditorGUILayout.HelpBox("A NonShader Texture shouldn't have a Material Property Name value.", MessageType.Warning);
                        }
                        GUIHelper.EndVerticalPadded(10);
                    }
                    GUILayout.Space(8);
                }
                GUIHelper.EndVerticalPadded(10);
            }
        }
        //Draws the converters in the 'By DNA' view
        private void DrawConvertersByDNA()
        {
            var           inUseNames = _target.GetUsedDNANames();
            List <string> namesToDraw;

            //if we have a dnanames asset we will loop through those names
            if (_dnaAsset != null && _dnaAsset.Names.Length > 0)
            {
                namesToDraw = new List <string>(_dnaAsset.Names);
            }
            //otherwise we will used the inUseNames from the plugins
            else
            {
                namesToDraw = inUseNames;
            }

            //Draw the output
            if (namesToDraw.Count == 0)
            {
                GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));
                if (_target.PluginCount == 0)
                {
                    EditorGUILayout.HelpBox("No plugins have been added yet. Use the 'Add' tool below to add some", MessageType.Info);
                }
                else
                {
                    EditorGUILayout.HelpBox("No plugins have been set up to use any dnaNames yet. Switch to the other view to add them", MessageType.Info);
                }
                GUIHelper.EndVerticalPadded(3);
            }
            else
            {
                GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));

                //Draw the search field
                var activeNamesToDraw = DrawDNASearchArea(EditorGUILayout.GetControlRect(), namesToDraw);

                DynamicDNAPlugin plugin;

                for (int i = 0; i < activeNamesToDraw.Count; i++)
                {
                    if (!_expandedDNANames.ContainsKey(activeNamesToDraw[i]))
                    {
                        _expandedDNANames.Add(activeNamesToDraw[i], false);
                    }
                    GUILayout.BeginHorizontal(EditorStyles.toolbarButton);
                    EditorGUI.indentLevel++;
                    _expandedDNANames[activeNamesToDraw[i]] = EditorGUILayout.Foldout(_expandedDNANames[activeNamesToDraw[i]], activeNamesToDraw[i]);
                    EditorGUI.indentLevel--;
                    GUILayout.EndHorizontal();
                    if (_expandedDNANames[activeNamesToDraw[i]])
                    {
                        GUI.color = new Color(0.75f, 0.875f, 1f, 0.3f);
                        GUILayout.BeginVertical(_pluginsByDNAAreaStyle);
                        GUI.color = Color.white;

                        //these would be a reorderable list in the other view so draw a reorderable list box around this whole list so it looks the same
                        //(plugins are not reorderable in this view because that would sort of suggest you can have plugins output in a different order
                        //depending on the dna name- which you cant)
                        GUILayout.BeginVertical(_pluginChooserAreaStyle);

                        for (int pi = 0; pi < _target.PluginCount; pi++)
                        {
                            plugin = _target.GetPlugin(pi);

                            if (plugin == null)
                            {
                                continue;
                            }

                            //make a space like the other view
                            if (pi > 0)
                            {
                                GUILayout.Space(EditorGUIUtility.standardVerticalSpacing * 2);
                            }

                            //tell the plugin to draw its entry for this dna name, plugins might use more than one dna name so its up to their drawers to sort out what to draw
                            //the general idea is that if this dna name appears anywhere in the plugin, then it should draw the relevant entry
                            _pluginsEditors[plugin].OnInspectorForDNAGUI(activeNamesToDraw[i]);
                        }

                        GUILayout.EndVertical();

                        GUILayout.EndVertical();
                    }
                }
                //TODO after we have drawn all the namesToDraw if there are any inUseNames that have not been drawn, draw those too
                GUIHelper.EndVerticalPadded(3);
            }
        }
Exemplo n.º 17
0
        void OnGUI()
        {
            GUILayout.Label("UMA Slot Builder");
            GUILayout.Space(20);
            normalReferenceMesh = EditorGUILayout.ObjectField("Seams Mesh (Optional)  ", normalReferenceMesh, typeof(SkinnedMeshRenderer), false) as SkinnedMeshRenderer;
            var newslotMesh = EditorGUILayout.ObjectField("Slot Mesh  ", slotMesh, typeof(SkinnedMeshRenderer), false) as SkinnedMeshRenderer;

            if (newslotMesh != slotMesh)
            {
                errmsg   = "";
                slotMesh = newslotMesh;
            }


            slotMaterial = EditorGUILayout.ObjectField("UMAMaterial	 ", slotMaterial, typeof(UMAMaterial), false) as UMAMaterial;
            slotFolder   = EditorGUILayout.ObjectField("Slot Destination Folder", slotFolder, typeof(UnityEngine.Object), false) as UnityEngine.Object;
            EnforceFolder(ref slotFolder);
            //
            // For now, we will disable this option.
            // It doesn't work in most cases.
            // RootBone = EditorGUILayout.TextField("Root Bone (ex:'Global')", RootBone);
            //
            slotName            = EditorGUILayout.TextField("Slot Name", slotName);
            binarySerialization = EditorGUILayout.Toggle(new GUIContent("Binary Serialization", "Forces the created Mesh object to be serialized as binary. Recommended for large meshes and blendshapes."), binarySerialization);

            GUILayout.BeginHorizontal(EditorStyles.toolbarButton);
            GUILayout.Space(10);
            showTags = EditorGUILayout.Foldout(showTags, "Tags");
            GUILayout.EndHorizontal();
            if (showTags)
            {
                GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));
                // Draw the button area
                GUILayout.BeginHorizontal();
                if (GUILayout.Button("Add Tag", GUILayout.Width(80)))
                {
                    Tags.Add("");
                    Repaint();
                }

                GUILayout.Label(Tags.Count + " Tags defined");
                GUILayout.EndHorizontal();

                if (Tags.Count == 0)
                {
                    GUILayout.Label("No tags defined", EditorStyles.helpBox);
                }
                else
                {
                    int del = -1;

                    for (int i = 0; i < Tags.Count; i++)
                    {
                        GUILayout.BeginHorizontal();
                        Tags[i] = GUILayout.TextField(Tags[i]);
                        if (GUILayout.Button("\u0078", EditorStyles.miniButton, GUILayout.ExpandWidth(false)))
                        {
                            del = i;
                        }
                        GUILayout.EndHorizontal();
                    }
                    if (del >= 0)
                    {
                        Tags.RemoveAt(del);
                        Repaint();
                    }
                }
                // Draw the tags (or "No tags defined");
                GUIHelper.EndVerticalPadded(10);
            }

            EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
            EditorGUILayout.BeginHorizontal();
            createOverlay = EditorGUILayout.Toggle("Create Overlay", createOverlay);
            EditorGUILayout.LabelField(slotName + "_Overlay");
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.BeginHorizontal();
            createRecipe = EditorGUILayout.Toggle("Create Wardrobe Recipe ", createRecipe);
            EditorGUILayout.LabelField(slotName + "_Recipe");
            EditorGUILayout.EndHorizontal();
            addToGlobalLibrary = EditorGUILayout.Toggle("Add To Global Library", addToGlobalLibrary);

            if (GUILayout.Button("Verify Slot"))
            {
                if (slotMesh == null)
                {
                    errmsg = "Slot is null.";
                }
                else
                {
                    Vector2[] uv = slotMesh.sharedMesh.uv;
                    foreach (Vector2 v in uv)
                    {
                        if (v.x > 1.0f || v.x < 0.0f || v.y > 1.0f || v.y < 0.0f)
                        {
                            errmsg = "UV Coordinates are out of range and will likely have issues with atlassed materials. Textures should not be tiled unless using non-atlassed materials.";
                            break;
                        }
                    }
                    if (string.IsNullOrEmpty(errmsg))
                    {
                        errmsg = "No errors found";
                    }
                }
            }

            if (!string.IsNullOrEmpty(errmsg))
            {
                EditorGUILayout.HelpBox(errmsg, MessageType.Warning);
            }

            if (GUILayout.Button("Create Slot"))
            {
                Debug.Log("Processing...");
                SlotDataAsset sd = CreateSlot();
                if (sd != null)
                {
                    Debug.Log("Success.");
                    string AssetPath = AssetDatabase.GetAssetPath(sd.GetInstanceID());
                    if (addToGlobalLibrary)
                    {
                        UMAAssetIndexer.Instance.EvilAddAsset(typeof(SlotDataAsset), sd);
                    }
                    OverlayDataAsset od = null;
                    if (createOverlay)
                    {
                        od = CreateOverlay(AssetPath.Replace(sd.name, sd.slotName + "_Overlay"), sd);
                    }
                    if (createRecipe)
                    {
                        CreateRecipe(AssetPath.Replace(sd.name, sd.slotName + "_Recipe"), sd, od);
                    }
                }
            }


            if (slotMesh != null)
            {
                if (slotMesh.localBounds.size.x > 10.0f || slotMesh.localBounds.size.y > 10.0f || slotMesh.localBounds.size.z > 10.0f)
                {
                    EditorGUILayout.HelpBox("This slot's size is very large. It's import scale may be incorrect!", MessageType.Warning);
                }

                if (slotMesh.localBounds.size.x < 0.01f || slotMesh.localBounds.size.y < 0.01f || slotMesh.localBounds.size.z < 0.01f)
                {
                    EditorGUILayout.HelpBox("This slot's size is very small. It's import scale may be incorrect!", MessageType.Warning);
                }

                if (slotName == null || slotName == "")
                {
                    slotName = slotMesh.name;
                }
                if (RootBone == null || RootBone == "")
                {
                    RootBone = "Global";
                }
            }

            GUILayout.Label("", EditorStyles.boldLabel);
            Rect dropArea = GUILayoutUtility.GetRect(0.0f, 50.0f, GUILayout.ExpandWidth(true));

            GUI.Box(dropArea, "Drag meshes here");
            GUILayout.Label("Automatic Drag and Drop processing", EditorStyles.boldLabel);
            relativeFolder = EditorGUILayout.ObjectField("Relative Folder", relativeFolder, typeof(UnityEngine.Object), false) as UnityEngine.Object;
            EnforceFolder(ref relativeFolder);

            DropAreaGUI(dropArea);
        }
        public override void OnInspectorGUI()
        {
            if (lastActionTime == 0)
            {
                lastActionTime = Time.realtimeSinceStartup;
            }

            serializedObject.Update();

            EditorGUI.BeginChangeCheck();

            EditorGUILayout.PropertyField(_overlayName);
            EditorGUILayout.PropertyField(_overlayType);
            EditorGUILayout.PropertyField(_rect);
            EditorGUILayout.LabelField("Note: It is recommended to use UV coordinates (0.0 -> 1.0) in 2.10+ for rect fields.", EditorStyles.helpBox);

            EditorGUILayout.PropertyField(_umaMaterial);

            if (_umaMaterial != null && _umaMaterial.objectReferenceValue != null)
            {
                int textureChannelCount  = 0;
                SerializedObject tempObj = new SerializedObject(_umaMaterial.objectReferenceValue);
                _channels = tempObj.FindProperty("channels");

                if (_channels == null)
                {
                    EditorGUILayout.HelpBox("Channels not found!", MessageType.Error);
                }
                else
                {
                    textureChannelCount = _channels.arraySize;
                }

                textureFoldout = GUIHelper.FoldoutBar(textureFoldout, "Texture Channels");

                if (textureFoldout)
                {
                    GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));
                    EditorGUILayout.PropertyField(_textureList.FindPropertyRelative("Array.size"));
                    for (int i = 0; i < _textureList.arraySize; i++)
                    {
                        SerializedProperty textureElement = _textureList.GetArrayElementAtIndex(i);
                        string             materialName   = "Unknown";

                        if (i < _channels.arraySize)
                        {
                            SerializedProperty channel = _channels.GetArrayElementAtIndex(i);
                            if (channel != null)
                            {
                                SerializedProperty materialPropertyName = channel.FindPropertyRelative("materialPropertyName");
                                if (materialPropertyName != null)
                                {
                                    materialName = materialPropertyName.stringValue;
                                }
                            }
                        }

                        EditorGUILayout.PropertyField(textureElement, new GUIContent(materialName));
                    }
                    GUIHelper.EndVerticalPadded(10);
                }

                if (_textureList.arraySize <= 0 || _textureList.arraySize != textureChannelCount)
                {
                    EditorGUILayout.HelpBox("Overlay Texture count and UMA Material channel count don't match!", MessageType.Error);
                }

                if (!_textureList.hasMultipleDifferentValues)
                {
                    bool allValid = true;
                    for (int i = 0; i < _textureList.arraySize; i++)
                    {
                        if (_textureList.GetArrayElementAtIndex(i).objectReferenceValue == null)
                        {
                            allValid = false;
                        }
                    }
                    if (!allValid)
                    {
                        EditorGUILayout.HelpBox("Not all textures in Texture List set!", MessageType.Error);
                    }
                }
            }
            else
            {
                EditorGUILayout.HelpBox("No UMA Material selected!", MessageType.Warning);
            }

            GUILayout.Space(20f);
            additionalFoldout = GUIHelper.FoldoutBar(additionalFoldout, "Additional Parameters");
            if (additionalFoldout)
            {
                GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));
                EditorGUILayout.PropertyField(_alphaMask);
                EditorGUILayout.PropertyField(_tags, true);
                EditorGUILayout.PropertyField(_occlusionEntries, true);
                GUIHelper.EndVerticalPadded(10);
            }

            serializedObject.ApplyModifiedProperties();
            if (EditorGUI.EndChangeCheck())
            {
                lastActionTime = Time.realtimeSinceStartup;
                doSave         = true;
            }
        }
Exemplo n.º 19
0
            public bool OnGUI()
            {
                bool changed = false;

                if (_race != null)
                {
                    if (_race.wardrobeSlots.Count > 0)
                    {
                        var context = UMAContextBase.Instance;
                        if (context == null)
                        {
                            var _errorMessage = "Editing a recipe requires a loaded scene with a valid UMAContextBase.";
                            Debug.LogWarning(_errorMessage);
                        }

                        if (_wardrobeSet == null || context == null)
                        {
                            return(false);
                        }
                        GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));

                        EditorGUILayout.HelpBox("Recently added recipes not showing up? Make sure you have added them to the 'UMA Global Library' and click the 'Refresh Recipes' button below.", MessageType.Info);
                        if (GUILayout.Button("Refresh Recipes"))
                        {
                            context.ValidateDictionaries();
                            return(false);
                        }
                        //a dictionary of slots that are being assigned by WardrobeCollections
                        var slotsAssignedByWCs = new Dictionary <string, string>();
                        if (_allowWardrobeCollectionSlot)
                        {
                            var wcRecipesForRace = context.GetRecipesForRaceSlot(_race.raceName, "WardrobeCollection");
                            var wcGroupDict      = new Dictionary <string, List <UMARecipeBase> >();
                            //I'm using reflection here to get fields and methods from the UMAWardrobeCollection type so this will still work if 'StandardAssets' is moved to 'Standard Assets'
                            for (int i = 0; i < wcRecipesForRace.Count; i++)
                            {
                                Type wcType = wcRecipesForRace[i].GetType();
                                if (wcType.ToString().Replace(wcType.Namespace + ".", "") == "UMAWardrobeCollection")
                                {
                                    FieldInfo wcRecipeSlotField = wcType.GetField("wardrobeSlot", BindingFlags.Public | BindingFlags.Instance);
                                    var       wcRecipeSlot      = (string)wcRecipeSlotField.GetValue(wcRecipesForRace[i]);
                                    if (!wcGroupDict.ContainsKey(wcRecipeSlot))
                                    {
                                        wcGroupDict.Add(wcRecipeSlot, new List <UMARecipeBase>());
                                    }
                                    wcGroupDict[wcRecipeSlot].Add(wcRecipesForRace[i]);
                                }
                            }
                            if (wcGroupDict.Count > 0)
                            {
                                MethodInfo WCGetRacesWardrobeSetMethod = null;
                                EditorGUILayout.LabelField("WardrobeCollections");
                                EditorGUI.indentLevel++;
                                foreach (KeyValuePair <string, List <UMARecipeBase> > kp in wcGroupDict)
                                {
                                    if (WCGetRacesWardrobeSetMethod == null)
                                    {
                                        WCGetRacesWardrobeSetMethod = kp.Value[0].GetType().GetMethod("GetRacesWardrobeSet", new Type[] { typeof(RaceData) });
                                    }
                                    var selected      = 0;
                                    var prevRecipe    = "";
                                    var thisPopupVals = new List <string>();
                                    thisPopupVals.Add("None");
                                    for (int i = 0; i < kp.Value.Count; i++)
                                    {
                                        thisPopupVals.Add(kp.Value[i].name);
                                        //check if this is selected
                                        for (int wsi = 0; wsi < _wardrobeSet.Count; wsi++)
                                        {
                                            if (kp.Value[i].name == _wardrobeSet[wsi].recipe)
                                            {
                                                prevRecipe = _wardrobeSet[wsi].recipe;
                                                selected   = i + 1;
                                                var thisWCWardrobeSet = (List <WardrobeSettings>)WCGetRacesWardrobeSetMethod.Invoke(kp.Value[i], new object[] { _race });
                                                for (int wcwsi = 0; wcwsi < thisWCWardrobeSet.Count; wcwsi++)
                                                {
                                                    if (!slotsAssignedByWCs.ContainsKey(thisWCWardrobeSet[wcwsi].slot))
                                                    {
                                                        slotsAssignedByWCs.Add(thisWCWardrobeSet[wcwsi].slot, kp.Value[i].name);
                                                    }
                                                    else
                                                    {
                                                        slotsAssignedByWCs[thisWCWardrobeSet[wcwsi].slot] = kp.Value[i].name;
                                                    }
                                                }
                                                break;
                                            }
                                        }
                                    }
                                    EditorGUI.BeginChangeCheck();
                                    var newSelected = EditorGUILayout.Popup(kp.Key, selected, thisPopupVals.ToArray());
                                    if (EditorGUI.EndChangeCheck())
                                    {
                                        for (int wsi = 0; wsi < _wardrobeSet.Count; wsi++)
                                        {
                                            if (_wardrobeSet[wsi].recipe == prevRecipe)
                                            {
                                                //we need to remove the wardrobeSettings that has prevRecipe as its value from _wardrobeSettings
                                                if (newSelected == 0)
                                                {
                                                    _wardrobeSet.RemoveAt(wsi);
                                                }
                                                else
                                                {
                                                    //we need to make wardrobeSettings that has prevRecipe have the new value
                                                    _wardrobeSet[wsi].recipe = thisPopupVals[newSelected];
                                                }
                                            }
                                        }
                                        changed = true;
                                    }
                                }
                                EditorGUI.indentLevel--;
                                EditorGUILayout.Space();
                                EditorGUILayout.LabelField("WardrobeSlots");
                                EditorGUI.indentLevel++;
                            }
                        }
                        foreach (string wsl in _race.wardrobeSlots)
                        {
                            if (wsl == "None")
                            {
                                continue;
                            }

                            //Obsolete- now wardrobeCollections apply their WardrobeSet to any slots
                            //if (wsl == "FullOutfit" && _allowWardrobeCollectionSlot == false)
                            //	continue;

                            WardrobeSlotRecipePopup thisPicker = null;
                            bool assignedPicker = false;
                            for (int wsi = 0; wsi < _wardrobeSet.Count; wsi++)
                            {
                                if (_wardrobeSet[wsi].slot == wsl)
                                {
                                    thisPicker     = new WardrobeSlotRecipePopup(_race.raceName, wsl, _wardrobeSet[wsi].recipe);
                                    assignedPicker = true;
                                    break;
                                }
                            }
                            if (!assignedPicker)                            //means there was nothing in the wardrobe set for it
                            {
                                //This may still be being assigned by a wardrobe collection though so show that
                                var wcOverrideName = "";
                                if (slotsAssignedByWCs.ContainsKey(wsl))
                                {
                                    wcOverrideName = slotsAssignedByWCs[wsl];
                                }
                                thisPicker = new WardrobeSlotRecipePopup(_race.raceName, wsl, "");
                            }
                            if (thisPicker.OnGUI())
                            {
                                changed = true;
                                if (thisPicker.RecipeName != "None" && thisPicker.RecipeName != "")
                                {
                                    bool contained = false;
                                    for (int i = 0; i < _wardrobeSet.Count; i++)
                                    {
                                        if (_wardrobeSet[i].slot == wsl)
                                        {
                                            _wardrobeSet[i].recipe = thisPicker.RecipeName;
                                            contained = true;
                                            break;
                                        }
                                    }
                                    if (!contained)
                                    {
                                        _wardrobeSet.Add(new WardrobeSettings(wsl, thisPicker.RecipeName));
                                    }
                                }
                                else
                                {
                                    for (int i = 0; i < _wardrobeSet.Count; i++)
                                    {
                                        if (_wardrobeSet[i].slot == wsl)
                                        {
                                            _wardrobeSet.RemoveAt(i);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        if (_allowWardrobeCollectionSlot)
                        {
                            EditorGUI.indentLevel--;
                        }
                        if (WardrobeSet.Count > 0)
                        {
                            EditorGUILayout.Space();
                            if (GUILayout.Button(new GUIContent("UpdateSharedColors", "Automatically adds any shared colors defined in the selected recipes to this recipes SharedColors")))
                            {
                                for (int i = 0; i < _wardrobeSet.Count; i++)
                                {
                                    changed = AddSharedColorsFromRecipe(_wardrobeSet[i].recipe, _recipe) == true ? true : changed;
                                }
                            }
                        }
                        GUIHelper.EndVerticalPadded(10);
                    }
                }
                return(changed);
            }
Exemplo n.º 20
0
            public override bool OnGUI(string targetName, ref bool _dnaDirty, ref bool _textureDirty, ref bool _meshDirty)
            {
                bool changed = false;

                if (!OpenSlots.ContainsKey("wardrobeSet"))
                {
                    OpenSlots.Add("wardrobeSet", true);
                }

                if (_sharedColorsEditor.OnGUI(_recipe))
                {
                    changed = true;
                }
                //if this is a backwards compatible DCS recipe (i.e. has SlotData AND a Wardrobe set) we need to show BOTH things
                //for this to really work youd need to be able to edit the WardrobeSet and have that modify the slotDataList
                //Hence the epic UpdateBackwardsCompatibleData method
                if (_recipe.slotDataList.Length > 0)
                {
                    EditorGUILayout.HelpBox("This is a 'Backwards Compatible' DynamicCharacterAvatar recipe. The slots and overlays in the 'BackwardsCompatibleData' section will update as you change the items in the WardrobeSet.", MessageType.Info);
                }
                if (DrawWardrobeSetUI())
                {
                    changed = true;
                    if (_recipe.slotDataList.Length > 0)
                    {
                        UpdateBackwardsCompatibleData();
                    }
                }
                if (_recipe.slotDataList.Length > 0)
                {
                    if (!OpenSlots.ContainsKey("backwardsCompatibleData"))
                    {
                        OpenSlots.Add("backwardsCompatibleData", false);
                    }
                    GUILayout.BeginHorizontal(EditorStyles.toolbarButton);
                    GUILayout.Space(10);
                    bool bcdfoldoutOpen = OpenSlots["backwardsCompatibleData"];
                    bcdfoldoutOpen = EditorGUILayout.Foldout(OpenSlots["backwardsCompatibleData"], "Backwards Compatible Data");
                    OpenSlots["backwardsCompatibleData"] = bcdfoldoutOpen;
                    GUILayout.EndHorizontal();
                    if (bcdfoldoutOpen)
                    {
                        EditorGUI.BeginDisabledGroup(true);
                        GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));
                        EditorGUILayout.HelpBox("If you are going to use the recipe with a DynamicCharacterAvatar, it is recommended that you that you edit the 'WardrobeSet' section above and/or the base/wardrobe recipes directly. Changes you make manually below will only affect old style UMAAvatars", MessageType.Info);
                        for (int i = 0; i < _slotEditors.Count; i++)
                        {
                            var editor = _slotEditors[i];

                            if (editor == null)
                            {
                                GUILayout.Label("Empty Slot");
                                continue;
                            }

                            changed |= editor.OnGUI(ref _dnaDirty, ref _textureDirty, ref _meshDirty);

                            if (editor.Delete)
                            {
                                _dnaDirty     = true;
                                _textureDirty = true;
                                _meshDirty    = true;

                                _slotEditors.RemoveAt(i);
                                _recipe.SetSlot(editor.idx, null);
                                i--;
                                changed = true;
                            }
                        }
                        GUIHelper.EndVerticalPadded(10);
                        EditorGUI.EndDisabledGroup();
                    }
                }
                return(changed);
            }
            public override bool OnGUI(string targetName, ref bool _dnaDirty, ref bool _textureDirty, ref bool _meshDirty)
            {
                var context = UMAContext.FindInstance();

                if (context == null)
                {
                    var _errorMessage = "Editing a recipe requires a loaded scene with a valid UMAContext.";
                    Debug.LogWarning(_errorMessage);
                    return(false);
                }
                bool changed = forceGUIUpdate;

                //Make a foldout for WardrobeSets - the UI for an individual WardrobeSet is added for each compatible race in the collection
                GUILayout.BeginHorizontal(EditorStyles.toolbarButton);
                GUILayout.Space(10);
                bool wsfoldoutOpen = OpenSlots["wardrobeSets"];

                wsfoldoutOpen             = EditorGUILayout.Foldout(OpenSlots["wardrobeSets"], "Wardrobe Sets");
                OpenSlots["wardrobeSets"] = wsfoldoutOpen;
                GUILayout.EndHorizontal();
                if (wsfoldoutOpen)
                {
                    GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));

                    EditorGUILayout.HelpBox("Wardrobe Sets are added for each 'Compatible Race' assigned above. 'SharedColors' in this section are derived from all the recipes assigned in the set and are will be applied to the Avatar when the wardrobe sets recipes are added.", MessageType.Info);
                    if (_compatibleRaces.Count > 0)
                    {
                        //dont show shared colors unless there are 'FullOutfits' to apply them to
                        if (_sharedColorsEditor.OnGUI(_recipe))
                        {
                            changed       = true;
                            _textureDirty = true;
                        }
                        for (int i = 0; i < _compatibleRaces.Count; i++)
                        {
                            var thisRace = context.raceLibrary.GetRace(_compatibleRaces[i]);
                            if (thisRace != null)
                            {
                                GUILayout.BeginHorizontal(EditorStyles.toolbarButton);
                                GUILayout.Space(10);
                                bool foldoutOpen = OpenSlots[_compatibleRaces[i]];
                                foldoutOpen = EditorGUILayout.Foldout(OpenSlots[_compatibleRaces[i]], " Wardrobe Set: " + _compatibleRaces[i]);
                                OpenSlots[_compatibleRaces[i]] = foldoutOpen;
                                GUILayout.EndHorizontal();
                                if (foldoutOpen)
                                {
                                    var thisSetEditor = new WardrobeSetEditor(thisRace, _wardrobeCollection[thisRace.raceName], _recipe, false);
                                    if (thisSetEditor.OnGUI())
                                    {
                                        _wardrobeCollection[thisRace.raceName] = thisSetEditor.WardrobeSet;
                                        changed = true;
                                    }
                                }
                            }
                            else
                            {
                                //Do the foldout thing but show as 'missing'
                                GUILayout.BeginHorizontal(EditorStyles.toolbarButton);
                                GUILayout.Space(10);
                                bool foldoutOpen = OpenSlots[_compatibleRaces[i]];
                                foldoutOpen = EditorGUILayout.Foldout(OpenSlots[_compatibleRaces[i]], _compatibleRaces[i] + " Wardrobe Set (Missing)");
                                OpenSlots[_compatibleRaces[i]] = foldoutOpen;
                                GUILayout.EndHorizontal();
                                if (foldoutOpen)
                                {
                                    GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));
                                    EditorGUILayout.HelpBox("_compatibleRaces[i] could not be located by the Dynamic Race Library", MessageType.Warning);
                                    GUIHelper.EndVerticalPadded(10);
                                }
                            }
                        }
                    }
                    else
                    {
                        EditorGUILayout.HelpBox("Drag in compatible races at the top of this recipe and WardrobeSets for those races will show here", MessageType.Info);
                    }
                    GUIHelper.EndVerticalPadded(10);
                }
                GUILayout.Space(10);
                //the Arbitrary Recipes section
                GUILayout.BeginHorizontal(EditorStyles.toolbarButton);
                GUILayout.Space(10);
                bool arbiOpen = OpenSlots["arbitraryRecipes"];

                arbiOpen = EditorGUILayout.Foldout(OpenSlots["arbitraryRecipes"], "Arbitrary Recipes");
                OpenSlots["arbitraryRecipes"] = arbiOpen;
                Rect dropArea = new Rect();

                GUILayout.EndHorizontal();
                if (arbiOpen)
                {
                    GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));
                    EditorGUILayout.HelpBox("Drop recipes in to this area to create a collection that is not a full outfit or connected to any given race, for example a 'Hair Styles' pack or 'Tattoos' pack.", MessageType.Info);
                    dropArea = GUILayoutUtility.GetRect(0.0f, 50.0f, GUILayout.ExpandWidth(true));
                    GUI.Box(dropArea, "Drag WardrobeRecipes here. " + recipesAddErrMsg);
                    if (_arbitraryRecipes.Count > 0)
                    {
                        for (int i = 0; i < _arbitraryRecipes.Count; i++)
                        {
                            GUILayout.Space(2f);
                            GUI.enabled = false;                             //we readonly to prevent typos
                            Rect crfRect    = GUILayoutUtility.GetRect(0.0f, EditorGUIUtility.singleLineHeight, GUILayout.ExpandWidth(true));
                            Rect crfDelRect = crfRect;
                            crfRect.width    = crfRect.width - 20f - 5f;
                            crfDelRect.width = 20f + 2f;
                            crfDelRect.x     = crfRect.width + 20f + 10f;
                            EditorGUI.TextField(crfRect, _arbitraryRecipes[i]);
                            GUI.enabled = true;
                            if (GUI.Button(crfDelRect, "X"))
                            {
                                _arbitraryRecipes.RemoveAt(i);
                                changed = true;
                            }
                        }
                    }
                    GUIHelper.EndVerticalPadded(10);
                    if (AddRecipesDropAreaGUI(ref recipesAddErrMsg, dropArea, _arbitraryRecipes))
                    {
                        changed = true;
                    }
                }
                return(changed);
            }
Exemplo n.º 22
0
 private void DrawCCUI(string ccRaceName, SerializedProperty baseRaceRecipe, SerializedProperty thisCCSettings)
 {
     GUIHelper.BeginVerticalPadded(5, new Color(0.75f, 0.875f, 1f));
     EditorGUILayout.LabelField("Equivalent Slots with " + ccRaceName, EditorStyles.centeredGreyMiniLabel);
     if (baseRaceRecipe.objectReferenceValue == null)
     {
         EditorGUILayout.HelpBox("Please set this Races 'Base Race Recipe' before trying to set equivalent Slots.", MessageType.Warning);
     }
     else
     {
         //we need to get the base raceRecipeSlots for this compatible race
         var ccRaceData = GetCompatibleRaceData(ccRaceName);
         if (ccRaceData != null)
         {
             if (ccRaceData.baseRaceRecipe == null)
             {
                 EditorGUILayout.HelpBox("Please set " + ccRaceData.raceName + " Races 'Base Race Recipe' before trying to set equivalent Slots.", MessageType.Warning);
             }
             else
             {
                 var ccSlotsList                = new List <SlotData>();
                 var ccSlotsNamesList           = new List <string>();
                 UMAData.UMARecipe ccBaseRecipe = ccRaceData.baseRaceRecipe.GetCachedRecipe(UMAContextBase.Instance);
                 SlotData[]        ccBaseSlots  = ccBaseRecipe.GetAllSlots();
                 foreach (SlotData slot in ccBaseSlots)
                 {
                     if (slot != null)
                     {
                         ccSlotsList.Add(slot);
                         ccSlotsNamesList.Add(slot.slotName);
                     }
                 }
                 //if that worked we can draw the UI for any set values and a button to add new ones
                 GUIHelper.BeginVerticalPadded(2, new Color(1f, 1f, 1f, 0.5f));
                 var headerRect             = GUILayoutUtility.GetRect(0.0f, (EditorGUIUtility.singleLineHeight * 2), GUILayout.ExpandWidth(true));
                 var slotLabelRect          = headerRect;
                 var gapRect                = headerRect;
                 var cSlotLabelRect         = headerRect;
                 var overlaysMatchLabelRect = headerRect;
                 var deleteRect             = headerRect;
                 slotLabelRect.width          = (headerRect.width - 50f - 22f - 22f) / 2;
                 gapRect.xMin                 = slotLabelRect.xMax;
                 gapRect.width                = 22f;
                 cSlotLabelRect.xMin          = gapRect.xMax;
                 cSlotLabelRect.width         = slotLabelRect.width;
                 overlaysMatchLabelRect.xMin  = cSlotLabelRect.xMax;
                 overlaysMatchLabelRect.width = 50f;
                 deleteRect.xMin              = overlaysMatchLabelRect.xMax;
                 deleteRect.width             = 22f;
                 //move this up
                 var tableHeaderStyle = EditorStyles.wordWrappedMiniLabel;
                 tableHeaderStyle.alignment = TextAnchor.MiddleCenter;
                 //we need a gui style for this that wraps the text and vertically centers it in the space
                 EditorGUI.LabelField(slotLabelRect, "This Races Slot", tableHeaderStyle);
                 EditorGUI.LabelField(gapRect, "", tableHeaderStyle);
                 EditorGUI.LabelField(cSlotLabelRect, "Compatible Races Slot", tableHeaderStyle);
                 EditorGUI.LabelField(overlaysMatchLabelRect, "Overlays Match", tableHeaderStyle);
                 GUIHelper.EndVerticalPadded(2);
                 GUIHelper.BeginVerticalPadded(2, new Color(0.75f, 0.875f, 1f));
                 if (thisCCSettings.arraySize > 0)
                 {
                     for (int ccsd = 0; ccsd < thisCCSettings.arraySize; ccsd++)
                     {
                         if (DrawCCUISetting(ccsd, thisCCSettings, ccSlotsNamesList))
                         {
                             serializedObject.ApplyModifiedProperties();
                         }
                     }
                 }
                 else
                 {
                     EditorGUILayout.LabelField("No equivalent slots defined", EditorStyles.miniLabel);
                 }
                 GUIHelper.EndVerticalPadded(2);
                 var addButtonRect = GUILayoutUtility.GetRect(0.0f, EditorGUIUtility.singleLineHeight, GUILayout.ExpandWidth(true));
                 addButtonRect.xMin  = addButtonRect.xMax - 70f;
                 addButtonRect.width = 70f;
                 if (GUI.Button(addButtonRect, "Add"))
                 {
                     thisCCSettings.InsertArrayElementAtIndex(thisCCSettings.arraySize);
                     serializedObject.ApplyModifiedProperties();
                 }
             }
         }
         else
         {
             EditorGUILayout.HelpBox("The cross compatible race " + ccRaceName + " could not be found!", MessageType.Warning);
         }
     }
     GUIHelper.EndVerticalPadded(5);
 }
Exemplo n.º 23
0
            public bool OnGUI()
            {
                bool changed = false;

                if (_race != null)
                {
                    if (_race.wardrobeSlots.Count > 0)
                    {
                        var context = UMAContext.FindInstance();
                        if (context == null)
                        {
                            var _errorMessage = "Editing a recipe requires a loaded scene with a valid UMAContext.";
                            Debug.LogWarning(_errorMessage);
                        }

                        if (_wardrobeSet == null || context == null)
                        {
                            return(false);
                        }
                        GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));
                        if (_allowWardrobeCollectionSlot)
                        {
                            var wcRecipesForRace = context.dynamicCharacterSystem.GetRecipesForRaceSlot(_race.raceName, "WardrobeCollection");
                            var wcGroupDict      = new Dictionary <string, List <string> >();
                            //for 'Standard Assets' we need to do some kind of get Types thing I think because we then need to use reflection to get the wardrobeSlot field
                            //how can we get what we want here when WardrobeCollections dont exist in Standard Assets (if 'StandardAssets' has been moved there)
                            for (int i = 0; i < wcRecipesForRace.Count; i++)
                            {
                                Type wcType = wcRecipesForRace[i].GetType();
                                if (wcType.ToString().Replace(wcType.Namespace + ".", "") == "UMAWardrobeCollection")
                                {
                                    FieldInfo wcRecipeSlotField = wcType.GetField("wardrobeSlot", BindingFlags.Public | BindingFlags.Instance);
                                    var       wcRecipeSlot      = (string)wcRecipeSlotField.GetValue(wcRecipesForRace[i]);
                                    if (!wcGroupDict.ContainsKey(wcRecipeSlot))
                                    {
                                        wcGroupDict.Add(wcRecipeSlot, new List <string>());
                                    }
                                    wcGroupDict[wcRecipeSlot].Add(wcRecipesForRace[i].name);
                                }
                            }
                            if (wcGroupDict.Count > 0)
                            {
                                EditorGUILayout.LabelField("WardrobeCollections");
                                EditorGUI.indentLevel++;
                                foreach (KeyValuePair <string, List <string> > kp in wcGroupDict)
                                {
                                    var thisPopupVals = new List <string>();
                                    thisPopupVals.Add("None");
                                    thisPopupVals.AddRange(kp.Value);
                                    var selected   = 0;
                                    var prevRecipe = "";
                                    //if one of the recipes in the wardrobe set is one of these then its selected
                                    for (int pvi = 0; pvi < thisPopupVals.Count; pvi++)
                                    {
                                        for (int wsi = 0; wsi < _wardrobeSet.Count; wsi++)
                                        {
                                            if (thisPopupVals[pvi] == _wardrobeSet[wsi].recipe)
                                            {
                                                prevRecipe = _wardrobeSet[wsi].recipe;
                                                selected   = pvi;
                                                break;
                                            }
                                        }
                                    }
                                    EditorGUI.BeginChangeCheck();
                                    var newSelected = EditorGUILayout.Popup(kp.Key, selected, thisPopupVals.ToArray());
                                    if (EditorGUI.EndChangeCheck())
                                    {
                                        for (int wsi = 0; wsi < _wardrobeSet.Count; wsi++)
                                        {
                                            if (_wardrobeSet[wsi].recipe == prevRecipe)
                                            {
                                                //we need to remove the wardrobeSettings that has prevRecipe as its value from _wardrobeSettings
                                                if (newSelected == 0)
                                                {
                                                    _wardrobeSet.RemoveAt(wsi);
                                                }
                                                else
                                                {
                                                    //we need to make wardrobeSettings that has prevRecipe have the new value
                                                    _wardrobeSet[wsi].recipe = thisPopupVals[newSelected];
                                                }
                                            }
                                        }
                                        changed = true;
                                    }
                                }
                                EditorGUI.indentLevel--;
                                EditorGUILayout.Space();
                                EditorGUILayout.LabelField("WardrobeSlots");
                                EditorGUI.indentLevel++;
                            }
                        }
                        foreach (string wsl in _race.wardrobeSlots)
                        {
                            if (wsl == "None")
                            {
                                continue;
                            }

                            if (wsl == "FullOutfit" && _allowWardrobeCollectionSlot == false)
                            {
                                continue;
                            }

                            WardrobeSlotRecipePopup thisPicker = null;
                            bool assignedPicker = false;
                            for (int wsi = 0; wsi < _wardrobeSet.Count; wsi++)
                            {
                                if (_wardrobeSet[wsi].slot == wsl)
                                {
                                    thisPicker     = new WardrobeSlotRecipePopup(_race.raceName, wsl, _wardrobeSet[wsi].recipe);
                                    assignedPicker = true;
                                    break;
                                }
                            }
                            if (!assignedPicker)                            //means there was nothing in the wardrobe set for it
                            {
                                thisPicker = new WardrobeSlotRecipePopup(_race.raceName, wsl, "");
                            }
                            if (thisPicker.OnGUI())
                            {
                                changed = true;
                                if (thisPicker.RecipeName != "None" && thisPicker.RecipeName != "")
                                {
                                    bool contained = false;
                                    for (int i = 0; i < _wardrobeSet.Count; i++)
                                    {
                                        if (_wardrobeSet[i].slot == wsl)
                                        {
                                            _wardrobeSet[i].recipe = thisPicker.RecipeName;
                                            contained = true;
                                            break;
                                        }
                                    }
                                    if (!contained)
                                    {
                                        _wardrobeSet.Add(new WardrobeSettings(wsl, thisPicker.RecipeName));
                                    }
                                }
                                else
                                {
                                    for (int i = 0; i < _wardrobeSet.Count; i++)
                                    {
                                        if (_wardrobeSet[i].slot == wsl)
                                        {
                                            _wardrobeSet.RemoveAt(i);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        if (_allowWardrobeCollectionSlot)
                        {
                            EditorGUI.indentLevel--;
                        }
                        if (WardrobeSet.Count > 0)
                        {
                            EditorGUILayout.Space();
                            if (GUILayout.Button(new GUIContent("UpdateSharedColors", "Automatically adds any shared colors defined in the selected recipes to this recipes SharedColors")))
                            {
                                for (int i = 0; i < _wardrobeSet.Count; i++)
                                {
                                    changed = AddSharedColorsFromRecipe(_wardrobeSet[i].recipe, _recipe) == true ? true : changed;
                                }
                            }
                        }
                        GUIHelper.EndVerticalPadded(10);
                    }
                }
                return(changed);
            }
Exemplo n.º 24
0
 public static void EndVerticalPadded()
 {
     GUIHelper.EndVerticalPadded(10);
 }
Exemplo n.º 25
0
        public void RandomAvatarGUI(RandomAvatar ra)
        {
            bool del = false;

            GUIHelper.FoldoutBar(ref ra.GuiFoldout, ra.RaceName, out del);
            if (ra.GuiFoldout)
            {
                GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.875f, 1f));
                if (del)
                {
                    ra.Delete = true;
                }

                ra.Chance = EditorGUILayout.IntSlider("Weighted Chance", ra.Chance, 1, 100);

                ra.ColorsFoldout = GUIHelper.FoldoutBar(ra.ColorsFoldout, "Colors");
                if (ra.ColorsFoldout)
                {
                    GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.75f, 0.75f));
                    if (ra.SharedColors != null && ra.SharedColors.Count > 0)
                    {
                        foreach (RandomColors rc in ra.SharedColors)
                        {
                            RandomColorsGUI(ra, rc);
                        }
                    }
                    else
                    {
                        EditorGUILayout.LabelField("No shared colors found on base race");
                    }
                    GUIHelper.EndVerticalPadded(10);
                }

                ra.DnaFoldout = GUIHelper.FoldoutBar(ra.DnaFoldout, "DNA");
                if (ra.DnaFoldout)
                {
                    GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.75f, 0.75f));
                    // (popup with DNA names) and "Add" button.
                    EditorGUILayout.BeginHorizontal();
                    ra.SelectedDNA = EditorGUILayout.Popup("DNA", ra.SelectedDNA, ra.PossibleDNA);
                    bool pressed = GUILayout.Button("Add DNA", EditorStyles.miniButton);                    // GUIStyles.Popup?
                    EditorGUILayout.EndHorizontal();
                    if (pressed)
                    {
                        ra.DNAAdd = ra.PossibleDNA[ra.SelectedDNA];
                    }
                    if (ra.RandomDna.Count == 0)
                    {
                        EditorGUILayout.LabelField("No Random DNA has been added");
                    }
                    else
                    {
                        foreach (RandomDNA rd in ra.RandomDna)
                        {
                            EditorGUILayout.BeginHorizontal();
                            EditorGUILayout.LabelField(rd.DnaName, EditorStyles.miniLabel, GUILayout.Width(100));
                            float lastMin = rd.MinValue;
                            float lastMax = rd.MaxValue;
                            EditorGUILayout.MinMaxSlider(ref rd.MinValue, ref rd.MaxValue, 0.0f, 1.0f);
                            if (rd.MinValue != lastMin || rd.MaxValue != lastMax)
                            {
                                ra.DnaChanged = true;
                            }
                            rd.Delete = GUILayout.Button("\u0078", EditorStyles.miniButton, GUILayout.ExpandWidth(false));
                            string vals = rd.MinValue.ToString("N3") + " - " + rd.MaxValue.ToString("N3");
                            EditorGUILayout.LabelField(vals, EditorStyles.miniTextField, GUILayout.Width(80));
                            EditorGUILayout.EndHorizontal();
                        }
                    }
                    GUIHelper.EndVerticalPadded(10);
                }
                ra.WardrobeFoldout = GUIHelper.FoldoutBar(ra.WardrobeFoldout, "Wardrobe");
                if (ra.WardrobeFoldout)
                {
                    // add a null slot for a
                    GUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Select Wardrobe Slot", GUILayout.ExpandWidth(false));
                    ra.currentWardrobeSlot = EditorGUILayout.Popup(ra.currentWardrobeSlot, ra.raceData.wardrobeSlots.ToArray(), GUILayout.ExpandWidth(true));
                    if (GUILayout.Button("Add Null", GUILayout.ExpandWidth(false)))
                    {
                        ra.RandomWardrobeSlots.Add(new RandomWardrobeSlot(null, ra.raceData.wardrobeSlots[ra.currentWardrobeSlot]));
                        ra.RandomWardrobeSlots.Sort((x, y) => x.SortName.CompareTo(y.SortName));
                    }
                    GUILayout.EndHorizontal();
                    GUIHelper.BeginVerticalPadded(10, new Color(0.75f, 0.75f, 0.75f));

                    string lastSlot = "";

                    foreach (RandomWardrobeSlot rws in ra.RandomWardrobeSlots)
                    {
                        if (rws.SlotName != lastSlot)
                        {
                            GUILayout.Label("[" + rws.SlotName + "]");
                            lastSlot = rws.SlotName;
                        }
                        RandomWardrobeSlotGUI(ra, rws);
                    }
                    GUIHelper.EndVerticalPadded(10);
                }
                GUIHelper.EndVerticalPadded(10);
            }
        }
        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            Init();

            EditorGUILayout.LabelField("DNAEvaluationGraph Preset Library", EditorStyles.boldLabel);

            EditorGUILayout.HelpBox("A DNAEvaluationGraph Preset Library contains presets for graphs that will be available in a DNAEvaluationGraph field's dropdown list of available graphs. This asset does not need to be included in your build", MessageType.Info);

            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            GUILayout.Space(10f);
            extraInfoIsExpanded = EditorGUILayout.Foldout(extraInfoIsExpanded, "What is a DNAEvaluationGraph?", true);
            EditorGUILayout.EndHorizontal();
            if (extraInfoIsExpanded)
            {
                DrawFullHelp();
            }
            EditorGUILayout.Space();

            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            GUILayout.Space(10f);
            defaultPresetsIsExpanded = EditorGUILayout.Foldout(defaultPresetsIsExpanded, "Default Presets", true);
            EditorGUILayout.EndHorizontal();
            if (defaultPresetsIsExpanded)
            {
                GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));
                EditorGUILayout.HelpBox("These are the standard evaluation graphs that ship with UMA. You can add your own in the custom section below.", MessageType.Info);
                for (int i = 0; i < DNAEvaluationGraphPresetLibrary.DefaultGraphPresets.Count; i++)
                {
                    var rect = EditorGUILayout.GetControlRect(false, entryHeight + (padding * 2f));
                    rect.x     += padding;
                    rect.width -= padding * 2f;
                    Rect swatchRect = new Rect(rect.xMin, rect.yMin + padding, rect.width, rect.height - (padding * 2f));
                    dnaEvalDrawer.DrawSwatch(swatchRect, DNAEvaluationGraphPresetLibrary.DefaultGraphPresets[i], DNAEvaluationGraphPresetLibrary.DefaultGraphTooltips[i], false, false, (dnaGraph) =>
                    {
                        newGraph            = new AnimationCurve(DNAEvaluationGraphPresetLibrary.DefaultGraphPresets[i].GraphKeys);
                        addPresetIsExpanded = true;
                    }
                                             );
                }
                GUIHelper.EndVerticalPadded(3);
            }

            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            GUILayout.Space(10f);
            customPresetsIsExpanded = EditorGUILayout.Foldout(customPresetsIsExpanded, "Custom Presets", true);
            EditorGUILayout.EndHorizontal();
            if (customPresetsIsExpanded)
            {
                GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));
                EditorGUILayout.HelpBox("Add your own graph presets to this section using the tools below.", MessageType.Info);
                List <int> custToDel = new List <int>();
                for (int i = 0; i < _customPresets.Count; i++)
                {
                    var rect = EditorGUILayout.GetControlRect(false, entryHeight + (padding * 2f));
                    rect.x     += padding;
                    rect.width -= padding * 2f;
                    Rect swatchRect = new Rect(rect.xMin, rect.yMin + padding, rect.width - (swatchButWidth + padding), rect.height - (padding * 2f));
                    dnaEvalDrawer.DrawSwatch(swatchRect, _customPresets[i], _customPresetTooltips[i] + " [Click To Edit]", false, false, (dnaGraph) =>
                    {
                        newGraphName        = _customPresets[i].name;
                        newGraphTooltip     = _customPresetTooltips[i];
                        newGraph            = new AnimationCurve(_customPresets[i].GraphKeys);
                        addPresetIsExpanded = true;
                        _updatatingPreset   = _customPresets[i];
                    }
                                             );
                    //editCallback

                    var delRect = new Rect(swatchRect.xMax, swatchRect.yMin + padding, swatchButWidth, swatchButWidth);
                    if (GUI.Button(delRect, new GUIContent("X", "Delete " + _customPresets[i].name)))
                    {
                        custToDel.Add(i);
                    }
                }
                if (custToDel.Count > 0)
                {
                    for (int i = 0; i < custToDel.Count; i++)
                    {
                        DNAEvaluationGraphPresetLibrary.DeleteCustomPreset(_customPresets[custToDel[i]]);
                    }
                    initialized = false;
                    EditorUtility.SetDirty(_target);
                    AssetDatabase.SaveAssets();
                }
                DrawDNAEvaluationGraphAddBox();
                GUIHelper.EndVerticalPadded(3);
            }
            else
            {
                ResetMessages();
            }

            serializedObject.ApplyModifiedProperties();
        }
        private void DrawDNAEvaluationGraphAddBox()
        {
            GUIHelper.BeginVerticalPadded(3, new Color(0.75f, 0.875f, 1f, 0.3f));

            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            GUILayout.Space(10f);
            var label = _updatatingPreset ? "Update '" + newGraphName + "' Preset" : "Add a new Preset";

            addPresetIsExpanded = EditorGUILayout.Foldout(addPresetIsExpanded, label, true);
            EditorGUILayout.EndHorizontal();
            if (addPresetIsExpanded)
            {
                EditorGUILayout.Space();

                EditorGUI.BeginChangeCheck();

                if (_updatatingPreset != null)
                {
                    //warn the user that updating a preset wont update any fields that created their values from it
                    EditorGUILayout.HelpBox("Note: Updating this preset will not update the graphs in any existing DNAEvaluationGraph fields", MessageType.Warning);
                }

                newGraphName = EditorGUILayout.TextField("Preset Name", newGraphName);

                var descRect = EditorGUILayout.GetControlRect(false, 45);
                newGraphTooltip = EditorGUI.TextArea(descRect, newGraphTooltip, wordwrappedTextArea);
                //I want the placeholder text in here
                if (newGraphTooltip == "")
                {
                    EditorGUI.BeginDisabledGroup(true);
                    EditorGUI.TextArea(descRect, "Preset Tooltip", wordwrappedTextArea);
                    EditorGUI.EndDisabledGroup();
                }

                var graphRect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * 2f);

                if (EditorGUI.EndChangeCheck())
                {
                    ResetMessages();
                }

                newGraph = EditorGUI.CurveField(graphRect, "Preset Graph", newGraph);

                EditorGUILayout.Space();
                var btnRect = EditorGUILayout.GetControlRect();
                btnRect.width = btnRect.width / 2;
                var clearBtnRect = new Rect(btnRect.xMax, btnRect.yMin, btnRect.width, btnRect.height);
                var addBtnLabel  = "Add It!";
                if (_updatatingPreset != null)
                {
                    addBtnLabel = "Update '" + newGraphName + "'";
                }
                if (GUI.Button(btnRect, addBtnLabel))
                {
                    if (_target.AddNewPreset(newGraphName, newGraphTooltip, newGraph, ref nameError, ref graphError, _updatatingPreset))
                    {
                        serializedObject.Update();
                        serializedObject.ApplyModifiedProperties();
                        addSuccess = _updatatingPreset ? "Updated Graph " + newGraphName + " Successfully!" : "New Custom Graph " + newGraphName + " added Successfully!";
                        ResetNewGraphFields();
                        initialized = false;                        //force the cached custom list to Update
                        EditorUtility.SetDirty(_target);
                        AssetDatabase.SaveAssets();
                        Repaint();
                    }
                }
                if (GUI.Button(clearBtnRect, "Reset Fields"))
                {
                    ResetNewGraphFields();
                }
                if (graphError != "" || nameError != "")
                {
                    EditorGUILayout.HelpBox("There were the following issues when trying to add your graph:", MessageType.None);
                    if (nameError != "")
                    {
                        EditorGUILayout.HelpBox(nameError, MessageType.Error);
                    }
                    if (graphError != "")
                    {
                        EditorGUILayout.HelpBox(graphError, MessageType.Error);
                    }
                }
                else if (addSuccess != "")
                {
                    EditorGUILayout.HelpBox(addSuccess, MessageType.Info);
                }
            }
            else
            {
                ResetMessages();
            }

            GUIHelper.EndVerticalPadded(3);
        }