/// <summary>
        /// Writes user code to `code.js`
        ///
        /// Any free standing code written by users is written to this file
        /// </summary>
        private static void GenerateScripts(UTinyBuildOptions options, UTinyBuildResults results)
        {
            var project  = options.Project;
            var registry = project.Registry;
            var module   = project.Module.Dereference(registry);
            var report   = results.BuildReport.GetOrAddChild(UTinyBuildReport.CodeNode).AddChild();

            var writer = new UTinyCodeWriter(CodeStyle.JavaScript);

            PrependGeneratedHeader(writer, options.Project.Name);

            foreach (var script in module.EnumerateDependencies().Scripts())
            {
                if (null == script.TextAsset)
                {
                    continue;
                }

                var reportSystemPos = writer.Length;
                writer.WriteRaw(script.TextAsset.text)
                .Line();
                report.AddChild(AssetDatabase.GetAssetPath(script.TextAsset), Encoding.ASCII.GetBytes(writer.Substring(reportSystemPos)), script.TextAsset);
            }

            var file = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KCodeFileName));

            File.WriteAllText(file.FullName, writer.ToString(), Encoding.UTF8);
            report.Reset(file);
        }
        /// <summary>
        /// Generates the platform-agnostic IDL file from the given UTinyProject.
        /// </summary>
        public static void GenerateIDL(UTinyProject project, FileInfo destination)
        {
            var writer = new UTinyCodeWriter
            {
                CodeStyle = CodeStyle.CSharp
            };

            writer.Line("using UTiny;");

            var mainModule = project.Module.Dereference(project.Registry);

            foreach (var dep in mainModule.EnumerateDependencies())
            {
                if (dep.Equals(mainModule))
                {
                    continue;
                }
                writer.Line($"using {dep.Name};");
            }

            project.Visit(new GenerateIDLVisitor {
                Writer = writer
            });
            File.WriteAllText(destination.FullName, writer.ToString(), Encoding.UTF8);
        }
Esempio n. 3
0
 public static void WriteType(UTinyCodeWriter writer, string type, string desc = "")
 {
     using (var w = new Writer(writer))
     {
         w.Type(type);
         w.Desc(desc);
     }
 }
