public override SpriteFontContent Process(FontDescription input,
        ContentProcessorContext context)
    {
        {
            //ファイル読み込み
            string fullPath = Path.GetFullPath("kana_list.txt");
            context.AddDependency(fullPath);
            string letters = File.ReadAllText(fullPath, System.Text.Encoding.UTF8);

            //フォントの追加
            foreach (char c in letters)
            {
                input.Characters.Add(c);
            }
        }

        {
            //ファイル読み込み
            string fullPath = Path.GetFullPath("kanji_list.txt");
            context.AddDependency(fullPath);
            string letters = File.ReadAllText(fullPath, System.Text.Encoding.UTF8);

            //フォントの追加
            foreach (char c in letters)
            {
                input.Characters.Add(c);
            }
        }

        return base.Process(input, context);
    }
Exemple #2
0
        /// <summary>
        /// 指定されたテキストファイル内の文字を追加する
        /// </summary>
        /// <param name="filename">テキストファイル名</param>
        void AddCharacters(string filename, ContentProcessorContext context)
        {
            // 指定されたファイルから文字列を読み込む
            // FontDescription.Charctarsに追加する
            try
            {
                if (!File.Exists(filename))
                {
                    throw new FileNotFoundException(String.Format(
                                                        "MessageFilenamesで指定されたファイル[{0}]が存在しません",
                                                        Path.GetFullPath(filename)));
                }

                foreach (var line in File.ReadLines(filename, Encoding.Default))
                {
                    AddCharacters(line);
                }

                // CPにファイル依存していることを教える
                context.AddDependency(Path.GetFullPath(filename));
            }
            catch (Exception e)
            {
                // 予期しない例外が発生
                context.Logger.LogImportantMessage("例外発生!! {0}", e.Message);
                throw e;
            }
        }
Exemple #3
0
        private static void GetLocalisedResX(LocalizedFontDescription input, ContentProcessorContext context)
        {
            // Scan each .resx file in turn.
            foreach (string resourceFile in input.ResourceFiles)
            {
                string absolutePath = Path.GetFullPath(resourceFile);

                // Make sure the .resx file really does exist.
                if (!File.Exists(absolutePath))
                {
                    throw new InvalidContentException("Can't find " + absolutePath);
                }

                // Load the .resx data.
                XmlDocument xmlDocument = new XmlDocument();

                xmlDocument.Load(absolutePath);

                // Scan each string from the .resx file.
                foreach (XmlNode xmlNode in xmlDocument.SelectNodes("root/data/value"))
                {
                    string resourceString = xmlNode.InnerText;

                    // Scan each character of the string.
                    foreach (char usedCharacter in resourceString)
                    {
                        input.Characters.Add(usedCharacter);
                    }
                }

                // Mark that this font should be rebuilt if the resource file changes.
                context.AddDependency(absolutePath);
            }
        }
        public override SpriteFontContent Process(LocalizedFontDescription input, ContentProcessorContext context)
        {
            foreach (string resourceFile in input.ResourceFiles)
            {
                var fullPath = Path.GetFullPath(resourceFile);
                if (!File.Exists(fullPath))
                {
                    throw new InvalidContentException("Can't find " + fullPath);
                }

                var document = new XmlDocument();
                document.Load(fullPath);

                foreach (XmlNode node in document.SelectNodes("root/data/value"))
                {
                    foreach (var c in node.InnerText)
                    {
                        input.Characters.Add(c);
                    }
                }

                context.AddDependency(fullPath);
            }

            return(context.Convert <FontDescription, SpriteFontContent>(input, "FontDescriptionProcessor"));
        }
        /// <summary>
        /// The main Process method converts an intermediate format content pipeline
        /// NodeContent tree to a ModelContent object with embedded animation data.
        /// </summary>
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            contentPath = Environment.CurrentDirectory;

            using (XmlReader reader = XmlReader.Create(MaterialDataFilePath))
            {
                incomingMaterials = IntermediateSerializer.Deserialize<List<MaterialData>>(reader, null);
            }
            context.AddDependency(Path.Combine(Environment.CurrentDirectory, MaterialDataFilePath));

            // Chain to the base ModelProcessor class so it can convert the model data.
            ModelContent model = base.Process(input, context);

            // Put the material's flags into the ModelMeshPartContent's Tag property.
            foreach (ModelMeshContent mmc in model.Meshes)
            {
                foreach (ModelMeshPartContent mmpc in mmc.MeshParts)
                {
                    MaterialData mat = incomingMaterials.Single(m => m.Name == mmpc.Material.Name);
                    MaterialInfo extraInfo = new MaterialInfo();
                    extraInfo.HandlingFlags = mat.HandlingFlags;
                    extraInfo.RenderState = mat.RenderState;
                    mmpc.Tag = extraInfo;
                }
            }

            return model;
        }
        public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
            //System.Diagnostics.Debugger.Launch();

            // If this isn't a MonoGame platform then do the default processing.
            var platform = ContentHelper.GetMonoGamePlatform();
            if (platform == MonoGamePlatform.None)
                return base.Process(input, context);

            var options = new Options();
            options.SourceFile = input.Identity.SourceFilename;
            options.Profile = platform == MonoGamePlatform.Windows8 ? ShaderProfile.DirectX_11 : ShaderProfile.OpenGL;
            options.Debug = DebugMode == EffectProcessorDebugMode.Debug;
            options.OutputFile = context.OutputFilename;

            // Parse the MGFX file expanding includes, macros, and returning the techniques.
            ShaderInfo shaderInfo;
            try
            {
                shaderInfo = ShaderInfo.FromFile(options.SourceFile, options);
                foreach (var dep in shaderInfo.Dependencies)
                    context.AddDependency(dep);
            }
            catch (Exception ex)
            {
                // TODO: Extract good line numbers from mgfx parser!
                throw new InvalidContentException(ex.Message, input.Identity, ex);
            }

            // Create the effect object.
            EffectObject effect = null;
            var shaderErrorsAndWarnings = string.Empty;
            try
            {
                effect = EffectObject.CompileEffect(shaderInfo, out shaderErrorsAndWarnings);
            }
            catch (ShaderCompilerException)
            {
                throw ProcessErrorsAndWarnings(shaderErrorsAndWarnings, input, context);
            }

            // Write out the effect to a runtime format.
            CompiledEffectContent result;
            try
            {
                using (var stream = new MemoryStream())
                {
                    using (var writer = new BinaryWriter(stream))
                        effect.Write(writer, options);

                    result = new CompiledEffectContent(stream.GetBuffer());
                }
            }
            catch (Exception ex)
            {
                throw new InvalidContentException("Failed to serialize the effect!", input.Identity, ex);
            }

            return result;
        }
Exemple #7
0
        /// <summary>
        /// The main Process method converts an intermediate format content pipeline
        /// NodeContent tree to a ModelContent object with embedded animation data.
        /// </summary>
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            contentPath = Environment.CurrentDirectory;

            using (XmlReader reader = XmlReader.Create(MaterialDataFilePath))
            {
                incomingMaterials = IntermediateSerializer.Deserialize <List <MaterialData> >(reader, null);
            }
            context.AddDependency(Path.Combine(Environment.CurrentDirectory, MaterialDataFilePath));

            // Chain to the base ModelProcessor class so it can convert the model data.
            ModelContent model = base.Process(input, context);

            // Put the material's flags into the ModelMeshPartContent's Tag property.
            foreach (ModelMeshContent mmc in model.Meshes)
            {
                foreach (ModelMeshPartContent mmpc in mmc.MeshParts)
                {
                    MaterialData mat       = incomingMaterials.Single(m => m.Name == mmpc.Material.Name);
                    MaterialInfo extraInfo = new MaterialInfo();
                    extraInfo.HandlingFlags = mat.HandlingFlags;
                    extraInfo.RenderState   = mat.RenderState;
                    mmpc.Tag = extraInfo;
                }
            }

            return(model);
        }
 /// <summary>
 /// Adds a dependency to the specified file. This causes a rebuild of the file, when modified,
 /// on subsequent incremental builds.
 /// </summary>
 /// <param name="filename">The name of an asset file.</param>
 public void AddDependency(string filename)
 {
     if (_importerContext != null)
     {
         _importerContext.AddDependency(filename);
     }
     if (_processorContext != null)
     {
         _processorContext.AddDependency(filename);
     }
 }
 public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context)
 {
     string path = Path.GetFullPath(m_FilePath);
     context.AddDependency(path);
     string content = File.ReadAllText(path, Encoding.UTF8);//FontDescription.txt文件必须保存成utf-8格式,此处也需使用utf-8读取
     foreach (char c in content)//读取文件中字符,存放到FontDescription中
     {
         input.Characters.Add(c);
     }
     return base.Process(input, context);
 }
Exemple #10
0
        public override TerrainContent Process(byte[] input, ContentProcessorContext context)
        {
            this.mContext = context;

            if (mCroppedXValues < 2 || mCroppedXValues % SECTOR_SIZE != 1)
            {
                throw new InvalidContentException(String.Format("NumXValues property value after cropping must be an integer w = n * {0} + 1 where n: {1, 2, 3...}", SECTOR_SIZE));
            }
            if (mCroppedZValues < 2 || mCroppedZValues % SECTOR_SIZE != 1)
            {
                throw new InvalidContentException(String.Format("NumZValues property value after cropping must be an integer h = n * {0} + 1 where n: {1, 2, 3...}", SECTOR_SIZE));
            }
            if (input.Length != NumXValues * NumZValues)
            {
                throw new InvalidContentException("The number of bytes in the heightmap is not equal to the product of the Height and Width properties.");
            }
            if (XZScale <= 0.0f)
            {
                throw new InvalidContentException("XZScale property must be greater than 0.");
            }
            if (YScale <= 0.0f)
            {
                throw new InvalidContentException("YScale property must be greater than 0.");
            }


            VertexElement vePosition0  = new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0);
            VertexElement veNormal0    = new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0);
            int           vertexStride = 24; // This is set based on the above VertexElement composition.

            mOutputTC = new TerrainContent();
            mOutputTC.VertexCountAlongXAxis = (mCroppedXValues - 1) * (1 << NumSubdivisions) + 1;
            mOutputTC.VertexCountAlongZAxis = (mCroppedZValues - 1) * (1 << NumSubdivisions) + 1;
            mOutputTC.SectorSize            = SECTOR_SIZE;
            mOutputTC.XZScale             = XZScale / (float)(1 << NumSubdivisions);
            mOutputTC.VertexCount         = mOutputTC.VertexCountAlongXAxis * mOutputTC.VertexCountAlongZAxis;
            mOutputTC.VertexBufferContent = new VertexBufferContent(mOutputTC.VertexCount * vertexStride);
            mOutputTC.VertexBufferContent.VertexDeclaration.VertexElements.Add(vePosition0);
            mOutputTC.VertexBufferContent.VertexDeclaration.VertexElements.Add(veNormal0);
            mOutputTC.VertexBufferContent.VertexDeclaration.VertexStride = vertexStride;
            mOutputTC.TriangleCount = SECTOR_SIZE * SECTOR_SIZE * 2;

            mMapXRadius = mOutputTC.XZScale * (float)(mOutputTC.VertexCountAlongXAxis - 1) / 2.0f;
            mMapZRadius = mOutputTC.XZScale * (float)(mOutputTC.VertexCountAlongZAxis - 1) / 2.0f;

            GeneratePositions(input);
            GenerateNormals();
            InitializeIndices();

            context.AddDependency(Path.Combine(Environment.CurrentDirectory, MaterialDataFilePath));
            CreateMaterial();

            return(mOutputTC);
        }
        public override GLSLCompiledEffect Process(GLSLSourceCode input, ContentProcessorContext context)
        {
            input.ShaderInfo.Debug = debug;
            GLSLCompiledEffect compiled = new GLSLCompiledEffect(input);

            foreach (var dep in input.ShaderInfo.Dependencies)
            {
                context.AddDependency(dep);
            }
            compiled.Compile(context);
            return(compiled);
        }
        public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context)
        {
            string fullPath = Path.GetFullPath(MessageFile);

            context.AddDependency(fullPath);
            string letters = File.ReadAllText(fullPath, System.Text.Encoding.UTF8);

            foreach (char c in letters)
            {
                input.Characters.Add(c);
            }
            return(base.Process(input, context));
        }
