Exemple #1
0
 public static void Load()
 {
     using (ProfilingUtility.SampleBlock("Load Icons"))
     {
         Language.Load();
     }
 }
Exemple #2
0
        private static void DeserializeJson(fsSerializer serializer, string json, ref object instance, bool forceReflected)
        {
            using (ProfilingUtility.SampleBlock("DeserializeJson"))
            {
                fsResult result = DeserializeJsonUtil(serializer, json, ref instance, forceReflected);

                HandleResult("Deserialization", result, instance as UnityObject);
            }
        }
Exemple #3
0
        public static EditorTexture Load(IResourceProvider resources, string path, TextureResolution[] resolutions, CreateTextureOptions options, bool required)
        {
            using (ProfilingUtility.SampleBlock("Load Editor Texture"))
            {
                Ensure.That(nameof(resources)).IsNotNull(resources);
                Ensure.That(nameof(path)).IsNotNull(path);
                Ensure.That(nameof(resolutions)).HasItems(resolutions);

                var set = new EditorTexture();

                // Try with explicit resolutions first
                foreach (var resolution in resolutions)
                {
                    var width = resolution.width;
                    // var height = resolution.height;

                    var personalPath     = String.Empty;
                    var professionalPath = String.Empty;

                    personalPath     = resources.GetPersonalPath(path, width);
                    professionalPath = resources.GetProfessionalPath(path, width);

                    if (resources.FileExists(personalPath))
                    {
                        var tex = resources.LoadTexture(personalPath, options);
                        set.personal.Add(width, tex);
                    }

                    if (resources.FileExists(professionalPath))
                    {
                        var tex = resources.LoadTexture(professionalPath, options);
                        set.professional.Add(width, tex);
                    }
                }

                if (set.personal.Count == 0)
                {
                    if (required)
                    {
                        Debug.LogWarning($"Missing editor texture: {path}\n{resources.DebugPath(path)}");
                    }

                    // Never return an empty set; the codebase assumes this guarantee

                    return(null);
                }

                set.textureName = path;

                return(set);
            }
        }
Exemple #4
0
        public IUnitOption ToOption()
        {
            using (ProfilingUtility.SampleBlock("Row to option"))
            {
                var optionType = Codebase.DeserializeType(this.optionType);

                IUnitOption option;

                option = (IUnitOption)Activator.CreateInstance(optionType);

                option.Deserialize(this);

                return(option);
            }
        }
Exemple #5
0
        public static void Dump(TimeSpan threshold)
        {
            if (ProfilingUtility.rootSegment.children.Count == 0)
            {
                return;
            }

            var sb = new StringBuilder();

            Append(sb, 0, ProfilingUtility.rootSegment, threshold);

            ProfilingUtility.Clear();

            Debug.Log(sb);
        }
