A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using UnityEditor.Graphing;
5using UnityEditor.ShaderGraph.Drawing.Slots;
6using UnityEditor.ShaderGraph.Internal;
7using UnityEngine;
8
9using UnityEngine.UIElements;
10
11namespace UnityEditor.ShaderGraph
12{
13 [Serializable]
14 class DynamicVectorMaterialSlot : MaterialSlot, IMaterialSlotHasValue<Vector4>
15 {
16 [SerializeField]
17 private Vector4 m_Value;
18
19 [SerializeField]
20 private Vector4 m_DefaultValue = Vector4.zero;
21
22 static readonly string[] k_Labels = { "X", "Y", "Z", "W" };
23
24 private ConcreteSlotValueType m_ConcreteValueType = ConcreteSlotValueType.Vector1;
25
26 public DynamicVectorMaterialSlot()
27 {
28 }
29
30 public DynamicVectorMaterialSlot(
31 int slotId,
32 string displayName,
33 string shaderOutputName,
34 SlotType slotType,
35 Vector4 value,
36 ShaderStageCapability stageCapability = ShaderStageCapability.All,
37 bool hidden = false)
38 : base(slotId, displayName, shaderOutputName, slotType, stageCapability, hidden)
39 {
40 m_Value = value;
41 }
42
43 public Vector4 defaultValue { get { return m_DefaultValue; } }
44
45 public Vector4 value
46 {
47 get { return m_Value; }
48 set { m_Value = value; }
49 }
50
51 public override bool isDefaultValue => value.Equals(defaultValue);
52
53 public override VisualElement InstantiateControl()
54 {
55 var labels = k_Labels.Take(concreteValueType.GetChannelCount()).ToArray();
56 return new MultiFloatSlotControlView(owner, labels, () => value, (newValue) => value = newValue);
57 }
58
59 public override SlotValueType valueType { get { return SlotValueType.DynamicVector; } }
60
61 public override ConcreteSlotValueType concreteValueType
62 {
63 get { return m_ConcreteValueType; }
64 }
65
66 public void SetConcreteType(ConcreteSlotValueType valueType)
67 {
68 m_ConcreteValueType = valueType;
69 }
70
71 public override void GetPreviewProperties(List<PreviewProperty> properties, string name)
72 {
73 var propType = concreteValueType.ToPropertyType();
74 var pp = new PreviewProperty(propType) { name = name };
75 if (propType == PropertyType.Float)
76 pp.floatValue = value.x;
77 else
78 pp.vector4Value = new Vector4(value.x, value.y, value.z, value.w);
79 properties.Add(pp);
80 }
81
82 protected override string ConcreteSlotValueAsVariable()
83 {
84 var channelCount = SlotValueHelper.GetChannelCount(concreteValueType);
85 string values = NodeUtils.FloatToShaderValue(value.x);
86 if (channelCount == 1)
87 return string.Format("$precision({0})", values);
88 for (var i = 1; i < channelCount; i++)
89 values += ", " + NodeUtils.FloatToShaderValue(value[i]);
90 return string.Format("$precision{0}({1})", channelCount, values);
91 }
92
93 public override void AddDefaultProperty(PropertyCollector properties, GenerationMode generationMode)
94 {
95 if (!generationMode.IsPreview())
96 return;
97
98 var matOwner = owner as AbstractMaterialNode;
99 if (matOwner == null)
100 throw new Exception(string.Format("Slot {0} either has no owner, or the owner is not a {1}", this, typeof(AbstractMaterialNode)));
101
102 AbstractShaderProperty property;
103 switch (concreteValueType)
104 {
105 case ConcreteSlotValueType.Vector4:
106 property = new Vector4ShaderProperty();
107 break;
108 case ConcreteSlotValueType.Vector3:
109 property = new Vector3ShaderProperty();
110 break;
111 case ConcreteSlotValueType.Vector2:
112 property = new Vector2ShaderProperty();
113 break;
114 case ConcreteSlotValueType.Vector1:
115 property = new Vector1ShaderProperty();
116 break;
117 default:
118 // This shouldn't happen due to edge validation. The generated shader will
119 // have errors.
120 Debug.LogError($"Invalid value type {concreteValueType} passed to Vector Slot {displayName}. Value will be ignored, please plug in an edge with a vector type.");
121 return;
122 }
123
124 property.overrideReferenceName = matOwner.GetVariableNameForSlot(id);
125 property.generatePropertyBlock = false;
126 properties.AddShaderProperty(property);
127 }
128
129 public override void CopyValuesFrom(MaterialSlot foundSlot)
130 {
131 var slot = foundSlot as DynamicVectorMaterialSlot;
132 if (slot != null)
133 value = slot.value;
134 }
135
136 public override void CopyDefaultValue(MaterialSlot other)
137 {
138 base.CopyDefaultValue(other);
139 if (other is IMaterialSlotHasValue<Vector4> ms)
140 {
141 m_DefaultValue = ms.defaultValue;
142 }
143 }
144 }
145}