Exemple #13
0
        private string m_FilePath = String.Empty;//注意这里的路径,因为FontDescription.txt文件在XNAGameFontContent项目的Fonts文件夹中
        public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context)
        {
            string path = Path.GetFullPath(m_FilePath);

            context.AddDependency(path);
            string content = File.ReadAllText(path, Encoding.UTF8); //FontDescription.txt文件必须保存成utf-8格式,此处也需使用utf-8读取

            foreach (char c in content)                             //读取文件中字符,存放到FontDescription中
            {
                input.Characters.Add(c);
            }
            return(base.Process(input, context));
        }
Exemple #14
0
        public ExternalReference <TextureContent> LoadTexture(OpaqueDataDictionary parameters, ExternalReference <TextureContent> reference, ContentProcessorContext context)
        {
            if (!this.Cache.TryGetValue(reference.Filename, out var value))
            {
                value = BuildTexture(parameters, reference, context);

                var filename = reference.Filename;
                context.AddDependency(filename);
                this.Cache.Add(filename, value);
            }

            return(value);
        }
        public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context)
        {
            // TODO: 处理输入对象,并返回修改的数据。
            string fullPath = Path.GetFullPath(MessageFile);
            context.AddDependency(fullPath);
            string letters = File.ReadAllText(fullPath, System.Text.Encoding.UTF8);
            foreach (char c in letters)
            {
                input.Characters.Add(c);
            }

            return base.Process(input, context);
        }
        /// <summary>
        /// Converts a font description into SpriteFont format.
        /// </summary>
        public override SpriteFontContent Process(LocalizedFontDescription input,
                                                  ContentProcessorContext context)
        {
            // Scan each .resx file in turn.
            foreach (string resourceFile in input.ResourceFiles)
            {
                string absolutePath = Path.GetFullPath(
                    resourceFile.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar));

                // Make sure the .resx file really does exist.
                if (!File.Exists(absolutePath))
                {
                    throw new InvalidContentException("Can't find " + absolutePath);
                }

                // Load the .resx data.
                XmlDocument xmlDocument = new XmlDocument();

                xmlDocument.Load(absolutePath);

                // Scan each string from the .resx file.
                foreach (XmlNode xmlNode in xmlDocument.SelectNodes("root/data/value"))
                {
                    string resourceString = xmlNode.InnerText;

                    // Scan each character of the string.
                    foreach (var usedCharacter in resourceString.EnumerateRunes())
                    {
                        if (!input.Characters.Contains(usedCharacter))
                        {
                            input.Characters.Add(usedCharacter);
                        }
                    }
                }

                // Mark that this font should be rebuilt if the resource file changes.
                context.AddDependency(absolutePath);
            }

            var parameters = new OpaqueDataDictionary();

            parameters.Add("PremultiplyAlpha", PremultiplyAlpha);
            parameters.Add("TextureFormat", TextureFormat);

            // After adding the necessary characters, we can use the built in
            // FontDescriptionProcessor to do the hard work of building the font for us.
            return(context.Convert <FontDescription,
                                    SpriteFontContent>(input, "FontDescriptionProcessor", parameters));
        }
        protected override MaterialContent ConvertMaterial(MaterialContent material, ContentProcessorContext context)
        {
            ExternalReference <TextureContent> textureContent;

            //Dictionary<TextureUsage, ContentReference<TextureContent>> textureDictionary = new Dictionary<TextureUsage, ContentReference<TextureContent>>();

            if (material.Textures.TryGetValue("Texture", out textureContent))
            {
                string filename = textureContent.Filename;
                foreach (string name in attachedTextureNames.Keys)
                {
                    TextureUsage usage = TextureUsage.None;
                    if (!Enum.TryParse(name, out usage))
                    {
                        throw new InvalidContentException("Unknown texture usage: " + name);
                    }

                    string path            = filename.Substring(0, filename.LastIndexOf(Path.GetFileName(filename)));
                    string textureFilename = attachedTextureNames[name].Replace("*", Path.GetFileNameWithoutExtension(filename));
                    textureFilename = Path.Combine(path, textureFilename);

                    if (File.Exists(textureFilename))
                    {
                        string processor = null;
                        attachedTextureProcessors.TryGetValue(name, out processor);

                        ExternalReference <TextureContent> texture = new ExternalReference <TextureContent>(textureFilename);
                        texture = context.BuildAsset <TextureContent, TextureContent>(texture, processor);
                        //textureDictionary.Add(usage, new ContentReference<TextureContent>(texture.Filename));

                        context.AddDependency(textureFilename);
                    }
                }
            }

            //material.OpaqueData.Add("AttachedTextures", textureDictionary);

            try
            {
                return(base.ConvertMaterial(material, context));
            }
            catch (Exception e)
            {
                context.Logger.LogWarning(null, null, e.Message);
                material.Textures.Clear();
                return(material);
            }
        }
Exemple #18
0
        /// <summary>
        /// FontDescriptionにMessageFilenameで指定されたファイル内の文字を追加する
        /// </summary>
        void AppendCharacters(FontDescription input, ContentProcessorContext context)
        {
            // MessageFilenameは有効な文字列か?
            if (String.IsNullOrEmpty(MessageFilename))
            {
                return;
            }

            if (!File.Exists(MessageFilename))
            {
                throw new FileNotFoundException(
                          String.Format("MessageFilenameで指定されたファイル[{0}]が存在しません",
                                        Path.GetFullPath(MessageFilename)));
            }

            // 指定されたファイルから文字列を読み込み、
            // FontDescription.Charctarsに追加する
            try
            {
                int totalCharacterCount = 0;

                using (StreamReader sr = File.OpenText(MessageFilename))
                {
                    string line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        totalCharacterCount += line.Length;

                        foreach (char c in line)
                        {
                            input.Characters.Add(c);
                        }
                    }
                }

                context.Logger.LogImportantMessage("使用文字数{0}, 総文字数:{1}",
                                                   input.Characters.Count, totalCharacterCount);

                // CPにファイル依存していることを教える
                context.AddDependency(Path.GetFullPath(MessageFilename));
            }
            catch (Exception e)
            {
                // 予期しない例外が発生
                context.Logger.LogImportantMessage("例外発生!! {0}", e.Message);
                throw e;
            }
        }
		protected override MaterialContent ConvertMaterial(MaterialContent material, ContentProcessorContext context)
		{
			if (string.IsNullOrEmpty(StitchedEffect))
				throw new Exception("Stitched Effect property must be set for StitchUp Model Processor.");

			string fullPath = Path.GetFullPath(Path.Combine(new FileInfo(material.Identity.SourceFilename).DirectoryName, StitchedEffect));
			context.AddDependency(fullPath);

			EffectMaterialContent effectMaterial = new EffectMaterialContent
			{
				CompiledEffect = context.BuildAsset<StitchedEffectContent, CompiledEffectContent>(new ExternalReference<StitchedEffectContent>(fullPath), typeof(StitchedEffectProcessor).Name),
				Identity = material.Identity,
				Name = material.Name
			};

			return effectMaterial;
		}
Exemple #20
0
        public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context)
        {
            var fullPath = Path.GetFullPath(MessageFile);

            context.AddDependency(fullPath);

            var letters = File.ReadAllText(fullPath, System.Text.Encoding.UTF8);

            foreach (char c in letters)
            {
                if (c == '\r' || c == '\n')
                {
                    continue;
                }
                input.Characters.Add(c);
            }

            return base.Process(input, context);
        }
        protected override MaterialContent ConvertMaterial(MaterialContent material, ContentProcessorContext context)
        {
            if (string.IsNullOrEmpty(StitchedEffect))
            {
                throw new Exception("Stitched Effect property must be set for StitchUp Model Processor.");
            }

            string fullPath = Path.GetFullPath(Path.Combine(new FileInfo(material.Identity.SourceFilename).DirectoryName, StitchedEffect));

            context.AddDependency(fullPath);

            EffectMaterialContent effectMaterial = new EffectMaterialContent
            {
                CompiledEffect = context.BuildAsset <StitchedEffectContent, CompiledEffectContent>(new ExternalReference <StitchedEffectContent>(fullPath), typeof(StitchedEffectProcessor).Name),
                Identity       = material.Identity,
                Name           = material.Name
            };

            return(effectMaterial);
        }
Exemple #22
0
        private void CreateExEnOutput(Texture2DContent input, ContentProcessorContext context)
        {
            ExEnFontWriter.CreateOutputDirectory(input.Identity);

            // Put the processor in a format suitable for outputting to PNG
            var originalPremultiply = PremultiplyAlpha;
            var originalFormat      = TextureFormat;

            PremultiplyAlpha = false;
            TextureFormat    = TextureProcessorOutputFormat.Color;

            // Build normal size:
            SpriteFontContent spriteFontContent = base.Process(input, context);

            ExEnFontWriter.WriteTexture(spriteFontContent, false, context,
                                        ExEnFontWriter.AssetOutputFilename(input.Identity, context, "-exenfont.png"));
            ExEnFontWriter.WriteMetrics(spriteFontContent, context,
                                        ExEnFontWriter.AssetOutputFilename(input.Identity, context, "-exenfont.exenfont"));

            // Check for retina size:
            string pathAt2x = Path.Combine(Path.GetDirectoryName(input.Identity.SourceFilename),
                                           Path.GetFileNameWithoutExtension(input.Identity.SourceFilename) + "@2x"
                                           + Path.GetExtension(input.Identity.SourceFilename));

            if (File.Exists(pathAt2x))
            {
                var textureImporter = new TextureImporter();
                var textureAt2x     = (Texture2DContent)textureImporter.Import(pathAt2x, null);
                context.AddDependency(pathAt2x);

                var spriteFontContentAt2x = base.Process(textureAt2x, context);
                ExEnFontWriter.WriteTexture(spriteFontContentAt2x, false, context,
                                            ExEnFontWriter.AssetOutputFilename(input.Identity, context, "*****@*****.**"));
                ExEnFontWriter.WriteMetrics(spriteFontContentAt2x, context,
                                            ExEnFontWriter.AssetOutputFilename(input.Identity, context, "*****@*****.**"));
            }

            PremultiplyAlpha = originalPremultiply;
            TextureFormat    = originalFormat;
        }
Exemple #23
0
        /// <summary>
        /// Converts a font description into SpriteFont format.
        /// </summary>
        public override SpriteFontContent Process(LocalizedFontDescription input,
                                                  ContentProcessorContext context)
        {
            // Scan each .resx file in turn.
            foreach (string resourceFile in input.ResourceFiles)
            {
                string absolutePath = Path.GetFullPath(resourceFile);

                // Make sure the .resx file really does exist.
                if (!File.Exists(absolutePath))
                {
                    throw new InvalidContentException("Can't find " + absolutePath);
                }

                // Load the .resx data.
                XmlDocument xmlDocument = new XmlDocument();

                xmlDocument.Load(absolutePath);

                // Scan each string from the .resx file.
                foreach (XmlNode xmlNode in xmlDocument.SelectNodes("root/data/value"))
                {
                    string resourceString = xmlNode.InnerText;

                    // Scan each character of the string.
                    foreach (char usedCharacter in resourceString)
                    {
                        input.Characters.Add(usedCharacter);
                    }
                }

                // Mark that this font should be rebuilt if the resource file changes.
                context.AddDependency(absolutePath);
            }

            // After adding the necessary characters, we can use the built in
            // FontDescriptionProcessor to do the hard work of building the font for us.
            return(context.Convert <FontDescription,
                                    SpriteFontContent>(input, "FontDescriptionProcessor"));
        }
Exemple #24
0
        /// <summary>
        /// Processes the string representation of the specified effect into a platform-specific binary format using the specified context.
        /// </summary>
        /// <param name="input">The effect string to be processed.</param>
        /// <param name="context">Context for the specified processor.</param>
        /// <returns>A platform-specific compiled binary effect.</returns>
        /// <remarks>If you get an error during processing, compilation stops immediately. The effect processor displays an error message. Once you fix the current error, it is possible you may get more errors on subsequent compilation attempts.</remarks>
        public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
            var mgfxc      = Path.Combine(Path.GetDirectoryName(typeof(EffectProcessor).Assembly.Location), "mgfxc.dll");
            var sourceFile = input.Identity.SourceFilename;
            var destFile   = Path.GetTempFileName();
            var arguments  = "\"" + mgfxc + "\" \"" + sourceFile + "\" \"" + destFile + "\" /Profile:" + GetProfileForPlatform(context.TargetPlatform);

            if (debugMode == EffectProcessorDebugMode.Debug)
            {
                arguments += " /Debug";
            }

            if (!string.IsNullOrWhiteSpace(defines))
            {
                arguments += " \"/Defines:" + defines + "\"";
            }

            string stdout, stderr;

            var success = ExternalTool.Run("dotnet", arguments, out stdout, out stderr) == 0;
            var ret     = success ? new CompiledEffectContent(File.ReadAllBytes(destFile)) : null;

            File.Delete(destFile);

            var stdOutLines = stdout.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);

            foreach (var line in stdOutLines)
            {
                if (line.StartsWith("Dependency:") && line.Length > 12)
                {
                    context.AddDependency(line.Substring(12));
                }
            }

            ProcessErrorsAndWarnings(!success, stderr, input, context);

            return(ret);
        }
Exemple #25
0
        private void ProcessIncludesElement(XmlElement includesElement, LevelData levelData, ContentProcessorContext context)
        {
            foreach (XmlNode includeNode in includesElement.ChildNodes)
            {
                XmlElement includeElement = includeNode as XmlElement;
                if (includeElement != null)
                {
                    string includefile = includeElement.GetAttribute("name");

                    // add dependency
                    context.AddDependency(Path.GetFullPath(includefile));

                    // open document
                    XmlDocument document = new XmlDocument();
                    document.Load(includefile);
                    LevelData includedData = ProcessLevelData(document, context);

                    foreach (EntityData entityData in includedData.entities.Values)
                    {
                        levelData.entities.Add(entityData.name, entityData);
                    }
                }
            }
        }
Exemple #26
0
        internal static void WriteMetrics(object spriteFontContent, ContentProcessorContext context, string filename)
        {
            dynamic sfc = ExposedObject.From(spriteFontContent);

            using (FileStream fs = File.Open(filename, FileMode.Create, FileAccess.Write))
            {
                using (BinaryWriter bw = new BinaryWriter(fs, Encoding.Unicode))
                {
                    // Identifier and version:
                    bw.Write((int)0x6E457845);                     // ExEn
                    bw.Write((int)0x746E6F46);                     // Font
                    bw.Write((int)0);

                    // Write common properties
                    bw.Write((int)sfc.LineSpacing);
                    bw.Write((int)sfc.Spacing);
                    if (bw.WriteBoolean(((char?)sfc.DefaultCharacter).HasValue))
                    {
                        bw.Write(((char?)sfc.DefaultCharacter).Value);
                    }

                    // Write glyph list:
                    int count = sfc.CharacterMap.Count;
                    bw.Write(count);
                    for (int i = 0; i < count; i++)
                    {
                        bw.Write((char)sfc.CharacterMap[i]);
                        bw.Write((Rectangle)sfc.Glyphs[i]);
                        bw.Write((Rectangle)sfc.Cropping[i]);
                        bw.Write((Vector3)sfc.Kerning[i]);
                    }
                }
            }

            context.AddDependency(filename);
        }
Exemple #27
0
        public override Manifest Process(string input, ContentProcessorContext context)
        {
            // we assume the manifest is in the root of the content project.
            // we also assume there is only one content project in this file's directory.
            // using these assumptions we can create a path to the content project.
            string contentDirectory = input.Substring(0, input.LastIndexOf('\\'));

            string[] contentProjects = Directory.GetFiles(contentDirectory, "*.contentproj");
            if (contentProjects.Length != 1)
            {
                throw new InvalidOperationException("Could not locate content project.");
            }

            // we add a dependency on the content project itself to ensure our manifest is
            // rebuilt anytime the content project is modified
            context.AddDependency(contentProjects[0]);

            // create a list which we will fill with all the files being copied or built.
            // these will all be relative to the content project's root directory. built
            // content will not have an extension whereas copied content will maintain
            // its extension for loading.
            var manifest = new Manifest();
            //List<string> files = new List<string>();

            // we can now open up the content project for parsing which will allow us to
            // see what files are being built or copied
            XDocument document = XDocument.Load(contentProjects[0]);

            // we need the xmlns for us to find nodes in the document
            XNamespace xmlns = document.Root.Attribute("xmlns").Value;

            // we need the content root directory from the file to know where copied files will end up
            string contentRootDirectory = document.Descendants(xmlns + "ContentRootDirectory").First().Value;

            // first find all assets that are set to compile into XNB files
            var compiledAssets = document.Descendants(xmlns + "Compile");

            foreach (var asset in compiledAssets)
            {
                // get the include path and name
                string includePath = asset.Attribute("Include").Value;
                string name        = asset.Descendants(xmlns + "Name").First().Value;
                string extension   = System.IO.Path.GetExtension(includePath);

                // if the include path is a manifest, skip it
                if (includePath.EndsWith(".manifest"))
                {
                    continue;
                }

                string assetPath = null;

                // combine the two into the asset path if the include path
                // has a directory. otherwise we just use the name.
                if (includePath.Contains('\\'))
                {
                    string dir = includePath.Substring(0, includePath.LastIndexOf('\\'));
                    assetPath = Path.Combine(dir, name);
                }
                else
                {
                    assetPath = name;
                }

                Entry entry = new Entry();
                entry.Name = assetPath;
                entry.Type = ContentType.Unknown;

                if (extension == ".xml")
                {
                    entry.Type = ContentType.XML;
                }
                else
                {
                    string Importer = asset.Descendants(xmlns + "Importer").First().Value;

                    if (Importer == "TextureImporter")
                    {
                        entry.Type = ContentType.Texture;
                    }
                }
                manifest.Entries.Add(entry);
            }

            // next we find all assets that are set to copy to the output directory. we are going
            // to leverage LINQ to do this for us. this is the logic employed:
            //  1) we select all nodes that are children of an ItemGroup.
            //  2) from that set we find nodes that have a CopyToOutputDirectory node and make sure it is not set to None
            //  3) we then select that node's Include attribute as that is the value we want. we must also prepend
            //     the output directory to make the file path relative to the game instead of the content.
            var copiedAssetFiles = from node in document.Descendants(xmlns + "ItemGroup").Descendants()
                                   where node.Descendants(xmlns + "CopyToOutputDirectory").Count() > 0 &&
                                   node.Descendants(xmlns + "CopyToOutputDirectory").First().Value != "None"
                                   select /*Path.Combine(contentRootDirectory,*/ node.Attribute("Include").Value;//);

            // we can now just add all of those files to our list
            foreach (var F in copiedAssetFiles)
            {
                manifest.Entries.Add(new Entry {
                    Type = ContentType.Unknown, Name = F
                });
            }

            // lastly we want to override the manifest file with this list. this allows us to
            // easily see what files were included in the build for debugging.
            using (FileStream fileStream = new FileStream(input, FileMode.Create, FileAccess.Write))
            {
                using (StreamWriter writer = new StreamWriter(fileStream))
                {
                    // now write all the files into the manifest
                    foreach (var file in manifest.Entries)
                    {
                        writer.WriteLine(file.Type.ToString() + " " + file.Name);
                    }
                }
            }

            // just return the list which will be automatically serialized for us without
            // needing a ContentTypeWriter like we would have needed pre- XNA GS 3.1
            return(manifest);
        }
        /// <summary>
        /// Converts an intermediate format content pipeline AnimationContentDictionary
        /// object to our runtime AnimationClip format.
        /// </summary>
        static Dictionary<string, AnimationClip> ProcessAnimations(
            AnimationContentDictionary animations, IList<BoneContent> bones,
            ContentProcessorContext context, ContentIdentity sourceIdentity)
        {
            // Build up a table mapping bone names to indices.
            Dictionary<string, int> boneMap = new Dictionary<string, int>();

            for (int i = 0; i < bones.Count; i++)
            {
                string boneName = bones[i].Name;

                if (!string.IsNullOrEmpty(boneName))
                    boneMap.Add(boneName, i);
            }

            // Convert each animation in turn.
            Dictionary<string, AnimationClip> animationClips;
            animationClips = new Dictionary<string, AnimationClip>();

            foreach (KeyValuePair<string, AnimationContent> animation in animations)
            {
                AnimationClip processed = ProcessAnimation(animation.Value, boneMap, animation.Key);

                animationClips.Add(animation.Key, processed);
            }

            // Check to see if there's an animation clip definition
            // Here, we're checking for a file with the _Anims suffix.
            // So, if your model is named dude.fbx, we'd add dude_Anims.xml in the same folder
            // and the pipeline will see the file and use it to override the animations in the
            // original model file.
            string SourceModelFile = sourceIdentity.SourceFilename;
            string SourcePath = Path.GetDirectoryName(SourceModelFile);
            string AnimFilename = Path.GetFileNameWithoutExtension(SourceModelFile);
            AnimFilename += "_Anims.xml";
            string AnimPath = Path.Combine(SourcePath, AnimFilename);
            if (File.Exists(AnimPath))
            {
                context.AddDependency(AnimPath);

                AnimationDefinition AnimDef = context.BuildAndLoadAsset<XmlImporter, AnimationDefinition>(new ExternalReference<XmlImporter>(AnimPath), null);

                //breaks up original animation clips into new clips
                if (animationClips.ContainsKey(AnimDef.originalClipName))
                {
                    //graps main clip
                    AnimationClip MainClip = animationClips[AnimDef.originalClipName];
                    //remove original clip from animations
                    animationClips.Remove(AnimDef.originalClipName);

                    foreach (AnimationDefinition.clipPart Part in AnimDef.ClipParts)
                    {
                        //calculate frame times
                        TimeSpan StartTime = GetTimeSpanForFrame(Part.StartFrame, AnimDef.originalFrameCount, MainClip.Duration.Ticks);
                        TimeSpan EndTime = GetTimeSpanForFrame(Part.EndFrame, AnimDef.originalFrameCount, MainClip.Duration.Ticks);

                        //get keyframes for animation clip thats in start and end time
                        List<Keyframe> Keyframes = new List<Keyframe>();
                        foreach (Keyframe AnimFrame in MainClip.Keyframes)
                        {
                            if ((AnimFrame.Time >= StartTime) && (AnimFrame.Time <= EndTime))
                            {
                                Keyframe NewFrame = new Keyframe(AnimFrame.Bone, AnimFrame.Time - StartTime, AnimFrame.Transform);
                                Keyframes.Add(NewFrame);
                            }
                        }

                        //process events
                        /*List<AnimationEvent> Events = new List<AnimationEvent>();
                        if (Part.Events != null)
                        {
                            foreach (AnimationDefinition.clipPart.Event Event in Part.Events)
                            {
                                TimeSpan EventTime = GetTimeSpanForFrame(Event.Keyframe, AnimDef.originalFrameCount, MainClip.Duration.Ticks);
                                EventTime -= StartTime;

                                AnimationEvent newEvent = new AnimationEvent();
                                newEvent.EventTime = EventTime;
                                newEvent.EventName = Event.Name;
                                Events.Add(newEvent);
                            }
                        }*/

                        AnimationClip newClip = new AnimationClip(EndTime - StartTime, Keyframes, Part.ClipName);
                        animationClips[Part.ClipName] = newClip;
                    }
                }
            }

               /* if (animationClips.Count == 0)
            {
                throw new InvalidContentException(
                            "Input file does not contain any animations.");
            }*/

            return animationClips;
        }
        // Parses the XML file defining the splits.
        // This method returns null if the file is not found.
        // This method returns an empty collection if the file does not contain any split definitions or
        // if the format is invalid.
        private static List<SplitDefinition> ParseSplitAnimationFile(string splitFile, ContentIdentity contentIdentity, ContentProcessorContext context)
        {
            // Get full path of XML file. File location is relative to the location of the model.
              string sourcePath = Path.GetDirectoryName(contentIdentity.SourceFilename);
              string splitFilePath = Path.GetFullPath(Path.Combine(sourcePath, splitFile));
              XDocument document;
              try
              {
             document = XDocument.Load(splitFilePath);
              }
              catch (FileNotFoundException)
              {
            return null;
              }

              var splits = new List<SplitDefinition>();

              // Let the content pipeline know that we depend on this file and we need to rebuild the
              // content if the file is modified.
              context.AddDependency(splitFilePath);

              var animationsNode = document.Element("Animations");
              if (animationsNode == null)
              {
            context.Logger.LogWarning(null, contentIdentity, splitFile + " does not contain an <Animations> root node.");
            return splits;
              }

              double? framerate = (double?)animationsNode.Element("Framerate");

              foreach (var animationNode in animationsNode.Elements("Animation"))
              {
            var name = (string)animationNode.Attribute("Name");
            if (string.IsNullOrEmpty(name))
            {
              string message = string.Format("{0} contains an <Animation> element with a missing or empty 'Name' attribute", splitFile);
              throw new InvalidContentException(message, contentIdentity);
            }

            double? startTime = (double?)animationNode.Attribute("StartTime");
            double? endTime = (double?)animationNode.Attribute("EndTime");

            int? startFrame = (int?)animationNode.Attribute("StartFrame");
            int? endFrame = (int?)animationNode.Attribute("EndFrame");

            if (startTime == null && startFrame == null)
            {
              string message = string.Format("{0} contains an <Animation> element that does not contain a valid 'StartTime' or 'StartFrame' attribute.", splitFile);
              throw new InvalidContentException(message, contentIdentity);
            }

            if (endTime == null && endFrame == null)
            {
              string message = string.Format("{0} contains an <Animation> element that does not contain a valid 'EndTime' or 'EndFrame' attribute.", splitFile);
              throw new InvalidContentException(message, contentIdentity);
            }

            if (framerate == null && (startTime == null || endTime == null))
            {
              string message = string.Format("{0} must have a <Framerate> element if start and end are specified in 'frames'.", splitFile);
              throw new InvalidContentException(message, contentIdentity);
            }

            startTime = startTime ?? startFrame.Value / framerate.Value;
            endTime = endTime ?? endFrame.Value / framerate.Value;
            TimeSpan start = new TimeSpan((long)(startTime.Value * TimeSpan.TicksPerSecond));
            TimeSpan end = new TimeSpan((long)(endTime.Value * TimeSpan.TicksPerSecond));

            if (start > end)
            {
              string message = string.Format("{0} contains an invalid <Animation> element: The start time is larger than the end time.", splitFile);
              throw new InvalidContentException(message, contentIdentity);
            }

            splits.Add(new SplitDefinition { Name = name, StartTime = start, EndTime = end });
              }

              return splits;
        }
Exemple #30
0
        //--------------------------------------------------------------
        #region Avatar Expression Animation
        //--------------------------------------------------------------

        /// <summary>
        /// Converts the input expression animation file into expression animation keyframes.
        /// </summary>
        private AvatarExpressionKeyFrameAnimation ProcessExpressionAnimation(NodeContent input, ContentProcessorContext context)
        {
            if (string.IsNullOrEmpty(ExpressionFile))
            {
                return(null);
            }

            // Create a AvatarExpression key frame animation that will animate the Expression
            // property of an AvatarPose.
            var animation = new AvatarExpressionKeyFrameAnimation
            {
                TargetProperty = "Expression",
            };

            // Let the content pipeline know that we depend on this file and we need to rebuild the
            // content if the file is modified.
            string sourcePath = Path.GetDirectoryName(input.Identity.SourceFilename);
            string filePath   = Path.GetFullPath(Path.Combine(sourcePath, ExpressionFile));

            context.AddDependency(filePath);

            FileStream   fs = File.OpenRead(filePath);
            StreamReader sr = new StreamReader(fs);

            while (!sr.EndOfStream)
            {
                string currentLine = sr.ReadLine();

                // Skip comment lines
                if (currentLine.StartsWith("#"))
                {
                    continue;
                }

                string[] Components = currentLine.Split(',');

                // Check for the correct number of components
                if (Components.Length != 6)
                {
                    throw new InvalidContentException("Error processing facial expression file", input.Identity);
                }

                try
                {
                    TimeSpan         time             = TimeSpan.FromMilliseconds(Convert.ToDouble(Components[0]));
                    AvatarExpression avatarExpression = new AvatarExpression();
                    avatarExpression.LeftEye      = (AvatarEye)Convert.ToInt32(Components[1]);
                    avatarExpression.LeftEyebrow  = (AvatarEyebrow)Convert.ToInt32(Components[2]);
                    avatarExpression.Mouth        = (AvatarMouth)Convert.ToInt32(Components[3]);
                    avatarExpression.RightEye     = (AvatarEye)Convert.ToInt32(Components[4]);
                    avatarExpression.RightEyebrow = (AvatarEyebrow)Convert.ToInt32(Components[5]);

                    // Add key frame.
                    var keyFrame = new KeyFrame <AvatarExpression>(time, avatarExpression);
                    animation.KeyFrames.Add(keyFrame);
                }
                catch (Exception)
                {
                    throw new InvalidContentException("Error processing facial expression file", input.Identity);
                }
            }

            if (animation.KeyFrames.Count == 0)
            {
                return(null);
            }

            // Sort the animation frames
            animation.KeyFrames.Sort();

            return(animation);
        }
Exemple #31
0
        /// <summary>
        /// Processes the string representation of the specified effect into a platform-specific binary format using the specified context.
        /// </summary>
        /// <param name="input">The effect string to be processed.</param>
        /// <param name="context">Context for the specified processor.</param>
        /// <returns>A platform-specific compiled binary effect.</returns>
        /// <remarks>If you get an error during processing, compilation stops immediately. The effect processor displays an error message. Once you fix the current error, it is possible you may get more errors on subsequent compilation attempts.</remarks>
        public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
#if WINDOWS
            var options = new Options();
            options.SourceFile = input.Identity.SourceFilename;

            options.Profile = ShaderProfile.ForPlatform(context.TargetPlatform.ToString());
            if (options.Profile == null)
            {
                throw new InvalidContentException(string.Format("{0} effects are not supported.", context.TargetPlatform), input.Identity);
            }

            options.Debug      = DebugMode == EffectProcessorDebugMode.Debug;
            options.Defines    = Defines;
            options.OutputFile = context.OutputFilename;

            // Parse the MGFX file expanding includes, macros, and returning the techniques.
            ShaderResult shaderResult;
            try
            {
                shaderResult = ShaderResult.FromFile(options.SourceFile, options,
                                                     new ContentPipelineEffectCompilerOutput(context));

                // Add the include dependencies so that if they change
                // it will trigger a rebuild of this effect.
                foreach (var dep in shaderResult.Dependencies)
                {
                    context.AddDependency(dep);
                }
            }
            catch (InvalidContentException)
            {
                throw;
            }
            catch (Exception ex)
            {
                // TODO: Extract good line numbers from mgfx parser!
                throw new InvalidContentException(ex.Message, input.Identity, ex);
            }

            // Create the effect object.
            EffectObject effect = null;
            var          shaderErrorsAndWarnings = string.Empty;
            try
            {
                effect = EffectObject.CompileEffect(shaderResult, out shaderErrorsAndWarnings);

                // If there were any additional output files we register
                // them so that the cleanup process can manage them.
                foreach (var outfile in shaderResult.AdditionalOutputFiles)
                {
                    context.AddOutputFile(outfile);
                }
            }
            catch (ShaderCompilerException)
            {
                // This will log any warnings and errors and throw.
                ProcessErrorsAndWarnings(true, shaderErrorsAndWarnings, input, context);
            }

            // Process any warning messages that the shader compiler might have produced.
            ProcessErrorsAndWarnings(false, shaderErrorsAndWarnings, input, context);

            // Write out the effect to a runtime format.
            CompiledEffectContent result;
            try
            {
                using (var stream = new MemoryStream())
                {
                    using (var writer = new BinaryWriter(stream))
                        effect.Write(writer, options);

                    result = new CompiledEffectContent(stream.GetBuffer());
                }
            }
            catch (Exception ex)
            {
                throw new InvalidContentException("Failed to serialize the effect!", input.Identity, ex);
            }

            return(result);