Exemple #6
0
        public static void UpdateSettings()
        {
            using (ProfilingUtility.SampleBlock("Codebase settings update"))
            {
                var typeOptionsHashSet     = new HashSet <Type>(BoltCore.Configuration.typeOptions);
                var assemblyOptionsHashSet = new HashSet <LooseAssemblyName>(BoltCore.Configuration.assemblyOptions);
                _settingsAssemblies      = new List <Assembly>();
                _settingsAssembliesTypes = new List <Type>();
                _settingsTypes           = new List <Type>();

                foreach (var assembly in _assemblies)
                {
                    var couldHaveIncludeInSettingsAttribute = ludiqAssemblies.Contains(assembly);

                    // It's important not to provide types outside the settings assemblies,
                    // because only those assemblies will be added to the linker to preserve stripping.
                    if (IncludeInSettings(assembly, assemblyOptionsHashSet))
                    {
                        _settingsAssemblies.Add(assembly);

                        foreach (var type in assembly.GetTypesSafely())
                        {
                            // Apparently void can be returned somehow:
                            // http://support.ludiq.io/topics/483
                            if (type == typeof(void))
                            {
                                continue;
                            }

                            _settingsAssembliesTypes.Add(type);

                            // For optimization, we bypass [IncludeInSettings] for assemblies
                            // that could logically never have it.
                            if (IncludeInSettings(type, couldHaveIncludeInSettingsAttribute, typeOptionsHashSet))
                            {
                                _settingsTypes.Add(type);
                            }
                        }
                    }
                }

                settingsAssemblies      = _settingsAssemblies.AsReadOnly();
                settingsAssembliesTypes = _settingsAssembliesTypes.AsReadOnly();
                settingsTypes           = _settingsTypes.AsReadOnly();

                settingsChanged?.Invoke();
            }
        }
        public static EditorTexture Load(IResourceProvider resources, string path, TextureResolution[] resolutions, CreateTextureOptions options, bool required)
        {
            using (ProfilingUtility.SampleBlock("Load Editor Texture"))
            {
                Ensure.That(nameof(resources)).IsNotNull(resources);
                Ensure.That(nameof(path)).IsNotNull(path);
                Ensure.That(nameof(resolutions)).HasItems(resolutions);

                var set       = new EditorTexture();
                var name      = Path.GetFileNameWithoutExtension(path).PartBefore('@');
                var extension = Path.GetExtension(path);
                var directory = Path.GetDirectoryName(path);

                // Try with explicit resolutions first
                foreach (var resolution in resolutions)
                {
                    var width = resolution.width;
                    // var height = resolution.height;

                    var personalPath     = Path.Combine(directory, $"{name}@{width}x{extension}");
                    var professionalPath = Path.Combine(directory, $"{name}_Pro@{width}x{extension}");

                    if (resources.FileExists(personalPath))
                    {
                        set.personal.Add(width, resources.LoadTexture(personalPath, options));
                    }

                    if (resources.FileExists(professionalPath))
                    {
                        set.professional.Add(width, resources.LoadTexture(professionalPath, options));
                    }
                }

                if (set.personal.Count == 0)
                {
                    if (required)
                    {
                        Debug.LogWarning($"Missing editor texture: {name}\n{resources.DebugPath(path)}");
                    }

                    // Never return an empty set; the codebase assumes this guarantee

                    return(null);
                }

                return(set);
            }
        }
Exemple #8
0
        private static void UpdateCodebase(IEnumerable <Type> typeSet = null)
        {
            using var profilerScope = ProfilingUtility.SampleBlock("UpdateCodebase");
            if (typeSet == null)
            {
                typeSet = Codebase.settingsTypes;
            }
            else
            {
                typeSet = typeSet.Where(t => Codebase.settingsTypes.Contains(t));
            }

            Codebase.UpdateSettings();
            codebase = Codebase.Subset(typeSet, TypeFilter.Any.Configured(), MemberFilter.Any.Configured(), TypeFilter.Any.Configured(false));
            codebase.Cache();
        }
Exemple #9
0
        public static EditorTexture Load(IResourceProvider resources, string path, CreateTextureOptions options, bool required)
        {
            using (ProfilingUtility.SampleBlock("Load Editor Texture"))
            {
                Ensure.That(nameof(resources)).IsNotNull(resources);
                Ensure.That(nameof(path)).IsNotNull(path);

                var set       = new EditorTexture();
                var name      = Path.GetFileNameWithoutExtension(path).PartBefore('@');
                var extension = Path.GetExtension(path);
                var directory = Path.GetDirectoryName(path);

                var personalPath     = Path.Combine(directory, $"{name}{extension}");
                var professionalPath = Path.Combine(directory, $"{name}_Pro{extension}");

                var texture = resources.LoadTexture(personalPath, options);

                if (texture != null)
                {
                    set.personal.Add(texture.width, texture);
                }

                texture = resources.LoadTexture(professionalPath, options);

                if (texture != null)
                {
                    set.professional.Add(texture.width, texture);
                }

                if (set.personal.Count == 0)
                {
                    if (required)
                    {
                        Debug.LogWarning($"Missing editor texture: {name}\n{resources.DebugPath(path)}");
                    }

                    // Never return an empty set; the codebase assumes this guarantee

                    return(null);
                }

                set.textureName = path;

                return(set);
            }
        }
