Skip to content

Instantly share code, notes, and snippets.

@jeffvella
Created April 23, 2020 22:41
Show Gist options
  • Save jeffvella/e8a469abeed241d426e01d9aa6a41047 to your computer and use it in GitHub Desktop.
Save jeffvella/e8a469abeed241d426e01d9aa6a41047 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Unity.Physics.Authoring;
#if UNITY_EDITOR
using UnityEditor;
#endif
[Serializable]
public struct PhysicsCategoryMask
{
public uint Value;
public static implicit operator uint(PhysicsCategoryMask mask) => mask.Value;
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(PhysicsCategoryMask))]
public class PhysicsCategoryMaskDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var assets = GetAssets<PhysicsCategoryNames>();
var asset = assets.First();
var names = asset.CategoryNames.Where(name => !string.IsNullOrEmpty(name)).ToArray();
label = EditorGUI.BeginProperty(position, label, property);
var controlPosition = EditorGUI.PrefixLabel(position, label);
EditorGUI.indentLevel = 0;
var valueProperty = property.FindPropertyRelative(nameof(PhysicsCategoryMask.Value));
if (valueProperty == null)
throw new InvalidOperationException();
var value = valueProperty.intValue;
// MaskField wants 'Everything' represented as -1,
if (IsEverythingSet(value, names.Length))
{
value = ~0;
}
EditorGUI.BeginChangeCheck();
var maskField = EditorGUI.MaskField(controlPosition, GUIContent.none, value, names);
if (EditorGUI.EndChangeCheck())
{
if (maskField == -1)
{
// Calculate the cumulative value.
var everything = 0;
for (int i = 0, count = names.Length; i < count; ++i)
{
everything |= 1 << i;
}
maskField = everything;
}
valueProperty.intValue = maskField;
}
EditorGUI.EndProperty();
}
public static List<T> GetAssets<T>() where T : ScriptableObject
{
return AssetDatabase.FindAssets($"t:{typeof(T).Name}")
.Select(AssetDatabase.GUIDToAssetPath)
.Select(AssetDatabase.LoadAssetAtPath<T>)
.Where(c => c != null).ToList();
}
public static bool IsEverythingSet(int maskValue, int length)
{
var value = 0;
var everything = 0;
for (int i = 1, count = length; i < count; ++i)
{
var isSelected = (maskValue & (1 << i)) != 0;
value |= isSelected ? 1 << i : 0;
everything |= 1 << i;
}
return value == everything;
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment