Files
Project-M/Packages/com.shadercrew.the-toon-shader.core/Scripts/Runtime/Common/ReplaceAndSyncUtils.cs
T
kronic e362aaeb43 Import art/VFX asset packs + game-feel systems; normalize texture extensions to lowercase for LFS
Add BefourStudios SciFi environment packs, Gabriel Aguiar VFX, and the
ShaderCrew Toon Shader embedded packages, plus combat/enemy/wave/death
gameplay systems and supporting vault docs/screenshots.

Rename 11 vendor textures from uppercase .PNG/.HDR to lowercase so the
case-sensitive Git LFS filters (*.png/*.hdr) match on case-sensitive
filesystems (Linux CI, case-sensitive macOS), not just locally where
core.ignorecase=true masks the gap. Each .meta moved with its asset so
GUID references are preserved. All ~1000 binaries tracked via LFS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 22:50:43 -07:00

495 lines
24 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
namespace ShaderCrew.TheToonShader
{
public static class ReplaceAndSyncUtils
{
public static void AddTheToonShaderInstancePrefix(Material materialInstance)
{
string name = materialInstance.name;
name = name.Replace(" (Instance)", "");
if (!name.Contains(TheToonShaderConstants.THETOONSHADER_INSTANCE_PREFIX))
{
materialInstance.name = name + " (" + TheToonShaderConstants.THETOONSHADER_INSTANCE_PREFIX + ")";
}
}
private static Material getFirstInstancedMaterial(Transform[] transforms)
{
if (transforms != null && transforms.Length > 0)
{
foreach (Transform transform in transforms)
{
if (transform != null)
{
Renderer renderer = transform.GetComponent<Renderer>();
if (renderer != null)
{
Material[] materials = renderer.sharedMaterials;
if (materials != null && materials.Length > 0)
{
foreach (Material material in materials)
{
if (IsTheToonShaderMaterial(material))
{
return material;
}
}
}
}
}
}
}
return null;
}
/// <summary>
/// Gets all materials, including the ones in various LOD levels, which are associated with given transforms
public static List<Material> GetAllTheToonShaderMaterialsFromTransforms(Transform[] transforms, Material referenceMaterial)
{
List<Material> materialList = new List<Material>();
foreach (Transform transform in transforms)
{
if(transform != null)
{
//Renderer rendererNonLOD = transform.GetComponent<Renderer>();
Renderer[] rendererNonLODArray = transform.GetComponentsInChildren<Renderer>();
for (int i = 0; i < rendererNonLODArray.Length; i++)
{
if (transform.GetComponent<LODGroup>() != null)
{
foreach (LOD lod in transform.GetComponent<LODGroup>().GetLODs())
{
foreach (Renderer renderer in lod.renderers)
{
if (renderer == rendererNonLODArray[i])
{
rendererNonLODArray[i] = null;
}
if (renderer != null && renderer.sharedMaterials.Length > 0)
{
foreach (Material material in renderer.sharedMaterials)
{
if (material != null && IsTheToonShaderMaterial(material))
{
if (!materialList.Contains(material))
{
materialList.Add(material);
}
}
}
}
}
}
}
if (rendererNonLODArray[i] != null)
{
Material[] materials = rendererNonLODArray[i].sharedMaterials;
if (materials.Length > 0)
{
foreach (Material material in materials)
{
if (material != null && IsTheToonShaderMaterial(material))
{
if (!materialList.Contains(material))
{
materialList.Add(material);
}
}
}
}
}
}
}
}
return materialList;
}
private static bool IsTheToonShaderMaterial(Material material)
{
return (material != null && material.HasProperty(TheToonShaderConstants.THETOONSHADER_IDENTIFIER_PROPERTY));
}
public static void SyncKeywords(Material source, Material target)
{
if (source == null || target == null)
return;
if (source.shader != target.shader)
return;
//Debug.LogWarning("SyncKeywords: materials use different shaders.");
target.shaderKeywords = source.shaderKeywords;
}
public static void UpdateTheToonShaderMaterialPropertiesAndKeywords(List<Material> materials, Material referenceMaterial,
Dictionary<string, bool> propertyNameToBoolDictionary,
bool forceUpdateOfAllPropertiesAndKeywords = false)
{
if(forceUpdateOfAllPropertiesAndKeywords)
{
//bool doKeywordSync = false; //a bit of a hack, make cleaner 1
List<string> properties = new List<string>();
foreach (string propertyName in ShaderUtils.ALL_PROPERITES)
{
bool propertyInsideDictionary = propertyNameToBoolDictionary.TryGetValue(propertyName, out bool propertyToggled);
if (propertyInsideDictionary && propertyName != null)
{
if (propertyToggled)
{
properties.Add(propertyName);
////a bit of a hack, make cleaner 2
//if(propertyName.Equals("_ShadingMode"))
//{
// doKeywordSync = true;
//}
}
}
}
List<string> keywords = ShaderUtils.GetKeywordList(properties);
foreach (Material material in materials)
{
if (properties.Count > 0)
{
updateMaterialProperties(material, referenceMaterial, properties);
}
//if(doKeywordSync)//a bit of a hack, make cleaner 3
//{
// updateMaterialKeywords(material, referenceMaterial, ShaderUtils.THETOONSHADER_KEYWORDS_LIST);
//}
//SyncKeywords(referenceMaterial, material);
updateMaterialKeywords(material, referenceMaterial, keywords);
}
}
else
{
Material firstInstancedMaterial = null;
foreach (Material material in materials)
{
if (IsTheToonShaderMaterial(material))
{
firstInstancedMaterial = material;
break;
}
}
if (firstInstancedMaterial != null)
{
List<string> namesOfChangedProperties = GetNamesOfAllChangedPropertyValues(firstInstancedMaterial, referenceMaterial, propertyNameToBoolDictionary);
List<string> namesOfChangedKeywords = GetNamesOfAllChangedKeywordValues(firstInstancedMaterial, referenceMaterial, namesOfChangedProperties);
if ((namesOfChangedProperties != null && namesOfChangedProperties.Count > 0) || (namesOfChangedKeywords != null && namesOfChangedKeywords.Count > 0))
{
foreach (Material material in materials)
{
if (namesOfChangedProperties.Count > 0)
{
updateMaterialProperties(material, referenceMaterial, namesOfChangedProperties);
}
if (namesOfChangedKeywords.Count > 0)
{
//if(namesOfChangedProperties.Contains("_ShadingMode")) //a bit of a hack, make cleaner 4
{
updateMaterialKeywords(material, referenceMaterial, namesOfChangedKeywords);
}
}
}
}
}
}
}
public static void UpdateTheToonShaderMaterialPropertiesAndKeywords(Transform[] transforms, Material referenceMaterial,
Dictionary<string, bool> propertyNameToBoolDictionary,
bool forceUpdateOfAllPropertiesAndKeywords = false)
{
//bool doKeywordSync = false; //a bit of a hack, make cleaner 1
if (forceUpdateOfAllPropertiesAndKeywords)
{
//Debug.Log("UpdateTheToonShaderMaterialPropertiesAndKeywords forced");
List<string> properties = new List<string>();
foreach (string propertyName in ShaderUtils.ALL_PROPERITES)
{
bool propertyInsideDictionary = propertyNameToBoolDictionary.TryGetValue(propertyName, out bool propertyToggled);
if (propertyInsideDictionary && propertyName != null)
{
if (propertyToggled)
{
properties.Add(propertyName);
//if (propertyName.Equals("_ShadingMode")) //a bit of a hack, make cleaner 2
//{
// doKeywordSync = true;
//}
}
}
}
List<string> keywords = ShaderUtils.GetKeywordList(properties);
List<Material> allTheToonShaderMaterials = GetAllTheToonShaderMaterialsFromTransforms(transforms, referenceMaterial);
//Debug.Log("Toon Shader Count: " + allTheToonShaderMaterials.Count);
if (allTheToonShaderMaterials != null && allTheToonShaderMaterials.Count > 0)
{
foreach (Material material in allTheToonShaderMaterials)
{
//Debug.Log("Material name: " + material.name);
if (properties.Count > 0)
{
updateMaterialProperties(material, referenceMaterial, properties);
}
//if (doKeywordSync)//a bit of a hack, make cleaner 3
//{
// updateMaterialKeywords(material, referenceMaterial, ShaderUtils.THETOONSHADER_KEYWORDS_LIST);
//}
//SyncKeywords(referenceMaterial, material);
updateMaterialKeywords(material, referenceMaterial, keywords);
}
}
}
else
{
//Debug.Log("UpdateTheToonShaderMaterialPropertiesAndKeywords");
Material firstInstancedMaterial = getFirstInstancedMaterial(transforms);
if (firstInstancedMaterial != null)
{
List<string> namesOfChangedProperties = GetNamesOfAllChangedPropertyValues(firstInstancedMaterial, referenceMaterial, propertyNameToBoolDictionary);
List<string> namesOfChangedKeywords = GetNamesOfAllChangedKeywordValues(firstInstancedMaterial, referenceMaterial, namesOfChangedProperties);
if ((namesOfChangedProperties != null && namesOfChangedProperties.Count > 0) || (namesOfChangedKeywords != null && namesOfChangedKeywords.Count > 0))
{
List<Material> allTheToonShaderMaterials = GetAllTheToonShaderMaterialsFromTransforms(transforms, referenceMaterial);
if(allTheToonShaderMaterials != null && allTheToonShaderMaterials.Count > 0)
{
foreach (Material material in allTheToonShaderMaterials)
{
if (namesOfChangedProperties.Count > 0)
{
updateMaterialProperties(material, referenceMaterial, namesOfChangedProperties);
}
if (namesOfChangedKeywords.Count > 0)
{
//if (namesOfChangedProperties.Contains("_ShadingMode")) //a bit of a hack, make cleaner 4
{
updateMaterialKeywords(material, referenceMaterial, namesOfChangedKeywords);
}
}
}
}
}
}
}
}
private static void updateMaterialProperties(Material instancedMaterial, Material referenceMaterial, List<string> namesOfChangedProperties)
{
if (instancedMaterial != null && referenceMaterial != null && namesOfChangedProperties != null && namesOfChangedProperties.Count > 0)
{
Shader shader = referenceMaterial.shader;
foreach (string propertyName in namesOfChangedProperties)
{
if (referenceMaterial.HasProperty(propertyName) && instancedMaterial.HasProperty(propertyName))
{
ShaderPropertyType shaderPropertyType = shader.GetPropertyType(shader.FindPropertyIndex(propertyName));
if (shaderPropertyType == ShaderPropertyType.Float || shaderPropertyType == ShaderPropertyType.Range)
{
float value = referenceMaterial.GetFloat(propertyName);
instancedMaterial.SetFloat(propertyName, value);
}
else if (shaderPropertyType == ShaderPropertyType.Color)
{
Color value = referenceMaterial.GetColor(propertyName);
instancedMaterial.SetColor(propertyName, value);
}
else if (shaderPropertyType == ShaderPropertyType.Texture)
{
Texture texture = referenceMaterial.GetTexture(propertyName);
instancedMaterial.SetTexture(propertyName, texture);
Vector2 offset = referenceMaterial.GetTextureOffset(propertyName);
instancedMaterial.SetTextureOffset(propertyName, offset);
Vector2 scale = referenceMaterial.GetTextureScale(propertyName);
instancedMaterial.SetTextureScale(propertyName, scale);
}
else if (shaderPropertyType == ShaderPropertyType.Vector)
{
Vector4 vector = referenceMaterial.GetVector(propertyName);
instancedMaterial.SetVector(propertyName, vector);
}
}
}
}
}
private static void updateMaterialKeywords(Material instancedMaterial, Material referenceMaterial, List<string> namesOfChangedKeywords)
{
foreach (string keyword in namesOfChangedKeywords)
{
bool isKeywordEnabled = referenceMaterial.IsKeywordEnabled(keyword);
if (isKeywordEnabled)
{
instancedMaterial.EnableKeyword(keyword);
}
else
{
instancedMaterial.DisableKeyword(keyword);
}
}
}
private static List<string> GetNamesOfAllChangedPropertyValues(Material instancedMaterial,
Material referenceMaterial,
Dictionary<string, bool> propertyNameToBoolDictionary)
{
if (instancedMaterial != null && referenceMaterial != null)
{
if (IsTheToonShaderMaterial(instancedMaterial) && IsTheToonShaderMaterial(referenceMaterial))
{
Shader shader = referenceMaterial.shader;
List<string> namesOfChangedProperties = new List<string>();
foreach (string propertyName in ShaderUtils.ALL_PROPERITES)
{
if (referenceMaterial.HasProperty(propertyName) && instancedMaterial.HasProperty(propertyName))
{
bool propertyInsideDictionary = propertyNameToBoolDictionary.TryGetValue(propertyName, out bool propertyToggled);
if (propertyInsideDictionary && propertyName != null)
{
if (propertyToggled)
{
ShaderPropertyType shaderPropertyType = shader.GetPropertyType(referenceMaterial.shader.FindPropertyIndex(propertyName));
if (shaderPropertyType == ShaderPropertyType.Float || shaderPropertyType == ShaderPropertyType.Range)
{
float instancedValue = instancedMaterial.GetFloat(propertyName);
float referenceValue = referenceMaterial.GetFloat(propertyName);
if ((instancedValue != referenceValue)) // || force)
{
namesOfChangedProperties.Add(propertyName);
}
}
else if (shaderPropertyType == ShaderPropertyType.Color)
{
Color instancedColor = instancedMaterial.GetColor(propertyName);
Color referenceColor = referenceMaterial.GetColor(propertyName);
if (!instancedColor.Equals(referenceColor))
{
namesOfChangedProperties.Add(propertyName);
}
}
else if (shaderPropertyType == ShaderPropertyType.Texture)
{
Texture instancedTexture = instancedMaterial.GetTexture(propertyName);
Texture referenceTexture = referenceMaterial.GetTexture(propertyName);
if (instancedTexture != null && referenceTexture != null)
{
if (!String.Equals(instancedTexture.name, referenceTexture.name))
{
namesOfChangedProperties.Add(propertyName);
}
else if (instancedMaterial.GetTextureOffset(propertyName) != referenceMaterial.GetTextureOffset(propertyName)
|| instancedMaterial.GetTextureScale(propertyName) != referenceMaterial.GetTextureScale(propertyName))
{
namesOfChangedProperties.Add(propertyName);
}
}
else if ((instancedTexture != null) != (referenceTexture != null))
{
namesOfChangedProperties.Add(propertyName);
}
}
else if (shaderPropertyType == ShaderPropertyType.Vector)
{
Vector4 instancedVector = instancedMaterial.GetVector(propertyName);
Vector4 referenceVector = referenceMaterial.GetVector(propertyName);
if (!instancedVector.Equals(referenceVector))
{
namesOfChangedProperties.Add(propertyName);
}
}
}
}
}
}
return namesOfChangedProperties;
}
}
return null;
}
//private static List<string> GetNamesOfAllChangedKeywordValues(Material instancedMaterial, Material referenceMaterial)
//{
// if (instancedMaterial != null && referenceMaterial != null)
// {
// if (IsTheToonShaderMaterial(instancedMaterial) && IsTheToonShaderMaterial(referenceMaterial))
// {
// List<string> namesOfChangedProperties = new List<string>();
// //foreach (string keyword in ShaderUtils.THETOONSHADER_KEYWORDS_LIST)
// foreach (string keyword in referenceMaterial.shaderKeywords)
// {
// bool instancedValue = instancedMaterial.IsKeywordEnabled(keyword);
// bool referenceValue = referenceMaterial.IsKeywordEnabled(keyword);
// if (instancedValue != referenceValue)
// {
// namesOfChangedProperties.Add(keyword);
// }
// }
// return namesOfChangedProperties;
// }
// }
// return null;
//}
private static List<string> GetNamesOfAllChangedKeywordValues(Material instancedMaterial, Material referenceMaterial, List<string> namesOfChangedProperties)
{
if (instancedMaterial != null && referenceMaterial != null)
{
if (IsTheToonShaderMaterial(instancedMaterial) && IsTheToonShaderMaterial(referenceMaterial))
{
List<string> namesOfChangedKeywords= new List<string>();
//foreach (string keyword in ShaderUtils.THETOONSHADER_KEYWORDS_LIST)
//foreach (string keyword in referenceMaterial.shaderKeywords)
List<string> keywords = ShaderUtils.GetKeywordList(namesOfChangedProperties);
foreach (string keyword in keywords)
{
bool instancedValue = instancedMaterial.IsKeywordEnabled(keyword);
bool referenceValue = referenceMaterial.IsKeywordEnabled(keyword);
if (instancedValue != referenceValue)
{
namesOfChangedProperties.Add(keyword);
}
}
return namesOfChangedProperties;
}
}
return null;
}
}
}