Exemple #10
0
        private static void UpdateTypeMappings()
        {
            using var profilerScope = ProfilingUtility.SampleBlock("UpdateTypeMappings");

            typesToGuids = new Dictionary <Type, HashSet <string> >();
            guidsToTypes = new Dictionary <string, HashSet <Type> >();

            UnityAPI.AwaitForever(() =>
            {
                foreach (var script in UnityEngine.Resources.FindObjectsOfTypeAll <MonoScript>())
                {
                    var type = script.GetClass();

                    // Skip scripts without types
                    if (type == null)
                    {
                        continue;
                    }

                    var path = AssetDatabase.GetAssetPath(script);
                    // Skip built-in Unity plugins, which are referenced by full path
                    if (!path.StartsWith("Assets"))
                    {
                        continue;
                    }

                    var guid = AssetDatabase.AssetPathToGUID(path);
                    // Add the GUID to the list, even if it doesn't have any type
                    if (!guidsToTypes.ContainsKey(guid))
                    {
                        guidsToTypes.Add(guid, new HashSet <Type>());
                    }

                    if (!typesToGuids.ContainsKey(type))
                    {
                        typesToGuids.Add(type, new HashSet <string>());
                    }

                    typesToGuids[type].Add(guid);
                    guidsToTypes[guid].Add(type);
                }
            });
        }
Exemple #11
0
        private static string SerializeJson(fsSerializer serializer, object instance, bool forceReflected)
        {
            using (ProfilingUtility.SampleBlock("SerializeJson"))
            {
                fsData data;

                fsResult result;

                if (forceReflected)
                {
                    result = serializer.TrySerialize(instance.GetType(), typeof(fsReflectedConverter), instance, out data);
                }
                else
                {
                    result = serializer.TrySerialize(instance, out data);
                }

                HandleResult("Serialization", result, instance as UnityObject);

                return(fsJsonPrinter.CompressedJson(data));
            }
        }
