コード例 #1
0
            void ICustomVisit <UTinyEntity.Reference> .CustomVisit(UTinyEntity.Reference value)
            {
                int index;

                if (Property.Name == "parent" &&
                    m_Container is UTinyObject.PropertiesContainer &&
                    ((UTinyObject.PropertiesContainer)m_Container).ParentObject.Type.Equals(VisitorContext.Registry
                                                                                            .GetTransformType()))
                {
                    if (!VisitorContext.EntityIndexMap.TryGetValue(value, out index))
                    {
                        return;
                    }

                    var transformTypeName =
                        UTinyBuildPipeline.GetJsTypeName(VisitorContext.Registry.GetTransformType()
                                                         .Dereference(VisitorContext.Registry));

                    var line = $"e{index}.getComponent({transformTypeName}).appendChild({Entity});";
                    VisitorContext.Writer.Line(line);
                }
                else
                {
                    if (!VisitorContext.EntityIndexMap.TryGetValue(value, out index))
                    {
                        return;
                    }

                    VisitorContext.Writer.Line($"{PropertySetter(Property.Name)}(e{index});");
                }
            }
コード例 #2
0
            void ICustomVisit <UTinyEnum.Reference> .CustomVisit(UTinyEnum.Reference value)
            {
                if (!IsListItem)
                {
                    return;
                }

                var type       = value.Type.Dereference(VisitorContext.Registry);
                var normalized = ExportEnumAsValue
                    ? (type.DefaultValue as UTinyObject)?[value.Name]
                    : $"{UTinyBuildPipeline.GetJsTypeName(type)}.{value.Name}";

                VisitorContext.Writer.Line($"{Path}[{ListIndex}] = {normalized};");
            }
コード例 #3
0
            void ICustomVisit <UTinyObject> .CustomVisit(UTinyObject value)
            {
                if (!IsListItem)
                {
                    return;
                }

                var type = value.Type.Dereference(value.Registry);

                var index = ++VisitorContext.StructIndex;

                VisitorContext.Writer.Line($"var s{index} = new {UTinyBuildPipeline.GetJsTypeName(type)}();");
                value.Properties.Visit(new StructVisitor {
                    VisitorContext = VisitorContext, Path = $"s{index}"
                });
                VisitorContext.Writer.Line($"{Path}[{ListIndex}] = s{index};");
            }
        public bool DrawLayout()
        {
            var module = m_MainModule.Dereference(m_Registry);
            var system = System.Dereference(m_Registry);

            if (null == system || system.IsRuntimeIncluded)
            {
                return(false);
            }

            m_AvailableSystems.Clear();
            m_AvailableSystems.AddRange(module.EnumerateDependencies().SystemRefs());

            m_AvailableComponentTypes.Clear();
            m_AvailableComponentTypes.AddRange(module.EnumerateDependencies().ComponentTypeRefs().Select(r => (UTinyType.Reference)r.Dereference(m_Registry)));

            EditorGUI.BeginChangeCheck();

            using (var scroll = new GUILayout.ScrollViewScope(m_Scroll, GUILayout.ExpandWidth(true)))
            {
                m_Scroll = scroll.scrollPosition;

                EditorGUI.BeginChangeCheck();
                system.Name = EditorGUILayout.DelayedTextField("Name", system.Name);
                if (EditorGUI.EndChangeCheck())
                {
                    OnRenameEnded?.Invoke(system);
                }

                using (new EditorGUILayout.HorizontalScope())
                {
                    EditorGUILayout.PrefixLabel("Description");
                    system.Documentation.Summary = EditorGUILayout.TextArea(system.Documentation.Summary, GUILayout.Height(50));
                }

                m_ExecuteAfterList.list = new List <UTinySystem.Reference>(system.ExecuteAfter);
                m_ExecuteAfterList.DoLayoutList();

                m_ExecuteBeforeList.list = new List <UTinySystem.Reference>(system.ExecuteBefore);
                m_ExecuteBeforeList.DoLayoutList();

                m_ComponentList.list = new List <UTinyType.Reference>(system.Components);
                m_ComponentList.DoLayoutList();

                system.External = EditorGUILayout.Toggle(new GUIContent("External", "Use this to define systems externally"), system.External);

                if (system.External)
                {
                    EditorGUILayout.HelpBox($"This system is assumed to be defined in any included script with the following signature", MessageType.Info);
                    var name = UTinyBuildPipeline.GetJsTypeName(system);
                    EditorGUILayout.SelectableLabel($"{name}.update = function(s,w) {{ /* ... */ }}", "TextArea");
                }
                else
                {
                    system.IncludeIterator = EditorGUILayout.Toggle("Include Iterator", system.IncludeIterator);

                    EditorGUILayout.Space();

                    using (new GUIEnabledScope(false))
                    {
                        var systemPrefix = UTinyBuildPipeline.GenerateSystemPrefix(system);
                        if (system.IncludeIterator)
                        {
                            systemPrefix += UTinyBuildPipeline.GenerateSystemIteratorPrefix(system);
                        }

                        EditorGUILayout.TextArea(systemPrefix);
                    }

                    EditorGUILayout.Space();

                    system.TextAsset = (TextAsset)EditorGUILayout.ObjectField("Source", system.TextAsset, typeof(TextAsset), false);

                    EditorGUILayout.Space();

                    if (null != system.TextAsset)
                    {
                        using (new GUIEnabledScope(false))
                        {
                            var text = system.TextAsset.text;
                            if (text.Length > kMaxChars)
                            {
                                text = text.Substring(0, kMaxChars) + "...\n\n<...etc...>";
                            }
                            GUILayout.TextArea(text);
                        }
                    }

                    EditorGUILayout.Space();

                    using (new GUIEnabledScope(false))
                    {
                        var systemSuffix = UTinyBuildPipeline.GenerateSystemSuffix(system);
                        if (system.IncludeIterator)
                        {
                            systemSuffix = UTinyBuildPipeline.GenerateSystemIteratorSuffix(system) + systemSuffix;
                        }
                        EditorGUILayout.TextArea(systemSuffix);
                    }
                }
            }

            return(EditorGUI.EndChangeCheck());
        }
コード例 #5
0
            void ICustomVisit <UTinyEnum.Reference> .CustomVisit(UTinyEnum.Reference value)
            {
                var type       = value.Type.Dereference(VisitorContext.Registry);
                var normalized = ExportEnumAsValue ? (type.DefaultValue as UTinyObject)?[value.Name] : $"{UTinyBuildPipeline.GetJsTypeName(type)}.{value.Name}";

                VisitorContext.Writer.Line($"{PropertySetter(Property.Name)}({normalized});");
            }
コード例 #6
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();
        }
コード例 #7
0
        /// <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);
        }
コード例 #8
0
        /// <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);
        }
コード例 #9
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");
            }
        }