Esempio n. 4
0
 public static void WriteNamespace(UTinyCodeWriter writer, string desc = "")
 {
     using (var w = new Writer(writer))
     {
         w.Namespace();
         w.Desc(desc);
     }
 }
        /// <summary>
        /// Packages settings to `settings.js`
        /// </summary>
        private static void PackageSettings(UTinyBuildOptions options, UTinyBuildResults results)
        {
            var writer = new UTinyCodeWriter(CodeStyle.JavaScript);

            var file = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KSettingsFileName));

            var settings = options.Project.Settings;

            writer.Line($"var Module = {{TOTAL_MEMORY: {settings.MemorySize * 1024 * 1024}}};")
            .Line();

            // <HACK>
            // Workaround for issue `UTINY-1091`
            // Systems will not force binding generation to create namespace objects
            var namespaces = new HashSet <string>();

            foreach (var m in options.Project.Module.Dereference(options.Project.Registry).EnumerateDependencies())
            {
                // If we don't have types our module namespace is not generated automatically
                if (!m.Types.Any())
                {
                    var parts = m.Namespace.Split('.');
                    var name  = parts[0];

                    namespaces.Add(name);

                    for (var i = 1; i < parts.Length; i++)
                    {
                        name = $"{name}.{parts[i]}";
                        namespaces.Add(name);
                    }
                }
            }

            if (namespaces.Count > 0)
            {
                writer.Line("/*");
                writer.Line(" * Workaround for issue UTINY-1091");
                writer.Line(" */");
            }

            foreach (var n in namespaces)
            {
                writer.Line(!n.Contains('.') ? $"var {n} = {n} || {{}}" : $"{n} = {n} || {{}}");
            }
            // <HACK>

            if (writer.Length <= 0)
            {
                // No settings, nothing to write
                return;
            }

            PrependGeneratedHeader(writer, options.Project.Name);
            File.WriteAllText(file.FullName, writer.ToString(), Encoding.UTF8);
        }
        private static void PrependGeneratedHeader(UTinyCodeWriter writer, string name)
        {
            var builder = new StringBuilder();

            builder.AppendLine($"/**");
            builder.AppendLine($" * {UTinyConstants.ApplicationName.ToUpperInvariant()} GENERATED CODE, DO NOT EDIT BY HAND");
            builder.AppendLine($" * @project {name}");
            builder.AppendLine($" */");
            builder.AppendLine();
            writer.Prepend(builder.ToString());
        }
        /// <summary>
        /// Packages entity group objects to `entities.js`
        ///
        /// Since we don't have a scene format, groups are written as setup functions
        /// </summary>
        private static void GenerateEntityGroups(UTinyBuildOptions options, UTinyBuildResults results)
        {
            var writer = new UTinyCodeWriter(CodeStyle.JavaScript);
            var report = results.BuildReport.GetOrAddChild(UTinyBuildReport.CodeNode).AddChild();

            PrependGeneratedHeader(writer, options.Project.Name);

            // @NOTE Namespaces are generated through through `BindGen.exe`
            // e.g. `{ENTITY_GROUPS}.{PROJECT_NAMESPACE}.{GROUP_NAME}` will already exist as a component

            using (var visitor = new EntityGroupSetupVisitor {
                Writer = writer, Report = report
            })
            {
                options.Project.Visit(visitor);
            }

            var file = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KEntityGroupsFileName));

            File.WriteAllText(file.FullName, writer.ToString(), Encoding.UTF8);
            report.Reset(file);
        }
        /// <summary>
        /// Generates the platform-agnostic IDL file from the given UTinyProject.
        /// </summary>
        public static void GenerateIDL(UTinyProject project, FileInfo destination)
        {
            var writer = new UTinyCodeWriter
            {
                CodeStyle = CodeStyle.CSharp
            };

            writer.Line("using UTiny;");
            writer.Line("using UTiny.Shared;");

            var mainModule = project.Module.Dereference(project.Registry);

            foreach (var dep in mainModule.EnumerateDependencies())
            {
                if (dep.Equals(mainModule))
                {
                    continue;
                }
                if (dep.Name == "UTiny.Core") // Hack: The Core module does not actually generate a Core namespace, but Core namespace is the UTiny/ut namespace.
                {
                    continue;
                }
                if (dep.IsRuntimeIncluded)
                {
                    writer.Line($"using {dep.Name};"); // Core namespaces are of form "UTiny.Core2D".
                }
                else
                {
                    writer.Line($"using {dep.Namespace.Replace("UTiny.", "ut.")};"); // Runtime generated namespaces are of form "ut.tween".
                }
            }

            project.Visit(new GenerateIDLVisitor {
                Writer = writer
            });
            File.WriteAllText(destination.FullName, writer.ToString(), Encoding.UTF8);
        }
