2021-12-15 16:29:44 +03:00

487 lines
19 KiB
C#

//////////////////////////////////////////////////////
// MK Toon Property //
// //
// Created by Michael Kremmel //
// www.michaelkremmel.de //
// Copyright © 2021 All rights reserved. //
//////////////////////////////////////////////////////
using UnityEngine;
namespace MK.Toon
{
/////////////////////////////////////////////////////////////////////////////////////////////
// Property Base //
/////////////////////////////////////////////////////////////////////////////////////////////
public abstract class Property<T>
{
protected string[] _keywords;
protected Uniform _uniform;
public Uniform uniform
{
get{ return _uniform; }
}
public Property(Uniform uniform, params string[] keywords)
{
_keywords = keywords;
_uniform = uniform;
}
public abstract T GetValue(UnityEngine.Material material);
public abstract void SetValue(UnityEngine.Material material, T value);
protected void SetKeyword(UnityEngine.Material material, bool b, int keywordIndex)
{
if(b && _keywords != null && _keywords.Length > keywordIndex && _keywords.Length > 0)
{
for(int i = 0; i < _keywords.Length; i++)
material.DisableKeyword(_keywords[i]);
material.EnableKeyword(_keywords[keywordIndex]);
}
}
}
public abstract class Property<T, U> : Property<T>
{
public Property(Uniform uniform, params string[] keywords) : base(uniform, keywords) {}
public abstract void SetValue(UnityEngine.Material material, T valueM, U valueS);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Custom Properties //
/////////////////////////////////////////////////////////////////////////////////////////////
public class BoolProperty : Property<bool>
{
public BoolProperty(Uniform uniform, string keyword) : base(uniform, keyword) {}
public BoolProperty(Uniform uniform) : base(uniform) {}
public override bool GetValue(Material material)
{
return material.GetInt(_uniform.id) > 0 ? true : false;
}
public override void SetValue(Material material, bool value)
{
material.SetInt(_uniform.id, value ? 1 : 0);
SetKeyword(material, value, 0);
}
}
public class IntProperty : Property<int>
{
private int _keywordDisabled = 0;
public IntProperty(Uniform uniform, string keyword, int keywordDisabled = 0) : base(uniform, keyword) {}
public IntProperty(Uniform uniform) : base(uniform) {}
public override int GetValue(Material material)
{
return material.GetInt(_uniform.id);
}
public override void SetValue(Material material, int value)
{
material.SetInt(_uniform.id, value);
SetKeyword(material, value != _keywordDisabled, value);
}
}
public class StepProperty : Property<int>
{
private int _keywordDisabled = 0;
private int _minValue, _maxValue;
public StepProperty(Uniform uniform, int minValue, int maxValue, string keyword, int keywordDisabled = 0) : base(uniform, keyword)
{
_keywordDisabled = keywordDisabled;
_minValue = minValue;
_maxValue = maxValue;
}
public StepProperty(Uniform uniform, int minValue, int maxValue) : base(uniform)
{
_minValue = minValue;
_maxValue = maxValue;
}
public override int GetValue(Material material)
{
return material.GetInt(_uniform.id);
}
public override void SetValue(Material material, int value)
{
value = Mathf.Clamp(value, _minValue, _maxValue);
material.SetInt(_uniform.id, value);
SetKeyword(material, value != _keywordDisabled, value);
}
}
public class FloatProperty : Property<float>
{
private float _keywordDisabled = 0;
public FloatProperty(Uniform uniform, string keyword, float keywordDisabled = 0) : base(uniform, keyword) { _keywordDisabled = keywordDisabled; }
public FloatProperty(Uniform uniform) : base(uniform) {}
public override float GetValue(Material material)
{
return material.GetFloat(_uniform.id);
}
public override void SetValue(Material material, float value)
{
material.SetFloat(_uniform.id, value);
SetKeyword(material, value != _keywordDisabled, (int) value);
}
}
public class RangeProperty : Property<float>
{
private float _keywordDisabled = 0;
private float _minValue, _maxValue;
public RangeProperty(Uniform uniform, string keyword, float minValue, float maxValue, float keywordDisabled = 0) : base(uniform, keyword)
{
_keywordDisabled = keywordDisabled;
_minValue = minValue;
_maxValue = maxValue;
}
public RangeProperty(Uniform uniform, string keyword, float minValue, float keywordDisabled = 0) : base(uniform, keyword)
{
_keywordDisabled = keywordDisabled;
_minValue = minValue;
_maxValue = Mathf.Infinity;
}
public RangeProperty(Uniform uniform, float minValue, float maxValue) : base(uniform)
{
_minValue = minValue;
_maxValue = maxValue;
}
public RangeProperty(Uniform uniform, float minValue) : base(uniform)
{
_minValue = minValue;
_maxValue = Mathf.Infinity;
}
public override float GetValue(Material material)
{
return material.GetFloat(_uniform.id);
}
public override void SetValue(Material material, float value)
{
value = Mathf.Clamp(value, _minValue, _maxValue);
material.SetFloat(_uniform.id, value);
SetKeyword(material, value != _keywordDisabled, (int) value);
}
}
public class Vector2Property : Property<Vector2>
{
public Vector2Property(Uniform uniform) : base(uniform) {}
public override Vector2 GetValue(Material material)
{
return material.GetVector(_uniform.id);
}
public override void SetValue(Material material, Vector2 value)
{
material.SetVector(_uniform.id, value);
}
}
public class Vector3Property : Property<Vector3>
{
public Vector3Property(Uniform uniform) : base(uniform) {}
public override Vector3 GetValue(Material material)
{
return material.GetVector(_uniform.id);
}
public override void SetValue(Material material, Vector3 value)
{
material.SetVector(_uniform.id, value);
}
}
public class Vector4Property : Property<Vector4>
{
public Vector4Property(Uniform uniform) : base(uniform) {}
public override Vector4 GetValue(Material material)
{
return material.GetVector(_uniform.id);
}
public override void SetValue(Material material, Vector4 value)
{
material.SetVector(_uniform.id, value);
}
}
public class ColorProperty : Property<UnityEngine.Color>
{
public ColorProperty(Uniform uniform, string keyword) : base(uniform, keyword) {}
public ColorProperty(Uniform uniform) : base(uniform) {}
public override UnityEngine.Color GetValue(Material material)
{
return material.GetColor(_uniform.id);
}
public override void SetValue(Material material, UnityEngine.Color color)
{
material.SetColor(_uniform.id, color);
}
}
public class TextureProperty : Property<UnityEngine.Texture>
{
public TextureProperty(Uniform uniform, string keyword) : base(uniform, keyword) {}
public TextureProperty(Uniform uniform) : base(uniform) {}
public override UnityEngine.Texture GetValue(Material material)
{
return material.GetTexture(_uniform.id);
}
public override void SetValue(Material material, UnityEngine.Texture texture)
{
material.SetTexture(_uniform.id, texture);
SetKeyword(material, texture != null, 0);
}
}
public class EnumProperty<T> : Property<T> where T : System.Enum
{
public EnumProperty(Uniform uniform, params string[] keywords) : base(uniform, keywords) {}
public override T GetValue(Material material)
{
return (T) (object) material.GetInt(_uniform.id);
}
public override void SetValue(Material material, T value)
{
material.SetInt(_uniform.id, (int) (object) value);
SetKeyword(material,(int) (object) value != 0, (int) (object) value);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Explicit Properties //
/////////////////////////////////////////////////////////////////////////////////////////////
public class TilingProperty : Property<Vector2>
{
public TilingProperty(Uniform uniform) : base(uniform) {}
public override Vector2 GetValue(Material material)
{
return material.GetTextureScale(uniform.id);
}
public override void SetValue(Material material, Vector2 value)
{
material.SetTextureScale(uniform.id, value);
}
}
public class OffsetProperty : Property<Vector2>
{
public OffsetProperty(Uniform uniform) : base(uniform) {}
public override Vector2 GetValue(Material material)
{
return material.GetTextureOffset(uniform.id);
}
public override void SetValue(Material material, Vector2 value)
{
material.SetTextureOffset(uniform.id, value);
}
}
public class SpecularProperty : Property<Specular>
{
public SpecularProperty(Uniform uniform, params string[] keywords) : base(uniform, keywords) {}
public override Specular GetValue(Material material)
{
return (Specular) material.GetInt(_uniform.id);
}
public override void SetValue(Material material, Specular specular)
{
if(material.shader.name.Contains(Properties.shaderVariantSimpleName))
specular = (int) specular >= 1 ? Specular.Isotropic : Specular.Off;
material.SetInt(_uniform.id, (int) specular);
SetKeyword(material,(int) specular != 0, (int) specular);
}
}
public class EnvironmentReflectionProperty : Property<EnvironmentReflection>
{
public EnvironmentReflectionProperty(Uniform uniform, params string[] keywords) : base(uniform, keywords) {}
public override EnvironmentReflection GetValue(Material material)
{
return (EnvironmentReflection) material.GetInt(_uniform.id);
}
public override void SetValue(Material material, EnvironmentReflection environmentReflection)
{
if(material.shader.name.Contains(Properties.shaderVariantSimpleName))
environmentReflection = (int) environmentReflection >= 1 ? EnvironmentReflection.Ambient : EnvironmentReflection.Off;
material.SetInt(_uniform.id, (int) environmentReflection);
SetKeyword(material,(int) environmentReflection != 0, (int) environmentReflection);
}
}
public class StencilModeProperty : Property<Stencil>
{
public StencilModeProperty(Uniform uniform) : base(uniform) {}
public override Stencil GetValue(Material material)
{
return (Stencil)material.GetInt(_uniform.id);
}
public override void SetValue(Material material, Stencil stencil)
{
if(stencil == Stencil.Builtin)
{
Properties.stencilRef.SetValue(material, 0);
Properties.stencilReadMask.SetValue(material, 255);
Properties.stencilWriteMask.SetValue(material, 255);
Properties.stencilComp.SetValue(material, StencilComparison.Always);
Properties.stencilPass.SetValue(material, StencilOperation.Keep);
Properties.stencilFail.SetValue(material, StencilOperation.Keep);
Properties.stencilZFail.SetValue(material, StencilOperation.Keep);
}
material.SetInt(_uniform.id, (int)stencil);
}
}
public class RenderPriorityProperty : Property<int, bool>
{
public RenderPriorityProperty(Uniform uniform) : base(uniform) {}
public override int GetValue(Material material)
{
return material.GetInt(uniform.id);
}
public override void SetValue(Material material, int priority) => SetValue(material, priority, false);
public override void SetValue(Material material, int priority, bool alphaClipping)
{
Surface surface = Properties.surface.GetValue(material);
switch(surface)
{
default:
if(alphaClipping)
{
material.renderQueue = (int)RenderQueue.AlphaTest;
}
else
{
material.renderQueue = (int)RenderQueue.Geometry;
}
break;
case Surface.Transparent:
material.renderQueue = (int)RenderQueue.Transparent;
break;
}
material.SetInt(uniform.id, priority);
material.renderQueue -= Properties.renderPriority.GetValue(material);
}
}
public class SurfaceProperty : Property<Surface, bool>
{
public SurfaceProperty(Uniform uniform, params string[] keywords) : base(uniform, keywords) {}
public override Surface GetValue(Material material)
{
return (Surface)material.GetInt(uniform.id);
}
public override void SetValue(Material material, Surface surface) => SetValue(material, surface, false);
public override void SetValue(Material material, Surface surface, bool alphaClipping)
{
if(material.shader.name.Contains(Properties.shaderComponentOutlineName))
surface = Surface.Opaque;
if(material.shader.name.Contains(Properties.shaderComponentRefractionName))
surface = Surface.Transparent;
bool customBlendingEnabled = Properties.blend.GetValue(material) == Blend.Custom ? true : false;
switch(surface)
{
default:
if(!customBlendingEnabled)
{
Properties.zWrite.SetValue(material, ZWrite.On);
Properties.zTest.SetValue(material, ZTest.LessEqual);
}
if(alphaClipping)
{
material.SetOverrideTag("RenderType", "TransparentCutout");
material.SetOverrideTag("IgnoreProjector", "true");
}
else
{
material.SetOverrideTag("RenderType", "Opaque");
material.SetOverrideTag("IgnoreProjector", "false");
}
material.SetShaderPassEnabled("ShadowCaster", true);
break;
case Surface.Transparent:
if(!customBlendingEnabled)
{
Properties.zWrite.SetValue(material, ZWrite.Off);
Properties.zTest.SetValue(material, ZTest.LessEqual);
}
material.SetOverrideTag("RenderType", "Transparent");
material.SetOverrideTag("IgnoreProjector", "true");
material.SetShaderPassEnabled("ShadowCaster", false);
break;
}
Properties.blend.SetValue(material, Properties.blend.GetValue(material));
Properties.renderPriority.SetValue(material, Properties.renderPriority.GetValue(material));
material.SetInt(uniform.id, (int)surface);
SetKeyword(material,(int) surface != 0, (int) surface);
}
}
public class BlendProperty : Property<Blend>
{
public BlendProperty(Uniform uniform, params string[] keywords) : base(uniform, keywords) {}
public override Blend GetValue(Material material)
{
return (Blend)material.GetInt(uniform.id);
}
/// <summary>
/// Material will be changed to opaque
/// </summary>
/// <param uniform="material"></param>
/// <param uniform="blend"></param>
public override void SetValue(Material material, Blend blend)
{
if(Properties.blend.GetValue(material) != Blend.Custom)
{
Properties.zTest.SetValue(material, ZTest.LessEqual);
if(Properties.surface.GetValue(material) == Surface.Opaque)
{
Properties.blendSrc.SetValue(material, BlendFactor.One);
Properties.blendDst.SetValue(material, BlendFactor.Zero);
}
else
{
switch(blend)
{
case Blend.Alpha: //Alpha
Properties.blendSrc.SetValue(material, BlendFactor.SrcAlpha);
Properties.blendDst.SetValue(material, BlendFactor.OneMinusSrcAlpha);
break;
case Blend.Premultiply:
Properties.blendSrc.SetValue(material, BlendFactor.One);
Properties.blendDst.SetValue(material, BlendFactor.OneMinusSrcAlpha);
break;
case Blend.Additive:
Properties.blendSrc.SetValue(material, BlendFactor.One);
Properties.blendDst.SetValue(material, BlendFactor.One);
break;
case Blend.Multiply:
Properties.blendSrc.SetValue(material, BlendFactor.DstColor);
Properties.blendDst.SetValue(material, BlendFactor.Zero);
break;
default:
Properties.blendSrc.SetValue(material, BlendFactor.SrcAlpha);
Properties.blendDst.SetValue(material, BlendFactor.OneMinusSrcAlpha);
break;
}
}
material.SetInt(Properties.blend.uniform.id, (int) blend);
SetKeyword(material,(int) blend != 0, (int) blend);
}
else
{
material.SetInt(Properties.blend.uniform.id, (int) blend);
SetKeyword(material,(int) blend != 0, (int) blend);
}
}
}
}