#else
            throw new NotImplementedException();
#endif
        }
        public static void Split(AnimationContentDictionary animationDictionary, string splitFile, ContentIdentity contentIdentity, ContentProcessorContext context)
        {
            if (animationDictionary == null)
            {
                return;
            }

            if (string.IsNullOrEmpty(splitFile))
            {
                return;
            }

            if (contentIdentity == null)
            {
                throw new ArgumentNullException("contentIdentity");
            }

            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (animationDictionary.Count == 0)
            {
                context.Logger.LogWarning(null, contentIdentity, "The model does not have an animation. Animation splitting is skipped.");
                return;
            }

            if (animationDictionary.Count > 1)
            {
                context.Logger.LogWarning(null, contentIdentity, "The model contains more than 1 animation. The animation splitting is performed on the first animation. Other animations are deleted!");
            }

            // Load XML file.
            splitFile = ContentHelper.FindFile(splitFile, contentIdentity);
            XDocument document = XDocument.Load(splitFile, LoadOptions.SetLineInfo);

            // Let the content pipeline know that we depend on this file and we need to
            // rebuild the content if the file is modified.
            context.AddDependency(splitFile);

            // Parse XML.
            var animationsElement = document.Element("Animations");

            if (animationsElement == null)
            {
                context.Logger.LogWarning(null, contentIdentity, "The animation split file \"{0}\" does not contain an <Animations> root node.", splitFile);
                return;
            }

            var wrappedContext = new ContentPipelineContext(context);
            var splits         = ParseAnimationSplitDefinitions(animationsElement, contentIdentity, wrappedContext);

            if (splits == null || splits.Count == 0)
            {
                context.Logger.LogWarning(null, contentIdentity, "The XML file with the animation split definitions is invalid or empty. Animation is not split.");
                return;
            }

            // Split animations.
            Split(animationDictionary, splits, contentIdentity, context);
        }
Exemple #33
0
        internal static void WriteMetrics(object spriteFontContent, ContentProcessorContext context, string filename)
        {
            dynamic sfc = ExposedObject.From(spriteFontContent);

            using(FileStream fs = File.Open(filename, FileMode.Create, FileAccess.Write))
            {
                using(BinaryWriter bw = new BinaryWriter(fs, Encoding.Unicode))
                {
                    // Identifier and version:
                    bw.Write((int)0x6E457845); // ExEn
                    bw.Write((int)0x746E6F46); // Font
                    bw.Write((int)0);

                    // Write common properties
                    bw.Write((int)sfc.LineSpacing);
                    bw.Write((int)sfc.Spacing);
                    if(bw.WriteBoolean(((char?)sfc.DefaultCharacter).HasValue))
                        bw.Write(((char?)sfc.DefaultCharacter).Value);

                    // Write glyph list:
                    int count = sfc.CharacterMap.Count;
                    bw.Write(count);
                    for(int i = 0; i < count; i++)
                    {
                        bw.Write((char)sfc.CharacterMap[i]);
                        bw.Write((Rectangle)sfc.Glyphs[i]);
                        bw.Write((Rectangle)sfc.Cropping[i]);
                        bw.Write((Vector3)sfc.Kerning[i]);
                    }
                }
            }

            context.AddDependency(filename);
        }
        /// <summary>
        /// Entry point for animation processing. 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="input"></param>
        /// <param name="context"></param>
        private void ProcessAnimations(ModelContent model, NodeContent input, ContentProcessorContext context, ContentIdentity sourceIdentity)
        {
            // First build a lookup table so we can determine the
            // index into the list of bones from a bone name.
            for (int i = 0; i < model.Bones.Count; i++)
            {
                bones[model.Bones[i].Name] = i;
            }

            // For saving the bone transforms
            boneTransforms = new Matrix[model.Bones.Count];

            //
            // Collect up all of the animation data
            //

            ProcessAnimationsRecursive(input);

            // Check to see if there's an animation clip definition
            // Here, we're checking for a file with the _Anims suffix.
            // So, if your model is named dude.fbx, we'd add dude_Anims.xml in the same folder
            // and the pipeline will see the file and use it to override the animations in the
            // original model file.
            string SourceModelFile = sourceIdentity.SourceFilename;
            string SourcePath = Path.GetDirectoryName(SourceModelFile);
            string AnimFilename = Path.GetFileNameWithoutExtension(SourceModelFile);
            AnimFilename += "_Anims.xml";
            string AnimPath = Path.Combine(SourcePath, AnimFilename);
            if (File.Exists(AnimPath))
            {
                // Add the filename as a dependency, so if it changes, the model is rebuilt
                context.AddDependency(AnimPath);

                // Load the animation definition from the XML file
                AnimationDefinition AnimDef = context.BuildAndLoadAsset<XmlImporter, AnimationDefinition>(new ExternalReference<XmlImporter>(AnimPath), null);

                if (modelExtra.Clips.Count > 0) //if there are some animations in our model
                {
                    foreach (AnimationDefinition.ClipPart Part in AnimDef.ClipParts)
                    {
                        // Grab the main clip that we are using and copy to MainClip

                        AnimationClip MainClip = new AnimationClip();

                        float StartTime = GetTimeSpanForFrame(Part.StartFrame, AnimDef.OriginalFrameCount, modelExtra.Clips[AnimDef.OriginalClipName].Duration);
                        float EndTime = GetTimeSpanForFrame(Part.EndFrame, AnimDef.OriginalFrameCount, modelExtra.Clips[AnimDef.OriginalClipName].Duration);

                        MainClip.Duration = EndTime-StartTime;
                        MainClip.Name = modelExtra.Clips[AnimDef.OriginalClipName].Name;

                        // Process each of our new animation clip parts
                        for (int i = 0; i < modelExtra.Clips[AnimDef.OriginalClipName].Bones.Count; i++)
                        {
                            AnimationClip.Bone clipBone = new AnimationClip.Bone();
                            clipBone.Name = modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Name;
                            LinkedList<AnimationClip.Keyframe> keyframes = new LinkedList<AnimationClip.Keyframe>();

                            if (modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes.Count != 0)
                            {

                                for (int j = 0; j < modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes.Count; j++)
                                {

                                    if ((modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes[j].Time >= StartTime) && (modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes[j].Time <= EndTime))
                                    {
                                        AnimationClip.Keyframe frame = new AnimationClip.Keyframe();
                                        frame.Rotation = modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes[j].Rotation;
                                        frame.Time = modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes[j].Time - StartTime;
                                        frame.Translation = modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes[j].Translation;
                                        keyframes.AddLast(frame);
                                       //clipBone.Keyframes.Add(frame);
                                    }

                                }
                            }
                           // LinearKeyframeReduction(keyframes);
                            clipBone.Keyframes = keyframes.ToList<AnimationClip.Keyframe>();
                            MainClip.Bones.Add(clipBone);

                        }
                        modelExtra.Clips.Add(Part.ClipName, MainClip);

                    }
                }
            }

            // Ensure there is always a clip, even if none is included in the FBX
            // That way we can create poses using FBX files as one-frame
            // animation clips
            if (modelExtra.Clips.Count == 0)
            {
                AnimationClip clip = new AnimationClip();
                modelExtra.Clips.Add("Take 001",clip);

                string clipName = "Take 001";

                // Retain by name
                clips[clipName] = clip;

                clip.Name = clipName;
                foreach (ModelBoneContent bone in model.Bones)
                {
                    AnimationClip.Bone clipBone = new AnimationClip.Bone();
                    clipBone.Name = bone.Name;

                    clip.Bones.Add(clipBone);
                }
            }

            //Ensure all animations have a first key frame for every bone
            foreach (KeyValuePair<string,AnimationClip> clip in modelExtra.Clips)
            {
                for (int b = 0; b < bones.Count; b++)
                {
                    List<AnimationClip.Keyframe> keyframes = clip.Value.Bones[b].Keyframes;
                    if (keyframes.Count == 0 || keyframes[0].Time > 0)
                    {
                        AnimationClip.Keyframe keyframe = new AnimationClip.Keyframe();
                        keyframe.Time = 0;
                        keyframe.Transform = boneTransforms[b];
                        keyframes.Insert(0, keyframe);
                    }
                }
            }
        }
