/// <summary>
        /// Resolves #include declarations in the file before the code is evaluated internally by MonoGame.
        /// </summary>
        /// <remarks>
        /// This resolves the #include declarations before the code is processed by MonoGame.  This is required
        /// because the code is stored as a temporary file before being processed, instead of being processed at
        /// the source (because once we get the code, we are not processing per-file but per-asset).
        /// </remarks>
        /// <param name="assetDependencies">The asset dependencies interface to get included files from.</param>
        /// <param name="dirName">The folder name that this asset resides in.</param>
        /// <param name="code">The code to process.</param>
        /// <returns>The resulting code.</returns>
        protected async Task <string> ResolveIncludes(IAssetDependencies assetDependencies, string dirName, string code)
        {
            var regex = new Regex("^#include <([^>]+)>\\s*$", RegexOptions.IgnoreCase | RegexOptions.Multiline);

            var matches = regex.Matches(code).OfType <Match>().ToList();

            foreach (var currentMatch in matches)
            {
                var relName       = currentMatch.Groups[1].Captures[0].Value;
                var relComponents = relName.Split(new[] { '\\', '/' });
                var dirComponents = dirName.Split('.').ToList();
                for (var i = 0; i < relComponents.Length; i++)
                {
                    if (relComponents[i] == ".")
                    {
                        // Do nothing, same directory.
                    }
                    else if (relComponents[i] == "..")
                    {
                        // Parent directory.
                        if (dirComponents.Count > 0)
                        {
                            dirComponents.RemoveAt(dirComponents.Count - 1);
                        }
                    }
                    else
                    {
                        dirComponents.Add(relComponents[i]);
                    }
                }

                var includeFile = await assetDependencies.GetOptionalCompileTimeFileDependency(string.Join(".", dirComponents.ToArray())).ConfigureAwait(false);

                if (includeFile == null)
                {
                    throw new InvalidOperationException(
                              "Unable to include " + relName + "; resolved name " + dirComponents.ToArray() + " does not exist!");
                }

                // TODO: Calculate original filename from the PC that this asset was sourced from/
                var nameOnDisk = string.Join("\\", dirComponents.ToArray());

                using (var reader = new StreamReader(await includeFile.GetContentStream().ConfigureAwait(false)))
                {
                    var replace = reader.ReadToEnd();
                    replace = "#line 1 \"" + nameOnDisk + "\"\r\n" + replace;
                    replace = await this.ResolveIncludes(assetDependencies, Path.GetDirectoryName(includeFile.Name.Replace(".", "/")).Replace(Path.DirectorySeparatorChar, '.'), replace).ConfigureAwait(false);

                    code = code.Replace(currentMatch.Value, replace);
                }
            }

            return(code);
        }
Exemplo n.º 2
0
        public async Task CompileAsync(IAssetFsFile assetFile, IAssetDependencies assetDependencies, TargetPlatform platform, IWritableSerializedAsset output)
        {
            var otherAnimations = new Dictionary <string, byte[]>();

            if (assetFile.Extension != "x")
            {
                var otherFiles = (await assetDependencies.GetAvailableCompileTimeFiles())
                                 .Where(x => x.Name.StartsWith(assetFile.Name + "-"))
                                 .ToArray();
                foreach (var otherAnim in otherFiles)
                {
                    using (var otherStream = await otherAnim.GetContentStream().ConfigureAwait(false))
                    {
                        var b = new byte[otherStream.Length];
                        await otherStream.ReadAsync(b, 0, b.Length).ConfigureAwait(false);

                        otherAnimations[otherAnim.Name.Substring((assetFile.Name + "-").Length)] = b;
                    }
                }
            }

            var nameComponents = assetFile.Name.Split('.');

            nameComponents[nameComponents.Length - 1] = "_FolderOptions";
            var folderOptionsFile = await assetDependencies.GetOptionalCompileTimeFileDependency(string.Join(".", nameComponents)).ConfigureAwait(false);

            string[] importFolderOptions = null;
            if (folderOptionsFile != null)
            {
                using (var optionsReader = new StreamReader(await folderOptionsFile.GetContentStream().ConfigureAwait(false)))
                {
                    importFolderOptions = optionsReader.ReadToEnd()
                                          .Trim()
                                          .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                                          .Select(x => x.Trim())
                                          .Where(x => !x.StartsWith("#"))
                                          .ToArray();
                }
            }

            var optionsFile = await assetDependencies.GetOptionalCompileTimeFileDependency(assetFile.Name + ".Options").ConfigureAwait(false);

            string[] importOptions = null;
            if (optionsFile != null)
            {
                using (var optionsReader = new StreamReader(await optionsFile.GetContentStream().ConfigureAwait(false)))
                {
                    importOptions = optionsReader.ReadToEnd()
                                    .Trim()
                                    .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                                    .Select(x => x.Trim())
                                    .Where(x => !x.StartsWith("#"))
                                    .ToArray();
                }
            }

            if (importOptions == null)
            {
                importOptions = importFolderOptions;
            }

            byte[] modelData;
            using (var stream = await assetFile.GetContentStream().ConfigureAwait(false))
            {
                modelData = new byte[stream.Length];
                await stream.ReadAsync(modelData, 0, modelData.Length).ConfigureAwait(false);
            }

            var reader = new AssimpReader(_modelRenderConfigurations, _renderBatcher);
            var model  = reader.Load(modelData, assetFile.Name, assetFile.Extension, otherAnimations, importOptions);
            var data   = _modelSerializer.Serialize(model);

            output.SetLoader <IAssetLoader <ModelAsset> >();
            output.SetByteArray("Data", data);
        }
