public BuildTaskManager(BuildEngine engine, uint threads) { Engine = engine; TempFilePath = Path.Combine(engine.Project.Paths.IntermediateRoot, ".__tmp__"); _tasks = new BuildTask[threads]; for (uint i = 0; i < threads; ++i) { _tasks[i] = new BuildTask(this); } }
// Attempts to create an ImporterType out of a passed type, will return null if it is invalid public static ImporterType TryCreate(BuildEngine engine, Type type) { // Check if it is derived from IContentImporter if (type.GetInterface(INTERFACE_NAME) == null) { return(null); } // Must have the correct attribute ContentImporterAttribute attrib = (ContentImporterAttribute)type.GetCustomAttributes(ATTRIBUTE_TYPE, false)?.FirstOrDefault(); if (attrib == null) { engine.Logger.EngineError($"The type '{type.FullName}' is a ContentImporter but is missing the required attribute."); return(null); } if (!attrib.Enabled) { engine.Logger.EngineInfo($"Skipping ContentImporter type '{type.FullName}' - it is marked as disabled."); return(null); } // Validate the attribute information if (attrib.DefaultProcessor?.GetInterface(ProcessorType.INTERFACE_NAME) == null) { TypeError(engine, type, $"has an invalid default ContentProcessor type '{attrib.DefaultProcessor?.FullName}'"); return(null); } if (attrib.DisplayName == null) { TypeError(engine, type, "cannot have a null display name."); return(null); } // Ensure some required type info if (type.IsAbstract) { TypeError(engine, type, "is abstract and cannot be instantiated."); return(null); } if (type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.HasThis, new Type[0], null) == null) { TypeError(engine, type, "does not have a public no-args constructor, and cannot be instantiated."); return(null); } // Good to go return(new ImporterType(type, attrib)); }
public StageCache(BuildEngine engine) { Engine = engine; _importers = new Dictionary <string, ImporterType>(); _processors = new Dictionary <string, ProcessorType>(); // Add the builtin importers // TODO: This list must be updated whenever new builtin stages are added, or else they wont appear _importers.Add(nameof(PassthroughImporter), ImporterType.TryCreate(engine, typeof(PassthroughImporter))); _importers.Add(nameof(TextureImporter), ImporterType.TryCreate(engine, typeof(TextureImporter))); _importers.Add(nameof(AudioImporter), ImporterType.TryCreate(engine, typeof(AudioImporter))); // Add the builtin processors // TODO: This list must be updated whenever new builtin stages are added, or else they wont appear _processors.Add(nameof(PassthroughProcessor), ProcessorType.TryCreate(engine, typeof(PassthroughProcessor))); _processors.Add(nameof(TextureProcessor), ProcessorType.TryCreate(engine, typeof(TextureProcessor))); _processors.Add(nameof(AudioProcessor), ProcessorType.TryCreate(engine, typeof(AudioProcessor))); }
// Resets all settable fields back to default, and sets the ones that are included in the item args // If the parse from the content project string fails, then the field takes on its default value public void UpdateFields(BuildEngine engine, BuildEvent evt) { foreach (var field in Type.Fields) { var idx = evt.Item.ProcessorArgs.FindIndex(arg => arg.Key == field.ParamName); if (idx == -1) { field.Info.SetValue(Instance, field.DefaultValue); } else { if (ConverterCache.Convert(field.FieldType, evt.Item.ProcessorArgs[idx].Value, out object parsed)) { field.Info.SetValue(Instance, parsed); } else { engine.Logger.EngineError($"The content item '{evt.Item.ItemPath}' specified an invalid value for the parameter" + $" '{field.ParamName}'."); field.Info.SetValue(Instance, field.DefaultValue); } } } }
// This is guarenteed to already a valid ContentProcessor type public static ProcessorField[] LoadFromType(BuildEngine engine, Type type) { var valInst = Activator.CreateInstance(type); // Used to get the default values for all of the fields return(type .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly) .Select(f => (field: f, attrib: (PipelineParameterAttribute)f.GetCustomAttribute(ATTRIBUTE_TYPE, false))) .Where(f => f.attrib != null) .Where(f => { if (f.field.IsInitOnly) { engine.Logger.EngineWarn($"The ContentProcessor type '{type.Name}' cannot have a readonly pipeline parameter ({f.field.Name})."); return false; } if (!ConverterCache.CanConvert(f.field.FieldType)) { engine.Logger.EngineWarn($"The ContentProcessor type '{type.Name}' declared the pipeline parameter '{f.field.Name}' with an invalid type."); return false; } return true; }) .Select(f => new ProcessorField(f.field, f.attrib, f.field.GetValue(valInst))) .ToArray()); }
// Attempts to create an ProcessorType out of a passed type, will return null if it is invalid public static ProcessorType TryCreate(BuildEngine engine, Type type) { // Check if it is derived from IContentProcessor if (type.GetInterface(INTERFACE_NAME) == null) { return(null); } // Must have the correct attribute ContentProcessorAttribute attrib = (ContentProcessorAttribute)type.GetCustomAttributes(ATTRIBUTE_TYPE, false)?.FirstOrDefault(); if (attrib == null) { engine.Logger.EngineError($"The type '{type.FullName}' is a ContentProcessor but is missing the required attribute."); return(null); } if (!attrib.Enabled) { engine.Logger.EngineInfo($"Skipping ContentProcessor type '{type.FullName}' - it is marked as disabled."); return(null); } // Validate the attribute information if (attrib.DisplayName == null) { TypeError(engine, type, "cannot have a null display name."); return(null); } // Ensure some required type info if (type.IsAbstract) { TypeError(engine, type, "is abstract and cannot be instantiated."); return(null); } if (type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.HasThis, new Type[0], null) == null) { TypeError(engine, type, "does not have a public no-args constructor, and cannot be instantiated."); return(null); } // Validate the specified content writer Type writerType = type.BaseType.GetGenericArguments()[2]; if (writerType.IsAbstract) { WriterError(engine, writerType, "is abstract and cannot be instantiated."); return(null); } if (writerType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.HasThis, new Type[0], null) == null) { WriterError(engine, writerType, "does not have a public no-args constructor, and cannot be instantiated."); return(null); } // Get the fields var fields = ProcessorField.LoadFromType(engine, type); if (fields == null) { return(null); } // Good to go return(new ProcessorType(type, fields, attrib)); }
private static void WriterError(BuildEngine engine, Type type, string error) => engine.Logger.EngineError($"The ContentWriter type '{type.FullName}' {error}.");