/// <summary> /// Search the supplied objects type chain for a drawer that can be used /// </summary> /// <param name="type">The type object that will be unwinded to look for a processor</param> /// <returns>Returns a Parameter Drawer Attribute object that corresponds to a usable drawer</returns> private static CustomParameterDrawerAttribute CheckTypeChain(Type type) { //Create the exact descriptor required for this type CustomParameterDrawerAttribute buffer = new CustomParameterDrawerAttribute(type, false); //Check if the exact type exists that can be used if (parameterDrawers.ContainsKey(buffer)) { return(buffer); } //Otherwise, traverse the hierarchy chain while (type != null) { //Create the type that is being searched for buffer = new CustomParameterDrawerAttribute(type, true); //If there is an instance for the descriptor, retrieve it if (parameterDrawers.ContainsKey(buffer)) { return(buffer); } //Advance a step up the hierarchy type = type.BaseType; } //If gotten this far, nothing to find return(null); }
/*----------Functions----------*/ //PRIVATE /// <summary> /// Initialise the object with the available object definitions /// </summary> static ParameterDrawers() { //Create the lookup dictionaries CustomParameterDrawerComparer comp = new CustomParameterDrawerComparer(); parameterDrawers = new Dictionary <CustomParameterDrawerAttribute, Type>(comp); cachedDrawers = new Dictionary <CustomParameterDrawerAttribute, AParameterDrawer>(comp); typeMapping = new Dictionary <Type, AParameterDrawer>(); //Find all of the usable drawers within the project foreach (Type type in AssemblyTypeScanner.GetTypesWithinAssembly <AParameterDrawer>()) { //Look for the custom drawer processor attribute of the object CustomParameterDrawerAttribute descriptor = type.GetFirstCustomAttributeOf <CustomParameterDrawerAttribute>(); //If there is no attribute can't use it if (descriptor == null) { continue; } //Check if the type has already been used if (parameterDrawers.ContainsKey(descriptor)) { Debug.LogWarningFormat("Class '{0}' is being used to Draw for Types '{1}' (Include Children: {2}) and will override the processor '{3}'", type.FullName, descriptor.DrawerType.FullName, descriptor.HandleChildren, parameterDrawers[descriptor].FullName); } //Save the drawer for later use parameterDrawers[descriptor] = type; } }
/// <summary> /// Retrieve a drawer that can be used to render the supplied type /// </summary> /// <param name="type">The type of the object that is to be displayed</param> /// <param name="attribute">The optional attribute that is attached to the type for consideration</param> /// <returns>Returns a Parameter Drawer that will be used to display the value</returns> public static AParameterDrawer GetDrawer(Type type, ParameterAttribute attribute) { //Store a reference to the drawer that will be used to display the current value AParameterDrawer drawer = null; //Get the type of the attribute Type attributeType = (attribute != null ? attribute.GetType() : null); //Ensure that if there is an attribute, its drawer state is cached if (attributeType != null && !typeMapping.ContainsKey(attributeType)) { //Retrieve the descriptor for the attribute type CustomParameterDrawerAttribute buffer = CheckTypeChain(attributeType); //Cache the drawer that has been found for the attribute type typeMapping[attributeType] = (buffer != null ? GetDrawer(buffer) : null ); } //If there is an attribute drawer now, use that over the type if (attribute != null && typeMapping[attributeType] != null) { drawer = typeMapping[attributeType]; } //Otherwise, a drawer for the type is needed else if (!typeMapping.ContainsKey(type)) { //Retrieve the descriptor for the attribute type CustomParameterDrawerAttribute buffer = CheckTypeChain(type); //Store the processor in type mapping based on its existence drawer = typeMapping[type] = (buffer != null ? GetDrawer(buffer) : new ErrorParameterDrawer(EErrorType.DrawerMissing) ); } //Otherwise, just use the type drawer else { drawer = typeMapping[type]; } //Assign the base values to the drawer drawer.Processing = type; drawer.Attribute = attribute; //Return the stored drawer return(drawer); }
/// <summary> /// Retrieve a cached processor that can be used for the drawing of parameters /// </summary> /// <param name="descriptor">The descriptor defining the drawer to be retrieved</param> /// <returns>Retrieves an instance of the drawer that can be used or null if unable</returns> private static AParameterDrawer GetDrawer(CustomParameterDrawerAttribute descriptor) { //Make sure there is a cached instance for this descriptor if (!cachedDrawers.ContainsKey(descriptor)) { //Try to create an instance with the identified object try { cachedDrawers[descriptor] = (AParameterDrawer)Activator.CreateInstance(parameterDrawers[descriptor]); } catch (Exception exec) { Debug.LogErrorFormat("Failed to create an instance of the Parameter Drawer object '{0}'. Error: {1}", parameterDrawers[descriptor], exec.Message); cachedDrawers[descriptor] = new ErrorParameterDrawer(EErrorType.DrawerInstanceFailed, string.Format("Drawer Type '{0}' failed to instantiate. Error: {1}", parameterDrawers[descriptor], exec.Message)); } } //Returned the cached instance return(cachedDrawers[descriptor]); }