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); } }
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); } }
//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); } }
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; } }
public bool AddExtraStuff() { SerializedProperty baseRaceRecipe = serializedObject.FindProperty("baseRaceRecipe"); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(baseRaceRecipe, true); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } if (wardrobeSlotList == null) { InitWardrobeSlotList(); } EditorGUILayout.Space(); EditorGUI.BeginChangeCheck(); wardrobeSlotList.DoLayoutList(); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); if (!race.ValidateWardrobeSlots()) { EditorUtility.SetDirty(race); } } //new CrossCompatibilitySettings //To push any old settings in RaceData.backwardsCompatibleWith into the new crossCompatibilitySettings we have to call GetCrossCompatibleRaces() directly on the target #pragma warning disable 618 if (race.backwardsCompatibleWith.Count > 0) { var cc = race.GetCrossCompatibleRaces(); if (cc.Count > 0) { serializedObject.Update(); } } #pragma warning restore 618 SerializedProperty _crossCompatibilitySettings = serializedObject.FindProperty("_crossCompatibilitySettings"); SerializedProperty _crossCompatibilitySettingsData = _crossCompatibilitySettings.FindPropertyRelative("settingsData"); //draw the new version of the crossCompatibility list that allows users to define what slots in this races base recipe equate to in the backwards compatible races base recipe _crossCompatibilitySettings.isExpanded = EditorGUILayout.Foldout(_crossCompatibilitySettings.isExpanded, "Cross Compatibility Settings"); if (_crossCompatibilitySettings.isExpanded) { //draw an info foldout EditorGUI.indentLevel++; _crossCompatibilitySettingsData.isExpanded = EditorGUILayout.Foldout(_crossCompatibilitySettingsData.isExpanded, "Help"); if (_crossCompatibilitySettingsData.isExpanded) { var helpText = "CrossCompatibilitySettings allows this race to wear wardrobe slots from another race, if this race has a wardrobe slot that the recipe is set to."; helpText += " You can further configure the compatibility settings for each compatible race to define 'equivalent' slotdatas in the races' base recipes."; helpText += " For example you could define that this races 'highpolyMaleChest' slotdata in its base recipe is equivalent to HumanMales 'MaleChest' slot data in its base recipe."; helpText += " This would mean that any recipes which hid or applied an overlay to 'MaleChest' would hide or apply an overlay to 'highPolyMaleChest' on this race."; helpText += " If 'Overlays Match' is unchecked then overlays in a recipe wont be applied."; EditorGUILayout.HelpBox(helpText, MessageType.Info); } EditorGUI.indentLevel--; if (baseRaceRecipe.objectReferenceValue != null) { Rect dropArea = new Rect(); dropArea = GUILayoutUtility.GetRect(0.0f, 50.0f, GUILayout.ExpandWidth(true)); GUI.Box(dropArea, "Drag cross compatible Races here. Click to pick."); CompatibleRacesDropArea(dropArea, _crossCompatibilitySettingsData); EditorGUILayout.Space(); //update the foldouts list if the dropbox changes anything if (_BCFoldouts.Length != _crossCompatibilitySettingsData.arraySize) { Array.Resize <bool>(ref _BCFoldouts, _crossCompatibilitySettingsData.arraySize); } //we need an uptodate list of the slots in THIS races base recipe baseSlotsList.Clear(); baseSlotsNamesList.Clear(); //editing a race will require a context too because we need to get the base recipes and their slots if (UMAContextBase.Instance == null) { EditorUMAContextBase = UMAContextBase.CreateEditorContext(); } UMAData.UMARecipe thisBaseRecipe = (baseRaceRecipe.objectReferenceValue as UMARecipeBase).GetCachedRecipe(UMAContextBase.Instance); SlotData[] thisBaseSlots = thisBaseRecipe.GetAllSlots(); foreach (SlotData slot in thisBaseSlots) { if (slot != null) { baseSlotsList.Add(slot); baseSlotsNamesList.Add(slot.slotName); } } List <int> crossCompatibleSettingsToDelete = new List <int>(); //draw a foldout area for each compatible race that will show an entry for each slot in this races base recipe //with a picker to choose the slot from the compatible race's base recipe that it equates to for (int i = 0; i < _crossCompatibilitySettingsData.arraySize; i++) { bool del = false; var thisCCSettings = _crossCompatibilitySettingsData.GetArrayElementAtIndex(i).FindPropertyRelative("ccSettings"); var ccRaceName = _crossCompatibilitySettingsData.GetArrayElementAtIndex(i).FindPropertyRelative("ccRace").stringValue; //this could be missing- we should show that var label = ccRaceName; if (GetCompatibleRaceData(ccRaceName) == null) { label += " (missing)"; } GUIHelper.FoldoutBar(ref _BCFoldouts[i], label, out del); if (del) { crossCompatibleSettingsToDelete.Add(i); } if (_BCFoldouts[i]) { DrawCCUI(ccRaceName, baseRaceRecipe, thisCCSettings); } } if (crossCompatibleSettingsToDelete.Count > 0) { foreach (int del in crossCompatibleSettingsToDelete) { _crossCompatibilitySettingsData.DeleteArrayElementAtIndex(del); serializedObject.ApplyModifiedProperties(); } } } else { EditorGUILayout.HelpBox("Please define this races baseRaceRecipe before trying to define its cross compatibility settings.", MessageType.Info); } } EditorGUILayout.Space(); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(serializedObject.FindProperty("raceThumbnails"), true); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } return(false); }
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); } }