Esempio n. 9
0
        public static void WriteEntityGroupSetupFunction(UTinyCodeWriter writer, UTinyProject project, UTinyEntityGroup entityGroup, bool writeEntityGroupComponent = true, bool writeEntityLayer = true)
        {
            var entityIndex    = 0;
            var entityIndexMap = new Dictionary <UTinyEntity.Reference, int>();

            using (writer.Scope("function(w)"))
            {
                entityIndexMap.Clear();

                foreach (var reference in entityGroup.Entities)
                {
                    var entity = reference.Dereference(entityGroup.Registry);
                    ++entityIndex;
                    entityIndexMap[reference] = entityIndex;
                    writer.Line($"var e{entityIndex} = w.create({EscapeJsString(entity.Name)});");
                }

                if (writeEntityGroupComponent)
                {
                    foreach (var reference in entityGroup.Entities)
                    {
                        var index = entityIndexMap[reference];
                        writer.Line($"e{index}.addComponent(this.Component);");
                    }
                }

                if (writeEntityLayer)
                {
                    foreach (var reference in entityGroup.Entities)
                    {
                        var index  = entityIndexMap[reference];
                        var entity = reference.Dereference(entityGroup.Registry);
                        writer.Line($"e{index}.addComponent({GetFullyQualifiedLayerName(LayerMask.LayerToName(entity.Layer))});");
                    }
                }

                var context = new VisitorContext
                {
                    Project        = project,
                    Module         = project.Module.Dereference(project.Registry),
                    Registry       = project.Registry,
                    Writer         = writer,
                    EntityIndexMap = entityIndexMap
                };

                entityIndex = 0;
                foreach (var reference in entityGroup.Entities)
                {
                    var entity = reference.Dereference(entityGroup.Registry);
                    ++entityIndex;

                    foreach (var component in entity.Components)
                    {
                        var type = component.Type.Dereference(component.Registry);

                        if (null == type)
                        {
                            Debug.LogError($"{UTinyConstants.ApplicationName}: Missing component type, ComponentType=[{component.Type.Name}] Entity=[{entity.Name}] Group=[{entityGroup.Name}]");
                            continue;
                        }

                        var index = ++context.ComponentIndex;
                        writer.Line($"var c{index} = e{entityIndex}.addComponent({UTinyBuildPipeline.GetJsTypeName(type)});");
                        component.Properties.Visit(new ComponentVisitor
                        {
                            VisitorContext = context,
                            Path           = $"c{index}",
                            Entity         = $"e{entityIndex}"
                        });
                    }
                }

                writer.WriteIndent();
                writer.WriteRaw("return [");

                for (var i = 0; i < entityIndex; i++)
                {
                    writer.WriteRaw(i != 0 ? $", e{i + 1}" : $"e{i + 1}");
                }

                writer.WriteRaw("];\n");
            }

            writer.Line().Line();
        }
        /// <summary>
        /// Outputs the final `index.html` file
        /// </summary>
        private static void GenerateHTML(UTinyBuildOptions options, UTinyBuildResults results)
        {
            var project = options.Project;

            var settingsFile         = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KSettingsFileName));
            var runtimeFile          = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KRuntimeFileName));
            var bindingsFile         = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KBindingsFileName));
            var assetsFile           = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KAssetsFileName));
            var entityGroupsFile     = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KEntityGroupsFileName));
            var systemsFile          = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KSystemsFileName));
            var codeFile             = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KCodeFileName));
            var mainFile             = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KMainFileName));
            var webSocketClientFile  = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KWebSocketClientFileName));
            var webpDecompressorFile = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KWebPDecompressorFileName));

            // nb: this writer is not HTML-friendly
            var writer = new UTinyCodeWriter()
            {
                CodeStyle = new CodeStyle()
                {
                    BeginBrace  = string.Empty,
                    EndBrace    = string.Empty,
                    BraceLayout = BraceLayout.EndOfLine,
                    Indent      = "  ",
                    NewLine     = Environment.NewLine
                }
            };

            writer.Line("<!DOCTYPE html>");
            using (writer.Scope("<html>"))
            {
                using (writer.Scope("<head>"))
                {
                    writer.Line("<meta charset=\"UTF-8\">");
                    if (UsesAdSupport(project))
                    {
                        writer.Line("<script src=\"mraid.js\"></script>");
                    }

                    if (project.Settings.RunBabel)
                    {
                        // Babelize user code
                        var          title         = $"{UTinyConstants.ApplicationName} Build";
                        const string messageFormat = "Transpiling {0} to ECMAScript 5";

                        EditorUtility.DisplayProgressBar(title, "Transpiling to ECMAScript 5", 0.0f);
                        try
                        {
                            // We only need to transpile user authored code
                            var userCode = new [] { systemsFile, codeFile };
                            var babelDir = new DirectoryInfo(UTinyBuildPipeline.GetToolDirectory("babel"));
                            for (var i = 0; i < userCode.Length; i++)
                            {
                                var file = userCode[i];
                                EditorUtility.DisplayProgressBar(title, string.Format(messageFormat, file.Name), i / (float)userCode.Length);
                                UTinyBuildUtilities.RunNode(babelDir, "index.js", $"\"{file.FullName}\" \"{file.FullName}\"");
                            }
                        }
                        finally
                        {
                            EditorUtility.ClearProgressBar();
                        }
                    }

                    // Gather all game files (order is important)
                    var files = new List <FileInfo>
                    {
                        settingsFile,
                        runtimeFile,
                        bindingsFile,
                        assetsFile,
                        entityGroupsFile,
                        systemsFile,
                        codeFile,
                        mainFile,
                        webSocketClientFile,
                        webpDecompressorFile
                    }.Where(file => file != null && file.Exists).ToList();

                    // Extra steps for Release config
                    if (options.Configuration == UTinyBuildConfiguration.Release)
                    {
                        // Minify JavaScript
                        var gameFile = new FileInfo(Path.Combine(results.BinaryFolder.FullName, "game.js"));
                        EditorUtility.DisplayProgressBar($"{UTinyConstants.ApplicationName} Build", "Minifying JavaScript code...", 0.0f);
                        try
                        {
                            var minifyDir = new DirectoryInfo(UTinyBuildPipeline.GetToolDirectory("minify"));
                            UTinyBuildUtilities.RunNode(minifyDir, "index.js", $"\"{gameFile.FullName}\" {String.Join(" ", files.Select(file => '"' + file.FullName + '"'))}");
                            files.ForEach(file => file.Delete());
                        }
                        finally
                        {
                            EditorUtility.ClearProgressBar();
                        }

                        // Package as single html file
                        if (project.Settings.SingleFileHtml)
                        {
                            writer.Line("<script type=\"text/javascript\">");
                            writer.WriteRaw(File.ReadAllText(gameFile.FullName));
                            writer.Line();
                            writer.Line("</script>");
                            gameFile.Delete();
                        }
                        else
                        {
                            writer.LineFormat("<script src=\"{0}\"></script>", gameFile.Name);
                        }
                    }
                    else
                    {
                        files.ForEach(file => writer.LineFormat("<script src=\"{0}\"></script>", file.Name));
                    }
                    writer.LineFormat("<title>{0}</title>", project.Name);
                    writer.CodeStyle.EndBrace = "</head>";
                }
                using (writer.Scope("<body>"))
                {
                    writer.CodeStyle.EndBrace = "</body>";
                }
                writer.CodeStyle.EndBrace = "</html>";
            }

            // Write final index.html file
            var htmlFile = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KHtmlFileName));

            File.WriteAllText(htmlFile.FullName, writer.ToString(), Encoding.UTF8);
        }
        /// <summary>
        /// Generates entry point for the applicaton `main.js`
        /// This script will contain the system scheduling, window setup and initial group loading
        /// </summary>
        private static void GenerateMain(UTinyBuildOptions options, UTinyBuildResults results)
        {
            var project  = options.Project;
            var registry = project.Registry;
            var module   = project.Module.Dereference(registry);

            var file = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KMainFileName));

            var writer = new UTinyCodeWriter();

            PrependGeneratedHeader(writer, options.Project.Name);

            var distVersionFile = new FileInfo("UTiny/version.txt");
            var versionString   = "internal";

            if (distVersionFile.Exists)
            {
                versionString = File.ReadAllText(distVersionFile.FullName);
            }
            writer.LineFormat("console.log('runtime version: {0}');", versionString)
            .Line();

            var namespaces = new Dictionary <string, string>();

            foreach (var m in module.EnumerateDependencies())
            {
                if (string.IsNullOrEmpty(m.Namespace))
                {
                    continue;
                }

                if (m.IsRuntimeIncluded)
                {
                    writer.Line($"ut.importModule({m.Namespace});");
                    continue;
                }

                string content;
                namespaces.TryGetValue(m.Namespace, out content);
                content += m.Documentation.Summary;
                namespaces[m.Namespace] = content;
            }

            UTinyJsdoc.WriteType(writer, "ut.World", "Singleton world instance");
            writer.Line("var world;");
            using (writer.Scope("ut.main = function()"))
            {
                // Create and setup the world
                writer
                .Line("world = new ut.World();")
                .Line("var options = WorldSetup(world);");

                // Write configurations
                var context = new EntityGroupSetupVisitor.VisitorContext
                {
                    Project        = project,
                    Module         = project.Module.Dereference(project.Registry),
                    Registry       = project.Registry,
                    Writer         = writer,
                    EntityIndexMap = null
                };

                var configuration = project.Configuration.Dereference(registry);
                foreach (var component in configuration.Components)
                {
                    var moduleContainingType = registry.FindAllByType <UTinyModule>().First(m => m.Types.Contains(component.Type));
                    if (!module.EnumerateDependencies().Contains(moduleContainingType))
                    {
                        // Silently ignore components if the module is not included.
                        // This is by design to preserve user data
                        continue;
                    }

                    var type  = component.Type.Dereference(component.Registry);
                    var index = ++context.ComponentIndex;
                    writer.Line($"var c{index} = world.config({UTinyBuildPipeline.GetJsTypeName(type)});");
                    component.Properties.Visit(new EntityGroupSetupVisitor.ComponentVisitor
                    {
                        VisitorContext = context,
                        Path           = $"c{index}",
                    });
                }

                // Setup the scheduler
                writer.Line("var scheduler = world.scheduler();");

                // Schedule all systems
                var systems = project.Module.Dereference(project.Registry).GetSystemExecutionOrder();
                foreach (var reference in systems)
                {
                    var system = reference.Dereference(project.Registry);

                    if (system == null)
                    {
                        Debug.LogWarning($"Can't resolve system named '{reference.Name}' with ID {reference.Id} -- ignoring, you should delete this system");
                        continue;
                    }

                    var systemModule = UTinyUtility.GetModules(system).FirstOrDefault();
                    var systemName   = UTinyBuildPipeline.GetJsTypeName(systemModule, system);
                    writer.LineFormat("scheduler.schedule({0});", systemName);
                }

                // Enable/disable systems
                foreach (var reference in systems)
                {
                    var system = reference.Dereference(project.Registry);

                    // By default systems are enabled when scheduled, nothing to write
                    if (system == null || system.Enabled)
                    {
                        continue;
                    }

                    var systemModule = UTinyUtility.GetModules(system).FirstOrDefault();
                    var systemName   = UTinyBuildPipeline.GetJsTypeName(systemModule, system);

                    // @NOTE Disable currently accepts a string and NOT the `ut.System` object
                    writer.LineFormat("scheduler.disable({0});", EscapeJsString(systemName));
                }

                writer.Line("try { ut.Runtime.Service.run(world); } catch (e) { if (e !== 'SimulateInfiniteLoop') throw e; }");
            }

            writer.Line();

            using (writer.Scope("function WorldSetup(world)"))
            {
                writer.LineFormat("UT_ASSETS_SETUP(world);");

                var startupEntityGroup = module.StartupEntityGroup.Dereference(module.Registry);

                if (null != startupEntityGroup)
                {
                    writer.Line($"{KEntityGroupNamespace}.{module.Namespace}[\"{module.StartupEntityGroup.Dereference(module.Registry).Name}\"].load(world);");
                }
                else
                {
                    Debug.LogError($"{UTinyConstants.ApplicationName}: BuildError - No startup group has been set");
                }

                using (writer.Scope("return"))
                {
                    writer
                    .LineFormat("canvasWidth: {0},", project.Settings.CanvasWidth)
                    .LineFormat("canvasHeight: {0},", project.Settings.CanvasHeight)
                    .LineFormat("canvasAutoResize: {0},", project.Settings.CanvasAutoResize ? "true" : "false");
                }

#if UNITY_EDITOR_WIN
                writer.Length -= 2;
#else
                writer.Length -= 1;
#endif
                writer.WriteRaw(";").Line();
            }

            File.WriteAllText(file.FullName, writer.ToString(), Encoding.UTF8);
            results.BuildReport.GetOrAddChild(UTinyBuildReport.CodeNode).AddChild(file);
        }
        /// <summary>
        /// Packages system objects to `systems.js`
        ///
        /// All systems and system dependencies are written to this file
        /// </summary>
        private static void GenerateSystems(UTinyBuildOptions options, UTinyBuildResults results)
        {
            var project = options.Project;
            var report  = results.BuildReport.GetOrAddChild(UTinyBuildReport.CodeNode).AddChild();

            var file   = new FileInfo(Path.Combine(results.BinaryFolder.FullName, KSystemsFileName));
            var writer = new UTinyCodeWriter(CodeStyle.JavaScript);

            PrependGeneratedHeader(writer, options.Project.Name);

            foreach (var reference in project.Module.Dereference(project.Registry).GetSystemExecutionOrder())
            {
                var system = reference.Dereference(project.Registry);

                if (system == null)
                {
                    Debug.LogWarning($"Can't resolve system named '{reference.Name}' with ID {reference.Id} -- ignoring, you should delete this system");
                    continue;
                }

                if (system.External)
                {
                    continue;
                }

                // Fetch the module this system belongs to
                var systemModule = UTinyUtility.GetModules(system).FirstOrDefault();

                if (system.IsRuntimeIncluded)
                {
                    continue;
                }

                var reportSystemPos = writer.Length;

                UTinyJsdoc.WriteSystem(writer, system);

                writer.Line($"{UTinyBuildPipeline.GetJsTypeName(systemModule, system)}.update = {UTinyBuildPipeline.GenerateSystemPrefix(system)}");
                writer.IncrementIndent();

                if (system.IncludeIterator)
                {
                    writer.Line(UTinyBuildPipeline.GenerateSystemIteratorPrefix(system));
                    writer.IncrementIndent();
                }

                var text = system.TextAsset ? system.TextAsset.text : string.Empty;

                if (!string.IsNullOrEmpty(text))
                {
                    var lines = text.Split('\n');

                    foreach (var line in lines)
                    {
                        writer.Line(line);
                    }
                }

                if (system.IncludeIterator)
                {
                    writer.DecrementIndent();
                    writer.Line("});");
                }

                writer.DecrementIndent();
                writer.Line(UTinyBuildPipeline.GenerateSystemSuffix(system));

                report.AddChild(AssetDatabase.GetAssetPath(system.TextAsset), Encoding.ASCII.GetBytes(writer.Substring(reportSystemPos)), system.TextAsset);
            }

            File.WriteAllText(file.FullName, writer.ToString(), Encoding.UTF8);
            report.Reset(file);
        }
        /// <summary>
        /// Packages assets to `assets.js` or `Assets/*.*`
        /// </summary>
        private static void PackageAssets(UTinyBuildOptions options, UTinyBuildResults results)
        {
            var buildFolder = options.Destination;
            var binFolder   = results.BinaryFolder;

            // Export assets to the build directory
            var buildAssetsFolder = new DirectoryInfo(Path.Combine(buildFolder.FullName, "Assets"));

            buildAssetsFolder.Create();
            var export = UTinyAssetExporter.Export(options.Project, buildAssetsFolder);

            // copy assets to bin AND/OR encode assets to 'assets.js'
            var binAssetsFolder = new DirectoryInfo(Path.Combine(binFolder.FullName, "Assets"));

            binAssetsFolder.Create();

            var assetsFile = new FileInfo(Path.Combine(binFolder.FullName, KAssetsFileName));

            var writer = new UTinyCodeWriter();

            PrependGeneratedHeader(writer, options.Project.Name);

            var reportAssets     = results.BuildReport.AddChild(UTinyBuildReport.AssetsNode);
            var reportJavaScript = reportAssets.AddChild("JavaScript");

            using (var jsdoc = new UTinyJsdoc.Writer(writer))
            {
                jsdoc.Type("object");
                jsdoc.Desc("Map containing URLs for all assets.  If assets are included as base64 blobs, these will be data URLs.");
                jsdoc.Line("@example var assetUrl = UT_ASSETS[\"MyCustomAsset\"]");
            }

            long totalBase64Size = 0;

            using (writer.Scope("var UT_ASSETS ="))
            {
                var i = 0;
                foreach (var info in export)
                {
                    var reportAsset = reportAssets.AddChild(info.AssetInfo.AssetPath, 0, info.AssetInfo.Object);

                    var settings = UTinyUtility.GetAssetExportSettings(options.Project, info.AssetInfo.Object);
                    if (settings.Embedded)
                    {
                        foreach (var file in info.Exported)
                        {
                            var buffer        = File.ReadAllBytes(file.FullName);
                            var base64        = Convert.ToBase64String(buffer);
                            var fileExtension = Path.GetExtension(file.FullName).ToLower();

                            string mimeType;
                            switch (fileExtension)
                            {
                            case ".png":
                                mimeType = "image/png";
                                break;

                            case ".jpg":
                            case ".jpeg":
                                mimeType = "image/jpeg";
                                break;

                            case ".webp":
                                mimeType = "image/webp";
                                break;

                            case ".mp3":
                                mimeType = "audio/mpeg";
                                break;

                            case ".wav":
                                mimeType = "audio/wav";
                                break;

                            case ".json":
                                mimeType = "application/json";
                                break;

                            case ".ttf":
                                mimeType = "font/truetype";
                                break;

                            default:
                                Debug.LogWarningFormat("Asset {0} has unknown extension, included as text/plain in assets", file);
                                mimeType = "text/plain";
                                break;
                            }

                            var comma = i != 0 ? "," : "";
                            writer.Line($"{comma}\"{Path.GetFileNameWithoutExtension(file.Name)}\": \"data:{mimeType};base64,{base64}\"");
                            i++;

                            reportAsset.AddChild(UTinyBuildPipeline.GetRelativePath(file), Encoding.ASCII.GetBytes(base64), info.AssetInfo.Object);
                            totalBase64Size += base64.Length;

                            file.Delete();
                        }
                    }
                    else
                    {
                        foreach (var file in info.Exported)
                        {
                            var comma = i != 0 ? "," : "";
                            writer.Line($"{comma}\"{Path.GetFileNameWithoutExtension(file.Name)}\": \"Assets/{file.Name}\"");
                            i++;

                            reportAsset.AddChild(file, info.AssetInfo.Object);
                        }
                    }
                }
            }

            writer.Line();

            writer.WriteRaw("var UT_ASSETS_SETUP = ");
            {
                var registry = new UTinyRegistry();
                UTinyPersistence.LoadAllModules(registry);
                var entityGroup = UTinyAssetEntityGroupGenerator.Generate(registry, options.Project);
                EntityGroupSetupVisitor.WriteEntityGroupSetupFunction(writer, options.Project, entityGroup, false, false);
            }

            // Write `assets.js`
            File.WriteAllText(assetsFile.FullName, writer.ToString());

            reportJavaScript.Item.Size = assetsFile.Length - totalBase64Size;

            // Remaining assets are binplaced
            foreach (var info in export)
            {
                foreach (var file in info.Exported)
                {
                    if (!file.Exists)
                    {
                        // this asset has been packaged already
                        continue;
                    }

                    file.MoveTo(Path.Combine(binAssetsFolder.FullName, file.Name));
                }
            }

            // Clean up the build directory
            buildAssetsFolder.Delete(true);

            // if we have no standalone assets, cleanup
            if (binAssetsFolder.GetFiles().Length <= 0)
            {
                binAssetsFolder.Delete();
            }
        }
