1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class FoldSlot
{
public int opcode;
public float float0, float1, float2, float3;
public Vector4 vec0, vec1, vec2, vec3;
static string Prefix(int i) => $"_Vertex_Deformation_Slot_{i}_";
void ApplyToTarget(string pfx, Action<string, float> sf, Action<string, int> si, Action<string, Vector4> sv)
{
sf(pfx + "Enabled", 1f);
si(pfx + "Opcode", opcode);
sf(pfx + "Float_0", float0);
sf(pfx + "Float_1", float1);
sf(pfx + "Float_2", float2);
sf(pfx + "Float_3", float3);
sv(pfx + "Vector_0", vec0);
sv(pfx + "Vector_1", vec1);
sv(pfx + "Vector_2", vec2);
sv(pfx + "Vector_3", vec3);
}
static void ClearTarget(string pfx, Action<string, float> sf, Action<string, int> si, Action<string, Vector4> sv)
{
sf(pfx + "Enabled", 0f);
si(pfx + "Opcode", 0);
sf(pfx + "Float_0", 0f);
sf(pfx + "Float_1", 0f);
sf(pfx + "Float_2", 0f);
sf(pfx + "Float_3", 0f);
sv(pfx + "Vector_0", Vector4.zero);
sv(pfx + "Vector_1", Vector4.zero);
sv(pfx + "Vector_2", Vector4.zero);
sv(pfx + "Vector_3", Vector4.zero);
}
public void ApplyToMaterial(Material mat, int i) =>
ApplyToTarget(Prefix(i), mat.SetFloat, mat.SetInteger, (k, v) => mat.SetVector(k, v));
public void ApplyToPropertyBlock(MaterialPropertyBlock mpb, int i) =>
ApplyToTarget(Prefix(i), mpb.SetFloat, mpb.SetInteger, (k, v) => mpb.SetVector(k, v));
public static void ClearSlot(Material mat, int i) =>
ClearTarget(Prefix(i), mat.SetFloat, mat.SetInteger, (k, v) => mat.SetVector(k, v));
public static void ClearInPropertyBlock(MaterialPropertyBlock mpb, int i) =>
ClearTarget(Prefix(i), mpb.SetFloat, mpb.SetInteger, (k, v) => mpb.SetVector(k, v));
}
public class FoldPipelineBuilder
{
readonly List<FoldSlot> slots = new();
Material targetMaterial;
FoldPipelineBuilder() { }
public static FoldPipelineBuilder Create() => new();
public FoldPipelineBuilder For(Material material) { targetMaterial = material; return this; }
FoldPipelineBuilder AddSlot(FoldSlot slot) { slots.Add(slot); return this; }
FoldPipelineBuilder Prs(int opcode, Vector3 p, Vector3 r, Vector3 s, float t) =>
AddSlot(new FoldSlot { opcode = opcode, vec0 = p, vec1 = r, vec2 = s, float0 = t });
FoldPipelineBuilder Vec1t(int opcode, Vector3 v, float t) =>
AddSlot(new FoldSlot { opcode = opcode, vec0 = v, float0 = t });
public FoldPipelineBuilder TubeToPlane(Vector3 p, Vector3 r, Vector3 s, float t) => Prs(TubeToPlaneOp.Opcode, p, r, s, t);
public FoldPipelineBuilder PlaneToTube(Vector3 p, Vector3 r, Vector3 s, float t) => Prs(PlaneToTubeOp.Opcode, p, r, s, t);
public FoldPipelineBuilder PlaneToHemiOctahedron(Vector3 p, Vector3 r, Vector3 s, float t) => Prs(PlaneToHemiOctahedronOp.Opcode, p, r, s, t);
public FoldPipelineBuilder HemiOctahedronToPlane(Vector3 p, Vector3 r, Vector3 s, float t) => Prs(HemiOctahedronToPlaneOp.Opcode, p, r, s, t);
public FoldPipelineBuilder PlaneToOctahedron(Vector3 p, Vector3 r, Vector3 s, float t) => Prs(PlaneToOctahedronOp.Opcode, p, r, s, t);
public FoldPipelineBuilder OctahedronToPlane(Vector3 p, Vector3 r, Vector3 s, float t) => Prs(OctahedronToPlaneOp.Opcode, p, r, s, t);
public FoldPipelineBuilder PointAlign(Vector3 po, Vector3 pp, Vector3 r, float t) => Prs(PointAlignOp.Opcode, po, pp, r, t);
public FoldPipelineBuilder AxisAlign(Vector3 po, Vector3 pp, Vector3 r, float t) => Prs(AxisAlignOp.Opcode, po, pp, r, t);
public FoldPipelineBuilder Scale(Vector3 k, float t) => Vec1t(ScaleOp.Opcode, k, t);
public FoldPipelineBuilder Translate(Vector3 offset, float t) => Vec1t(TranslateOp.Opcode, offset, t);
public FoldPipelineBuilder Rotate(Vector3 center, Vector3 axis, float angle, float t) =>
AddSlot(new FoldSlot { opcode = RotateOp.Opcode, vec0 = center, vec1 = axis, float0 = angle, float1 = t });
public FoldPipelineBuilder NormConversion(float inputK, float outputK, float t) =>
AddSlot(new FoldSlot { opcode = NormConversionOp.Opcode, float0 = inputK, float1 = outputK, float2 = t });
public FoldPipelineBuilder Seal(float A, float k, float st, float t) =>
AddSlot(new FoldSlot { opcode = SealOp.Opcode, float0 = A, float1 = k, float2 = st, float3 = t });
public FoldPipelineBuilder SineWaves() => AddSlot(new FoldSlot { opcode = SineWavesOp.Opcode });
public FoldPipelineBuilder FBM() => AddSlot(new FoldSlot { opcode = FBMOp.Opcode });
public FoldPipelineBuilder Custom(int opcode,
float f0 = 0, float f1 = 0, float f2 = 0, float f3 = 0,
Vector4? v0 = null, Vector4? v1 = null, Vector4? v2 = null, Vector4? v3 = null) =>
AddSlot(new FoldSlot
{
opcode = opcode,
float0 = f0, float1 = f1, float2 = f2, float3 = f3,
vec0 = v0 ?? Vector4.zero,
vec1 = v1 ?? Vector4.zero,
vec2 = v2 ?? Vector4.zero,
vec3 = v3 ?? Vector4.zero
});
public void Apply()
{
if (targetMaterial == null)
{
Debug.LogError("No target material set. Use .For(material) before .Apply()");
return;
}
if (slots.Count > 16)
Debug.LogWarning($"Too many operations ({slots.Count}). Only the first 16 will be applied.");
Undo.RecordObject(targetMaterial, "Apply Vertex Deformation");
targetMaterial.SetFloat("_Vertex_Deformation_Enabled", 1f);
for (int i = 0; i < 16; i++)
FoldSlot.ClearSlot(targetMaterial, i);
for (int i = 0; i < slots.Count && i < 16; i++)
slots[i].ApplyToMaterial(targetMaterial, i);
EditorUtility.SetDirty(targetMaterial);
}
public void Clear() => slots.Clear();
public int Count => slots.Count;
public FoldSlot GetSlot(int index) => index < slots.Count ? slots[index] : null;
}
|