Exemple #35
0
        public static void Bind(ContentProcessorContext context, NodeContent node, string defaultNormalTexture, string defaultSpecularTexture, string defaultMaskTexture, string defaultReflectionTexture)
        {
            if (node is MeshContent mesh)
            {
                var modelPath = mesh.Identity.SourceFilename;
                var lookup    = new MaterialDescriptionFile(modelPath);

                context.AddDependency(lookup.File);

                foreach (var geometry in mesh.Geometry)
                {
                    if (geometry.Material.Textures.TryGetValue("Texture", out var texture))
                    {
                        var fileName = texture.Filename;
                        geometry.Material.Textures.Clear();
                        if (lookup.TryGetValue(fileName, out var description))
                        {
                            geometry.Material.Textures.Add(
                                "Texture",
                                new ExternalReference <TextureContent>(description.Diffuse));

                            geometry.Material.Textures.Add(
                                "NormalMap",
                                string.IsNullOrEmpty(description.Normal)
                                    ? new ExternalReference <TextureContent>(defaultNormalTexture)
                                    : new ExternalReference <TextureContent>(description.Normal));

                            geometry.Material.Textures.Add(
                                "SpecularMap",
                                string.IsNullOrEmpty(description.Specular)
                                    ? new ExternalReference <TextureContent>(defaultSpecularTexture)
                                    : new ExternalReference <TextureContent>(description.Specular));

                            geometry.Material.Textures.Add(
                                "Mask",
                                string.IsNullOrEmpty(description.Mask)
                                    ? new ExternalReference <TextureContent>(defaultMaskTexture)
                                    : new ExternalReference <TextureContent>(description.Mask));

                            geometry.Material.Textures.Add(
                                "ReflectionMap",
                                string.IsNullOrEmpty(description.Reflection)
                                    ? new ExternalReference <TextureContent>(defaultReflectionTexture)
                                    : new ExternalReference <TextureContent>(description.Reflection));
                        }
                        else
                        {
                            context.Logger.LogWarning("", node.Identity, $"Could not find texture {fileName} in lookup");
                        }
                    }
                    else
                    {
                        geometry.Material.Textures.Clear();
                        context.Logger.LogWarning("", node.Identity, $"Could not find Texture reference in model");
                    }
                }
            }

            foreach (var child in node.Children)
            {
                Bind(context, child, defaultNormalTexture, defaultSpecularTexture, defaultMaskTexture, defaultReflectionTexture);
            }
        }
        public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
            //System.Diagnostics.Debugger.Launch();

            // If this isn't a MonoGame platform then do the default processing.
            var platform = ContentHelper.GetMonoGamePlatform();

            if (platform == MonoGamePlatform.None)
            {
                return(base.Process(input, context));
            }

            var options = new Options();

            options.SourceFile  = input.Identity.SourceFilename;
            options.DX11Profile = platform == MonoGamePlatform.Windows8 ? true : false;
            options.Debug       = DebugMode == EffectProcessorDebugMode.Debug;
            options.OutputFile  = context.OutputFilename;

            // Parse the MGFX file expanding includes, macros, and returning the techniques.
            ShaderInfo shaderInfo;

            try
            {
                shaderInfo = ShaderInfo.FromFile(options.SourceFile, options);
                foreach (var dep in shaderInfo.Dependencies)
                {
                    context.AddDependency(dep);
                }
            }
            catch (Exception ex)
            {
                // TODO: Extract good line numbers from mgfx parser!
                throw new InvalidContentException(ex.Message, input.Identity, ex);
            }

            // Create the effect object.
            DXEffectObject effect = null;

            try
            {
                effect = DXEffectObject.FromShaderInfo(shaderInfo);
            }
            catch (Exception ex)
            {
                throw ProcessErrorsAndWarnings(ex.Message, input, context);
            }

            // Write out the effect to a runtime format.
            CompiledEffectContent result;

            try
            {
                using (var stream = new MemoryStream())
                {
                    using (var writer = new BinaryWriter(stream))
                        effect.Write(writer, options);

                    result = new CompiledEffectContent(stream.GetBuffer());
                }
            }
            catch (Exception ex)
            {
                throw new InvalidContentException("Failed to serialize the effect!", input.Identity, ex);
            }

            return(result);
        }
Exemple #37
0
        private void CreateExEnOutput(Texture2DContent input, ContentProcessorContext context)
        {
            ExEnFontWriter.CreateOutputDirectory(input.Identity);

            // Put the processor in a format suitable for outputting to PNG
            var originalPremultiply = PremultiplyAlpha;
            var originalFormat = TextureFormat;
            PremultiplyAlpha = false;
            TextureFormat = TextureProcessorOutputFormat.Color;

            // Build normal size:
            SpriteFontContent spriteFontContent = base.Process(input, context);
            ExEnFontWriter.WriteTexture(spriteFontContent, false, context,
                    ExEnFontWriter.AssetOutputFilename(input.Identity, context, "-exenfont.png"));
            ExEnFontWriter.WriteMetrics(spriteFontContent, context,
                    ExEnFontWriter.AssetOutputFilename(input.Identity, context, "-exenfont.exenfont"));

            // Check for retina size:
            string pathAt2x = Path.Combine(Path.GetDirectoryName(input.Identity.SourceFilename),
                    Path.GetFileNameWithoutExtension(input.Identity.SourceFilename) + "@2x"
                    + Path.GetExtension(input.Identity.SourceFilename));
            if(File.Exists(pathAt2x))
            {
                var textureImporter = new TextureImporter();
                var textureAt2x = (Texture2DContent)textureImporter.Import(pathAt2x, null);
                context.AddDependency(pathAt2x);

                var spriteFontContentAt2x = base.Process(textureAt2x, context);
                ExEnFontWriter.WriteTexture(spriteFontContentAt2x, false, context,
                        ExEnFontWriter.AssetOutputFilename(input.Identity, context, "*****@*****.**"));
                ExEnFontWriter.WriteMetrics(spriteFontContentAt2x, context,
                        ExEnFontWriter.AssetOutputFilename(input.Identity, context, "*****@*****.**"));
            }

            PremultiplyAlpha = originalPremultiply;
            TextureFormat = originalFormat;
        }
        /// <summary>
        /// FontDescription��MessageFilename�Ŏw�肳�ꂽ�t�@�C����̕�����lj�����
        /// </summary>
        void AppendCharacters(FontDescription input, ContentProcessorContext context)
        {
            // MessageFilename�͗L���ȕ����񂩁H
            if (String.IsNullOrEmpty(MessageFilename))
                return;

            if (!File.Exists(MessageFilename))
            {
                throw new FileNotFoundException(
                    String.Format( "MessageFilename�Ŏw�肳�ꂽ�t�@�C��[{0}]�����݂��܂���",
                                    Path.GetFullPath(MessageFilename)));
            }

            // �w�肳�ꂽ�t�@�C�����當�����ǂݍ��݁A
            // FontDescription.Charctars�ɒlj�����
            try
            {
                int totalCharacterCount = 0;

                using (StreamReader sr = File.OpenText(MessageFilename))
                {
                    string line;
                    while ( ( line = sr.ReadLine() ) != null )
                    {
                        totalCharacterCount += line.Length;

                        foreach( char c in line )
                            input.Characters.Add( c );
                    }
                }

                context.Logger.LogImportantMessage("�g�p������{0}, ��������:{1}",
                    input.Characters.Count, totalCharacterCount);

                // CP�Ƀt�@�C���ˑ����Ă��邱�Ƃ������
                context.AddDependency(Path.GetFullPath(MessageFilename));
            }
            catch (Exception e)
            {
                // �\�����Ȃ���O������
                context.Logger.LogImportantMessage("��O����!! {0}", e.Message);
                throw e;
            }
        }
Exemple #39
0
        /// <summary>
        /// Processes the string representation of the specified effect into a platform-specific binary format using the specified context.
        /// </summary>
        /// <param name="input">The effect string to be processed.</param>
        /// <param name="context">Context for the specified processor.</param>
        /// <returns>A platform-specific compiled binary effect.</returns>
        /// <remarks>If you get an error during processing, compilation stops immediately. The effect processor displays an error message. Once you fix the current error, it is possible you may get more errors on subsequent compilation attempts.</remarks>
        public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
#if WINDOWS
            var options = new Options();
            options.SourceFile = input.Identity.SourceFilename;

            switch (context.TargetPlatform)
            {
            case TargetPlatform.Windows:
            case TargetPlatform.WindowsPhone8:
            case TargetPlatform.WindowsStoreApp:
                options.Profile = ShaderProfile.DirectX_11;
                break;

            case TargetPlatform.iOS:
            case TargetPlatform.Android:
            case TargetPlatform.Linux:
            case TargetPlatform.MacOSX:
            case TargetPlatform.Ouya:
            case TargetPlatform.RaspberryPi:
                options.Profile = ShaderProfile.OpenGL;
                break;

            default:
                throw new InvalidContentException(string.Format("{0} effects are not supported.", context.TargetPlatform), input.Identity);
            }

            options.Debug      = DebugMode == EffectProcessorDebugMode.Debug;
            options.OutputFile = context.OutputFilename;

            // Parse the MGFX file expanding includes, macros, and returning the techniques.
            ShaderInfo shaderInfo;
            try
            {
                shaderInfo = ShaderInfo.FromFile(options.SourceFile, options);

                // Add the include dependencies so that if they change
                // it will trigger a rebuild of this effect.
                foreach (var dep in shaderInfo.Dependencies)
                {
                    context.AddDependency(dep);
                }
            }
            catch (Exception ex)
            {
                // TODO: Extract good line numbers from mgfx parser!
                throw new InvalidContentException(ex.Message, input.Identity, ex);
            }

            // Create the effect object.
            EffectObject effect = null;
            try
            {
                effect = EffectObject.FromShaderInfo(shaderInfo);

                // If there were any additional output files we register
                // them so that the cleanup process can manage them.
                foreach (var outfile in shaderInfo.AdditionalOutputFiles)
                {
                    context.AddOutputFile(outfile);
                }
            }
            catch (Exception ex)
            {
                throw ProcessErrorsAndWarnings(ex.Message, input, context);
            }

            // Write out the effect to a runtime format.
            CompiledEffectContent result;
            try
            {
                using (var stream = new MemoryStream())
                {
                    using (var writer = new BinaryWriter(stream))
                        effect.Write(writer, options);

                    result = new CompiledEffectContent(stream.GetBuffer());
                }
            }
            catch (Exception ex)
            {
                throw new InvalidContentException("Failed to serialize the effect!", input.Identity, ex);
            }

            return(result);
#else
            throw new NotImplementedException();
