704 lines
24 KiB
C#
704 lines
24 KiB
C#
![]() |
using UnityEngine;
|
||
|
using System;
|
||
|
using System.Text;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using DigitalOpus.MB.Core;
|
||
|
using UnityEngine.Serialization;
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Used internally during the material baking process
|
||
|
/// </summary>
|
||
|
[Serializable]
|
||
|
public class MB_AtlasesAndRects{
|
||
|
/// <summary>
|
||
|
/// One atlas per texture property.
|
||
|
/// </summary>
|
||
|
public Texture2D[] atlases;
|
||
|
[NonSerialized]
|
||
|
public List<MB_MaterialAndUVRect> mat2rect_map;
|
||
|
public string[] texPropertyNames;
|
||
|
}
|
||
|
|
||
|
public class MB_TextureArrayResultMaterial
|
||
|
{
|
||
|
public MB_AtlasesAndRects[] slices;
|
||
|
}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class MB_MultiMaterial{
|
||
|
public Material combinedMaterial;
|
||
|
public bool considerMeshUVs;
|
||
|
#if UNITY_2020_2_OR_NEWER
|
||
|
[NonReorderable] //see MB-136 for why this is here
|
||
|
#endif
|
||
|
public List<Material> sourceMaterials = new List<Material>();
|
||
|
}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class MB_TexArraySliceRendererMatPair
|
||
|
{
|
||
|
public Material sourceMaterial;
|
||
|
public GameObject renderer;
|
||
|
}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class MB_TexArraySlice
|
||
|
{
|
||
|
public bool considerMeshUVs;
|
||
|
#if UNITY_2020_2_OR_NEWER
|
||
|
[NonReorderable] //see MB-136 for why this is here
|
||
|
#endif
|
||
|
public List<MB_TexArraySliceRendererMatPair> sourceMaterials = new List<MB_TexArraySliceRendererMatPair>();
|
||
|
public bool ContainsMaterial(Material mat)
|
||
|
{
|
||
|
for (int i = 0; i < sourceMaterials.Count; i++)
|
||
|
{
|
||
|
if (sourceMaterials[i].sourceMaterial == mat) return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public HashSet<Material> GetDistinctMaterials()
|
||
|
{
|
||
|
HashSet<Material> distinctMats = new HashSet<Material>();
|
||
|
if (sourceMaterials == null) return distinctMats;
|
||
|
for (int i = 0; i < sourceMaterials.Count; i++)
|
||
|
{
|
||
|
distinctMats.Add(sourceMaterials[i].sourceMaterial);
|
||
|
}
|
||
|
|
||
|
return distinctMats;
|
||
|
}
|
||
|
|
||
|
public bool ContainsMaterialAndMesh(Material mat, Mesh mesh)
|
||
|
{
|
||
|
for (int i = 0; i < sourceMaterials.Count; i++)
|
||
|
{
|
||
|
if (sourceMaterials[i].sourceMaterial == mat &&
|
||
|
MB_Utility.GetMesh(sourceMaterials[i].renderer) == mesh) return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public List<Material> GetAllUsedMaterials(List<Material> usedMats)
|
||
|
{
|
||
|
usedMats.Clear();
|
||
|
for (int i = 0; i < sourceMaterials.Count; i++)
|
||
|
{
|
||
|
usedMats.Add(sourceMaterials[i].sourceMaterial);
|
||
|
}
|
||
|
return usedMats;
|
||
|
}
|
||
|
|
||
|
public List<GameObject> GetAllUsedRenderers(List<GameObject> allObjsFromTextureBaker)
|
||
|
{
|
||
|
if (considerMeshUVs)
|
||
|
{
|
||
|
List<GameObject> usedRendererGOs = new List<GameObject>();
|
||
|
for (int i = 0; i < sourceMaterials.Count; i++)
|
||
|
{
|
||
|
usedRendererGOs.Add(sourceMaterials[i].renderer);
|
||
|
}
|
||
|
|
||
|
return usedRendererGOs;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return allObjsFromTextureBaker;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class MB_TextureArrayReference
|
||
|
{
|
||
|
public string texFromatSetName;
|
||
|
public Texture2DArray texArray;
|
||
|
|
||
|
public MB_TextureArrayReference(string formatSetName, Texture2DArray ta)
|
||
|
{
|
||
|
texFromatSetName = formatSetName;
|
||
|
texArray = ta;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class MB_TexArrayForProperty
|
||
|
{
|
||
|
public string texPropertyName;
|
||
|
#if UNITY_2020_2_OR_NEWER
|
||
|
[NonReorderable] //see MB-136 for why this is here
|
||
|
#endif
|
||
|
public MB_TextureArrayReference[] formats = new MB_TextureArrayReference[0];
|
||
|
|
||
|
public MB_TexArrayForProperty(string name, MB_TextureArrayReference[] texRefs)
|
||
|
{
|
||
|
texPropertyName = name;
|
||
|
formats = texRefs;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class MB_MultiMaterialTexArray
|
||
|
{
|
||
|
public Material combinedMaterial;
|
||
|
#if UNITY_2020_2_OR_NEWER
|
||
|
[NonReorderable] //see MB-136 for why this is here
|
||
|
#endif
|
||
|
public List<MB_TexArraySlice> slices = new List<MB_TexArraySlice>();
|
||
|
#if UNITY_2020_2_OR_NEWER
|
||
|
[NonReorderable] //see MB-136 for why this is here
|
||
|
#endif
|
||
|
public List<MB_TexArrayForProperty> textureProperties = new List<MB_TexArrayForProperty>();
|
||
|
}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class MB_TextureArrayFormat
|
||
|
{
|
||
|
public string propertyName;
|
||
|
public TextureFormat format;
|
||
|
[Tooltip("The ammount of time Unity takes exploring different compression options to find the compressed version of a texture that most closely matches the original art." +
|
||
|
"This is only used For iOS (and some Android formats)")]
|
||
|
public MB_TextureCompressionQuality compressionQuality = MB_TextureCompressionQuality.normal;
|
||
|
}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class MB_TextureArrayFormatSet
|
||
|
{
|
||
|
public string name;
|
||
|
public TextureFormat defaultFormat;
|
||
|
|
||
|
[Tooltip("The ammount of time Unity takes exploring different compression options to find the compressed version of a texture that most closely matches the original art." +
|
||
|
"This is only used For iOS (and some Android formats)")]
|
||
|
public MB_TextureCompressionQuality defaultCompressionQuality = MB_TextureCompressionQuality.normal;
|
||
|
#if UNITY_2020_2_OR_NEWER
|
||
|
[NonReorderable] //see MB-136 for why this is here
|
||
|
#endif
|
||
|
public MB_TextureArrayFormat[] formatOverrides;
|
||
|
|
||
|
public bool ValidateTextureImporterFormatsExistsForTextureFormats(MB2_EditorMethodsInterface editorMethods, int idx)
|
||
|
{
|
||
|
if (editorMethods == null) return true;
|
||
|
if (!editorMethods.TextureImporterFormatExistsForTextureFormat(defaultFormat))
|
||
|
{
|
||
|
Debug.LogError("TextureImporter format does not exist for Texture Array Output Formats: " + idx + " Defaut Format " + defaultFormat);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < formatOverrides.Length; i++)
|
||
|
{
|
||
|
if (!editorMethods.TextureImporterFormatExistsForTextureFormat(formatOverrides[i].format))
|
||
|
{
|
||
|
Debug.LogError("TextureImporter format does not exist for Texture Array Output Formats: " + idx + " Format Overrides: " + i + " (" + formatOverrides[i].format + ")");
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public TextureFormat GetFormatForProperty(string propName, out MB_TextureCompressionQuality compressionQuality)
|
||
|
{
|
||
|
for (int i = 0; i < formatOverrides.Length; i++)
|
||
|
{
|
||
|
if (formatOverrides.Equals(formatOverrides[i].propertyName))
|
||
|
{
|
||
|
compressionQuality = formatOverrides[i].compressionQuality;
|
||
|
return formatOverrides[i].format;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
compressionQuality = defaultCompressionQuality;
|
||
|
return defaultFormat;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class MB_MaterialAndUVRect
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// The source material that was baked into the atlas.
|
||
|
/// </summary>
|
||
|
public Material material;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The addressables primary key for this material at bake time.
|
||
|
/// DECIDED NOT TO USE THIS BECAUSE THERE IS NOT EDITOR API FOR GETTING ADDRESS.
|
||
|
/// </summary>
|
||
|
//public string matAddressablesPKey;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The runtime material that corresponds to the bake time material.
|
||
|
/// The user may be baking textures in the editor and baking meshes at runtime.
|
||
|
/// Materials may at runtime loaded from asset bundles which are a different instance of the Material than the baked asset
|
||
|
/// We use the Addressables address (cached at texture bake time) to look up the runtime material.
|
||
|
/// DECIDED NOT TO USE THIS BECAUSE THERE IS NOT EDITOR API FOR GETTING ADDRESS.
|
||
|
/// </summary>
|
||
|
/// [System.NonSerialized]
|
||
|
//public Material runtimeMaterial;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The rectangle in the atlas where the texture (including all tiling) was copied to.
|
||
|
/// </summary>
|
||
|
public Rect atlasRect;
|
||
|
|
||
|
/// <summary>
|
||
|
/// For debugging. The name of the first srcObj that uses this MaterialAndUVRect.
|
||
|
/// </summary>
|
||
|
public string srcObjName;
|
||
|
|
||
|
public int textureArraySliceIdx = -1;
|
||
|
|
||
|
/// <summary>
|
||
|
/// True if the albedoMap, normalMap, specMap, etc... all use the same tiling.
|
||
|
/// </summary>
|
||
|
public bool allPropsUseSameTiling = true;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Only valid if allPropsUseSameTiling = true. Else should be 0,0,0,0
|
||
|
/// The material tiling on the source material
|
||
|
/// </summary>
|
||
|
[FormerlySerializedAs("sourceMaterialTiling")]
|
||
|
public Rect allPropsUseSameTiling_sourceMaterialTiling;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Only valid if allPropsUseSameTiling = true. Else should be 0,0,0,0
|
||
|
/// The encapsulating sampling rect that was used to sample for the atlas. Note that the case
|
||
|
/// of dont-considerMeshUVs is the same as do-considerMeshUVs where the uv rect is 0,0,1,1
|
||
|
/// </summary>
|
||
|
[FormerlySerializedAs("samplingEncapsulatinRect")]
|
||
|
public Rect allPropsUseSameTiling_samplingEncapsulatinRect;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Only valid if allPropsUseSameTiling = false.
|
||
|
/// The UVrect of the source mesh that was baked. We are using a trick here.
|
||
|
/// Instead of storing the material tiling for each
|
||
|
/// texture property here, we instead bake all those tilings into the atlases and here we pretend
|
||
|
/// that all those tilings were 0,0,1,1. Then all we need is to store is the
|
||
|
/// srcUVsamplingRect
|
||
|
/// </summary>
|
||
|
public Rect propsUseDifferntTiling_srcUVsamplingRect;
|
||
|
|
||
|
[NonSerialized]
|
||
|
public List<GameObject> objectsThatUse;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The tiling type for this rectangle in the atlas.
|
||
|
/// Usually use:
|
||
|
/// considerUVs if we baked with the considerUVs feature
|
||
|
/// none if we didn't bake with the considerUVs feature
|
||
|
/// the edge to edge options are for atlases that stretch from one edge to the other with no padding (can be tiled)
|
||
|
/// </summary>
|
||
|
public MB_TextureTilingTreatment tilingTreatment = MB_TextureTilingTreatment.unknown;
|
||
|
|
||
|
/// <param name="mat">The Material</param>
|
||
|
/// <param name="destRect">The rect in the atlas this material maps to</param>
|
||
|
/// <param name="allPropsUseSameTiling">If true then use sourceMaterialTiling and samplingEncapsulatingRect.
|
||
|
/// if false then use srcUVsamplingRect. None used values should be 0,0,0,0.</param>
|
||
|
/// <param name="sourceMaterialTiling">allPropsUseSameTiling_sourceMaterialTiling</param>
|
||
|
/// <param name="samplingEncapsulatingRect">allPropsUseSameTiling_samplingEncapsulatinRect</param>
|
||
|
/// <param name="srcUVsamplingRect">propsUseDifferntTiling_srcUVsamplingRect</param>
|
||
|
public MB_MaterialAndUVRect(Material mat,
|
||
|
Rect destRect,
|
||
|
bool allPropsUseSameTiling,
|
||
|
Rect sourceMaterialTiling,
|
||
|
Rect samplingEncapsulatingRect,
|
||
|
Rect srcUVsamplingRect,
|
||
|
MB_TextureTilingTreatment treatment,
|
||
|
string objName)
|
||
|
{
|
||
|
if (allPropsUseSameTiling)
|
||
|
{
|
||
|
Debug.Assert(srcUVsamplingRect == new Rect(0, 0, 0, 0));
|
||
|
}
|
||
|
|
||
|
if (!allPropsUseSameTiling) {
|
||
|
Debug.Assert(samplingEncapsulatingRect == new Rect(0, 0, 0, 0));
|
||
|
Debug.Assert(sourceMaterialTiling == new Rect(0, 0, 0, 0));
|
||
|
}
|
||
|
|
||
|
material = mat;
|
||
|
atlasRect = destRect;
|
||
|
tilingTreatment = treatment;
|
||
|
this.allPropsUseSameTiling = allPropsUseSameTiling;
|
||
|
allPropsUseSameTiling_sourceMaterialTiling = sourceMaterialTiling;
|
||
|
allPropsUseSameTiling_samplingEncapsulatinRect = samplingEncapsulatingRect;
|
||
|
propsUseDifferntTiling_srcUVsamplingRect = srcUVsamplingRect;
|
||
|
srcObjName = objName;
|
||
|
}
|
||
|
|
||
|
public override int GetHashCode()
|
||
|
{
|
||
|
return material.GetInstanceID() ^ allPropsUseSameTiling_samplingEncapsulatinRect.GetHashCode() ^ propsUseDifferntTiling_srcUVsamplingRect.GetHashCode();
|
||
|
}
|
||
|
|
||
|
public override bool Equals(object obj)
|
||
|
{
|
||
|
if (!(obj is MB_MaterialAndUVRect)) return false;
|
||
|
MB_MaterialAndUVRect b = (MB_MaterialAndUVRect)obj;
|
||
|
return material == b.material &&
|
||
|
allPropsUseSameTiling_samplingEncapsulatinRect == b.allPropsUseSameTiling_samplingEncapsulatinRect &&
|
||
|
allPropsUseSameTiling_sourceMaterialTiling == b.allPropsUseSameTiling_sourceMaterialTiling &&
|
||
|
allPropsUseSameTiling == b.allPropsUseSameTiling &&
|
||
|
propsUseDifferntTiling_srcUVsamplingRect == b.propsUseDifferntTiling_srcUVsamplingRect;
|
||
|
}
|
||
|
|
||
|
public Rect GetEncapsulatingRect()
|
||
|
{
|
||
|
if (allPropsUseSameTiling)
|
||
|
{
|
||
|
return allPropsUseSameTiling_samplingEncapsulatinRect;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return propsUseDifferntTiling_srcUVsamplingRect;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Rect GetMaterialTilingRect()
|
||
|
{
|
||
|
if (allPropsUseSameTiling)
|
||
|
{
|
||
|
return allPropsUseSameTiling_sourceMaterialTiling;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return new Rect(0, 0, 1, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// This class stores the results from an MB2_TextureBaker when materials are combined into atlases. It stores
|
||
|
/// a list of materials and the corresponding UV rectangles in the atlases. It also stores the configuration
|
||
|
/// options that were used to generate the combined material.
|
||
|
///
|
||
|
/// It can be saved as an asset in the project so that textures can be baked in one scene and used in another.
|
||
|
/// </summary>
|
||
|
public class MB2_TextureBakeResults : ScriptableObject {
|
||
|
public class CoroutineResult
|
||
|
{
|
||
|
public bool isComplete;
|
||
|
}
|
||
|
|
||
|
|
||
|
public enum ResultType
|
||
|
{
|
||
|
atlas,
|
||
|
textureArray,
|
||
|
}
|
||
|
|
||
|
public static int VERSION { get { return 3252; } }
|
||
|
|
||
|
public int version;
|
||
|
|
||
|
public ResultType resultType = ResultType.atlas;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Information about the atlas UV rects.
|
||
|
/// IMPORTANT a source material can appear more than once in this list. If we are using considerUVs,
|
||
|
/// then different parts of a source texture could be extracted to different atlas rects.
|
||
|
/// </summary>
|
||
|
public MB_MaterialAndUVRect[] materialsAndUVRects;
|
||
|
|
||
|
/// <summary>
|
||
|
/// This is like the combinedMeshRenderer.sharedMaterials. Some materials may be omitted if they have zero submesh triangles.
|
||
|
/// There is one of these per MultiMaterial mapping.
|
||
|
/// Lists source materials that were combined into each result material, and whether considerUVs was used.
|
||
|
/// This is the result materials if building for atlases.
|
||
|
/// </summary>
|
||
|
public MB_MultiMaterial[] resultMaterials;
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// This is like combinedMeshRenderer.sharedMaterials. Each result mat likely uses a different shader.
|
||
|
/// There is one of these per MultiMaterialTexArray mapping.
|
||
|
/// Each of these lists the slices and each slice has list of source mats that are in that slice.
|
||
|
/// This is the result materials if building for texArrays.
|
||
|
/// </summary>
|
||
|
public MB_MultiMaterialTexArray[] resultMaterialsTexArray;
|
||
|
|
||
|
public bool doMultiMaterial;
|
||
|
|
||
|
public MB2_TextureBakeResults()
|
||
|
{
|
||
|
version = VERSION;
|
||
|
}
|
||
|
|
||
|
private void OnEnable()
|
||
|
{
|
||
|
// backward compatibility copy depricated fixOutOfBounds values to resultMaterials
|
||
|
if (version < 3251)
|
||
|
{
|
||
|
for (int i = 0; i < materialsAndUVRects.Length; i++)
|
||
|
{
|
||
|
materialsAndUVRects[i].allPropsUseSameTiling = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
version = VERSION;
|
||
|
}
|
||
|
|
||
|
public int NumResultMaterials()
|
||
|
{
|
||
|
if (resultType == ResultType.atlas) return resultMaterials.Length;
|
||
|
else return resultMaterialsTexArray.Length;
|
||
|
}
|
||
|
|
||
|
public Material GetCombinedMaterialForSubmesh(int idx)
|
||
|
{
|
||
|
if (resultType == ResultType.atlas)
|
||
|
{
|
||
|
return resultMaterials[idx].combinedMaterial;
|
||
|
} else
|
||
|
{
|
||
|
return resultMaterialsTexArray[idx].combinedMaterial;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// If using addressables and baking meshes at runtime with atlases that were baked in the editor.
|
||
|
/// This method should be called after asset bundles have completed loading but before baking meshes.
|
||
|
///
|
||
|
/// In this case materials used by a mesh at runtime may have been loaded from somewhere other
|
||
|
/// than the build. These materials will be different instances than the Material assets in the project folder.
|
||
|
/// Looking up assets will fail.
|
||
|
/// </summary>
|
||
|
public IEnumerator FindRuntimeMaterialsFromAddresses(CoroutineResult isComplete)
|
||
|
{
|
||
|
yield return MBVersion.FindRuntimeMaterialsFromAddresses(this, isComplete);
|
||
|
isComplete.isComplete = true;
|
||
|
}
|
||
|
|
||
|
public bool GetConsiderMeshUVs(int idxInSrcMats, Material srcMaterial)
|
||
|
{
|
||
|
if (resultType == ResultType.atlas)
|
||
|
{
|
||
|
return resultMaterials[idxInSrcMats].considerMeshUVs;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// TODO do this once and cache.
|
||
|
List<MB_TexArraySlice> slices = resultMaterialsTexArray[idxInSrcMats].slices;
|
||
|
for (int i = 0; i < slices.Count; i++)
|
||
|
{
|
||
|
if (slices[i].ContainsMaterial(srcMaterial)) return slices[i].considerMeshUVs;
|
||
|
}
|
||
|
|
||
|
Debug.LogError("There were no source materials for any slice in this result material.");
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public List<Material> GetSourceMaterialsUsedByResultMaterial(int resultMatIdx)
|
||
|
{
|
||
|
if (resultType == ResultType.atlas)
|
||
|
{
|
||
|
return resultMaterials[resultMatIdx].sourceMaterials;
|
||
|
} else
|
||
|
{
|
||
|
// TODO do this once and cache.
|
||
|
HashSet<Material> output = new HashSet<Material>();
|
||
|
List<MB_TexArraySlice> slices = resultMaterialsTexArray[resultMatIdx].slices;
|
||
|
for (int i = 0; i < slices.Count; i++)
|
||
|
{
|
||
|
List<Material> usedMaterials = new List<Material>();
|
||
|
slices[i].GetAllUsedMaterials(usedMaterials);
|
||
|
for (int j = 0; j < usedMaterials.Count; j++)
|
||
|
{
|
||
|
output.Add(usedMaterials[j]);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
List<Material> outMats = new List<Material>(output);
|
||
|
return outMats;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Creates for materials on renderer.
|
||
|
/// </summary>
|
||
|
/// <returns>Generates an MB2_TextureBakeResult that can be used if all objects to be combined use the same material.
|
||
|
/// Returns a MB2_TextureBakeResults that will map all materials used by renderer r to
|
||
|
/// the rectangle 0,0..1,1 in the atlas.</returns>
|
||
|
public static MB2_TextureBakeResults CreateForMaterialsOnRenderer(GameObject[] gos, List<Material> matsOnTargetRenderer)
|
||
|
{
|
||
|
HashSet<Material> fullMaterialList = new HashSet<Material>(matsOnTargetRenderer);
|
||
|
for (int i = 0; i < gos.Length; i++)
|
||
|
{
|
||
|
if (gos[i] == null)
|
||
|
{
|
||
|
Debug.LogError(string.Format("Game object {0} in list of objects to add was null", i));
|
||
|
return null;
|
||
|
}
|
||
|
Material[] oMats = MB_Utility.GetGOMaterials(gos[i]);
|
||
|
if (oMats.Length == 0)
|
||
|
{
|
||
|
Debug.LogError(string.Format("Game object {0} in list of objects to add no renderer", i));
|
||
|
return null;
|
||
|
}
|
||
|
for (int j = 0; j < oMats.Length; j++)
|
||
|
{
|
||
|
if (!fullMaterialList.Contains(oMats[j])) { fullMaterialList.Add(oMats[j]); }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Material[] rms = new Material[fullMaterialList.Count];
|
||
|
fullMaterialList.CopyTo(rms);
|
||
|
MB2_TextureBakeResults tbr = (MB2_TextureBakeResults) ScriptableObject.CreateInstance( typeof(MB2_TextureBakeResults) );
|
||
|
List<MB_MaterialAndUVRect> mss = new List<MB_MaterialAndUVRect>();
|
||
|
for (int i = 0; i < rms.Length; i++)
|
||
|
{
|
||
|
if (rms[i] != null)
|
||
|
{
|
||
|
MB_MaterialAndUVRect matAndUVRect = new MB_MaterialAndUVRect(rms[i], new Rect(0f, 0f, 1f, 1f), true, new Rect(0f,0f,1f,1f), new Rect(0f,0f,1f,1f), new Rect(0,0,0,0), MB_TextureTilingTreatment.none, "");
|
||
|
if (!mss.Contains(matAndUVRect))
|
||
|
{
|
||
|
mss.Add(matAndUVRect);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
tbr.resultMaterials = new MB_MultiMaterial[mss.Count];
|
||
|
for (int i = 0; i < mss.Count; i++){
|
||
|
tbr.resultMaterials[i] = new MB_MultiMaterial();
|
||
|
List<Material> sourceMats = new List<Material>();
|
||
|
sourceMats.Add (mss[i].material);
|
||
|
tbr.resultMaterials[i].sourceMaterials = sourceMats;
|
||
|
tbr.resultMaterials[i].combinedMaterial = mss[i].material;
|
||
|
tbr.resultMaterials[i].considerMeshUVs = false;
|
||
|
}
|
||
|
if (rms.Length == 1)
|
||
|
{
|
||
|
tbr.doMultiMaterial = false;
|
||
|
} else
|
||
|
{
|
||
|
tbr.doMultiMaterial = true;
|
||
|
}
|
||
|
|
||
|
tbr.materialsAndUVRects = mss.ToArray();
|
||
|
return tbr;
|
||
|
}
|
||
|
|
||
|
public bool DoAnyResultMatsUseConsiderMeshUVs()
|
||
|
{
|
||
|
if (resultType == ResultType.atlas)
|
||
|
{
|
||
|
if (resultMaterials == null) return false;
|
||
|
for (int i = 0; i < resultMaterials.Length; i++)
|
||
|
{
|
||
|
if (resultMaterials[i].considerMeshUVs) return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (resultMaterialsTexArray == null) return false;
|
||
|
for (int i = 0; i < resultMaterialsTexArray.Length; i++)
|
||
|
{
|
||
|
MB_MultiMaterialTexArray resMat = resultMaterialsTexArray[i];
|
||
|
for (int j = 0; j < resMat.slices.Count; j++)
|
||
|
{
|
||
|
if (resMat.slices[j].considerMeshUVs) return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool ContainsMaterial(Material m)
|
||
|
{
|
||
|
for (int i = 0; i < materialsAndUVRects.Length; i++)
|
||
|
{
|
||
|
if (materialsAndUVRects[i].material == m){
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
public string GetDescription(){
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
sb.Append("Shaders:\n");
|
||
|
HashSet<Shader> shaders = new HashSet<Shader>();
|
||
|
if (materialsAndUVRects != null){
|
||
|
for (int i = 0; i < materialsAndUVRects.Length; i++){
|
||
|
if (materialsAndUVRects[i].material != null)
|
||
|
{
|
||
|
shaders.Add(materialsAndUVRects[i].material.shader);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
foreach(Shader m in shaders){
|
||
|
sb.Append(" ").Append(m.name).AppendLine();
|
||
|
}
|
||
|
sb.Append("Materials:\n");
|
||
|
if (materialsAndUVRects != null){
|
||
|
for (int i = 0; i < materialsAndUVRects.Length; i++){
|
||
|
if (materialsAndUVRects[i].material != null)
|
||
|
{
|
||
|
sb.Append(" ").Append(materialsAndUVRects[i].material.name).AppendLine();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return sb.ToString();
|
||
|
}
|
||
|
|
||
|
public void UpgradeToCurrentVersion(MB2_TextureBakeResults tbr)
|
||
|
{
|
||
|
if (tbr.version < 3252)
|
||
|
{
|
||
|
for (int i = 0; i < tbr.materialsAndUVRects.Length; i++)
|
||
|
{
|
||
|
tbr.materialsAndUVRects[i].allPropsUseSameTiling = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static bool IsMeshAndMaterialRectEnclosedByAtlasRect(MB_TextureTilingTreatment tilingTreatment, Rect uvR, Rect sourceMaterialTiling, Rect samplingEncapsulatinRect, MB2_LogLevel logLevel)
|
||
|
{
|
||
|
Rect potentialRect = new Rect();
|
||
|
// test to see if this would fit in what was baked in the atlas
|
||
|
|
||
|
potentialRect = MB3_UVTransformUtility.CombineTransforms(ref uvR, ref sourceMaterialTiling);
|
||
|
if (logLevel >= MB2_LogLevel.trace)
|
||
|
{
|
||
|
if (logLevel >= MB2_LogLevel.trace) Debug.Log("IsMeshAndMaterialRectEnclosedByAtlasRect Rect in atlas uvR=" + uvR.ToString("f5") + " sourceMaterialTiling=" + sourceMaterialTiling.ToString("f5") + "Potential Rect (must fit in encapsulating) " + potentialRect.ToString("f5") + " encapsulating=" + samplingEncapsulatinRect.ToString("f5") + " tilingTreatment=" + tilingTreatment);
|
||
|
}
|
||
|
|
||
|
if (tilingTreatment == MB_TextureTilingTreatment.edgeToEdgeX)
|
||
|
{
|
||
|
if (MB3_UVTransformUtility.LineSegmentContainsShifted(samplingEncapsulatinRect.y, samplingEncapsulatinRect.height, potentialRect.y, potentialRect.height))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
else if (tilingTreatment == MB_TextureTilingTreatment.edgeToEdgeY)
|
||
|
{
|
||
|
if (MB3_UVTransformUtility.LineSegmentContainsShifted(samplingEncapsulatinRect.x, samplingEncapsulatinRect.width, potentialRect.x, potentialRect.width))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
else if (tilingTreatment == MB_TextureTilingTreatment.edgeToEdgeXY)
|
||
|
{
|
||
|
//only one rect in atlas and is edge to edge in both X and Y directions.
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (MB3_UVTransformUtility.RectContainsShifted(ref samplingEncapsulatinRect, ref potentialRect))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
}
|