Exemplo n.º 3
0
        public async Task CompileAsync(IAssetFsFile assetFile, IAssetDependencies assetDependencies, TargetPlatform platform, IWritableSerializedAsset output)
        {
            var tempPath = System.IO.Path.GetTempFileName();

            try
            {
                using (var stream = new FileStream(tempPath, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    using (var sourceStream = await assetFile.GetContentStream().ConfigureAwait(false))
                    {
                        await sourceStream.CopyToAsync(stream).ConfigureAwait(false);
                    }
                }

                var importer       = new TextureImporter();
                var monogameOutput = importer.Import(tempPath, new DummyContentImporterContext());

                var originalWidth  = monogameOutput.Faces[0][0].Width;
                var originalHeight = monogameOutput.Faces[0][0].Height;

                var nameComponents = assetFile.Name.Split('.');
                nameComponents[nameComponents.Length - 1] = "_FolderOptions";
                var folderOptionsFile = await assetDependencies.GetOptionalCompileTimeFileDependency(string.Join(".", nameComponents)).ConfigureAwait(false);

                string[] importFolderOptions = null;
                if (folderOptionsFile != null)
                {
                    using (var optionsReader = new StreamReader(await folderOptionsFile.GetContentStream().ConfigureAwait(false)))
                    {
                        importFolderOptions = optionsReader.ReadToEnd()
                                              .Trim()
                                              .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                                              .Select(x => x.Trim())
                                              .Where(x => !x.StartsWith("#"))
                                              .ToArray();
                    }
                }

                var optionsFile = await assetDependencies.GetOptionalCompileTimeFileDependency(assetFile.Name + ".Options").ConfigureAwait(false);

                string[] importOptions = null;
                if (optionsFile != null)
                {
                    using (var optionsReader = new StreamReader(await optionsFile.GetContentStream().ConfigureAwait(false)))
                    {
                        importOptions = optionsReader.ReadToEnd()
                                        .Trim()
                                        .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                                        .Select(x => x.Trim())
                                        .Where(x => !x.StartsWith("#"))
                                        .ToArray();
                    }
                }

                if (importOptions == null)
                {
                    importOptions = importFolderOptions;
                }
                if (importOptions == null)
                {
                    importOptions = new string[0];
                }

                var allowResizeToPowerOfTwo = !IsPowerOfTwo((ulong)originalWidth) || !IsPowerOfTwo((ulong)originalHeight);
                var allowMakeSquare         = originalWidth != originalHeight;

                var manager = new PipelineManager(
                    Environment.CurrentDirectory,
                    Environment.CurrentDirectory,
                    Environment.CurrentDirectory);
                TextureContent content = CompileTexture(assetFile, platform, monogameOutput, importOptions, allowResizeToPowerOfTwo, allowMakeSquare, manager);

                Console.WriteLine("Texture " + assetFile.Name + " resized " + originalWidth + "x" + originalHeight + " -> " + content.Faces[0][0].Width + "x" + content.Faces[0][0].Height);

                output.SetLoader <IAssetLoader <TextureAsset> >();
                output.SetPlatform(platform);
                output.SetByteArray("Data", CompileAndGetBytes(content));
                output.SetInt32("OriginalWidth", originalWidth);
                output.SetInt32("OriginalHeight", originalHeight);
            }
            finally
            {
                try
                {
                    File.Delete(tempPath);
                }
                catch
                {
                }
            }
        }