#endif
        }
        /// <summary>
        /// The main Process method converts an intermediate format content pipeline
        /// NodeContent tree to a ModelContent object with embedded animation data.
        /// </summary>
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            ValidateMesh(input, context, null);

            // Find the skeleton.
            BoneContent skeleton = MeshHelper.FindSkeleton(input);

            if (skeleton == null)
                throw new InvalidContentException("Input skeleton not found.");

            // We don't want to have to worry about different parts of the model being
            // in different local coordinate systems, so let's just bake everything.
            FlattenTransforms(input, skeleton);

            // Read the bind pose and skeleton hierarchy data.
            IList<BoneContent> bones = MeshHelper.FlattenSkeleton(skeleton);

            // This value must match the constant of the same name in the Constants.fxh file.
            const int MAX_BONES = 72;

            if (bones.Count > MAX_BONES)
            {
                throw new InvalidContentException(string.Format(
                    "Skeleton has {0} bones, but the maximum supported is {1}.",
                    bones.Count, MAX_BONES));
            }

            List<Matrix> bindPose = new List<Matrix>();
            List<Matrix> inverseBindPose = new List<Matrix>();
            List<int> skeletonHierarchy = new List<int>();

            foreach (BoneContent bone in bones)
            {
                bindPose.Add(bone.Transform);
                inverseBindPose.Add(Matrix.Invert(bone.AbsoluteTransform));
                skeletonHierarchy.Add(bones.IndexOf(bone.Parent as BoneContent));
            }

            contentPath = Environment.CurrentDirectory;

            using (XmlReader reader = XmlReader.Create(MaterialDataFilePath))
            {
                incomingMaterials = IntermediateSerializer.Deserialize<List<MaterialData>>(reader, null);
            }
            context.AddDependency(Path.Combine(Environment.CurrentDirectory, MaterialDataFilePath));

            // Placeholder for when you could perform other ModelMeshPart/GeometryContent processing:
            //TraverseGeometryContents(input);

            AnimationPackageData incomingAnimation;

            using (XmlReader reader = XmlReader.Create(AnimationPackageDataFilePath))
            {
                incomingAnimation = IntermediateSerializer.Deserialize<AnimationPackageData>(reader, null);
            }
            context.AddDependency(Path.Combine(Environment.CurrentDirectory, AnimationPackageDataFilePath));

            // Convert animation data to our runtime format.
            Dictionary<string, Clip> animationClips;
            animationClips = ProcessAnimations(skeleton.Animations, bones, incomingAnimation.Clips);

            // Chain to the base ModelProcessor class so it can convert the model data.
            ModelContent model = base.Process(input, context);

            int modelMaxWeightsPerVert = 0;

            const string WEIGHTSPERVERT_PARAM_NAME = "gWeightsPerVert";

            // Put the material's extra data into the ModelMeshPartContent's Tag property.
            // Also, note the largest value of "WeightsPerVert" used in any material.
            foreach (ModelMeshContent mmc in model.Meshes)
            {
                foreach (ModelMeshPartContent mmpc in mmc.MeshParts)
                {
                    MaterialData mat = incomingMaterials.Single(m => m.Name == mmpc.Material.Name);
                    MaterialInfo extraInfo = new MaterialInfo();
                    extraInfo.HandlingFlags = mat.HandlingFlags;
                    extraInfo.RenderState = mat.RenderState;
                    mmpc.Tag = extraInfo;

                    EffectParam wpvEp = mat.EffectParams.Find(wpv => wpv.Name == WEIGHTSPERVERT_PARAM_NAME);
                    if (wpvEp != null)
                    {
                        modelMaxWeightsPerVert = Math.Max(modelMaxWeightsPerVert, (int)(wpvEp.Value));
                    }
                }
            }

            // Store our custom animation data in the Tag property of the model.
            SkinningData skinningData = new SkinningData(animationClips, bindPose, inverseBindPose, skeletonHierarchy, modelMaxWeightsPerVert);

            model.Tag = new AnimationPackage(
                skinningData,
                incomingAnimation.AnimationStateDescriptions,
                incomingAnimation.AnimationNodeDescriptions,
                incomingAnimation.InitialStateName,
                incomingAnimation.Transitions);

            return model;
        }
Exemple #41
0
        /// <summary>
        /// FontDescriptionにMessageFilenameで指定されたファイル内の文字を追加する
        /// </summary>
        void AppendCharacters(FontDescription input, ContentProcessorContext context)
        {
            // MessageFilenameは有効な文字列か?
            if (String.IsNullOrEmpty(MessageFilename))
                return;

            if (!File.Exists(MessageFilename))
            {
                throw new FileNotFoundException(
                    String.Format( "MessageFilenameで指定されたファイル[{0}]が存在しません",
                                    Path.GetFullPath(MessageFilename)));
            }

            // 指定されたファイルから文字列を読み込み、
            // FontDescription.Charctarsに追加する
            try
            {
                int totalCharacterCount = 0;

                using (StreamReader sr = File.OpenText(MessageFilename))
                {
                    string line;
                    while ( ( line = sr.ReadLine() ) != null )
                    {
                        totalCharacterCount += line.Length;

                        foreach( char c in line )
                            input.Characters.Add(c);
                    }
                }

                context.Logger.LogImportantMessage("使用文字数{0}, 総文字数:{1}",
                    input.Characters.Count, totalCharacterCount);

                // CPにファイル依存していることを教える
                context.AddDependency(Path.GetFullPath(MessageFilename));
            }
            catch (Exception e)
            {
                // 予期しない例外が発生
                context.Logger.LogImportantMessage("例外発生!! {0}", e.Message);
                throw e;
            }
        }
Exemple #42
0
        public override DummyObject Process(PackedImageSpritesContent input, ContentProcessorContext context)
        {
            TexturePacker           packer   = new TexturePacker((int)ContainerSize);
            List <Texture2DContent> textures = new List <Texture2DContent>();

            foreach (var group in input.Groups)
            {
                textures.Clear();

                // load the textures to be packed
                foreach (var fileName in group.Filenames)
                {
                    string textureFile = Path.GetDirectoryName(input.Identity.SourceFilename) + @"\" + fileName;
                    context.AddDependency(textureFile);

                    ExternalReference <Texture2DContent> textureReference = new ExternalReference <Texture2DContent>(textureFile);
                    Texture2DContent texture = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(textureReference, null);
                    texture.Name = Path.GetFileNameWithoutExtension(fileName);
                    textures.Add(texture);
                }

                // pack the textures
                int containerTextures = 0;
                while (textures.Count > 0 && containerTextures < MaximumContainersPerGroup)
                {
                    packer.Pack(textures);
                    var packedTextures = packer.GetContents();

                    Texture2DContent containerTexture = CreateContainerTexture(packedTextures);
                    ExternalReference <Texture2DContent> container = context.WriteAsset(containerTexture, group.Name + "Texture" + containerTextures);

                    foreach (var pack in packedTextures)
                    {
                        // undo the padding
                        Rectangle texturePosition = pack.Value;
                        texturePosition.X      += 1;
                        texturePosition.Y      += 1;
                        texturePosition.Width  -= 2;
                        texturePosition.Height -= 2;

                        // write the stub
                        ImageSpriteStub stub = new ImageSpriteStub(container, texturePosition);
                        context.WriteAsset(stub, pack.Key.Name);

                        context.Logger.LogImportantMessage("Packed {0} at {1}", pack.Key.Name, texturePosition);
                    }

                    // repeat with the textures that did not fit
                    textures = packer.GetOverflow();
                    containerTextures++;
                }

                // warn if we bailed out
                if (containerTextures > MaximumContainersPerGroup)
                {
                    context.Logger.LogImportantMessage(
                        "Too many textures to pack in group {0}; {1} left over.", group.Name, textures.Count);
                }
            }

            return(new DummyObject());
        }
