123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- using UnityEngine;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Reflection;
- namespace DigitalOpus.MB.Core
- {
- public class MB3_TextureCombinerNonTextureProperties
- {
- public interface MaterialProperty
- {
- string PropertyName { get; set; }
- MaterialPropertyValueAveraged GetAverageCalculator();
- object GetDefaultValue();
- }
- public class MaterialPropertyFloat : MaterialProperty
- {
- public string PropertyName { get; set; }
- MaterialPropertyValueAveragedFloat _averageCalc;
- float _defaultValue;
- public MaterialPropertyFloat(string name, float defValue)
- {
- _averageCalc = new MaterialPropertyValueAveragedFloat();
- _defaultValue = defValue;
- PropertyName = name;
- }
- public MaterialPropertyValueAveraged GetAverageCalculator()
- {
- return _averageCalc;
- }
- public object GetDefaultValue()
- {
- return _defaultValue;
- }
- }
- public class MaterialPropertyColor : MaterialProperty
- {
- public string PropertyName { get; set; }
- MaterialPropertyValueAveragedColor _averageCalc;
- Color _defaultValue;
- public MaterialPropertyColor(string name, Color defaultVal)
- {
- _averageCalc = new MaterialPropertyValueAveragedColor();
- _defaultValue = defaultVal;
- PropertyName = name;
- }
- public MaterialPropertyValueAveraged GetAverageCalculator()
- {
- return _averageCalc;
- }
- public object GetDefaultValue()
- {
- return _defaultValue;
- }
- }
- public interface MaterialPropertyValueAveraged
- {
- void TryGetPropValueFromMaterialAndBlendIntoAverage(Material mat, MaterialProperty property);
- object GetAverage();
- int NumValues();
- void SetAverageValueOrDefaultOnMaterial(Material mat, MaterialProperty property);
- }
- public class MaterialPropertyValueAveragedFloat : MaterialPropertyValueAveraged
- {
- public float averageVal;
- public int numValues;
- public void TryGetPropValueFromMaterialAndBlendIntoAverage(Material mat, MaterialProperty property)
- {
- if (mat.HasProperty(property.PropertyName))
- {
- float v = mat.GetFloat(property.PropertyName);
- averageVal = averageVal * ((float)numValues) / (numValues + 1) + v / (numValues + 1);
- numValues++;
- }
- }
- public object GetAverage()
- {
- return averageVal;
- }
- public int NumValues()
- {
- return numValues;
- }
- public void SetAverageValueOrDefaultOnMaterial(Material mat, MaterialProperty property)
- {
- if (mat.HasProperty(property.PropertyName))
- {
- if (numValues > 0)
- {
- mat.SetFloat(property.PropertyName, averageVal);
- } else
- {
- mat.SetFloat(property.PropertyName, (float)property.GetDefaultValue());
- }
- }
- }
- }
- public class MaterialPropertyValueAveragedColor : MaterialPropertyValueAveraged
- {
- public Color averageVal;
- public int numValues;
- public void TryGetPropValueFromMaterialAndBlendIntoAverage(Material mat, MaterialProperty property)
- {
- if (mat.HasProperty(property.PropertyName))
- {
- Color v = mat.GetColor(property.PropertyName);
- averageVal = averageVal * ((float)numValues) / (numValues + 1) + v / (numValues + 1);
- numValues++;
- }
- }
- public object GetAverage()
- {
- return averageVal;
- }
- public int NumValues()
- {
- return numValues;
- }
- public void SetAverageValueOrDefaultOnMaterial(Material mat, MaterialProperty property)
- {
- if (mat.HasProperty(property.PropertyName))
- {
- if (numValues > 0)
- {
- mat.SetColor(property.PropertyName, averageVal);
- }
- else
- {
- mat.SetColor(property.PropertyName, (Color) property.GetDefaultValue());
- }
- }
- }
- }
- public struct TexPropertyNameColorPair
- {
- public string name;
- public Color color;
- public TexPropertyNameColorPair(string nm, Color col)
- {
- name = nm;
- color = col;
- }
- }
- private interface NonTextureProperties
- {
- bool NonTexturePropertiesAreEqual(Material a, Material b);
- Texture2D TintTextureWithTextureCombiner(Texture2D t, MB_TexSet sourceMaterial, ShaderTextureProperty shaderPropertyName);
- void AdjustNonTextureProperties(Material resultMat, List<ShaderTextureProperty> texPropertyNames, MB2_EditorMethodsInterface editorMethods);
- Color GetColorForTemporaryTexture(Material matIfBlender, ShaderTextureProperty texProperty);
- Color GetColorAsItWouldAppearInAtlasIfNoTexture(Material matIfBlender, ShaderTextureProperty texProperty);
- }
- private class NonTexturePropertiesDontBlendProps : NonTextureProperties
- {
- MB3_TextureCombinerNonTextureProperties _textureProperties;
- public NonTexturePropertiesDontBlendProps(MB3_TextureCombinerNonTextureProperties textureProperties)
- {
- _textureProperties = textureProperties;
- }
- public bool NonTexturePropertiesAreEqual(Material a, Material b)
- {
- Debug.Assert(_textureProperties._considerNonTextureProperties == false);
- return true;
- }
- public Texture2D TintTextureWithTextureCombiner(Texture2D t, MB_TexSet sourceMaterial, ShaderTextureProperty shaderPropertyName)
- {
- Debug.Assert(_textureProperties._considerNonTextureProperties == false);
- Debug.LogError("TintTextureWithTextureCombiner should never be called if resultMaterialTextureBlender is null");
- return t;
- }
- public void AdjustNonTextureProperties(Material resultMat, List<ShaderTextureProperty> texPropertyNames, MB2_EditorMethodsInterface editorMethods)
- {
- Debug.Assert(_textureProperties._considerNonTextureProperties == false);
- if (resultMat == null || texPropertyNames == null) return;
- for (int nonTexPropIdx = 0; nonTexPropIdx < _textureProperties._nonTextureProperties.Length; nonTexPropIdx++)
- {
- MaterialProperty nonTexProperty = _textureProperties._nonTextureProperties[nonTexPropIdx];
- if (resultMat.HasProperty(nonTexProperty.PropertyName))
- {
- nonTexProperty.GetAverageCalculator().SetAverageValueOrDefaultOnMaterial(resultMat, nonTexProperty);
- }
- }
- if (editorMethods != null)
- {
- editorMethods.CommitChangesToAssets();
- }
- }
- public Color GetColorAsItWouldAppearInAtlasIfNoTexture(Material matIfBlender, ShaderTextureProperty texProperty)
- {
- Debug.Assert(false, "Should never be called");
- return Color.white;
- }
- public Color GetColorForTemporaryTexture(Material matIfBlender, ShaderTextureProperty texProperty)
- {
- Debug.Assert(_textureProperties._considerNonTextureProperties == false);
- if (texProperty.isNormalMap)
- {
- return NEUTRAL_NORMAL_MAP_COLOR;
- }
- else if (_textureProperties.textureProperty2DefaultColorMap.ContainsKey(texProperty.name))
- {
- return _textureProperties.textureProperty2DefaultColorMap[texProperty.name];
- }
- return new Color(1f, 1f, 1f, 0f);
- }
- }
- private class NonTexturePropertiesBlendProps : NonTextureProperties
- {
- MB3_TextureCombinerNonTextureProperties _textureProperties;
- TextureBlender resultMaterialTextureBlender;
- public NonTexturePropertiesBlendProps(MB3_TextureCombinerNonTextureProperties textureProperties, TextureBlender resultMats)
- {
- resultMaterialTextureBlender = resultMats;
- _textureProperties = textureProperties;
- }
- public bool NonTexturePropertiesAreEqual(Material a, Material b)
- {
- Debug.Assert(resultMaterialTextureBlender != null);
- return resultMaterialTextureBlender.NonTexturePropertiesAreEqual(a, b);
- }
- public Texture2D TintTextureWithTextureCombiner(Texture2D t, MB_TexSet sourceMaterial, ShaderTextureProperty shaderPropertyName)
- {
- Debug.Assert(resultMaterialTextureBlender != null);
- resultMaterialTextureBlender.OnBeforeTintTexture(sourceMaterial.matsAndGOs.mats[0].mat, shaderPropertyName.name);
- if (_textureProperties.LOG_LEVEL >= MB2_LogLevel.trace) Debug.Log(string.Format("Blending texture {0} mat {1} with non-texture properties using TextureBlender {2}", t.name, sourceMaterial.matsAndGOs.mats[0].mat, resultMaterialTextureBlender));
- for (int i = 0; i < t.height; i++)
- {
- Color[] cs = t.GetPixels(0, i, t.width, 1);
- for (int j = 0; j < cs.Length; j++)
- {
- cs[j] = resultMaterialTextureBlender.OnBlendTexturePixel(shaderPropertyName.name, cs[j]);
- }
- t.SetPixels(0, i, t.width, 1, cs);
- }
- t.Apply();
- return t;
- }
- public void AdjustNonTextureProperties(Material resultMat, List<ShaderTextureProperty> texPropertyNames, MB2_EditorMethodsInterface editorMethods)
- {
- if (resultMat == null || texPropertyNames == null) return;
- //try to use a texture blender if we can find one to set the non-texture property values
- if (_textureProperties.LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("Adjusting non texture properties using TextureBlender for shader: " + resultMat.shader.name);
- resultMaterialTextureBlender.SetNonTexturePropertyValuesOnResultMaterial(resultMat);
- if (editorMethods != null)
- {
- editorMethods.CommitChangesToAssets();
- }
- }
- public Color GetColorAsItWouldAppearInAtlasIfNoTexture(Material matIfBlender, ShaderTextureProperty texProperty)
- {
- resultMaterialTextureBlender.OnBeforeTintTexture(matIfBlender, texProperty.name);
- Color c = GetColorForTemporaryTexture(matIfBlender, texProperty);
- return resultMaterialTextureBlender.OnBlendTexturePixel(texProperty.name, c);
- }
- public Color GetColorForTemporaryTexture(Material matIfBlender, ShaderTextureProperty texProperty)
- {
- return resultMaterialTextureBlender.GetColorIfNoTexture(matIfBlender, texProperty);
- }
- }
- public static Color NEUTRAL_NORMAL_MAP_COLOR = new Color(.5f, .5f, 1f);
- TexPropertyNameColorPair[] defaultTextureProperty2DefaultColorMap = new TexPropertyNameColorPair[]
- {
- new TexPropertyNameColorPair("_MainTex", new Color(1f, 1f, 1f, 0f)),
- new TexPropertyNameColorPair("_MetallicGlossMap", new Color(0f, 0f, 0f, 1f)),
- new TexPropertyNameColorPair("_ParallaxMap", new Color(0f, 0f, 0f, 0f)),
- new TexPropertyNameColorPair("_OcclusionMap", new Color(1f, 1f, 1f, 1f)),
- new TexPropertyNameColorPair("_EmissionMap", new Color(0f, 0f, 0f, 0f)),
- new TexPropertyNameColorPair("_DetailMask", new Color(0f, 0f, 0f, 0f)),
- };
- MB3_TextureCombinerNonTextureProperties.MaterialProperty[] _nonTextureProperties = new MB3_TextureCombinerNonTextureProperties.MaterialProperty[]
- {
- new MB3_TextureCombinerNonTextureProperties.MaterialPropertyColor("_Color", Color.white),
- //new MB3_TextureCombinerNonTextureProperties.MaterialPropertyFloat("_Cutoff"),
- new MB3_TextureCombinerNonTextureProperties.MaterialPropertyFloat("_Glossiness", .5f),
- new MB3_TextureCombinerNonTextureProperties.MaterialPropertyFloat("_GlossMapScale", 1f),
- new MB3_TextureCombinerNonTextureProperties.MaterialPropertyFloat("_Metallic", 0f),
- //new MB3_TextureCombinerNonTextureProperties.MaterialPropertyFloat("_SpecularHightlights"),
- //new MB3_TextureCombinerNonTextureProperties.MaterialPropertyFloat("_GlossyReflections"),
- new MB3_TextureCombinerNonTextureProperties.MaterialPropertyFloat("_BumpScale", .1f),
- new MB3_TextureCombinerNonTextureProperties.MaterialPropertyFloat("_Parallax", .02f),
- new MB3_TextureCombinerNonTextureProperties.MaterialPropertyFloat("_OcclusionStrength", 1f),
- new MB3_TextureCombinerNonTextureProperties.MaterialPropertyColor("_EmissionColor", Color.black),
- };
- MB2_LogLevel LOG_LEVEL = MB2_LogLevel.info;
- bool _considerNonTextureProperties = false;
- private TextureBlender resultMaterialTextureBlender;
- private TextureBlender[] textureBlenders = new TextureBlender[0];
- private Dictionary<string, Color> textureProperty2DefaultColorMap = new Dictionary<string, Color>();
- private NonTextureProperties _nonTexturePropertiesBlender;
- public MB3_TextureCombinerNonTextureProperties(MB2_LogLevel ll, bool considerNonTextureProps)
- {
- LOG_LEVEL = ll;
- _considerNonTextureProperties = considerNonTextureProps;
- textureProperty2DefaultColorMap = new Dictionary<string, Color>();
- for (int i = 0; i < defaultTextureProperty2DefaultColorMap.Length; i++)
- {
- textureProperty2DefaultColorMap.Add(defaultTextureProperty2DefaultColorMap[i].name,
- defaultTextureProperty2DefaultColorMap[i].color);
- _nonTexturePropertiesBlender = new NonTexturePropertiesDontBlendProps(this);
- }
- }
- internal void CollectAverageValuesOfNonTextureProperties(Material resultMaterial, Material mat)
- {
- for (int i = 0; i < _nonTextureProperties.Length; i++)
- {
- MB3_TextureCombinerNonTextureProperties.MaterialProperty prop = _nonTextureProperties[i];
- if (resultMaterial.HasProperty(prop.PropertyName))
- {
- prop.GetAverageCalculator().TryGetPropValueFromMaterialAndBlendIntoAverage(mat, prop);
- }
- }
- }
- internal void LoadTextureBlendersIfNeeded(Material resultMaterial)
- {
- if (_considerNonTextureProperties)
- {
- LoadTextureBlenders();
- FindBestTextureBlender(resultMaterial);
- }
- }
- #if UNITY_WSA && !UNITY_EDITOR
- //not defined for WSA runtime
- #else
- private static bool InterfaceFilter(Type typeObj, System.Object criteriaObj)
- {
- return typeObj.ToString() == criteriaObj.ToString();
- }
- #endif
- private void FindBestTextureBlender(Material resultMaterial)
- {
- Debug.Assert(_considerNonTextureProperties);
- resultMaterialTextureBlender = FindMatchingTextureBlender(resultMaterial.shader.name);
- if (resultMaterialTextureBlender != null)
- {
- if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("Using Consider Non-Texture Properties found a TextureBlender for result material. Using: " + resultMaterialTextureBlender);
- }
- else
- {
- if (LOG_LEVEL >= MB2_LogLevel.error) Debug.LogWarning("Using _considerNonTextureProperties could not find a TextureBlender that matches the shader on the result material. Using the Fallback Texture Blender.");
- resultMaterialTextureBlender = new TextureBlenderFallback();
- }
- _nonTexturePropertiesBlender = new NonTexturePropertiesBlendProps(this, resultMaterialTextureBlender);
- }
- private void LoadTextureBlenders()
- {
- #if UNITY_WSA && !UNITY_EDITOR
- //not defined for WSA runtime
- #else
- Debug.Assert(_considerNonTextureProperties);
- string qualifiedInterfaceName = "DigitalOpus.MB.Core.TextureBlender";
- var interfaceFilter = new TypeFilter(InterfaceFilter);
- List<Type> types = new List<Type>();
- foreach (Assembly ass in AppDomain.CurrentDomain.GetAssemblies())
- {
- System.Collections.IEnumerable typesIterator = null;
- try
- {
- typesIterator = ass.GetTypes();
- }
- catch (Exception e)
- {
- //Debug.Log("The assembly that I could not read types for was: " + ass.GetName());
- //suppress error
- e.Equals(null);
- }
- if (typesIterator != null)
- {
- foreach (Type ty in ass.GetTypes())
- {
- var myInterfaces = ty.FindInterfaces(interfaceFilter, qualifiedInterfaceName);
- if (myInterfaces.Length > 0)
- {
- types.Add(ty);
- }
- }
- }
- }
- TextureBlender fallbackTB = null;
- List<TextureBlender> textureBlendersList = new List<TextureBlender>();
- foreach (Type tt in types)
- {
- if (!tt.IsAbstract && !tt.IsInterface)
- {
- TextureBlender instance = (TextureBlender) System.Activator.CreateInstance(tt);
- if (instance is TextureBlenderFallback)
- {
- fallbackTB = instance;
- }
- else
- {
- textureBlendersList.Add(instance);
- }
- }
- }
- if (fallbackTB != null) textureBlendersList.Add(fallbackTB); // must come last in list
- textureBlenders = textureBlendersList.ToArray();
- if (LOG_LEVEL >= MB2_LogLevel.debug)
- {
- Debug.Log(string.Format("Loaded {0} TextureBlenders.", textureBlenders.Length));
- }
- #endif
- }
- internal bool NonTexturePropertiesAreEqual(Material a, Material b)
- {
- return _nonTexturePropertiesBlender.NonTexturePropertiesAreEqual(a, b);
- }
- internal Texture2D TintTextureWithTextureCombiner(Texture2D t, MB_TexSet sourceMaterial, ShaderTextureProperty shaderPropertyName)
- {
- return _nonTexturePropertiesBlender.TintTextureWithTextureCombiner(t, sourceMaterial, shaderPropertyName);
- }
- //If we are switching from a Material that uses color properties to
- //using atlases don't want some properties such as _Color to be copied
- //from the original material because the atlas texture will be multiplied
- //by that color
- internal void AdjustNonTextureProperties(Material resultMat, List<ShaderTextureProperty> texPropertyNames, MB2_EditorMethodsInterface editorMethods)
- {
- if (resultMat == null || texPropertyNames == null) return;
- _nonTexturePropertiesBlender.AdjustNonTextureProperties(resultMat, texPropertyNames, editorMethods);
- }
- internal Color GetColorAsItWouldAppearInAtlasIfNoTexture(Material matIfBlender, ShaderTextureProperty texProperty)
- {
- return _nonTexturePropertiesBlender.GetColorAsItWouldAppearInAtlasIfNoTexture(matIfBlender, texProperty);
- }
- internal Color GetColorForTemporaryTexture(Material matIfBlender, ShaderTextureProperty texProperty)
- {
- return _nonTexturePropertiesBlender.GetColorForTemporaryTexture(matIfBlender, texProperty);
- }
- private TextureBlender FindMatchingTextureBlender(string shaderName)
- {
- for (int i = 0; i < textureBlenders.Length; i++)
- {
- if (textureBlenders[i].DoesShaderNameMatch(shaderName))
- {
- return textureBlenders[i];
- }
- }
- return null;
- }
- }
- }
|