yum/3ner

A toon shader for Unity's BIRP.

git clone https://git.yummers.dev/yum/3ner

yumFold: fix edge case when adding new operators82ef107

master
4.6 KiB101 linesraw
1using System;
2using UnityEngine;
3
4namespace Yum.Fold
5{
6    [Serializable]
7    public sealed class FoldOperator
8    {
9        // Packed shader/animation storage. Named fields, defaults and jumpback
10        // policies live in the per-operator definitions in FoldOperators.cs.
11        public bool enabled;
12        public int opcode;
13        public float float0, float1, float2, float3;
14        public Vector4 vector0, vector1, vector2, vector3;
15
16        public static FoldOperator Defaults(int opcode) => FoldOperators.Defaults(opcode);
17        public FoldOperator JumpbackDefaults() => FoldOperators.Jumpback(this);
18        public static FoldOperator AnimationDefaults(int opcode) => Defaults(opcode).JumpbackDefaults();
19
20        public FoldOperator Copy() => (FoldOperator)MemberwiseClone();
21        public static string Prefix(int slot) => "_Vertex_Deformation_Slot_" + slot + "_";
22        public static FoldOperator Read(Material material, int slot)
23        {
24            string p = Prefix(slot);
25            return new FoldOperator {
26                enabled = material.GetFloat(p + "Enabled") > .5f,
27                opcode = material.GetInteger(p + "Opcode"),
28                float0 = material.GetFloat(p + "Float_0"), float1 = material.GetFloat(p + "Float_1"),
29                float2 = material.GetFloat(p + "Float_2"), float3 = material.GetFloat(p + "Float_3"),
30                vector0 = material.GetVector(p + "Vector_0"), vector1 = material.GetVector(p + "Vector_1"),
31                vector2 = material.GetVector(p + "Vector_2"), vector3 = material.GetVector(p + "Vector_3")
32            };
33        }
34
35        public void Write(Material material, int slot)
36        {
37            string p = Prefix(slot);
38            material.SetFloat(p + "Enabled", enabled ? 1 : 0);
39            material.SetInteger(p + "Opcode", opcode);
40            material.SetFloat(p + "Float_0", float0); material.SetFloat(p + "Float_1", float1);
41            material.SetFloat(p + "Float_2", float2); material.SetFloat(p + "Float_3", float3);
42            material.SetVector(p + "Vector_0", vector0); material.SetVector(p + "Vector_1", vector1);
43            material.SetVector(p + "Vector_2", vector2); material.SetVector(p + "Vector_3", vector3);
44        }
45
46        static readonly int[][] PropertyIds = CreatePropertyIds();
47        static int[][] CreatePropertyIds()
48        {
49            var ids = new int[16][];
50            string[] names = { "Enabled", "Opcode", "Float_0", "Float_1", "Float_2", "Float_3", "Vector_0", "Vector_1", "Vector_2", "Vector_3" };
51            for (int i = 0; i < 16; i++)
52            {
53                ids[i] = new int[names.Length];
54                for (int j = 0; j < names.Length; j++) ids[i][j] = Shader.PropertyToID(Prefix(i) + names[j]);
55            }
56            return ids;
57        }
58        public void Write(MaterialPropertyBlock block, int slot)
59        {
60            var ids = PropertyIds[slot];
61            block.SetFloat(ids[0], enabled ? 1 : 0);
62            block.SetInteger(ids[1], opcode);
63            block.SetFloat(ids[2], float0); block.SetFloat(ids[3], float1);
64            block.SetFloat(ids[4], float2); block.SetFloat(ids[5], float3);
65            block.SetVector(ids[6], vector0); block.SetVector(ids[7], vector1);
66            block.SetVector(ids[8], vector2); block.SetVector(ids[9], vector3);
67        }
68    }
69
70    [ExecuteAlways, DisallowMultipleComponent, RequireComponent(typeof(Renderer))]
71    [AddComponentMenu("Yum Food/Fold Stack")]
72    public sealed class FoldStack : MonoBehaviour
73    {
74        public FoldMaterialAnimator[] materials = Array.Empty<FoldMaterialAnimator>();
75
76        public static bool Compatible(Material material)
77        {
78            if (!material || !material.shader || material.shader.name != "yum_food/3ner") return false;
79            if (material.HasProperty("_ShaderOptimizerEnabled") && material.GetFloat("_ShaderOptimizerEnabled") != 0) return false;
80            if (!material.HasProperty("_Vertex_Deformation_Enabled")) return false;
81            for (int i = 0; i < 16; i++)
82            {
83                string p = FoldOperator.Prefix(i);
84                if (!material.HasProperty(p + "Enabled") || !material.HasProperty(p + "Opcode")) return false;
85                for (int j = 0; j < 4; j++)
86                    if (!material.HasProperty(p + "Float_" + j) || !material.HasProperty(p + "Vector_" + j)) return false;
87            }
88            return true;
89        }
90
91        public void Apply()
92        {
93            foreach (var material in materials) if (material) material.Apply();
94        }
95        void OnEnable() => Apply();
96        void OnDisable()
97        {
98            foreach (var material in materials) if (material) material.Restore();
99        }
100    }
101}