#region Using Statements using System; using System.Collections.Generic; using System.Linq; using System.Text; using ANX.Framework.Content.Pipeline.Graphics; using System.ComponentModel; #endregion // This file is part of the ANX.Framework created by the // "ANX.Framework developer group" and released under the Ms-PL license. // For details see: http://anxframework.codeplex.com/license namespace ANX.Framework.Content.Pipeline.Processors { [ContentProcessor] public class MaterialProcessor : ContentProcessor<MaterialContent, MaterialContent> { [DefaultValue(typeof(Color), "255; 0; 255; 255")] public virtual Color ColorKeyColor { get; set; } [DefaultValue(true)] public virtual bool ColorKeyEnabled { get; set; } [DefaultValue(MaterialProcessorDefaultEffect.BasicEffect)] public virtual MaterialProcessorDefaultEffect DefaultEffect { get; set; } [DefaultValue(true)] public virtual bool GenerateMipmaps { get; set; } [DefaultValue(true)] public virtual bool PremultiplyTextureAlpha { get; set; } [DefaultValue(false)] public virtual bool ResizeTexturesToPowerOfTwo { get; set; } [DefaultValue(TextureProcessorOutputFormat.DxtCompressed)] public virtual TextureProcessorOutputFormat TextureFormat { get; set; } public MaterialProcessor() { ColorKeyColor = Color.FromNonPremultiplied(255, 0, 255, 255); ColorKeyEnabled = true; DefaultEffect = MaterialProcessorDefaultEffect.BasicEffect; GenerateMipmaps = true; PremultiplyTextureAlpha = true; ResizeTexturesToPowerOfTwo = false; TextureFormat = TextureProcessorOutputFormat.DxtCompressed; } /// <summary> /// Builds the texture and effect content for the material. /// </summary> /// <remarks> /// If the MaterialContent is of type EffectMaterialContent, a build is requested for Effect. /// Process requests builds for all textures in Textures. /// </remarks> /// <param name="input">The material content to build.</param> /// <param name="context">Context for the specified processor.</param> /// <returns>The built material.</returns> public override MaterialContent Process(MaterialContent input, ContentProcessorContext context) { if (input == null) throw new ArgumentNullException("input"); if (context == null) throw new ArgumentNullException("context"); //If no specific material seems to be specified, try to convert it to the default effect. if (input is BasicMaterialContent) { switch (this.DefaultEffect) { case MaterialProcessorDefaultEffect.AlphaTestEffect: input = ConvertMaterial<AlphaTestMaterialContent>(input); break; case MaterialProcessorDefaultEffect.DualTextureEffect: input = ConvertMaterial<DualTextureMaterialContent>(input); break; case MaterialProcessorDefaultEffect.EnvironmentMapEffect: input = ConvertMaterial<EnvironmentMapMaterialContent>(input); break; case MaterialProcessorDefaultEffect.SkinnedEffect: input = ConvertMaterial<SkinnedMaterialContent>(input); break; } } foreach (var pair in input.Textures) { this.BuildTexture(pair.Key, pair.Value, context); } if (input is EffectMaterialContent) { var effectMaterialContent = (EffectMaterialContent)input; if (effectMaterialContent.Effect == null) throw new InvalidContentException(string.Format("EffectMaterialContent doesn't contain an effect."), effectMaterialContent.Identity); effectMaterialContent.CompiledEffect = this.BuildEffect(effectMaterialContent.Effect, context); } return input; } protected virtual T ConvertMaterial<T>(MaterialContent material) where T : MaterialContent, new() { if (material == null) throw new ArgumentNullException("material"); T instance = new T() { Name = material.Name, Identity = material.Identity, }; foreach (var pair in material.OpaqueData) { instance.OpaqueData.Add(pair.Key, pair.Value); } foreach (var pair in material.Textures) { instance.Textures.Add(pair.Key, pair.Value); } return instance; } /// <summary> /// Builds effect content. /// </summary> /// <remarks> /// If the input to process is of type EffectMaterialContent, this function will be called to request that the EffectContent be built. /// The EffectProcessor is used to process the EffectContent. /// Subclasses of MaterialProcessor can override this function to modify the parameters used to build EffectContent. /// For example, a different version of this function could request a different processor for the EffectContent. /// </remarks> /// <param name="effect">An external reference to the effect content. </param> /// <param name="context">Context for the specified processor.</param> /// <returns>A compiled binary effect.</returns> protected virtual ExternalReference<CompiledEffectContent> BuildEffect(ExternalReference<EffectContent> effect, ContentProcessorContext context) { return context.BuildAsset<EffectContent, CompiledEffectContent>(effect, typeof(EffectProcessor).Name); } protected virtual ExternalReference<TextureContent> BuildTexture(string textureName, ExternalReference<TextureContent> texture, ContentProcessorContext context) { OpaqueDataDictionary opaqueDataDictionary = new OpaqueDataDictionary(); opaqueDataDictionary.Add("ColorKeyColor", this.ColorKeyColor); opaqueDataDictionary.Add("ColorKeyEnabled", this.ColorKeyEnabled); opaqueDataDictionary.Add("TextureFormat", this.TextureFormat); opaqueDataDictionary.Add("GenerateMipmaps", this.GenerateMipmaps); opaqueDataDictionary.Add("PremultiplyAlpha", this.PremultiplyTextureAlpha); opaqueDataDictionary.Add("ResizeToPowerOfTwo", this.ResizeTexturesToPowerOfTwo); return context.BuildAsset<TextureContent, TextureContent>(texture, typeof(TextureProcessor).Name, opaqueDataDictionary, null, null); } } }