- Home /
Question by
HammockHead21 · May 13, 2021 at 02:10 AM ·
c#inspectorpropertydrawer
PropertyDrawer is not nested in inspector
I have a class meant to encapsulate ComputeShaders. It looks something like:
[Serializable]
public class ComputeShaderWrapper
{
[SerializeField] ComputeShader computeShader;
[SerializeField] string kernalName;
[SerializeField] int kernalIndex;
[SerializeField] int kernalSizeX;
[SerializeField] int kernalSizeY;
[SerializeField] int kernalSizeZ;
public ComputeShader UnderlyingComputeShader => computeShader;
public int KernalIndex => kernalIndex;
public void Dispatch(in int3 xyzSizes, in bool safeFromBufferOverFlow = false)
{
int3 kernalSize = new int3(kernalSizeX, kernalSizeY, kernalSizeZ);
int3 threadGroups = xyzSizes / kernalSize;
int3 leftover = xyzSizes % kernalSize;
if (!safeFromBufferOverFlow && !leftover.Equals(int3.zero))
{
throw new System.Exception($"{kernalSize} must divide {xyzSizes}");
}
threadGroups += (int3)(leftover != int3.zero);
computeShader.Dispatch(kernalIndex, threadGroups.x, threadGroups.y, threadGroups.z);
}
}
I want to automatically populate the values for kernalIndex and kernalSizeX/Y/Z so I have defined a custom PropertyDrawer that looks like:
[CustomPropertyDrawer(typeof(ComputeShaderWrapper))]
public class ComputeShaderWrapperPropertyDrawer : PropertyDrawer {
static void SetComputeShaderMetaData(SerializedProperty property) {
var computeShader = GetComputeShaderSP(property).objectReferenceValue as ComputeShader;
if (computeShader == null) return;
string kernalName = GetKernalNameSP(property).stringValue;
if (!computeShader.HasKernel(kernalName)) return;
int kernalIndex = computeShader.FindKernel(kernalName);
GetKernalIndexSP(property).intValue = kernalIndex;
computeShader.GetKernelThreadGroupSizes(kernalIndex, out uint x, out uint y, out uint z);
GetKernalSizeXSP(property).intValue = (int)x;
GetKernalSizeYSP(property).intValue = (int)y;
GetKernalSizeZSP(property).intValue = (int)z;
property.serializedObject.ApplyModifiedProperties();
}
public override VisualElement CreatePropertyGUI(SerializedProperty property) {
var container = new VisualElement();
container.Add(new PropertyField(GetComputeShaderSP(property)));
var kernalNameVE = new PropertyField(GetKernalNameSP(property));
container.Add(kernalNameVE);
kernalNameVE.RegisterCallback<ChangeEvent<string>>(e => {
SetComputeShaderMetaData(property);
});
var forceRefreshVE = new Button(() => {
SetComputeShaderMetaData(property);
});
forceRefreshVE.text = "Refresh";
container.Add(forceRefreshVE);
return container;
}
}
When I add ComputeShaderWrapper to a Monobehaviour as a public member. I can see each of the fields within ComputeShaderWrapper however it is not nested.
public class VoxelTest : MonoBehaviour
{
public ComputeShaderWrapper computeShaderWrapper;
}
not-nested.png
(10.9 kB)
Comment