/// <summary> /// Create a Wardrobe Recipe from the slot (and optionally overlay) /// </summary> /// <param name="path"></param> /// <param name="sd"></param> /// <param name="od"></param> /// <param name="slotName"></param> /// <param name="addToGlobalLibrary"></param> public static UMAWardrobeRecipe CreateRecipe(string path, SlotDataAsset sd, OverlayDataAsset od, string slotName, bool addToGlobalLibrary) { // Generate an asset in memory UMAWardrobeRecipe asset = ScriptableObject.CreateInstance <CharacterSystem.UMAWardrobeRecipe>(); UMAData.UMARecipe recipe = new UMAData.UMARecipe(); recipe.ClearDna(); SlotData mySlot = new SlotData(sd); if (od != null) { OverlayData myOverlay = new OverlayData(od); mySlot.AddOverlay(myOverlay); } recipe.SetSlot(0, mySlot); asset.Save(recipe, UMAContextBase.Instance); asset.DisplayValue = slotName; // Write the asset to disk AssetDatabase.CreateAsset(asset, path); AssetDatabase.SaveAssets(); if (addToGlobalLibrary) { // Add it to the global libary UMAAssetIndexer.Instance.EvilAddAsset(typeof(CharacterSystem.UMAWardrobeRecipe), asset); EditorUtility.SetDirty(UMAAssetIndexer.Instance); } // Inform the asset database a file has changes AssetDatabase.Refresh(); return(asset); }
public SlotData Duplicate() { SlotData tempSlotData = CreateInstance <SlotData>(); tempSlotData.slotName = slotName; tempSlotData.listID = listID; tempSlotData.materialSample = materialSample; tempSlotData.overlayScale = overlayScale; tempSlotData.slotDNA = slotDNA; tempSlotData.subMeshIndex = subMeshIndex; // All this data is passed as reference tempSlotData.boneWeights = boneWeights; tempSlotData.animatedBones = animatedBones; tempSlotData.meshRenderer = meshRenderer; tempSlotData.boneWeights = boneWeights; tempSlotData.umaBoneData = umaBoneData; tempSlotData.textureNameList = textureNameList; //Overlays are duplicated, to lose reference for (int i = 0; i < overlayList.Count; i++) { tempSlotData.AddOverlay(overlayList[i].Duplicate()); } return(tempSlotData); }
protected override void Start() { if (generatedMaterialLookup == null) { generatedMaterialLookup = new Dictionary <GeneratedMaterialLookupKey, UMAData.GeneratedMaterial>(20); } else { generatedMaterialLookup.Clear(); } backUpTexture = umaData.backUpTextures(); umaData.CleanTextures(); generatedMaterials = new List <UMAData.GeneratedMaterial>(20); atlassedMaterials.Clear(); uniqueRenderers.Clear(); SlotData[] slots = umaData.umaRecipe.slotDataList; for (int i = 0; i < slots.Length; i++) { SlotData slot = slots[i]; if (slot == null) { continue; } if (slot.Suppressed) { continue; } //Keep a running list of unique RendererHashes from our slots //Null rendererAsset gets added, which is good, it is the default renderer. if (!uniqueRenderers.Contains(slot.rendererAsset)) { uniqueRenderers.Add(slot.rendererAsset); } // Let's only add the default overlay if the slot has meshData and NO overlays // This should be able to be removed if default overlay/textures are ever added to uma materials... if ((slot.asset.meshData != null) && (slot.OverlayCount == 0)) { if (umaGenerator.defaultOverlaydata != null) { slot.AddOverlay(umaGenerator.defaultOverlaydata); } } OverlayData overlay0 = slot.GetOverlay(0); if ((slot.asset.material != null) && (overlay0 != null)) { GeneratedMaterialLookupKey lookupKey = new GeneratedMaterialLookupKey { overlayList = slot.GetOverlayList(), rendererAsset = slot.rendererAsset }; UMAData.GeneratedMaterial generatedMaterial; if (!generatedMaterialLookup.TryGetValue(lookupKey, out generatedMaterial)) { generatedMaterial = FindOrCreateGeneratedMaterial(slot.asset.material, slot.rendererAsset); generatedMaterialLookup.Add(lookupKey, generatedMaterial); } int validOverlayCount = 0; for (int j = 0; j < slot.OverlayCount; j++) { var overlay = slot.GetOverlay(j); if (overlay != null) { validOverlayCount++; #if (UNITY_STANDALONE || UNITY_IOS || UNITY_ANDROID || UNITY_PS4 || UNITY_XBOXONE) && !UNITY_2017_3_OR_NEWER //supported platforms for procedural materials if (overlay.isProcedural) { overlay.GenerateProceduralTextures(); } #endif } } UMAData.MaterialFragment tempMaterialDefinition = new UMAData.MaterialFragment(); tempMaterialDefinition.baseOverlay = new UMAData.textureData(); tempMaterialDefinition.baseOverlay.textureList = overlay0.textureArray; tempMaterialDefinition.baseOverlay.alphaTexture = overlay0.alphaMask; tempMaterialDefinition.baseOverlay.overlayType = overlay0.overlayType; tempMaterialDefinition.umaMaterial = slot.asset.material; tempMaterialDefinition.baseColor = overlay0.colorData.color; tempMaterialDefinition.size = overlay0.pixelCount; tempMaterialDefinition.overlays = new UMAData.textureData[validOverlayCount - 1]; tempMaterialDefinition.overlayColors = new Color32[validOverlayCount - 1]; tempMaterialDefinition.rects = new Rect[validOverlayCount - 1]; tempMaterialDefinition.overlayData = new OverlayData[validOverlayCount]; tempMaterialDefinition.channelMask = new Color[validOverlayCount][]; tempMaterialDefinition.channelAdditiveMask = new Color[validOverlayCount][]; tempMaterialDefinition.overlayData[0] = slot.GetOverlay(0); tempMaterialDefinition.channelMask[0] = slot.GetOverlay(0).colorData.channelMask; tempMaterialDefinition.channelAdditiveMask[0] = slot.GetOverlay(0).colorData.channelAdditiveMask; tempMaterialDefinition.slotData = slot; int overlayID = 0; for (int j = 1; j < slot.OverlayCount; j++) { OverlayData overlay = slot.GetOverlay(j); if (overlay == null) { continue; } if (IsUVCoordinates(overlay.rect)) { tempMaterialDefinition.rects[overlayID] = ScaleToBase(overlay.rect, overlay0.textureArray[0]); } else { tempMaterialDefinition.rects[overlayID] = overlay.rect; // JRRM: Convert here into base overlay coordinates? } tempMaterialDefinition.overlays[overlayID] = new UMAData.textureData(); tempMaterialDefinition.overlays[overlayID].textureList = overlay.textureArray; tempMaterialDefinition.overlays[overlayID].alphaTexture = overlay.alphaMask; tempMaterialDefinition.overlays[overlayID].overlayType = overlay.overlayType; tempMaterialDefinition.overlayColors[overlayID] = overlay.colorData.color; overlayID++; tempMaterialDefinition.overlayData[overlayID] = overlay; tempMaterialDefinition.channelMask[overlayID] = overlay.colorData.channelMask; tempMaterialDefinition.channelAdditiveMask[overlayID] = overlay.colorData.channelAdditiveMask; } tempMaterialDefinition.overlayList = lookupKey.overlayList; tempMaterialDefinition.isRectShared = false; for (int j = 0; j < generatedMaterial.materialFragments.Count; j++) { if (tempMaterialDefinition.overlayList == generatedMaterial.materialFragments[j].overlayList) { tempMaterialDefinition.isRectShared = true; tempMaterialDefinition.rectFragment = generatedMaterial.materialFragments[j]; break; } } generatedMaterial.materialFragments.Add(tempMaterialDefinition); } } //**************************************************** //* Set parameters based on shader parameter mapping //**************************************************** for (int i = 0; i < generatedMaterials.Count; i++) { UMAData.GeneratedMaterial ugm = generatedMaterials[i]; if (ugm.umaMaterial.shaderParms != null) { for (int j = 0; j < ugm.umaMaterial.shaderParms.Length; j++) { UMAMaterial.ShaderParms parm = ugm.umaMaterial.shaderParms[j]; if (ugm.material.HasProperty(parm.ParameterName)) { foreach (OverlayColorData ocd in umaData.umaRecipe.sharedColors) { if (ocd.name == parm.ColorName) { ugm.material.SetColor(parm.ParameterName, ocd.color); break; } } } } } } packTexture = new MaxRectsBinPack(umaGenerator.atlasResolution, umaGenerator.atlasResolution, false); }
/// <summary> /// Combine additional slot with current data. /// </summary> /// <param name="slot">Slot.</param> /// <param name="additional">If set to <c>true</c> slot will not be serialized.</param> public void MergeSlot(SlotData slot, bool additional) { if ((slot == null) || (slot.asset == null)) { return; } int overlayCount = 0; for (int i = 0; i < slotDataList.Length; i++) { if (slotDataList[i] == null) { continue; } if (slot.asset == slotDataList[i].asset) { SlotData originalSlot = slotDataList[i]; overlayCount = slot.OverlayCount; for (int j = 0; j < overlayCount; j++) { OverlayData overlay = slot.GetOverlay(j); OverlayData originalOverlay = originalSlot.GetEquivalentOverlay(overlay); if (originalOverlay != null) { // originalOverlay.CopyColors(overlay); } else { OverlayData overlayCopy = overlay.Duplicate(); if (overlayCopy.colorData.HasName()) { int sharedIndex; if (mergedSharedColors.TryGetValue(overlayCopy.colorData.name, out sharedIndex)) { overlayCopy.colorData = sharedColors[sharedIndex]; } } originalSlot.AddOverlay(overlayCopy); } } return; } } int insertIndex = slotDataList.Length; System.Array.Resize <SlotData>(ref slotDataList, slotDataList.Length + 1); if (additional) { additionalSlotCount += 1; } else { for (int i = 0; i < additionalSlotCount; i++) { slotDataList[insertIndex] = slotDataList[insertIndex - 1]; insertIndex--; } } SlotData slotCopy = slot.Copy(); overlayCount = slotCopy.OverlayCount; for (int j = 0; j < overlayCount; j++) { OverlayData overlay = slotCopy.GetOverlay(j); if (overlay.colorData.HasName()) { int sharedIndex; if (mergedSharedColors.TryGetValue(overlay.colorData.name, out sharedIndex)) { overlay.colorData = sharedColors[sharedIndex]; } } } slotDataList[insertIndex] = slotCopy; MergeMatchingOverlays(); }
protected override void Start() { if (generatedMaterialLookup == null) { generatedMaterialLookup = new Dictionary <List <OverlayData>, UMAData.GeneratedMaterial>(20); } else { generatedMaterialLookup.Clear(); } backUpTexture = umaData.backUpTextures(); umaData.CleanTextures(); generatedMaterials = new List <UMAData.GeneratedMaterial>(20); atlassedMaterials.Clear(); rendererCount = 0; SlotData[] slots = umaData.umaRecipe.slotDataList; for (int i = 0; i < slots.Length; i++) { var slot = slots[i]; if (slot == null) { continue; } if ((slot.asset.material != null) && (slot.GetOverlay(0) != null)) { if (!slot.asset.material.RequireSeperateRenderer) { // At least one slot that doesn't require a seperate renderer, so we reserve renderer 0 for those. rendererCount = 1; break; } } } for (int i = 0; i < slots.Length; i++) { SlotData slot = slots[i]; if (slot == null) { continue; } // Let's only add the default overlay if the slot has overlays and NO meshData if ((slot.asset.meshData != null) && (slot.OverlayCount == 0)) { if (umaGenerator.defaultOverlaydata != null) { slot.AddOverlay(umaGenerator.defaultOverlaydata); } } OverlayData overlay0 = slot.GetOverlay(0); if ((slot.asset.material != null) && (overlay0 != null)) { List <OverlayData> overlayList = slot.GetOverlayList(); UMAData.GeneratedMaterial generatedMaterial; if (!generatedMaterialLookup.TryGetValue(overlayList, out generatedMaterial)) { generatedMaterial = FindOrCreateGeneratedMaterial(slot.asset.material); generatedMaterialLookup.Add(overlayList, generatedMaterial); } int validOverlayCount = 0; for (int j = 0; j < slot.OverlayCount; j++) { var overlay = slot.GetOverlay(j); if (overlay != null) { validOverlayCount++; #if UNITY_STANDALONE || UNITY_IOS || UNITY_ANDROID || UNITY_PS4 || UNITY_XBOXONE //supported platforms for procedural materials if (overlay.isProcedural) { overlay.GenerateProceduralTextures(); } #endif } } UMAData.MaterialFragment tempMaterialDefinition = new UMAData.MaterialFragment(); tempMaterialDefinition.baseOverlay = new UMAData.textureData(); tempMaterialDefinition.baseOverlay.textureList = overlay0.textureArray; tempMaterialDefinition.baseOverlay.alphaTexture = overlay0.alphaMask; tempMaterialDefinition.baseOverlay.overlayType = overlay0.overlayType; tempMaterialDefinition.umaMaterial = slot.asset.material; tempMaterialDefinition.baseColor = overlay0.colorData.color; tempMaterialDefinition.size = overlay0.pixelCount; tempMaterialDefinition.overlays = new UMAData.textureData[validOverlayCount - 1]; tempMaterialDefinition.overlayColors = new Color32[validOverlayCount - 1]; tempMaterialDefinition.rects = new Rect[validOverlayCount - 1]; tempMaterialDefinition.overlayData = new OverlayData[validOverlayCount]; tempMaterialDefinition.channelMask = new Color[validOverlayCount][]; tempMaterialDefinition.channelAdditiveMask = new Color[validOverlayCount][]; tempMaterialDefinition.overlayData[0] = slot.GetOverlay(0); tempMaterialDefinition.channelMask[0] = slot.GetOverlay(0).colorData.channelMask; tempMaterialDefinition.channelAdditiveMask[0] = slot.GetOverlay(0).colorData.channelAdditiveMask; tempMaterialDefinition.slotData = slot; int overlayID = 0; for (int j = 1; j < slot.OverlayCount; j++) { OverlayData overlay = slot.GetOverlay(j); if (overlay == null) { continue; } tempMaterialDefinition.rects[overlayID] = overlay.rect; tempMaterialDefinition.overlays[overlayID] = new UMAData.textureData(); tempMaterialDefinition.overlays[overlayID].textureList = overlay.textureArray; tempMaterialDefinition.overlays[overlayID].alphaTexture = overlay.alphaMask; tempMaterialDefinition.overlays[overlayID].overlayType = overlay.overlayType; tempMaterialDefinition.overlayColors[overlayID] = overlay.colorData.color; overlayID++; tempMaterialDefinition.overlayData[overlayID] = overlay; tempMaterialDefinition.channelMask[overlayID] = overlay.colorData.channelMask; tempMaterialDefinition.channelAdditiveMask[overlayID] = overlay.colorData.channelAdditiveMask; } tempMaterialDefinition.overlayList = overlayList; tempMaterialDefinition.isRectShared = false; for (int j = 0; j < generatedMaterial.materialFragments.Count; j++) { if (tempMaterialDefinition.overlayList == generatedMaterial.materialFragments[j].overlayList) { tempMaterialDefinition.isRectShared = true; tempMaterialDefinition.rectFragment = generatedMaterial.materialFragments[j]; break; } } generatedMaterial.materialFragments.Add(tempMaterialDefinition); } } packTexture = new MaxRectsBinPack(umaGenerator.atlasResolution, umaGenerator.atlasResolution, false); }