/// <summary> /// Retrieve the Data Drawer object that will be used to display the supplied data /// </summary> /// <param name="data">The SerialData object that contains the type information that needs to be displayed</param> /// <returns>Returns a data drawer that will be used to show the information</returns> private IDataDrawer GetDrawerForData(SerialData data) { // Determine if the there is a modifier drawer that is needed for this type if (data.Modifier != null) { // Check if there is a data drawer that can be used for the IDataDrawer modDrawer = GetDrawerForType(data.Modifier.GetType()); if (modDrawer != null) { return(modDrawer); } } // Check if there is a drawer setup for the data type itself IDataDrawer valDrawer = GetDrawerForType(data.DataType); if (valDrawer != null) { return(valDrawer); } // If got this far, we're displaying with the default drawer return(defaultDrawer); }
/// <summary> /// Setup the required elements needed to display the current data elements within the inspector /// </summary> /// <param name="serialDataProperty">The property that defines the location of the data to retrieve</param> /// <param name="data">Passes out the data actual objects that are being shown within the inspector</param> /// <param name="valueProperty">Passes out the serial value property that is being displayed within the inspector</param> /// <param name="storage">Passes out the storage objects that will hold the data values that are being shown</param> /// <param name="dataDrawer">Passes out the Drawer instance that will be used to display the required information</param> private void SetupDataForDisplay(SerializedProperty serialDataProperty, out SerialData[] data, out SerializedProperty valueProperty, out SerialStorage[] storage, out IDataDrawer dataDrawer) { // Retrieve the data objects that are to be shown data = GetPropertyValues(serialDataProperty); // If the data can be displayed, find a useful data drawer if (CanDataBeDisplayed(data, out valueProperty, out storage, out dataDrawer)) { dataDrawer = GetDrawerForData(data[0]); } // If there is a data object, apply it's settings to the drawer if (data[0] != null) { dataDrawer.DataType = data[0].DataType; dataDrawer.Modifier = data[0].Modifier; } }
/// <summary> /// Determine if the specified data objects can be displayed using a drawer /// </summary> /// <param name="data">The data objects that are to be shown within the inspector</param> /// <param name="valueProperty">The serialised value property that is to be displayed</param> /// <param name="storage">The storage elements that are being used to hold the display values</param> /// <param name="invalidDrawer">A Drawer that will be used in the case that will be used in the case the data can't be shown</param> /// <returns>Returns true if the data can be shown to inspector window</returns> private bool CanDataBeDisplayed(SerialData[] data, out SerializedProperty valueProperty, out SerialStorage[] storage, out IDataDrawer invalidDrawer) { // Set the default out values valueProperty = null; storage = null; invalidDrawer = null; // Check that all of the data objects are valid for display SerialData baseLine = null; if (data != null) { for (int i = 0; i < data.Length; ++i) { // If this value is null then we have a problem if (data == null) { baseLine = null; break; } // If there is no baseline instance, use this else if (baseLine == null) { baseLine = data[i]; } // If there is a type mismatch then we have a problem else if (baseLine.DataType != data[i].DataType || !object.Equals(baseLine.Modifier, data[i].Modifier)) { baseLine = null; break; } } } // If there is no baseline then there is a type mismatch that can't be resolved if (baseLine == null) { invalidDrawer = mismatchDrawer; return(false); } // If the data isn't serialisable then can't display if (!baseLine.IsValid) { invalidDrawer = nonSerialDrawer; return(false); } // Get the collection of storage objects that will be used for display storage = GetStorageForData(baseLine.DataType, data.Length); if (storage == null) { invalidDrawer = generateDrawer; return(false); } // Assign the data to the storage objects for display for (int i = 0; i < data.Length; ++i) { // Ensure the live value reflects the serial data properly data[i].OnAfterDeserialize(); // Assign the specified value to the storage element if (!storage[i].SetValue(data[i].Value)) { Debug.LogErrorFormat("Unable to assign the value '{0}' to the storage object '{1}'. Check storage asset is compatible with this type", data[i].Value, storage[i]); storage = null; invalidDrawer = generateDrawer; return(false); } } // Try to serialise the storage objects for display SerializedObject serialStorage = new SerializedObject(storage); valueProperty = serialStorage.FindProperty(storage[0].GetValuePropertyName()); if (valueProperty == null) { storage = null; invalidDrawer = missingSerialDrawer; return(false); } // If got this far, valid return(true); }
/*----------Functions----------*/ //PRIVATE /// <summary> /// Identify the object elements within the currently loaded assembly for display /// </summary> static SerialDataPropertyDrawer() { // Find all of the drawer types that can be used Type drawerAttributeType = typeof(CustomDataDrawerAttribute); TypeMarkerAttributeComparer comparer = new TypeMarkerAttributeComparer(); dataDrawerTypes = new Dictionary <TypeMarkerAttribute, Type>(comparer); foreach (Type type in AssemblyTypeScanner.GetTypesWithinAssembly <IDataDrawer>()) { // Look for the drawer marker attribute for use object[] atts = type.GetCustomAttributes(drawerAttributeType, false); if (atts == null || atts.Length == 0) { continue; } // Get the attribute that will be used to identify the type it will be used for CustomDataDrawerAttribute att = null; for (int i = 0; i < atts.Length; ++i) { att = atts[i] as CustomDataDrawerAttribute; if (att != null) { break; } } if (att == null || att.AssociatedType == null) { continue; } // Check that this type can be created for use if (type.IsAbstract) { Debug.LogErrorFormat("Unable to use Drawer type '{0}' for the type '{1}' as the drawer is abstract", type, att.AssociatedType); continue; } else if (type.GetConstructor(Type.EmptyTypes) == null) { Debug.LogErrorFormat("Unable to use Drawer type '{0}' for the type '{1}' as the drawer has no default constructor", type, att.AssociatedType); continue; } // If there is an existing drawer for this type, warn of override if (dataDrawerTypes.ContainsKey(att)) { Debug.LogWarningFormat("Drawer Type '{0}' is overriding '{1}' for use to draw '{2}'", type, dataDrawerTypes[att], att); } dataDrawerTypes[att] = type; } // Find all of the serial storage types that can be used Type serialAttributeType = typeof(CustomSerialStorageAttribute); dataStorageTypes = new Dictionary <TypeMarkerAttribute, Type>(comparer); foreach (Type type in AssemblyTypeScanner.GetTypesWithinAssembly <SerialStorage>()) { // Look for the storage attribute for use object[] atts = type.GetCustomAttributes(serialAttributeType, false); if (atts == null || atts.Length == 0) { continue; } // Get the attribute that will be used to identify the type it will be used for CustomSerialStorageAttribute att = null; for (int i = 0; i < atts.Length; ++i) { att = atts[i] as CustomSerialStorageAttribute; if (att != null) { break; } } if (att == null || att.AssociatedType == null) { continue; } // If there is an existing storage type for the value type, warn of override if (dataStorageTypes.ContainsKey(att)) { Debug.LogWarningFormat("Storage Type '{0}' is overriding '{1}' for storage of type '{2}'", type, dataStorageTypes[att], att.AssociatedType); } dataStorageTypes[att] = type; } // Create the management drawer objects mismatchDrawer = new TypeMismatchDataDrawer(); nonSerialDrawer = new NonSerialDataDrawer(); generateDrawer = new GenerateStorageDataDrawer(); missingSerialDrawer = new MissingSerialPropertyDrawer(); defaultDrawer = new DefaultDataDrawer(); }