//This is used when an inspected recipe asset is saved public override void Save(UMAData.UMARecipe umaRecipe, UMAContextBase context) { if (recipeType == "Wardrobe") //Wardrobe Recipes can save the standard UMA way- they dont have WardrobeSets- although the recipe string wont have a packedRecipeType field { base.Save(umaRecipe, context); } else if (recipeType != "Standard") //this will just be for type DynamicCharacterAvatar- and WardrobeCollection if we add that { var packedRecipe = PackRecipeV3(umaRecipe); //DCSPackRecipe doesn't do any more work, it just gets the values from PackRecipeV3 that we need and discards the rest var packedRecipeToSave = new DCSPackRecipe(packedRecipe, this.name, recipeType, activeWardrobeSet); recipeString = JsonUtility.ToJson(packedRecipeToSave); } else //This will be Standard- this is 'backwards Compatible' and is also how the Recipe Editor saves 'backwardsCompatible' 'Standard' recipes when they are inspected { umaRecipe.MergeMatchingOverlays(); var packedRecipe = PackRecipeV3(umaRecipe); var packedRecipeToSave = new DCSUniversalPackRecipe(packedRecipe); //this gets us a recipe with all the standard stuff plus our extra fields //so now we can save the wardrobeSet into it if it existed if (activeWardrobeSet != null) { if (activeWardrobeSet.Count > 0) { packedRecipeToSave.wardrobeSet = activeWardrobeSet; } } recipeString = JsonUtility.ToJson(packedRecipeToSave); } }
//TODO: once everyone has their recipes updated remove this- we only want UMATextRecipes to save as 'Standard' /// <summary> /// Saves a 'Standard' UMATextRecipe. If saving a DynamicCharacterAvatar as 'Backwards Compatible' this will save a recipe that has slots/overlay data AND a wardrobe set /// </summary> public void Save(UMAData.UMARecipe umaRecipe, UMAContextBase context, Dictionary <string, UMATextRecipe> wardrobeRecipes, bool backwardsCompatible = true) { if (wardrobeRecipes.Count > 0) { activeWardrobeSet = GenerateWardrobeSet(wardrobeRecipes); } recipeType = backwardsCompatible ? "Standard" : "DynamicCharacterAvatar"; Save(umaRecipe, context); }
/// <summary> /// Return a cached version of the UMA recipe, Load if required. /// </summary> /// <returns>The cached recipe.</returns> /// <param name="context">Context.</param> public UMAData.UMARecipe GetCachedRecipe(UMAContext context) { if (!cached) { umaRecipe = new UMAData.UMARecipe(); Load(umaRecipe, context); } return(umaRecipe); }
//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, UMAContext context) { if ((recipeString != null) && (recipeString.Length > 0)) { var packedRecipe = PackedLoadDCSInternal(context); if (packedRecipe != null) { UnpackRecipeVersion2(umaRecipe, packedRecipe, context); } } }
/// <summary> /// This is used to save a DCS avatar to a 'backwards compatible' UMA model /// </summary> /// <param name="recipeToSave"></param> /// <param name="wardrobeRecipes"></param> /// <param name="pRecipeType"></param> public DCSUniversalPackRecipe(UMAData.UMARecipe recipeToSave, Dictionary <string, UMATextRecipe> wardrobeRecipes = null, string pRecipeType = "DynamicCharacterAvatar") { //Debug.Log("Created universal model from Avatar"); var packedRecipe = PackRecipeV3(recipeToSave); packedRecipeType = pRecipeType; version = packedRecipe.version; packedSlotDataList = packedRecipe.packedSlotDataList; slotsV3 = packedRecipe.slotsV3; colors = packedRecipe.colors; fColors = packedRecipe.fColors; sharedColorCount = packedRecipe.sharedColorCount; race = packedRecipe.race; umaDna = packedRecipe.umaDna; packedDna = packedRecipe.packedDna; wardrobeSet = GenerateWardrobeSet(wardrobeRecipes); }
//Why do we still need this? Its for updating recipes using old dna (no type hash) //It tries to find a new home for the dna value in the recipe //but obviously I had to add it to make something work on 22/12/2018?!? //This method is f****d anyway because it doesn't account for the fact that a RaceData (or slotData) //may contain multiple converters that use the same dna... //Sooo maybe its ok to stay here? public static void FixUpUMADnaToDynamicUMADna(UMAData.UMARecipe _recipe) { var recipeDNA = _recipe.GetAllDna(); //22/12/2018 we also need to check slots using DynamicDNA var slotDNABehaviours = new Dictionary <int, IDNAConverter>(); foreach (SlotData slot in _recipe.GetAllSlots()) { if (slot != null && slot.asset != null && slot.asset.slotDNA != null && !slotDNABehaviours.ContainsKey(slot.asset.slotDNA.DNATypeHash)) { slotDNABehaviours.Add(slot.asset.slotDNA.DNATypeHash, slot.asset.slotDNA); } } for (int i = 0; i < recipeDNA.Length; i++) { int dnaToImport = recipeDNA[i].Count; int dnaImported = 0; //if (!_recipe.raceData.raceDictionary.ContainsKey(recipeDNA[i].GetType())) //A RaceData may contain multiple DynamicDnaConverters use GetConverter instead and use the hash //FixDNAPrefabs: A RaceData may contain multiple converters that use the same dna names now - check GetConverters instead if (_recipe.raceData.GetConverters(recipeDNA[i]).Length == 0 && !slotDNABehaviours.ContainsKey(recipeDNA[i].DNATypeHash)) { for (int j = 0; j < recipeDNA.Length; j++) { if (recipeDNA[j] is DynamicUMADnaBase) { // Keep trying to find a new home for DNA values until they have all been set dnaImported += ((DynamicUMADnaBase)recipeDNA[j]).ImportUMADnaValues(recipeDNA[i]); if (dnaImported >= dnaToImport) { break; } } } if (dnaImported > 0) { if (_recipe.GetDna(recipeDNA[i].DNATypeHash) != null) { _recipe.RemoveDna(recipeDNA[i].DNATypeHash); } } } } }
//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, UMAContext context) { if ((recipeString != null) && (recipeString.Length > 0)) { if (RecipeHasWardrobeSet(recipeString)) { activeWardrobeSet = GetRecipesWardrobeSet(recipeString); } else { Debug.LogWarning("[UMADynamicCharacterAvatar] recipe did not have wardrobe set"); } var packedRecipe = PackedLoadDCSInternal(context); if (packedRecipe != null) { UnpackRecipeVersion2(umaRecipe, packedRecipe, context); } } }
/// <summary> /// Return a cached version of the UMA recipe, Load if required. /// </summary> /// <returns>The cached recipe.</returns> /// <param name="context">Context.</param> public UMAData.UMARecipe GetCachedRecipe(UMAContextBase context) { if (!cached || umaRecipe == null) { umaRecipe = new UMAData.UMARecipe(); Load(umaRecipe, context); #if !UNITY_EDITOR #if UMA_ADDRESSABLES // don't cache addressables, as they can be unloaded. cached = false; #else // do not cache in the editor cached = true; #endif #endif } return(umaRecipe); }
/// <summary> /// Get the DNA. Unlike DynamicCharacterAvatar, this is cached because the character cannot be rebuilt. /// </summary> /// <param name="recipe"></param> /// <returns></returns> public Dictionary <string, DnaSetter> GetDNA(UMAData.UMARecipe recipe = null) { if (dna.Keys.Count == 0) { UMADnaBase[] dnaBase = umaData.GetAllDna(); if (recipe == null) { dnaBase = umaData.GetAllDna(); } else { dnaBase = recipe.GetAllDna(); } foreach (UMADnaBase db in dnaBase) { string Category = db.GetType().ToString(); IDNAConverter[] dcb = originalRace.GetConverters(db); if (dcb.Length > 0 && dcb[0] != null && (!string.IsNullOrEmpty(dcb[0].DisplayValue))) { Category = dcb[0].DisplayValue; } for (int i = 0; i < db.Count; i++) { if (dna.ContainsKey(db.Names[i])) { dna[db.Names[i]] = new DnaSetter(db.Names[i], db.Values[i], i, db, Category); } else { dna.Add(db.Names[i], new DnaSetter(db.Names[i], db.Values[i], i, db, Category)); } } } } return(dna); }
public static void FixUpUMADnaToDynamicUMADna(UMAData.UMARecipe _recipe) { var recipeDNA = _recipe.GetAllDna(); for (int i = 0; i < recipeDNA.Length; i++) { //if (!_recipe.raceData.raceDictionary.ContainsKey(recipeDNA[i].GetType())) //A RaceData may contain multiple DynamicDnaConverters use GetConverter instead and use the hash if (_recipe.raceData.GetConverter(recipeDNA[i]) == null) { int dnaToImport = recipeDNA[i].Count; int dnaImported = 0; for (int j = 0; j < recipeDNA.Length; j++) { if (recipeDNA[j] is DynamicUMADnaBase) { // Keep trying to find a new home for DNA values until they have all been set dnaImported += ((DynamicUMADnaBase)recipeDNA[j]).ImportUMADnaValues(recipeDNA[i]); if (dnaImported >= dnaToImport) { break; } } } if (dnaImported > 0) { if (_recipe.GetDna(recipeDNA[i].DNATypeHash) != null) { _recipe.RemoveDna(recipeDNA[i].DNATypeHash); } } } } }
public override void Load(UMA.UMAData.UMARecipe umaRecipe, UMAContext context) { var packedRecipe = PackedLoad(context); UnpackRecipe(umaRecipe, packedRecipe, context); }
public static UMAPackRecipe PackRecipe(UMA.UMAData.UMARecipe umaRecipe) { UMAPackRecipe umaPackRecipe = new UMAPackRecipe(); //var umaPackRecipe = new Packed umaPackRecipe.packedSlotDataList = new packedSlotData[umaRecipe.slotDataList.Length]; umaPackRecipe.race = umaRecipe.raceData.raceName; umaPackRecipe.packedDna.Clear(); foreach (var dna in umaRecipe.GetAllDna()) { UMAPackedDna packedDna = new UMAPackedDna(); packedDna.dnaType = dna.GetType().Name; packedDna.packedDna = UMA.UMADna.SaveInstance(dna); umaPackRecipe.packedDna.Add(packedDna); } for (int i = 0; i < umaRecipe.slotDataList.Length; i++) { if (umaRecipe.slotDataList[i] != null) { if (umaRecipe.slotDataList[i].listID != -1 && umaPackRecipe.packedSlotDataList[i] == null) { packedSlotData tempPackedSlotData; tempPackedSlotData = new packedSlotData(); tempPackedSlotData.slotID = umaRecipe.slotDataList[i].slotName; tempPackedSlotData.overlayScale = Mathf.FloorToInt(umaRecipe.slotDataList[i].overlayScale * 100); tempPackedSlotData.OverlayDataList = new packedOverlayData[umaRecipe.slotDataList[i].OverlayCount]; for (int overlayID = 0; overlayID < tempPackedSlotData.OverlayDataList.Length; overlayID++) { tempPackedSlotData.OverlayDataList[overlayID] = new packedOverlayData(); tempPackedSlotData.OverlayDataList[overlayID].overlayID = umaRecipe.slotDataList[i].GetOverlay(overlayID).overlayName; if (umaRecipe.slotDataList[i].GetOverlay(overlayID).color != new Color(1.0f, 1.0f, 1.0f, 1.0f)) { //Color32 instead of Color? tempPackedSlotData.OverlayDataList[overlayID].colorList = new int[4]; tempPackedSlotData.OverlayDataList[overlayID].colorList[0] = Mathf.FloorToInt(umaRecipe.slotDataList[i].GetOverlay(overlayID).color.r * 255.0f); tempPackedSlotData.OverlayDataList[overlayID].colorList[1] = Mathf.FloorToInt(umaRecipe.slotDataList[i].GetOverlay(overlayID).color.g * 255.0f); tempPackedSlotData.OverlayDataList[overlayID].colorList[2] = Mathf.FloorToInt(umaRecipe.slotDataList[i].GetOverlay(overlayID).color.b * 255.0f); tempPackedSlotData.OverlayDataList[overlayID].colorList[3] = Mathf.FloorToInt(umaRecipe.slotDataList[i].GetOverlay(overlayID).color.a * 255.0f); } if (umaRecipe.slotDataList[i].GetOverlay(overlayID).rect != new Rect(0, 0, 0, 0)) { //Might need float in next version tempPackedSlotData.OverlayDataList[overlayID].rectList = new int[4]; tempPackedSlotData.OverlayDataList[overlayID].rectList[0] = (int)umaRecipe.slotDataList[i].GetOverlay(overlayID).rect.x; tempPackedSlotData.OverlayDataList[overlayID].rectList[1] = (int)umaRecipe.slotDataList[i].GetOverlay(overlayID).rect.y; tempPackedSlotData.OverlayDataList[overlayID].rectList[2] = (int)umaRecipe.slotDataList[i].GetOverlay(overlayID).rect.width; tempPackedSlotData.OverlayDataList[overlayID].rectList[3] = (int)umaRecipe.slotDataList[i].GetOverlay(overlayID).rect.height; } if (umaRecipe.slotDataList[i].GetOverlay(overlayID).channelMask != null) { tempPackedSlotData.OverlayDataList[overlayID].channelMaskList = new int[umaRecipe.slotDataList[i].GetOverlay(overlayID).channelMask.Length][]; for (int channelAdjust = 0; channelAdjust < umaRecipe.slotDataList[i].GetOverlay(overlayID).channelMask.Length; channelAdjust++) { tempPackedSlotData.OverlayDataList[overlayID].channelMaskList[channelAdjust] = new int[4]; tempPackedSlotData.OverlayDataList[overlayID].channelMaskList[channelAdjust][0] = umaRecipe.slotDataList[i].GetOverlay(overlayID).channelMask[channelAdjust].r; tempPackedSlotData.OverlayDataList[overlayID].channelMaskList[channelAdjust][1] = umaRecipe.slotDataList[i].GetOverlay(overlayID).channelMask[channelAdjust].g; tempPackedSlotData.OverlayDataList[overlayID].channelMaskList[channelAdjust][2] = umaRecipe.slotDataList[i].GetOverlay(overlayID).channelMask[channelAdjust].b; tempPackedSlotData.OverlayDataList[overlayID].channelMaskList[channelAdjust][3] = umaRecipe.slotDataList[i].GetOverlay(overlayID).channelMask[channelAdjust].a; } } if (umaRecipe.slotDataList[i].GetOverlay(overlayID).channelAdditiveMask != null) { tempPackedSlotData.OverlayDataList[overlayID].channelAdditiveMaskList = new int[umaRecipe.slotDataList[i].GetOverlay(overlayID).channelAdditiveMask.Length][]; for (int channelAdjust = 0; channelAdjust < umaRecipe.slotDataList[i].GetOverlay(overlayID).channelAdditiveMask.Length; channelAdjust++) { tempPackedSlotData.OverlayDataList[overlayID].channelAdditiveMaskList[channelAdjust] = new int[4]; tempPackedSlotData.OverlayDataList[overlayID].channelAdditiveMaskList[channelAdjust][0] = umaRecipe.slotDataList[i].GetOverlay(overlayID).channelAdditiveMask[channelAdjust].r; tempPackedSlotData.OverlayDataList[overlayID].channelAdditiveMaskList[channelAdjust][1] = umaRecipe.slotDataList[i].GetOverlay(overlayID).channelAdditiveMask[channelAdjust].g; tempPackedSlotData.OverlayDataList[overlayID].channelAdditiveMaskList[channelAdjust][2] = umaRecipe.slotDataList[i].GetOverlay(overlayID).channelAdditiveMask[channelAdjust].b; tempPackedSlotData.OverlayDataList[overlayID].channelAdditiveMaskList[channelAdjust][3] = umaRecipe.slotDataList[i].GetOverlay(overlayID).channelAdditiveMask[channelAdjust].a; } } } umaPackRecipe.packedSlotDataList[i] = tempPackedSlotData; //Shared overlays wont generate duplicated data for (int i2 = i + 1; i2 < umaRecipe.slotDataList.Length; i2++) { if (umaRecipe.slotDataList[i2] != null) { if (umaPackRecipe.packedSlotDataList[i2] == null) { if (umaRecipe.slotDataList[i].GetOverlayList() == umaRecipe.slotDataList[i2].GetOverlayList()) { tempPackedSlotData = new packedSlotData(); tempPackedSlotData.slotID = umaRecipe.slotDataList[i2].slotName; tempPackedSlotData.copyOverlayIndex = i; //umaPackRecipe.packedSlotDataList[i2] = tempPackedSlotData; } } } } } } } return(umaPackRecipe); }
public override void Save(UMA.UMAData.UMARecipe umaRecipe, UMAContext context) { var packedRecipe = PackRecipe(umaRecipe); PackedSave(packedRecipe, context); }
/// <summary> /// Load data into the specified umaRecipe. /// </summary> /// <param name="umaRecipe">UMA recipe.</param> /// <param name="context">Context.</param> public abstract void Load(UMAData.UMARecipe umaRecipe, UMAContext context);
private void GenerateLookups(UMAContextBase context, List <AssetItem> wardrobe) { float pos = 0.0f; float inc = 1.0f / wardrobe.Count; // Get the slots, overlays, textures. // calculate the number of references for each of them. // Map the usage foreach (AssetItem recipeItem in wardrobe) { UMATextRecipe uwr = recipeItem.Item as UMATextRecipe; int iPos = Mathf.CeilToInt(pos); EditorUtility.DisplayProgressBar("Generating", "Calculating Usage: " + uwr.name, iPos); // todo: cache this UMAData.UMARecipe ur = UMAAssetIndexer.Instance.GetRecipe(uwr, context); if (ur.slotDataList == null) { continue; } foreach (SlotData sd in ur.slotDataList) { if (sd == null) { continue; } AssetItem ai = UMAAssetIndexer.Instance.GetAssetItem <SlotDataAsset>(sd.slotName); if (ai != null && ai.IsAlwaysLoaded == false) { // is this a utility slot? if so, we need to not delete it as an orphan. if (sd.asset.isUtilitySlot) { ai.IsAlwaysLoaded = true; } } //if (!(ai != null && ai.IsAlwaysLoaded)) //{ //AddToTracker = false; //} //else //{ int slotInstance = sd.asset.GetInstanceID(); if (!SlotTracker.ContainsKey(slotInstance)) { ai.IsAddressable = true; SlotTracker.Add(slotInstance, new List <UMATextRecipe>()); } SlotTracker[slotInstance].Add(uwr); if (!AddressLookup.ContainsKey(slotInstance)) { AddressLookup.Add(slotInstance, "Slt-" + sd.slotName); } //} List <OverlayData> odList = sd.GetOverlayList(); foreach (OverlayData od in odList) { if (od == null) { continue; } /* = GetAssetItem<OverlayDataAsset>(od.overlayName); * * if (ai != null && ai.IsAlwaysLoaded) * { * continue; * }*/ int OverlayInstance = od.asset.GetInstanceID(); if (!OverlayTracker.ContainsKey(OverlayInstance)) { OverlayTracker.Add(OverlayInstance, new List <UMATextRecipe>()); } OverlayTracker[OverlayInstance].Add(uwr); if (!AddressLookup.ContainsKey(OverlayInstance)) { ai.IsAddressable = true; AddressLookup.Add(OverlayInstance, "Ovl-" + od.overlayName); } foreach (Texture tx in od.textureArray) { if (tx == null) { continue; } int TextureID = tx.GetInstanceID(); if (!TextureTracker.ContainsKey(TextureID)) { TextureTracker.Add(TextureID, new List <UMATextRecipe>()); } TextureTracker[TextureID].Add(uwr); if (!AddressLookup.ContainsKey(TextureID)) { AddressLookup.Add(TextureID, "Tex-" + tx.name); } } } } pos += inc; } }
public static void UnpackRecipeVersion2(UMA.UMAData.UMARecipe umaRecipe, UMAPackRecipe umaPackRecipe, UMAContext context) { umaRecipe.slotDataList = new SlotData[umaPackRecipe.slotsV2.Length]; umaRecipe.SetRace(context.GetRace(umaPackRecipe.race)); umaRecipe.ClearDna(); List <UMADnaBase> packedDna = UnPackDNA(umaPackRecipe.packedDna); foreach (UMADnaBase umd in packedDna) { umaRecipe.AddDna(umd); } OverlayColorData[] colorData; if (UMAPackRecipe.ArrayHasData(umaPackRecipe.fColors)) { colorData = new OverlayColorData[umaPackRecipe.fColors.Length]; for (int i = 0; i < colorData.Length; i++) { colorData[i] = new OverlayColorData(); umaPackRecipe.fColors[i].SetOverlayColorData(colorData[i]); } } else if (UMAPackRecipe.ArrayHasData(umaPackRecipe.colors)) { colorData = new OverlayColorData[umaPackRecipe.colors.Length]; for (int i = 0; i < colorData.Length; i++) { colorData[i] = new OverlayColorData(); umaPackRecipe.colors[i].SetOverlayColorData(colorData[i]); } } else { colorData = new OverlayColorData[0]; } umaRecipe.sharedColors = new OverlayColorData[umaPackRecipe.sharedColorCount]; for (int i = 0; i < umaRecipe.sharedColors.Length; i++) { umaRecipe.sharedColors[i] = colorData[i]; } for (int i = 0; i < umaPackRecipe.slotsV2.Length; i++) { PackedSlotDataV2 packedSlot = umaPackRecipe.slotsV2[i]; if (UMAPackRecipe.SlotIsValid(packedSlot)) { var tempSlotData = context.InstantiateSlot(packedSlot.id); tempSlotData.overlayScale = packedSlot.scale * 0.01f; umaRecipe.slotDataList[i] = tempSlotData; if (packedSlot.copyIdx == -1) { for (int i2 = 0; i2 < packedSlot.overlays.Length; i2++) { PackedOverlayDataV2 packedOverlay = packedSlot.overlays[i2]; OverlayData overlayData = context.InstantiateOverlay(packedOverlay.id); overlayData.rect = new Rect(packedOverlay.rect[0], packedOverlay.rect[1], packedOverlay.rect[2], packedOverlay.rect[3]); if (packedOverlay.colorIdx < umaPackRecipe.sharedColorCount) { overlayData.colorData = umaRecipe.sharedColors[packedOverlay.colorIdx]; } else { overlayData.colorData = colorData[packedOverlay.colorIdx].Duplicate(); overlayData.colorData.name = OverlayColorData.UNSHARED; } if (UMAPackRecipe.MaterialIsValid(overlayData.asset.material)) { overlayData.EnsureChannels(overlayData.asset.material.channels.Length); } tempSlotData.AddOverlay(overlayData); } } else { tempSlotData.SetOverlayList(umaRecipe.slotDataList[packedSlot.copyIdx].GetOverlayList()); } } } }
public static UMAPackRecipe PackRecipeV2(UMA.UMAData.UMARecipe umaRecipe) { UMAPackRecipe umaPackRecipe = new UMAPackRecipe(); umaPackRecipe.version = 2; int slotCount = umaRecipe.slotDataList.Length; umaPackRecipe.slotsV2 = new PackedSlotDataV2[slotCount]; if (UMAPackRecipe.RaceIsValid(umaRecipe.raceData)) { umaPackRecipe.race = umaRecipe.raceData.raceName; } /*foreach (var dna in umaRecipe.GetAllDna()) * { * UMAPackedDna packedDna = new UMAPackedDna(); * //DynamicUMADna:: needs the typeHash as this is randomly generated by the DynamicDnaConverter * packedDna.dnaTypeHash = dna.DNATypeHash; * packedDna.dnaType = dna.GetType().Name; * //DynamicUMADna:: test here for DynamicUMADna here because UMADna_generated doesn't have it * if (packedDna.dnaType == "DynamicUMADna") * { * packedDna.packedDna = UMA.DynamicUMADna.SaveInstance(dna as UMA.DynamicUMADna); * } * else * packedDna.packedDna = UMA.UMADna.SaveInstance(dna); * umaPackRecipe.packedDna.Add(packedDna); * }*/ umaPackRecipe.packedDna = GetPackedDNA(umaRecipe); umaPackRecipe.sharedColorCount = 0; if (UMAPackRecipe.ArrayHasData(umaRecipe.sharedColors)) { umaPackRecipe.sharedColorCount = umaRecipe.sharedColors.Length; } List <OverlayColorData> colorEntries = new List <OverlayColorData>(umaPackRecipe.sharedColorCount); List <PackedOverlayColorDataV3> packedColorEntries = new List <PackedOverlayColorDataV3>(umaPackRecipe.sharedColorCount); for (int i = 0; i < umaPackRecipe.sharedColorCount; i++) { colorEntries.Add(umaRecipe.sharedColors[i]); packedColorEntries.Add(new PackedOverlayColorDataV3(umaRecipe.sharedColors[i])); } for (int i = 0; i < slotCount; i++) { if (UMAPackRecipe.SlotIsValid(umaRecipe.slotDataList[i]) && !umaRecipe.slotDataList[i].dontSerialize) { PackedSlotDataV2 tempPackedSlotData = new PackedSlotDataV2(); umaPackRecipe.slotsV2[i] = tempPackedSlotData; tempPackedSlotData.id = umaRecipe.slotDataList[i].asset.slotName; tempPackedSlotData.scale = Mathf.FloorToInt(umaRecipe.slotDataList[i].overlayScale * 100); bool copiedOverlays = false; for (int i2 = 0; i2 < i; i2++) { if (UMAPackRecipe.SlotIsValid(umaRecipe.slotDataList[i2]) && UMAPackRecipe.SlotIsValid(umaPackRecipe.slotsV2[i2])) { if (umaRecipe.slotDataList[i].GetOverlayList() == umaRecipe.slotDataList[i2].GetOverlayList()) { tempPackedSlotData.copyIdx = i2; copiedOverlays = true; break; } } } if (copiedOverlays) { continue; } tempPackedSlotData.overlays = new PackedOverlayDataV2[umaRecipe.slotDataList[i].OverlayCount]; for (int overlayIdx = 0; overlayIdx < tempPackedSlotData.overlays.Length; overlayIdx++) { PackedOverlayDataV2 tempPackedOverlay = new PackedOverlayDataV2(); OverlayData overlayData = umaRecipe.slotDataList[i].GetOverlay(overlayIdx); tempPackedOverlay.id = overlayData.asset.overlayName; tempPackedOverlay.rect = new int[4]; tempPackedOverlay.rect[0] = Mathf.FloorToInt(overlayData.rect.x); tempPackedOverlay.rect[1] = Mathf.FloorToInt(overlayData.rect.y); tempPackedOverlay.rect[2] = Mathf.FloorToInt(overlayData.rect.width); tempPackedOverlay.rect[3] = Mathf.FloorToInt(overlayData.rect.height); OverlayColorData colorData = overlayData.colorData; int colorIndex = -1; int cIndex = 0; foreach (OverlayColorData cData in colorEntries) { if (cData.name != null && cData.name.Equals(colorData.name) && cData.Equals(colorData)) { colorIndex = cIndex; break; } cIndex++; } if (colorIndex < 0) { PackedOverlayColorDataV3 newColorEntry = new PackedOverlayColorDataV3(colorData); packedColorEntries.Add(newColorEntry); colorIndex = colorEntries.Count; colorEntries.Add(colorData); } tempPackedOverlay.colorIdx = colorIndex; tempPackedSlotData.overlays[overlayIdx] = tempPackedOverlay; } } } umaPackRecipe.fColors = packedColorEntries.ToArray(); return(umaPackRecipe); }