//private List<CheckedMaterial> Materials = new List<CheckedMaterial>(); void Refresh() { Context = UMAContextBase.Instance; if (Context == null) { EditorUtility.DisplayDialog("Error", "There is no UMA Context in the current scene!", "OK"); return; } Slots.Clear(); if (Race == null) { EditorUtility.DisplayDialog("Error", "No RaceData selected!", "OK"); return; } Recipe = new UMAData.UMARecipe(); Race.baseRaceRecipe.Load(Recipe, Context); if (Recipe == null) { return; } foreach (SlotData s in Recipe.slotDataList) { if (s == null) { continue; } Slots.Add(new CheckedSlot(s, true)); } }
protected void SaveRecipe(UMAData umaData, UMAContextBase context) { string assetPath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(saveFolderPath, umaData.umaRecipe.raceData.raceName + ".asset")); var asset = ScriptableObject.CreateInstance <UMATextRecipe>(); asset.Save(umaData.umaRecipe, context); AssetDatabase.CreateAsset(asset, assetPath); AssetDatabase.SaveAssets(); }
/// <summary> /// Fills in a UMA recipe with random partial fragments from the sections. /// </summary> /// <param name="umaRecipe">UMA recipe.</param> /// <param name="context">Context.</param> public void FillUMARecipe(UMAData.UMARecipe umaRecipe, UMAContextBase context) { if (raceData == null) { Debug.LogWarning("Race Data must be set!"); return; } umaRecipe.SetRace(raceData); int sectionCount = (recipeSections == null) ? 0 : recipeSections.Length; for (int i = 0; i < sectionCount; i++) { RecipeSection section = recipeSections[i]; if ((section.recipes == null) || (section.recipes.Length == 0)) { continue; } switch (section.selectionRule) { case SelectionType.IncludeNone: break; case SelectionType.IncludeAll: for (int j = 0; j < section.recipes.Length; j++) { IncludeRecipe(section.recipes[j], umaRecipe, context, false); } break; case SelectionType.IncludeSome: float chance = 1f / (float)(section.recipes.Length + 1); for (int j = 0; j < section.recipes.Length; j++) { if (Random.value < chance) { IncludeRecipe(section.recipes[j], umaRecipe, context, false); } } break; case SelectionType.IncludeOne: default: int index = Random.Range(0, section.recipes.Length); IncludeRecipe(section.recipes[index], umaRecipe, context, false); break; } } for (int i = 0; i < additionalRecipes.Length; i++) { IncludeRecipe(additionalRecipes[i], umaRecipe, context, true); } }
//Override Load from PackedRecipeBase /// <summary> /// NOTE: Use GetUniversalPackRecipe to get a recipe that includes a wardrobeSet. Load this Recipe's recipeString into the specified UMAData.UMARecipe. /// </summary> public override void Load(UMA.UMAData.UMARecipe umaRecipe, UMAContextBase context) { if ((recipeString != null) && (recipeString.Length > 0)) { var packedRecipe = PackedLoadDCSInternal(context); if (packedRecipe != null) { UnpackRecipe(umaRecipe, packedRecipe, context); } } }
void OnEnable() { RendererElements = serializedObject.FindProperty("RendererElements"); showHelp = serializedObject.FindProperty("showHelp"); context = UMAContextBase.Instance; DCARendererManager manager = target as DCARendererManager; avatar = manager.GetComponent<DynamicCharacterAvatar>(); UpdateOptions(); }
private void InitializeAnimator() { if (umaObject == null) { return; } UMAContextBase uc = UMAContextBase.Instance; if (uc == null) { return; } UMAGeneratorBase ugb = uc.gameObject.GetComponentInChildren <UMAGeneratorBase>(); _animator = umaObject.gameObject.GetComponent <Animator> (); if (_animator == null) { _animator = umaObject.gameObject.AddComponent <Animator> (); } var umaTransform = umaObject.transform; var oldParent = umaTransform.parent; var originalRot = umaTransform.localRotation; var originalPos = umaTransform.localPosition; umaTransform.SetParent(null, false); umaTransform.localRotation = Quaternion.identity; umaTransform.localPosition = Vector3.zero; _umaData.KeepAvatar = false; UMAGeneratorBase.SetAvatar(_umaData, _animator); if (ugb != null) { ugb.UpdateAvatar(_umaData); } umaTransform.SetParent(oldParent, false); umaTransform.localRotation = originalRot; umaTransform.localPosition = originalPos; //if (saveAvatar) // AssetDatabase.CreateAsset(_animator.avatar, "Assets/CreatedAvatar.asset"); }
void OnEnable() { UMAContextBase context = UMAContextBase.Instance; RaceData[] races = context.GetAllRaces(); raceToChangeTo = serializedObject.FindProperty("raceToChangeTo"); raceOptions = new string[races.Length]; for (int i = 0; i < races.Length; i++) { raceOptions[i] = races[i].raceName; if (raceToChangeTo.stringValue == raceOptions[i]) { selectedIndex = i; } } }
public override void Init() { if (initialized || isInitializing) { return; } if (context == null) { context = UMAContextBase.Instance; } isInitializing = true; Recipes.Clear(); var possibleRaces = context.GetAllRaces(); for (int i = 0; i < possibleRaces.Length; i++) { //we need to check that this is not null- the user may not have downloaded it yet if (possibleRaces[i] == null) { continue; } if (possibleRaces[i].raceName == "RaceDataPlaceholder") { continue; } if (Recipes.ContainsKey(possibleRaces[i].raceName)) { if (Debug.isDebugBuild) { Debug.LogWarning("Warning: multiple races found for key:" + possibleRaces[i].raceName); } } else { Recipes.Add(possibleRaces[i].raceName, new Dictionary <string, List <UMATextRecipe> >()); } } GatherCharacterRecipes(); GatherRecipeFiles(); initialized = true; isInitializing = false; }
public void SetRaceLists() { UMAContextBase ubc = UMAContext.Instance; if (ubc != null) { RaceData[] raceDataArray = ubc.GetAllRaces(); foundRaces.Clear(); foundRaceNames.Clear(); foundRaces.Add(null); foundRaceNames.Add("None Set"); foreach (RaceData race in raceDataArray) { if (race != null && race.raceName != "RaceDataPlaceholder") { foundRaces.Add(race); foundRaceNames.Add(race.raceName); } } } }
//Override Load from PackedRecipeBase /// <summary> /// NOTE: Use GetUniversalPackRecipe to get a recipe that includes a wardrobeSet. Load this Recipe's recipeString into the specified UMAData.UMARecipe. /// </summary> public override void Load(UMA.UMAData.UMARecipe umaRecipe, UMAContextBase context) { if ((recipeString != null) && (recipeString.Length > 0)) { if (RecipeHasWardrobeSet(recipeString)) { activeWardrobeSet = GetRecipesWardrobeSet(recipeString); } else { if (Debug.isDebugBuild) { Debug.LogWarning("[UMADynamicCharacterAvatar] recipe did not have wardrobe set"); } } var packedRecipe = PackedLoadDCSInternal(context); if (packedRecipe != null) { UnpackRecipe(umaRecipe, packedRecipe, context); } } }
void Init() { if (initialized || updating) { return; } if (context == null) { context = UMAContextBase.FindInstance(); } updating = true; collectionIndex.Clear(); if (Application.isPlaying) { StartCoroutine(StartGatherCoroutine()); } initialized = true; updating = false; }
void Awake() { if (space <= 0) { space = 1; } if (UMAContextBase == null) { UMAContextBase = UMAContext.Instance; } if (generator == null) { GameObject go = GameObject.Find("UMAGenerator"); if (go != null) { generator = go.GetComponent <UMAGenerator>(); } else { generator = UMAContextBase.GetComponent <UMAGenerator>(); } } }
/// <summary> /// Gets a DCSUnversalPackRecipeModel that has the wardrobeSet set to be the set in this collection for the given race of the sent avatar /// Or if this recipe is cross compatible returns the wardrobe set for the first matched cross compatible race /// </summary> public DCSUniversalPackRecipe GetUniversalPackRecipe(DynamicCharacterAvatar dca, UMAContextBase context) { var thisPackRecipe = PackedLoadDCSInternal(context); RaceData race = dca.activeRace.racedata; if (dca.activeRace.racedata == null) { race = dca.activeRace.data; } var setToUse = GetRacesWardrobeSet(race); thisPackRecipe.wardrobeSet = setToUse; thisPackRecipe.race = dca.activeRace.name; return(thisPackRecipe); }
private void IncludeRecipe(UMARecipeBase recipe, UMAData.UMARecipe umaRecipe, UMAContextBase context, bool dontSerialize) { UMAData.UMARecipe cachedRecipe = recipe.GetCachedRecipe(context); umaRecipe.Merge(cachedRecipe, dontSerialize); }
#pragma warning restore 0414 // Use this for initialization void Start() { avatar = GetComponent <DynamicCharacterAvatar>(); avatar.CharacterBegun.AddListener(CharacterBegun); context = UMAContextBase.Instance; }
public static void Apply(UMA.UMAData umaData, CrowdRaceData race, Color skinColor, Color HairColor, Color Shine, HashSet <string> Keywords, UMAContextBase context) { var slotParts = new HashSet <string>(); umaData.umaRecipe.slotDataList = new SlotData[race.slotElements.Length]; for (int i = 0; i < race.slotElements.Length; i++) { var currentElement = race.slotElements[i]; if (!string.IsNullOrEmpty(currentElement.requirement) && !slotParts.Contains(currentElement.requirement)) { continue; } if (!string.IsNullOrEmpty(currentElement.condition)) { if (currentElement.condition.StartsWith("!")) { if (Keywords.Contains(currentElement.condition.Substring(1))) { continue; } } else { if (!Keywords.Contains(currentElement.condition)) { continue; } } } if (currentElement.possibleSlots.Length == 0) { continue; } int randomResult = Random.Range(0, currentElement.possibleSlots.Length); var slot = currentElement.possibleSlots[randomResult]; if (string.IsNullOrEmpty(slot.slotID)) { continue; } slotParts.Add(slot.slotID); SlotData slotData; if (slot.useSharedOverlayList && slot.overlayListSource >= 0 && slot.overlayListSource < i) { slotData = context.InstantiateSlot(slot.slotID, umaData.umaRecipe.slotDataList[slot.overlayListSource].GetOverlayList()); } else { if (slot.useSharedOverlayList) { Debug.LogError("UMA Crowd: Invalid overlayListSource for " + slot.slotID); } slotData = context.InstantiateSlot(slot.slotID); } umaData.umaRecipe.slotDataList[i] = slotData; for (int overlayIdx = 0; overlayIdx < slot.overlayElements.Length; overlayIdx++) { var currentOverlayElement = slot.overlayElements[overlayIdx]; randomResult = Random.Range(0, currentOverlayElement.possibleOverlays.Length); var overlay = currentOverlayElement.possibleOverlays[randomResult]; if (string.IsNullOrEmpty(overlay.overlayID)) { continue; } overlay.UpdateVersion(); slotParts.Add(overlay.overlayID); Color overlayColor = Color.black; var overlayData = context.InstantiateOverlay(overlay.overlayID, overlayColor); switch (overlay.overlayType) { case UMACrowdRandomSet.OverlayType.Color: overlayColor = overlay.minRGB; overlayData.colorData.color = overlayColor; break; case UMACrowdRandomSet.OverlayType.Texture: overlayColor = Color.white; overlayData.colorData.color = overlayColor; break; case UMACrowdRandomSet.OverlayType.Hair: overlayColor = HairColor * overlay.hairColorMultiplier; overlayColor.a = 1.0f; overlayData.colorData.color = overlayColor; break; case UMACrowdRandomSet.OverlayType.Skin: overlayColor = skinColor; // + new Color(Random.Range(overlay.minRGB.r, overlay.maxRGB.r), Random.Range(overlay.minRGB.g, overlay.maxRGB.g), Random.Range(overlay.minRGB.b, overlay.maxRGB.b), 1); overlayData.colorData.color = overlayColor; if (overlayData.colorData.channelAdditiveMask.Length > 2) { overlayData.colorData.channelAdditiveMask[2] = Shine; } else { break; } break; case UMACrowdRandomSet.OverlayType.Random: { float randomShine = Random.Range(0.05f, 0.25f); float randomMetal = Random.Range(0.1f, 0.3f); overlayColor = new Color(Random.Range(overlay.minRGB.r, overlay.maxRGB.r), Random.Range(overlay.minRGB.g, overlay.maxRGB.g), Random.Range(overlay.minRGB.b, overlay.maxRGB.b), Random.Range(overlay.minRGB.a, overlay.maxRGB.a)); overlayData.colorData.color = overlayColor; if (overlayData.colorData.channelAdditiveMask.Length > 2) { overlayData.colorData.channelAdditiveMask[2] = new Color(randomMetal, randomMetal, randomMetal, randomShine); } } break; default: Debug.LogError("Unknown RandomSet overlayType: " + ((int)overlay.overlayType)); overlayColor = overlay.minRGB; overlayData.colorData.color = overlayColor; break; } slotData.AddOverlay(overlayData); if (overlay.colorChannelUse != ChannelUse.None) { overlayColor.a *= overlay.minRGB.a; if (overlay.colorChannelUse == ChannelUse.InverseColor) { Vector3 color = new Vector3(overlayColor.r, overlayColor.g, overlayColor.b); var len = color.magnitude; if (len < 1f) { len = 1f; } color = new Vector3(1.001f, 1.001f, 1.001f) - color; color = color.normalized * len; overlayColor = new Color(color.x, color.y, color.z, overlayColor.a); } overlayData.SetColor(overlay.colorChannel, overlayColor); } } } }
public void LoadSelectedCollection(string collectionName) { var thisUWC = WardrobeCollectionLibrary.Instance.collectionIndex[collectionName]; if (thisUWC != null) { thisUWC.EnsureLocalAvailability(); } if (thisCustomizer.Avatar != null) { //is this UWC compatible with the current race of the avatar? //even if its not it should be made available to races that are? if (!thisUWC.compatibleRaces.Contains(thisCustomizer.Avatar.activeRace.name) && thisUWC.compatibleRaces.Count > 0) { //show a messagebox- but for now if (Debug.isDebugBuild) { Debug.LogWarning("This wardrobe collection was not compatible with that avatar"); } return; } //if not show a message otherwise load the recipe var thisContext = thisCustomizer.Avatar.context != null ? thisCustomizer.Avatar.context : UMAContextBase.FindInstance(); if (thisContext != null) { // make sure it's downloaded... probably don't need this now. UMAContext.Instance.GetRecipe(collectionName, true); //if there is actually a 'FullOutfit' defined for the current avatar(i.e. the WardrobeSet for this race is not empty) load it if (thisUWC.wardrobeCollection[thisCustomizer.Avatar.activeRace.name].Count > 0) { thisCustomizer.Avatar.SetSlot(thisUWC); thisCustomizer.Avatar.BuildCharacter(true); } } onLoadCollection.Invoke(); //if this was not a recipe that will actually load a FullOutfit onto this race, show a message saying the assets have been added to the library if (thisUWC.wardrobeCollection[thisCustomizer.Avatar.activeRace.name].Count == 0 && thisUWC.arbitraryRecipes.Count > 0) { dialogBoxes.SetActive(true); messageBox.SetActive(true); messageHeader.text = thisUWC.name + " Loaded!"; messageBody.text = "The wardrobe recipes in " + thisUWC.name + " have been added to the DCS libraries. Compatible recipes can now be applied to your character using the 'Wardrobe' section of the UI."; } } }
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); }