AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
MaterialPropertyAttribute.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 
4 using System;
5 using System.Collections.Generic;
6 using System.Reflection;
7 using UnityEngine;
8 #if UNITY_EDITOR
9 using UnityEditor;
10 #endif
11 
12 namespace HoloToolkit.Unity
13 {
14  // Displays a drop-down list of available material properties from the material supplied in a named member
15  [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
17  {
18  public enum PropertyTypeEnum
19  {
20  Color,
21  Float,
22  Range,
23  Vector,
24  }
25 
26  public string Property { get; private set; }
27  public PropertyTypeEnum PropertyType { get; private set; }
28  public string MaterialMemberName { get; private set; }
29  public bool AllowNone { get; private set; }
30  public string DefaultProperty { get; private set; }
31  public string CustomLabel { get; private set; }
32 
33  public MaterialPropertyAttribute(PropertyTypeEnum propertyType, string materialMemberName, bool allowNone = true, string defaultProperty = "_Color", string customLabel = null)
34  {
35  PropertyType = propertyType;
36  MaterialMemberName = materialMemberName;
37  AllowNone = allowNone;
38  DefaultProperty = defaultProperty;
39  CustomLabel = customLabel;
40  }
41 
42 #if UNITY_EDITOR
43  public override void DrawEditor(UnityEngine.Object target, FieldInfo field, SerializedProperty property)
44  {
45  Material mat = GetMaterial(target);
46 
47  string fieldValue = MaterialPropertyName(
48  (string)field.GetValue(target),
49  mat,
50  PropertyType,
51  AllowNone,
52  DefaultProperty,
53  (string.IsNullOrEmpty(CustomLabel) ? SplitCamelCase(field.Name) : CustomLabel));
54 
55  field.SetValue(target, fieldValue);
56  }
57 
58  public override void DrawEditor(UnityEngine.Object target, PropertyInfo prop)
59  {
60  Material mat = GetMaterial(target);
61 
62  string propValue = MaterialPropertyName(
63  (string)prop.GetValue(target, null),
64  mat,
65  PropertyType,
66  AllowNone,
67  DefaultProperty,
68  (string.IsNullOrEmpty(CustomLabel) ? SplitCamelCase(prop.Name) : CustomLabel));
69 
70  prop.SetValue(target, propValue, null);
71  }
72 
73  private Material GetMaterial(object target)
74  {
75  MemberInfo[] members = target.GetType().GetMember(MaterialMemberName);
76  if (members.Length == 0)
77  {
78  Debug.LogError("Couldn't find material member " + MaterialMemberName);
79  return null;
80  }
81 
82  Material mat = null;
83 
84  switch (members[0].MemberType)
85  {
86  case MemberTypes.Field:
87  FieldInfo matField = target.GetType().GetField(MaterialMemberName);
88  mat = matField.GetValue(target) as Material;
89  break;
90 
91  case MemberTypes.Property:
92  PropertyInfo matProp = target.GetType().GetProperty(MaterialMemberName);
93  mat = matProp.GetValue(target, null) as Material;
94  break;
95 
96  default:
97  Debug.LogError("Couldn't find material member " + MaterialMemberName);
98  break;
99  }
100 
101  return mat;
102  }
103 
104  private static string MaterialPropertyName(string property, Material mat, PropertyTypeEnum type, bool allowNone, string defaultProperty, string labelName)
105  {
106  Color tColor = GUI.color;
107  // Create a list of available color and value properties
108  List<string> props = new List<string>();
109 
110  int selectedPropIndex = 0;
111 
112  if (allowNone)
113  {
114  props.Add("(None)");
115  }
116 
117  if (mat != null)
118  {
119  int propertyCount = ShaderUtil.GetPropertyCount(mat.shader);
120  string propName = string.Empty;
121  for (int i = 0; i < propertyCount; i++)
122  {
123  if (ShaderUtil.GetPropertyType(mat.shader, i).ToString() == type.ToString())
124  {
125  propName = ShaderUtil.GetPropertyName(mat.shader, i);
126  if (propName == property)
127  {
128  // We've found our current property
129  selectedPropIndex = props.Count;
130  }
131  props.Add(propName);
132  }
133  }
134 
135  if (string.IsNullOrEmpty(labelName))
136  {
137  labelName = type.ToString();
138  }
139  int newPropIndex = EditorGUILayout.Popup(labelName, selectedPropIndex, props.ToArray());
140  if (allowNone)
141  {
142  property = (newPropIndex > 0 ? props[newPropIndex] : string.Empty);
143  }
144  else
145  {
146  if (props.Count > 0)
147  {
148  property = props[newPropIndex];
149  }
150  else
151  {
152  property = defaultProperty;
153  }
154  }
155  return property;
156  }
157  else
158  {
159  GUI.color = Color.Lerp(tColor, Color.gray, 0.5f);
160  // Draw an empty property
161  EditorGUILayout.Popup(labelName, selectedPropIndex, props.ToArray());
162  GUI.color = tColor;
163  return string.Empty;
164  }
165  }
166 #endif
167 
168  }
169 }
MaterialPropertyAttribute(PropertyTypeEnum propertyType, string materialMemberName, bool allowNone=true, string defaultProperty="_Color", string customLabel=null)