Esempio n. 14
0
 public Writer(UTinyCodeWriter writer)
 {
     m_Writer = writer;
     m_Writer.Line("/**");
 }
Esempio n. 15
0
        public static void WriteSystem(UTinyCodeWriter writer, UTinySystem system)
        {
            using (var w = new Writer(writer))
            {
                w.Method();
                w.Desc($"System {system.Documentation.Summary}");

                if (system.Components.Count > 0)
                {
                    var sb = new StringBuilder();
                    sb.Append("Components [");
                    for (var i = 0; i < system.Components.Count; i++)
                    {
                        var componentRef = system.Components[i];
                        var component    = componentRef.Dereference(system.Registry);
                        if (null != component)
                        {
                            sb.AppendFormat(i == 0 ? "{{@link {0}}}" : ", {{@link {0}}}", UTinyBuildPipeline.GetJsTypeName(component));
                        }
                        else
                        {
                            throw new Exception($"System component is missing System=[{system.Name}] Component=[{componentRef.Name}]");
                        }
                    }
                    sb.Append("]");
                    w.Line(sb.ToString());
                }

                if (system.ExecuteAfter.Count > 0)
                {
                    var sb = new StringBuilder();
                    sb.Append("Execute After [");
                    for (var i = 0; i < system.ExecuteAfter.Count; i++)
                    {
                        var executeAfterRef = system.ExecuteAfter[i];
                        var executeAfter    = executeAfterRef.Dereference(system.Registry);

                        if (null != executeAfter)
                        {
                            sb.AppendFormat(i == 0 ? "{{@link {0}}}" : ", {{@link {0}}}", UTinyBuildPipeline.GetJsTypeName(executeAfter));
                        }
                        else
                        {
                            throw new Exception($"System reference is missing System=[{system.Name}] ExecuteAfter=[{executeAfterRef.Name}]");
                        }
                    }
                    sb.Append("]");
                    w.Line(sb.ToString());
                }

                if (system.ExecuteBefore.Count > 0)
                {
                    var sb = new StringBuilder();
                    sb.Append("Execute Before [");
                    for (var i = 0; i < system.ExecuteBefore.Count; i++)
                    {
                        var executeBeforeRef = system.ExecuteBefore[i];
                        var executeBefore    = executeBeforeRef.Dereference(system.Registry);

                        if (null != executeBefore)
                        {
                            sb.AppendFormat(i == 0 ? "{{@link {0}}}" : ", {{@link {0}}}", UTinyBuildPipeline.GetJsTypeName(executeBefore));
                        }
                        else
                        {
                            throw new Exception($"System reference is missing System=[{system.Name}] ExecuteBefore=[{executeBeforeRef.Name}]");
                        }
                    }
                    sb.Append("]");
                    w.Line(sb.ToString());
                }

                w.Param("ut.Scheduler", "sched");
                w.Param("ut.World", "world");
            }
        }