Exemple #43
0
        /// <summary>
        /// The main Process method converts an intermediate format content pipeline
        /// NodeContent tree to a ModelContent object with embedded animation data.
        /// </summary>
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            ValidateMesh(input, context, null);

            // Find the skeleton.
            BoneContent skeleton = MeshHelper.FindSkeleton(input);

            if (skeleton == null)
            {
                throw new InvalidContentException("Input skeleton not found.");
            }

            // We don't want to have to worry about different parts of the model being
            // in different local coordinate systems, so let's just bake everything.
            FlattenTransforms(input, skeleton);

            // Read the bind pose and skeleton hierarchy data.
            IList <BoneContent> bones = MeshHelper.FlattenSkeleton(skeleton);

            // This value must match the constant of the same name in the Constants.fxh file.
            const int MAX_BONES = 72;

            if (bones.Count > MAX_BONES)
            {
                throw new InvalidContentException(string.Format(
                                                      "Skeleton has {0} bones, but the maximum supported is {1}.",
                                                      bones.Count, MAX_BONES));
            }

            List <Matrix> bindPose          = new List <Matrix>();
            List <Matrix> inverseBindPose   = new List <Matrix>();
            List <int>    skeletonHierarchy = new List <int>();

            foreach (BoneContent bone in bones)
            {
                bindPose.Add(bone.Transform);
                inverseBindPose.Add(Matrix.Invert(bone.AbsoluteTransform));
                skeletonHierarchy.Add(bones.IndexOf(bone.Parent as BoneContent));
            }

            contentPath = Environment.CurrentDirectory;

            using (XmlReader reader = XmlReader.Create(MaterialDataFilePath))
            {
                incomingMaterials = IntermediateSerializer.Deserialize <List <MaterialData> >(reader, null);
            }
            context.AddDependency(Path.Combine(Environment.CurrentDirectory, MaterialDataFilePath));

            // Placeholder for when you could perform other ModelMeshPart/GeometryContent processing:
            //TraverseGeometryContents(input);

            AnimationPackageData incomingAnimation;

            using (XmlReader reader = XmlReader.Create(AnimationPackageDataFilePath))
            {
                incomingAnimation = IntermediateSerializer.Deserialize <AnimationPackageData>(reader, null);
            }
            context.AddDependency(Path.Combine(Environment.CurrentDirectory, AnimationPackageDataFilePath));

            // Convert animation data to our runtime format.
            Dictionary <string, Clip> animationClips;

            animationClips = ProcessAnimations(skeleton.Animations, bones, incomingAnimation.Clips);

            // Chain to the base ModelProcessor class so it can convert the model data.
            ModelContent model = base.Process(input, context);

            int modelMaxWeightsPerVert = 0;

            const string WEIGHTSPERVERT_PARAM_NAME = "gWeightsPerVert";

            // Put the material's extra data into the ModelMeshPartContent's Tag property.
            // Also, note the largest value of "WeightsPerVert" used in any material.
            foreach (ModelMeshContent mmc in model.Meshes)
            {
                foreach (ModelMeshPartContent mmpc in mmc.MeshParts)
                {
                    MaterialData mat       = incomingMaterials.Single(m => m.Name == mmpc.Material.Name);
                    MaterialInfo extraInfo = new MaterialInfo();
                    extraInfo.HandlingFlags = mat.HandlingFlags;
                    extraInfo.RenderState   = mat.RenderState;
                    mmpc.Tag = extraInfo;

                    EffectParam wpvEp = mat.EffectParams.Find(wpv => wpv.Name == WEIGHTSPERVERT_PARAM_NAME);
                    if (wpvEp != null)
                    {
                        modelMaxWeightsPerVert = Math.Max(modelMaxWeightsPerVert, (int)(wpvEp.Value));
                    }
                }
            }

            // Store our custom animation data in the Tag property of the model.
            SkinningData skinningData = new SkinningData(animationClips, bindPose, inverseBindPose, skeletonHierarchy, modelMaxWeightsPerVert);

            model.Tag = new AnimationPackage(
                skinningData,
                incomingAnimation.AnimationStateDescriptions,
                incomingAnimation.AnimationNodeDescriptions,
                incomingAnimation.InitialStateName,
                incomingAnimation.Transitions);

            return(model);
        }
        public static void Split(AnimationContentDictionary animationDictionary, string splitFile, ContentIdentity contentIdentity, ContentProcessorContext context)
        {
            if (animationDictionary == null)
            return;

              if (string.IsNullOrEmpty(splitFile))
            return;

              if (contentIdentity == null)
            throw new ArgumentNullException("contentIdentity");

              if (context == null)
            throw new ArgumentNullException("context");

              if (animationDictionary.Count == 0)
              {
            context.Logger.LogWarning(null, contentIdentity, "The model does not have an animation. Animation splitting is skipped.");
            return;
              }

              if (animationDictionary.Count > 1)
            context.Logger.LogWarning(null, contentIdentity, "The model contains more than 1 animation. The animation splitting is performed on the first animation. Other animations are deleted!");

              // Load XML file.
              splitFile = ContentHelper.FindFile(splitFile, contentIdentity);
              XDocument document = XDocument.Load(splitFile, LoadOptions.SetLineInfo);

              // Let the content pipeline know that we depend on this file and we need to
              // rebuild the content if the file is modified.
              context.AddDependency(splitFile);

              // Parse XML.
              var animationsElement = document.Element("Animations");
              if (animationsElement == null)
              {
            context.Logger.LogWarning(null, contentIdentity, "The animation split file \"{0}\" does not contain an <Animations> root node.", splitFile);
            return;
              }

              var wrappedContext = new ContentPipelineContext(context);
              var splits = ParseAnimationSplitDefinitions(animationsElement, contentIdentity, wrappedContext);
              if (splits == null || splits.Count == 0)
              {
            context.Logger.LogWarning(null, contentIdentity, "The XML file with the animation split definitions is invalid or empty. Animation is not split.");
            return;
              }

              // Split animations.
              Split(animationDictionary, splits, contentIdentity, context);
        }
        /// <summary>
        /// Converts an intermediate format content pipeline AnimationContentDictionary
        /// object to our runtime AnimationClip format.
        /// </summary>
        static Dictionary<string, AnimationClip> ProcessAnimations(
            AnimationContentDictionary animations, IList<BoneContent> bones,
            ContentProcessorContext context, ContentIdentity sourceIdentity)
        {
            // Build up a table mapping bone names to indices.
            Dictionary<string, int> boneMap = new Dictionary<string, int>();

            for (int i = 0; i < bones.Count; i++)
            {
                string boneName = bones[i].Name;

                if (!string.IsNullOrEmpty(boneName))
                    boneMap.Add(boneName, i);
            }

            // Convert each animation in turn.
            Dictionary<string, AnimationClip> animationClips;
            animationClips = new Dictionary<string, AnimationClip>();

            // We process the original animation first, so we can use their keyframes
            foreach (KeyValuePair<string, AnimationContent> animation in animations)
            {
                AnimationClip processed = ProcessAnimation(animation.Value, boneMap, animation.Key);

                animationClips.Add(animation.Key, processed);
            }

            // Check to see if there's an animation clip definition
            // Here, we're checking for a file with the _Anims suffix.
            // So, if your model is named dude.fbx, we'd add dude_Anims.xml in the same folder
            // and the pipeline will see the file and use it to override the animations in the
            // original model file.
            string SourceModelFile = sourceIdentity.SourceFilename;
            string SourcePath = Path.GetDirectoryName(SourceModelFile);
            string AnimFilename = Path.GetFileNameWithoutExtension(SourceModelFile);
            AnimFilename += "_Anims.xml";
            string AnimPath = Path.Combine(SourcePath, AnimFilename);
            if (File.Exists(AnimPath))
            {
                // Add the filename as a dependency, so if it changes, the model is rebuilt
                context.AddDependency(AnimPath);

                // Load the animation definition from the XML file
                AnimationDefinition AnimDef = context.BuildAndLoadAsset<XmlImporter, AnimationDefinition>(new ExternalReference<XmlImporter>(AnimPath), null);

                // Break up the original animation clips into our new clips
                // First, we check if the clips contains our clip to break up
                if (animationClips.ContainsKey(AnimDef.OriginalClipName))
                {
                    // Grab the main clip that we are using
                    AnimationClip MainClip = animationClips[AnimDef.OriginalClipName];

                    // Now remove the original clip from our animations
                    animationClips.Remove(AnimDef.OriginalClipName);

                    // Process each of our new animation clip parts
                    foreach (AnimationDefinition.ClipPart Part in AnimDef.ClipParts)
                    {
                        // Calculate the frame times
                        TimeSpan StartTime = GetTimeSpanForFrame(Part.StartFrame, AnimDef.OriginalFrameCount, MainClip.Duration.Ticks);
                        TimeSpan EndTime = GetTimeSpanForFrame(Part.EndFrame, AnimDef.OriginalFrameCount, MainClip.Duration.Ticks);

                        // Get all the keyframes for the animation clip
                        // that fall within the start and end time
                        List<Keyframe> Keyframes = new List<Keyframe>();
                        foreach (Keyframe AnimFrame in MainClip.Keyframes)
                        {
                            if ((AnimFrame.Time >= StartTime) && (AnimFrame.Time <= EndTime))
                            {
                                Keyframe NewFrame = new Keyframe(AnimFrame.Bone, AnimFrame.Time - StartTime, AnimFrame.Transform);
                                Keyframes.Add(NewFrame);
                            }
                        }

                        // Process the events
                        List<AnimationEvent> Events = new List<AnimationEvent>();
                        if (Part.Events != null)
                        {
                            // Process each event
                            foreach (AnimationDefinition.ClipPart.Event Event in Part.Events)
                            {
                                // Get the event time within the animation
                                TimeSpan EventTime = GetTimeSpanForFrame(Event.Keyframe, AnimDef.OriginalFrameCount, MainClip.Duration.Ticks);

                                // Offset the event time so it is relative to the start of the animation
                                EventTime -= StartTime;

                                // Create the event
                                AnimationEvent NewEvent = new AnimationEvent();
                                NewEvent.EventTime = EventTime;
                                NewEvent.EventName = Event.Name;
                                Events.Add(NewEvent);
                            }
                        }

                        // Create the clip
                        AnimationClip NewClip = new AnimationClip(EndTime - StartTime, Keyframes, Events, Part.ClipName);
                        animationClips[Part.ClipName] = NewClip;
                    }
                }
            }

            if (animationClips.Count == 0)
            {
                throw new InvalidContentException(
                            "Input file does not contain any animations.");
            }

            return animationClips;
        }
Exemple #46
0
        /// <summary>
        /// Processes the string representation of the specified effect into a platform-specific binary format using the specified context.
        /// </summary>
        /// <param name="input">The effect string to be processed.</param>
        /// <param name="context">Context for the specified processor.</param>
        /// <returns>A platform-specific compiled binary effect.</returns>
        /// <remarks>If you get an error during processing, compilation stops immediately. The effect processor displays an error message. Once you fix the current error, it is possible you may get more errors on subsequent compilation attempts.</remarks>
        public override CompiledEffectContent Process(EffectContent input, ContentProcessorContext context)
        {
#if WINDOWS
            var options = new Options();
            options.SourceFile  = input.Identity.SourceFilename;
            options.DX11Profile = context.TargetPlatform == TargetPlatform.Windows ||
                                  context.TargetPlatform == TargetPlatform.WindowsPhone8 ||
                                  context.TargetPlatform == TargetPlatform.WindowsStoreApp ||
                                  context.TargetPlatform == TargetPlatform.Xbox360;
            options.Debug      = DebugMode == EffectProcessorDebugMode.Debug;
            options.OutputFile = context.OutputFilename;

            // Parse the MGFX file expanding includes, macros, and returning the techniques.
            ShaderInfo shaderInfo;
            try
            {
                shaderInfo = ShaderInfo.FromFile(options.SourceFile, options);
                foreach (var dep in shaderInfo.Dependencies)
                {
                    context.AddDependency(dep);
                }
            }
            catch (Exception ex)
            {
                // TODO: Extract good line numbers from mgfx parser!
                throw new InvalidContentException(ex.Message, input.Identity, ex);
            }

            // Create the effect object.
            DXEffectObject effect = null;
            try
            {
                effect = DXEffectObject.FromShaderInfo(shaderInfo);
            }
            catch (Exception ex)
            {
                throw ProcessErrorsAndWarnings(ex.Message, input, context);
            }

            // Write out the effect to a runtime format.
            CompiledEffectContent result;
            try
            {
                using (var stream = new MemoryStream())
                {
                    using (var writer = new BinaryWriter(stream))
                        effect.Write(writer, options);

                    result = new CompiledEffectContent(stream.GetBuffer());
                }
            }
            catch (Exception ex)
            {
                throw new InvalidContentException("Failed to serialize the effect!", input.Identity, ex);
            }

            return(result);
#else
            throw new NotImplementedException();
#endif
        }
    private void ProcessCursors(ThemeContent theme, ContentProcessorContext context)
    {
      theme.Cursors = new NamedObjectCollection<ThemeCursorContent>();

      // Hardware cursors are only supported on Windows.
      if (context.TargetPlatform != TargetPlatform.Windows)
        return;

      var document = theme.Description;
      if (document.Root == null)
      {
        string message = string.Format("Root element \"<Theme>\" is missing in XML.");
        throw new InvalidContentException(message, theme.Identity);
      }

      var cursorsElement = document.Root.Element("Cursors");
      if (cursorsElement == null)
        return;

      foreach (var cursorElement in cursorsElement.Elements("Cursor"))
      {
        string name = GetMandatoryAttribute(cursorElement, "Name", theme.Identity);
        bool isDefault = (bool?)cursorElement.Attribute("IsDefault") ?? false;
        string filename = GetMandatoryAttribute(cursorElement, "File", theme.Identity);

        // Find cursor file.
        string cursorSourcePath = FindFile(theme, filename);
        string cursorSourceDirectory = Path.GetDirectoryName(cursorSourcePath) + Path.DirectorySeparatorChar;
        context.AddDependency(cursorSourcePath);

        // Get output path.
        // If cursor is in or under the content directory, then we keep the relative directory
        // structure. If cursor is in a parent directory, then we copy the cursor
        // directly into the theme directory.
        string cursorOutputPath;
        if (cursorSourceDirectory.StartsWith(_sourceRootDirectory))
        {
          // Cursor file is in/under the content root directory.
          string relativeCursorSourcePath =
            _themeSourceDirectoryUri.MakeRelativeUri(new Uri(cursorSourcePath)).ToString();
          relativeCursorSourcePath = Uri.UnescapeDataString(relativeCursorSourcePath);
          cursorOutputPath = Path.GetFullPath(Path.Combine(_themeOutputDirectory, relativeCursorSourcePath));
        }
        else
        {
          // Cursor file is not in/under the content root directory.
          string cursorFilename = Path.GetFileName(cursorSourcePath) ?? string.Empty;
          cursorOutputPath = Path.GetFullPath(Path.Combine(_themeOutputDirectory, cursorFilename));
        }
        string cursorOutputDirectory = Path.GetDirectoryName(cursorOutputPath) + Path.DirectorySeparatorChar;

        // Create output directory if it does not exist.
        if (!Directory.Exists(cursorOutputDirectory))
          Directory.CreateDirectory(cursorOutputDirectory);

        // Copy cursor file to output directory.
        File.Copy(cursorSourcePath, cursorOutputPath, true);
        context.AddOutputFile(cursorOutputPath);

        // Get filename relative to the theme directory.
        filename =
          _themeOutputDirectoryUri.MakeRelativeUri(new Uri(cursorOutputPath)).OriginalString;
        filename = Uri.UnescapeDataString(filename);

        var cursor = new ThemeCursorContent
        {
          Name = name,
          IsDefault = isDefault,
          FileName = filename,
        };

        theme.Cursors.Add(cursor);
      }
    }