Exemple #12
0
        private static void Load()
        {
            if (IsUnitOptionsBuilt())
            {
                // Update before loading if required, ensuring no "in-between" state
                // where the loaded options are not yet loaded.
                // The update code will not touch the options array if it is null.
                if (BoltFlow.Configuration.updateNodesAutomatically)
                {
                    try
                    {
                        ProgressUtility.DisplayProgressBar("Checking for codebase changes...", null, 0);

                        if (requiresUpdate)
                        {
                            Update();
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.LogError($"Failed to update node options.\nRetry with '{UnitOptionUtility.GenerateUnitDatabasePath}'.\n{ex}");
                    }
                    finally
                    {
                        ProgressUtility.ClearProgressBar();
                    }
                }

                lock (@lock)
                {
                    using (ProfilingUtility.SampleBlock("Load Node Database"))
                    {
                        using (NativeUtility.Module("sqlite3.dll"))
                        {
                            ProgressUtility.DisplayProgressBar("Loading node database...", null, 0);

                            SQLiteConnection database = null;

                            try
                            {
                                database = new SQLiteConnection(BoltFlow.Paths.unitOptions, SQLiteOpenFlags.ReadOnly);

                                int total;

                                total = database.Table <UnitOptionRow>().Count();

                                var progress = 0f;

                                options = new HashSet <IUnitOption>();

                                var failedOptions = new Dictionary <UnitOptionRow, Exception>();

                                foreach (var row in database.Table <UnitOptionRow>())
                                {
                                    try
                                    {
                                        var option = row.ToOption();

                                        options.Add(option);
                                    }
                                    catch (Exception rowEx)
                                    {
                                        failedOptions.Add(row, rowEx);
                                    }

                                    ProgressUtility.DisplayProgressBar("Loading node database...", BoltCore.Configuration.humanNaming ? row.labelHuman : row.labelProgrammer, progress++ / total);
                                }

                                if (failedOptions.Count > 0)
                                {
                                    var sb = new StringBuilder();

                                    sb.AppendLine($"{failedOptions.Count} node options failed to load and were skipped.");
                                    sb.AppendLine($"Try rebuilding the node options with '{UnitOptionUtility.GenerateUnitDatabasePath}' to purge outdated nodes.");
                                    sb.AppendLine();

                                    foreach (var failedOption in failedOptions)
                                    {
                                        sb.AppendLine(failedOption.Key.favoriteKey);
                                    }

                                    sb.AppendLine();

                                    foreach (var failedOption in failedOptions)
                                    {
                                        sb.AppendLine(failedOption.Key.favoriteKey + ": ");
                                        sb.AppendLine(failedOption.Value.ToString());
                                        sb.AppendLine();
                                    }

                                    Debug.LogWarning(sb.ToString());
                                }
                            }
                            catch (Exception ex)
                            {
                                options = new HashSet <IUnitOption>();
                                Debug.LogError($"Failed to load node options.\nTry to rebuild them with '{UnitOptionUtility.GenerateUnitDatabasePath}'.\n\n{ex}");
                            }
                            finally
                            {
                                database?.Close();
                                //ConsoleProfiler.Dump();
                                ProgressUtility.ClearProgressBar();
                            }
                        }
                    }
                }
            }
        }
Exemple #13
0
        public static void Update()
        {
            if (!IsUnitOptionsBuilt())
            {
                Build();
                return;
            }

            lock (@lock)
            {
                using (ProfilingUtility.SampleBlock("Update Node Database"))
                {
                    using (NativeUtility.Module("sqlite3.dll"))
                    {
                        var progressTitle = "Updating node database...";

                        SQLiteConnection database = null;

                        try
                        {
                            VersionControlUtility.Unlock(BoltFlow.Paths.unitOptions);

                            var steps = 7f;
                            var step  = 0f;

                            ProgressUtility.DisplayProgressBar(progressTitle, "Connecting to database...", step++ / steps);

                            database = new SQLiteConnection(BoltFlow.Paths.unitOptions);

                            ProgressUtility.DisplayProgressBar(progressTitle, "Updating type mappings...", step++ / steps);

                            UpdateTypeMappings();

                            ProgressUtility.DisplayProgressBar(progressTitle, "Fetching modified scripts...", step++ / steps);

                            var modifiedScriptGuids = GetModifiedScriptGuids().Distinct().ToHashSet();

                            ProgressUtility.DisplayProgressBar(progressTitle, "Fetching deleted scripts...", step++ / steps);

                            var deletedScriptGuids = GetDeletedScriptGuids().Distinct().ToHashSet();

                            ProgressUtility.DisplayProgressBar(progressTitle, "Updating codebase...", step++ / steps);

                            var modifiedScriptTypes = modifiedScriptGuids.SelectMany(GetScriptTypes).ToArray();

                            UpdateCodebase(modifiedScriptTypes);

                            var outdatedScriptGuids = new HashSet <string>();
                            outdatedScriptGuids.UnionWith(modifiedScriptGuids);
                            outdatedScriptGuids.UnionWith(deletedScriptGuids);

                            ProgressUtility.DisplayProgressBar(progressTitle, "Removing outdated node options...", step++ / steps);

                            options?.RemoveWhere(option => outdatedScriptGuids.Overlaps(option.sourceScriptGuids));

                            // We want to use the database level WHERE here for speed,
                            // so we'll run multiple queries, one for each outdated script GUID.

                            foreach (var outdatedScriptGuid in outdatedScriptGuids)
                            {
                                foreach (var outdatedRowId in database.Table <UnitOptionRow>()
                                         .Where(row => row.sourceScriptGuids.Contains(outdatedScriptGuid))
                                         .Select(row => row.id))
                                {
                                    database.Delete <UnitOptionRow>(outdatedRowId);
                                }
                            }

                            ProgressUtility.DisplayProgressBar(progressTitle, "Converting codebase to node options...", step++ / steps);

                            var newOptions = new HashSet <IUnitOption>(modifiedScriptGuids.SelectMany(GetScriptTypes)
                                                                       .Distinct()
                                                                       .SelectMany(GetIncrementalOptions));

                            var rows = new HashSet <UnitOptionRow>();

                            float progress = 0;

                            foreach (var newOption in newOptions)
                            {
                                options?.Add(newOption);

                                try
                                {
                                    ProgressUtility.DisplayProgressBar(progressTitle, newOption.label, (step / steps) + ((1 / step) * (progress / newOptions.Count)));
                                    rows.Add(newOption.Serialize());
                                }
                                catch (Exception ex)
                                {
                                    Debug.LogError($"Failed to serialize option '{newOption.GetType()}'.\n{ex}");
                                }

                                progress++;
                            }

                            ProgressUtility.DisplayProgressBar(progressTitle, "Writing to database...", 1);

                            try
                            {
                                database.InsertAll(rows);
                            }
                            catch (Exception ex)
                            {
                                Debug.LogError($"Failed to write options to database.\n{ex}");
                            }

                            // Make sure the database is touched to the current date,
                            // even if we didn't do any change. This will avoid unnecessary
                            // analysis in future update checks.
                            File.SetLastWriteTimeUtc(BoltFlow.Paths.unitOptions, DateTime.UtcNow);
                        }
                        finally
                        {
                            database?.Close();
                            ProgressUtility.ClearProgressBar();
                            UnityAPI.Async(AssetDatabase.Refresh);
                            //ConsoleProfiler.Dump();
                        }
                    }
                }
            }
        }
Exemple #14
0
        public static void Build(bool initialBuild = false)
        {
            if (IsUnitOptionsBuilt())
            {
                return;
            }

            if (initialBuild)
            {
                ProgressUtility.SetTitleOverride("Visual Scripting: Initial Node Generation...");
            }

            const string progressTitle = "Visual Scripting: Building node database...";

            lock (@lock)
            {
                using (ProfilingUtility.SampleBlock("Update Node Database"))
                {
                    using (NativeUtility.Module("sqlite3.dll"))
                    {
                        SQLiteConnection database = null;

                        try
                        {
                            ProgressUtility.DisplayProgressBar(progressTitle, "Creating database...", 0);

                            PathUtility.CreateParentDirectoryIfNeeded(BoltFlow.Paths.unitOptions);
                            database = new SQLiteConnection(BoltFlow.Paths.unitOptions);
                            database.CreateTable <UnitOptionRow>();

                            ProgressUtility.DisplayProgressBar(progressTitle, "Updating codebase...", 0);

                            UpdateCodebase();

                            ProgressUtility.DisplayProgressBar(progressTitle, "Updating type mappings...", 0);

                            UpdateTypeMappings();

                            ProgressUtility.DisplayProgressBar(progressTitle,
                                                               "Converting codebase to node options...", 0);

                            options = new HashSet <IUnitOption>(GetStaticOptions());

                            var rows = new HashSet <UnitOptionRow>();

                            var progress          = 0;
                            var lastShownProgress = 0f;

                            foreach (var option in options)
                            {
                                try
                                {
                                    var shownProgress = (float)progress / options.Count;

                                    if (shownProgress > lastShownProgress + 0.01f)
                                    {
                                        ProgressUtility.DisplayProgressBar(progressTitle,
                                                                           "Converting codebase to node options...", shownProgress);
                                        lastShownProgress = shownProgress;
                                    }

                                    rows.Add(option.Serialize());
                                }
                                catch (Exception ex)
                                {
                                    Debug.LogError($"Failed to save option '{option.GetType()}'.\n{ex}");
                                }

                                progress++;
                            }

                            ProgressUtility.DisplayProgressBar(progressTitle, "Writing to database...", 1);

                            try
                            {
                                database.CreateTable <UnitOptionRow>();
                                database.InsertAll(rows);
                            }
                            catch (Exception ex)
                            {
                                Debug.LogError($"Failed to write options to database.\n{ex}");
                            }
                        }
                        finally
                        {
                            database?.Close();
                            ProgressUtility.ClearProgressBar();
                            ProgressUtility.ClearTitleOverride();
                            AssetDatabase.Refresh();
                            //ConsoleProfiler.Dump();
                        }
                    }
                }
            }
        }
 public ProfilingScope(string name)
 {
     ProfilingUtility.BeginSample(name);
 }
Exemple #16
0
        static Codebase()
        {
            using (ProfilingUtility.SampleBlock("Codebase initialization"))
            {
                _assemblies             = new List <Assembly>();
                _runtimeAssemblies      = new List <Assembly>();
                _editorAssemblies       = new List <Assembly>();
                _ludiqAssemblies        = new List <Assembly>();
                _ludiqRuntimeAssemblies = new List <Assembly>();
                _ludiqEditorAssemblies  = new List <Assembly>();

                _types             = new List <Type>();
                _runtimeTypes      = new List <Type>();
                _editorTypes       = new List <Type>();
                _ludiqTypes        = new List <Type>();
                _ludiqRuntimeTypes = new List <Type>();
                _ludiqEditorTypes  = new List <Type>();

                foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
                {
                    try
                    {
#if NET_4_6
                        if (assembly.IsDynamic)
                        {
                            continue;
                        }
#endif

                        _assemblies.Add(assembly);

                        var isRuntimeAssembly = IsRuntimeAssembly(assembly);
                        var isEditorAssembly  = IsEditorAssembly(assembly, new HashSet <string>());
                        var isLudiqRuntimeDependentAssembly = IsLudiqRuntimeDependentAssembly(assembly);
                        var isLudiqEditorDependentAssembly  = IsLudiqEditorDependentAssembly(assembly);
                        var isLudiqAssembly        = isLudiqRuntimeDependentAssembly || isLudiqEditorDependentAssembly;
                        var isLudiqEditorAssembly  = isLudiqEditorDependentAssembly;
                        var isLudiqRuntimeAssembly = isLudiqRuntimeDependentAssembly && !isLudiqEditorDependentAssembly;

                        if (isRuntimeAssembly)
                        {
                            _runtimeAssemblies.Add(assembly);
                        }

                        if (isEditorAssembly)
                        {
                            _editorAssemblies.Add(assembly);
                        }

                        if (isLudiqAssembly)
                        {
                            _ludiqAssemblies.Add(assembly);
                        }

                        if (isLudiqEditorAssembly)
                        {
                            _ludiqEditorAssemblies.Add(assembly);
                        }

                        if (isLudiqRuntimeAssembly)
                        {
                            _ludiqRuntimeAssemblies.Add(assembly);
                        }

                        foreach (var type in assembly.GetTypesSafely())
                        {
                            _types.Add(type);

                            if (isRuntimeAssembly)
                            {
                                _runtimeTypes.Add(type);
                            }

                            if (isEditorAssembly)
                            {
                                _editorTypes.Add(type);
                            }

                            if (isLudiqAssembly)
                            {
                                _ludiqTypes.Add(type);
                            }

                            if (isLudiqEditorAssembly)
                            {
                                _ludiqEditorTypes.Add(type);
                            }

                            if (isLudiqRuntimeAssembly)
                            {
                                _ludiqRuntimeTypes.Add(type);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.LogWarning($"Failed to analyze assembly '{assembly}':\n{ex}");
                    }
                }

                assemblies             = _assemblies.AsReadOnly();
                runtimeAssemblies      = _runtimeAssemblies.AsReadOnly();
                editorAssemblies       = _editorAssemblies.AsReadOnly();
                ludiqAssemblies        = _ludiqAssemblies.AsReadOnly();
                ludiqRuntimeAssemblies = _ludiqRuntimeAssemblies.AsReadOnly();
                ludiqEditorAssemblies  = _ludiqEditorAssemblies.AsReadOnly();

                types             = _types.AsReadOnly();
                runtimeTypes      = _runtimeTypes.AsReadOnly();
                editorTypes       = _editorTypes.AsReadOnly();
                ludiqTypes        = _ludiqTypes.AsReadOnly();
                ludiqRuntimeTypes = _ludiqRuntimeTypes.AsReadOnly();
                ludiqEditorTypes  = _ludiqEditorTypes.AsReadOnly();
            }
        }
Exemple #17
0
        private static void Initialize()
        {
            EditorApplication.delayCall -= initializeCallbackFunction;

            using (ProfilingUtility.SampleBlock("Plugin Container Initialization"))
            {
                initializing = true;

                pluginTypesById = Codebase.ludiqEditorTypes
                                  .Where(t => typeof(Plugin).IsAssignableFrom(t) && t.IsConcrete())
                                  .ToDictionary(GetPluginID);

                pluginDependencies = new Dictionary <string, HashSet <string> >();

                foreach (var pluginTypeById in pluginTypesById)
                {
                    pluginDependencies.Add(pluginTypeById.Key, pluginTypeById.Value.GetAttributes <PluginDependencyAttribute>().Select(pda => pda.id).ToHashSet());
                }

                var moduleTypes = Codebase.ludiqEditorTypes
                                  .Where(t => typeof(IPluginModule).IsAssignableFrom(t) && t.HasAttribute <PluginModuleAttribute>(false))
                                  .OrderByDependencies(t => t.GetAttributes <PluginModuleDependencyAttribute>().Select(pmda => pmda.moduleType))
                                  .ToArray();

                pluginsById = new Dictionary <string, Plugin>();

                var allModules = new List <IPluginModule>();

                foreach (var pluginId in pluginTypesById.Keys.OrderByDependencies(pluginId => pluginDependencies[pluginId]))
                {
                    var pluginType = pluginTypesById[pluginId];

                    Plugin plugin;

                    try
                    {
                        using (ProfilingUtility.SampleBlock($"{pluginType.Name} (Instantiation)"))
                        {
                            plugin = (Plugin)pluginType.Instantiate();
                        }
                    }
                    catch (Exception ex)
                    {
                        throw new TargetInvocationException($"Could not instantiate plugin '{pluginId}' ('{pluginType.CSharpName()}').", ex);
                    }

                    var modules = new List <IPluginModule>();

                    foreach (var moduleType in moduleTypes)
                    {
                        try
                        {
                            var required = moduleType.GetAttribute <PluginModuleAttribute>(false).required;

                            var moduleProperty = pluginType.GetProperties().FirstOrDefault(p => p.PropertyType.IsAssignableFrom(moduleType));

                            if (moduleProperty == null)
                            {
                                continue;
                            }

                            IPluginModule module = null;

                            var moduleOverrideType = Codebase.ludiqEditorTypes
                                                     .FirstOrDefault(t => moduleType.IsAssignableFrom(t) && t.IsConcrete() && t.HasAttribute <PluginAttribute>() && t.GetAttribute <PluginAttribute>().id == pluginId);

                            if (moduleOverrideType != null)
                            {
                                try
                                {
                                    using (ProfilingUtility.SampleBlock($"{moduleOverrideType.Name} (Instantiation)"))
                                    {
                                        module = (IPluginModule)InstantiateLinkedType(moduleOverrideType, plugin);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    throw new TargetInvocationException($"Failed to instantiate user-defined plugin module '{moduleOverrideType.CSharpName()}' for '{pluginId}'.", ex);
                                }
                            }
                            else if (moduleType.IsConcrete())
                            {
                                try
                                {
                                    using (ProfilingUtility.SampleBlock($"{moduleType.Name} (Instantiation)"))
                                    {
                                        module = (IPluginModule)InstantiateLinkedType(moduleType, plugin);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    throw new TargetInvocationException($"Failed to instantiate built-in plugin module '{moduleType.CSharpName()}' for '{pluginId}'.", ex);
                                }
                            }
                            else if (required)
                            {
                                throw new InvalidImplementationException($"Missing implementation of plugin module '{moduleType.CSharpName()}' for '{pluginId}'.");
                            }

                            if (module != null)
                            {
                                moduleProperty.SetValue(plugin, module, null);

                                modules.Add(module);
                                allModules.Add(module);
                            }
                        }
                        catch (Exception ex)
                        {
                            Debug.LogException(ex);
                        }
                    }

                    pluginsById.Add(plugin.id, plugin);

                    foreach (var module in modules)
                    {
                        try
                        {
                            using (ProfilingUtility.SampleBlock($"{module.GetType().Name} (Initialization)"))
                            {
                                module.Initialize();
                            }
                        }
                        catch (Exception ex)
                        {
                            Debug.LogException(new Exception($"Failed to initialize plugin module '{plugin.id}.{module.GetType().CSharpName()}'.", ex));
                        }
                    }

                    if (plugin.manifest.versionMismatch)
                    {
                        anyVersionMismatch = true;
                    }
                }

                foreach (var module in allModules)
                {
                    try
                    {
                        using (ProfilingUtility.SampleBlock($"{module.GetType().Name} (Late Initialization)"))
                        {
                            module.LateInitialize();
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.LogException(new Exception($"Failed to late initialize plugin module '{module.plugin.id}.{module.GetType().CSharpName()}'.", ex));
                    }
                }

                var afterPluginTypes = Codebase.ludiqEditorTypes
                                       .Where(t => t.HasAttribute <InitializeAfterPluginsAttribute>());

                using (ProfilingUtility.SampleBlock($"BeforeInitializeAfterPlugins"))
                {
                    EditorApplicationUtility.BeforeInitializeAfterPlugins();
                }

                foreach (var afterPluginType in afterPluginTypes)
                {
                    using (ProfilingUtility.SampleBlock($"{afterPluginType.Name} (Static Initializer)"))
                    {
                        RuntimeHelpers.RunClassConstructor(afterPluginType.TypeHandle);
                    }
                }

                using (ProfilingUtility.SampleBlock($"AfterInitializeAfterPlugins"))
                {
                    EditorApplicationUtility.AfterInitializeAfterPlugins();
                }

                using (ProfilingUtility.SampleBlock($"Delayed Calls"))
                {
                    lock (delayQueue)
                    {
                        while (delayQueue.Count > 0)
                        {
                            delayQueue.Dequeue().Invoke();
                        }
                    }
                }

                InternalEditorUtility.RepaintAllViews();

                ProfilingUtility.Clear();

                using (ProfilingUtility.SampleBlock($"Product Container Initialization"))
                {
                    ProductContainer.Initialize();
                }

                initializing = false;

                initialized = true;

                using (ProfilingUtility.SampleBlock($"Update Process"))
                {
                    // Automatically show update wizard

                    if (!EditorApplication.isPlayingOrWillChangePlaymode && plugins.Any(plugin => plugin.manifest.versionMismatch))
                    {
                        // Delay call seems to be needed here to avoid arcane exceptions...
                        // Too lazy to debug why, it works that way.
                        EditorApplication.delayCall += PerformUpdate;
                    }
                }
            }
        }
 public void Dispose()
 {
     ProfilingUtility.EndSample();
 }