예제 #1
0
        private void Backup(string gameDataPath)
        {
            var savePath = EditorUtility.SaveFilePanel(Resources.UI_UNITYPLUGIN_INSPECTOR_BACKUP_BUTTON, Path.GetFullPath("./"), Path.GetFileName(gameDataPath), null);

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

            var format = default(string);

            switch (Path.GetExtension(savePath))
            {
            case "gdml": format = "xml"; break;

            case "gdmp": format = "msgpack"; break;

            case "gdbs": format = "bson"; break;

            case "gdjs": format = "json"; break;

            default: format = Path.GetExtension(savePath); break;
            }

            CharonCli.BackupAsync(gameDataPath, CommandOutput.File(savePath, format)).ContinueWith(_ => this.Repaint());
        }
 public static ProductInformation[] GetKnownProducts()
 {
     return(new[] {
         new ProductInformation(PRODUCT_CHARON, Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_CHARON_NAME, disabled: false)
         {
             CurrentVersion = CharonCli.GetVersionAsync().IgnoreFault(),
             Location = Path.GetFullPath(Settings.CharonExecutablePath),
             ExpectedVersion = String.IsNullOrEmpty(Settings.Current.EditorVersion) ? default(SemanticVersion) : new SemanticVersion(Settings.Current.EditorVersion)
         },
         new ProductInformation(PRODUCT_CHARON_UNITY, Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_CHARON_UNITY_PLUGIN_NAME, disabled: !IsAssemblyLoaded(PRODUCT_CHARON_UNITY_ASSEMBLY))
         {
             CurrentVersion = Promise.FromResult(GetAssemblyVersion(PRODUCT_CHARON_UNITY_ASSEMBLY)),
             Location = GetAssemblyLocation(PRODUCT_CHARON_UNITY_ASSEMBLY)
         },
         new ProductInformation(PRODUCT_EXPRESSIONS, Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_EXPRESSIONS_PLUGIN_NAME, disabled: !IsAssemblyLoaded(PackageManager.PRODUCT_EXPRESSIONS_ASSEMBLY))
         {
             CurrentVersion = Promise.FromResult(GetAssemblyVersion(PackageManager.PRODUCT_EXPRESSIONS_ASSEMBLY)),
             Location = GetAssemblyLocation(PackageManager.PRODUCT_EXPRESSIONS_ASSEMBLY)
         },
         new ProductInformation(PRODUCT_TEXT_TEMPLATES, Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_TEXT_TRANSFORM_PLUGIN_NAME, disabled: !IsAssemblyLoaded(PRODUCT_TEXT_TEMPLATES_ASSEMBLY))
         {
             CurrentVersion = Promise.FromResult(GetAssemblyVersion(PRODUCT_TEXT_TEMPLATES_ASSEMBLY)),
             Location = GetAssemblyLocation(PRODUCT_TEXT_TEMPLATES_ASSEMBLY)
         }
     });
 }
예제 #3
0
        private IEnumerable ReportIssueAsync(string reporter, string description, IssueType type, HashSet <string> attachments)
        {
            if (reporter == null)
            {
                throw new ArgumentNullException("reporter");
            }
            if (description == null)
            {
                throw new ArgumentNullException("description");
            }

            if (attachments == null)
            {
                attachments = new HashSet <string>();
            }

            var reportIssue = CharonCli.ReportIssueAsync(reporter, type, description, attachments.ToArray());

            yield return(reportIssue.IgnoreFault());

            var errorOutput = reportIssue.HasErrors ? reportIssue.Error.Message : reportIssue.GetResult().GetErrorData();

            if (string.IsNullOrEmpty(errorOutput) == false)
            {
                throw new InvalidOperationException("Failed to report issue: " + (errorOutput.Length > 0 ? errorOutput : "An unknown error occurred. Please report this issue directly to developer."));
            }
        }
예제 #4
0
 protected void Awake()
 {
     if (File.Exists(CharonCli.GetDefaultLockFilePath()) == false && this)
     {
         this.titleContent = new GUIContent(Resources.UI_UNITYPLUGIN_WINDOW_EDITOR_TITLE);
         this.Close();
     }
 }
		private void Restore(string gameDataPath)
		{
			var openFile = EditorUtility.OpenFilePanelWithFilters(Resources.UI_UNITYPLUGIN_INSPECTOR_RESTORE_BUTTON, Path.GetFullPath("./"), GameDataTracker.GameDataExtensionFilters);
			if (string.IsNullOrEmpty(openFile))
				return;

			CharonCli.RestoreAsync(gameDataPath, CommandInput.File(openFile, "auto")).ContinueWith(_ => this.Repaint());
		}
예제 #6
0
        private void KillProcess()
        {
            CharonCli.FindAndEndGracefully();

            if (this)
            {
                this.Close();
            }
        }
예제 #7
0
        /// <inheritdoc />
        protected override void OnDestroy()
        {
            base.OnDestroy();

            if (Settings.Current.Verbose)
            {
                Debug.Log("Ending game data editor process because window is closed.");
            }

            CharonCli.FindAndEndGracefully();
        }
예제 #8
0
        protected void Update()
        {
            if (this.checkRequirements == null)
            {
                this.checkRequirements = CharonCli.CheckRequirementsAsync();
            }
            if (this.checkRequirements.IsCompleted == false)
            {
                return;
            }

            if (this.checkRequirements.HasErrors)
            {
                this.editorVersion = this.checkRequirements.Error.Unwrap().Message;
                return;
            }

            var result = this.checkRequirements.GetResult();

            // ReSharper disable once SwitchStatementMissingSomeCases REASON: Other cases are irrelevant for display purposes
            switch (result)
            {
            case RequirementsCheckResult.MissingRuntime:
                this.editorVersion = Resources.UI_UNITYPLUGIN_WINDOW_CHECK_RESULT_MISSING_MONO_OR_DOTNET;
                break;

            case RequirementsCheckResult.MissingExecutable:
                this.editorVersion = Resources.UI_UNITYPLUGIN_WINDOWCHECK_RESULT_MISSING_TOOLS;
                break;

            case RequirementsCheckResult.Ok:
                if (this.checkToolsVersion == null)
                {
                    this.editorVersion     = Resources.UI_UNITYPLUGIN_WINDOW_CHECKING_VERSION;
                    this.checkToolsVersion = CharonCli.GetVersionAsync();
                    this.checkToolsVersion.ContinueWith(r =>
                    {
                        if (r.HasErrors)
                        {
                            this.editorVersion = r.Error.Unwrap().Message;
                        }
                        else
                        {
                            this.editorVersion = r.GetResult().ToString();
                        }
                        this.Repaint();
                    });
                    this.Repaint();
                }
                break;
            }
        }
        private static void Initialize()
        {
            EditorApplication.update -= InitializeCallback;

            try
            {
                System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(GameDataInspector).TypeHandle);
                System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Settings).TypeHandle);
                System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Menu).TypeHandle);

                CharonCli.CleanUpLogsDirectory();
            }
            catch (Exception initializationError)
            {
                Debug.LogError("Failed to initialize Charon plugin. Look for exception below.");
                Debug.LogError(initializationError);
            }
        }
예제 #10
0
        private static IEnumerable PostCharonDeployAsync(string charonPath, Action <string, float> progressCallback = null)
        {
            // ensure config file
            var charonConfigPath = charonPath + ".config";

            if (File.Exists(charonConfigPath) == false)
            {
                var embeddedConfigStream = typeof(Menu).Assembly.GetManifestResourceStream("GameDevWare.Charon.Charon.exe.config");
                if (embeddedConfigStream != null)
                {
                    using (embeddedConfigStream)
                        using (var configFileStream = File.Create(charonConfigPath, 8 * 1024, FileOptions.SequentialScan))
                        {
                            var buffer = new byte[8 * 1024];
                            var read   = 0;
                            while ((read = embeddedConfigStream.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                configFileStream.Write(buffer, 0, read);
                            }
                        }
                }
            }

            var currentVersion = default(Version);

            if (File.Exists(charonPath))
            {
                if (progressCallback != null)
                {
                    progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_CHECKING_TOOLS_VERSION, 0.95f);
                }

                var checkToolsVersion = CharonCli.GetVersionAsync();
                yield return(checkToolsVersion.IgnoreFault());

                currentVersion = checkToolsVersion.HasErrors ? default(Version) : checkToolsVersion.GetResult();
            }

            Settings.Current.EditorVersion = currentVersion != null?currentVersion.ToString() : null;

            Settings.Current.Save();
        }
예제 #11
0
        public static IEnumerable ExtractT4Templates(string extractionPath)
        {
            var checkRequirements = CharonCli.CheckRequirementsAsync();

            yield return(checkRequirements);

            switch (checkRequirements.GetResult())
            {
            case RequirementsCheckResult.MissingRuntime: yield return(UpdateRuntimeWindow.ShowAsync()); break;

            case RequirementsCheckResult.WrongVersion:
            case RequirementsCheckResult.MissingExecutable: yield return(CharonCli.DownloadCharon(ProgressUtils.ReportToLog(Resources.UI_UNITYPLUGIN_MENU_CHECK_UPDATES))); break;

            case RequirementsCheckResult.Ok: break;

            default: throw new InvalidOperationException("Unknown Tools check result.");
            }

            if (Settings.Current.Verbose)
            {
                Debug.Log(string.Format("Extracting T4 Templates to '{0}'...", extractionPath));
            }
            var dumpProcess = CharonCli.DumpTemplatesAsync(extractionPath);

            yield return(dumpProcess);

            using (var dumpResult = dumpProcess.GetResult())
            {
                if (string.IsNullOrEmpty(dumpResult.GetErrorData()) == false)
                {
                    Debug.LogWarning(string.Format(Resources.UI_UNITYPLUGIN_T4_EXTRACTION_FAILED, dumpResult.GetErrorData()));
                }
                else
                {
                    Debug.Log(Resources.UI_UNITYPLUGIN_T4_EXTRACTION_COMPLETE + "\r\n" + dumpResult.GetOutputData());
                }
            }
        }
예제 #12
0
        private static IEnumerable LoadEditor(string gameDataPath, string reference, Promise waitTask)
        {
            // un-select gamedata file in Project window
            if (Selection.activeObject != null && AssetDatabase.GetAssetPath(Selection.activeObject) == gameDataPath)
            {
                Selection.activeObject = null;
            }

            if (waitTask != null)
            {
                yield return(waitTask.IgnoreFault());
            }

            var title = Path.GetFileName(gameDataPath);

            if (EditorUtility.DisplayCancelableProgressBar(title, Resources.UI_UNITYPLUGIN_WINDOW_EDITOR_CHECKING_RUNTIME, 0.05f))
            {
                throw new InvalidOperationException("Interrupted by user.");
            }

            var checkRequirements = CharonCli.CheckRequirementsAsync();

            yield return(checkRequirements);

            switch (checkRequirements.GetResult())
            {
            case RequirementsCheckResult.MissingRuntime:
                yield return(UpdateRuntimeWindow.ShowAsync());

                break;

            case RequirementsCheckResult.WrongVersion:
            case RequirementsCheckResult.MissingExecutable:
                yield return(CharonCli.DownloadCharon(ProgressUtils.ShowCancellableProgressBar(Resources.UI_UNITYPLUGIN_MENU_CHECK_UPDATES, 0.05f, 0.50f)));

                break;

            case RequirementsCheckResult.Ok:
                break;

            default:
                throw new InvalidOperationException("Unknown requirements check result.");
            }

            var port = Settings.Current.EditorPort;
            var gameDataEditorUrl = "http://localhost:" + port + "/";
            var lockFilePath      = CharonCli.GetDefaultLockFilePath();

            CharonCli.FindAndEndGracefully(lockFilePath);

            if (Settings.Current.Verbose)
            {
                Debug.Log("Starting gamedata editor at " + gameDataEditorUrl + "...");
            }


            if (EditorUtility.DisplayCancelableProgressBar(title, Resources.UI_UNITYPLUGIN_WINDOW_EDITOR_LAUNCHING_EXECUTABLE, 0.50f))
            {
                throw new InvalidOperationException("Interrupted by user.");
            }
            if (EditorApplication.isCompiling)
            {
                throw new InvalidOperationException("Interrupted by Unity's script compilation. Retry after Unity is finished script compilation.");
            }

            var charonRunTask = CharonCli.Listen(gameDataPath, lockFilePath, port, shadowCopy: true,
                                                 progressCallback: ProgressUtils.ShowCancellableProgressBar(title, 0.50f, 0.60f));

            if (Settings.Current.Verbose)
            {
                Debug.Log("Launching gamedata editor process.");
            }

            // wait untill server process start
            var timeoutPromise       = Promise.Delayed(TimeSpan.FromSeconds(10));
            var startPromise         = (Promise)charonRunTask.IgnoreFault();
            var startCompletePromise = Promise.WhenAny(timeoutPromise, startPromise);
            var cancelPromise        = new Coroutine <bool>(RunCancellableProgress(title, Resources.UI_UNITYPLUGIN_WINDOW_EDITOR_LAUNCHING_EXECUTABLE, 0.65f, 0.80f, TimeSpan.FromSeconds(5), startCompletePromise));

            yield return(Promise.WhenAny(timeoutPromise, startPromise, cancelPromise));

            if (timeoutPromise.IsCompleted)
            {
                EditorUtility.ClearProgressBar();
                Debug.LogWarning(Resources.UI_UNITYPLUGIN_WINDOW_FAILED_TO_START_EDITOR_TIMEOUT);
                yield break;
            }
            else if (cancelPromise.IsCompleted)
            {
                EditorUtility.ClearProgressBar();

                if (EditorApplication.isCompiling)
                {
                    throw new InvalidOperationException("Interrupted by Unity's script compilation. Retry after Unity is finished script compilation.");
                }
                else
                {
                    throw new InvalidOperationException("Interrupted by user.");
                }
            }
            else if (charonRunTask.HasErrors)
            {
                throw new InvalidOperationException("Failed to start editor.", charonRunTask.Error.Unwrap());
            }

            if (EditorUtility.DisplayCancelableProgressBar(title, Resources.UI_UNITYPLUGIN_WINDOW_EDITOR_LAUNCHING_EXECUTABLE, 0.80f))
            {
                throw new InvalidOperationException("Interrupted by user.");
            }
            if (EditorApplication.isCompiling)
            {
                throw new InvalidOperationException("Interrupted by Unity's script compilation. Retry after Unity is finished script compilation.");
            }

            // wait untill server start to respond
            var downloadStream = new MemoryStream();

            timeoutPromise       = Promise.Delayed(TimeSpan.FromSeconds(10));
            startPromise         = HttpUtils.DownloadTo(downloadStream, new Uri(gameDataEditorUrl), timeout: TimeSpan.FromSeconds(1));
            startCompletePromise = new Promise();
            cancelPromise        = new Coroutine <bool>(RunCancellableProgress(title, Resources.UI_UNITYPLUGIN_WINDOW_EDITOR_LAUNCHING_EXECUTABLE, 0.80f, 0.90f, TimeSpan.FromSeconds(5), startCompletePromise));
            while (!timeoutPromise.IsCompleted)
            {
                yield return(startPromise.IgnoreFault());

                if (startPromise.HasErrors == false && downloadStream.Length > 0)
                {
                    break;
                }

                if (EditorUtility.DisplayCancelableProgressBar(title, Resources.UI_UNITYPLUGIN_WINDOW_EDITOR_LAUNCHING_EXECUTABLE, 0.93f))
                {
                    throw new InvalidOperationException("Interrupted by user.");
                }
                if (EditorApplication.isCompiling)
                {
                    throw new InvalidOperationException("Interrupted by Unity's script compilation. Retry after Unity is finished script compilation.");
                }

                downloadStream.SetLength(0);
                startPromise = HttpUtils.DownloadTo(downloadStream, new Uri(gameDataEditorUrl), timeout: TimeSpan.FromSeconds(1));
            }
            if (timeoutPromise.IsCompleted && (!startPromise.IsCompleted || startPromise.HasErrors))
            {
                EditorUtility.ClearProgressBar();
                startCompletePromise.TrySetCompleted();
                Debug.LogWarning(Resources.UI_UNITYPLUGIN_WINDOW_FAILED_TO_START_EDITOR_TIMEOUT);
                yield break;
            }
            startCompletePromise.TrySetCompleted();

            if (EditorUtility.DisplayCancelableProgressBar(title, Resources.UI_UNITYPLUGIN_WINDOW_EDITOR_OPENING_BROWSER, 0.95f))
            {
                throw new InvalidOperationException("Interrupted by user.");
            }
            if (EditorApplication.isCompiling)
            {
                throw new InvalidOperationException("Interrupted by Unity's script compilation. Retry after Unity is finished script compilation.");
            }

            var nearPanels   = typeof(SceneView);
            var editorWindow = GetWindow <GameDataEditorWindow>(nearPanels);

            editorWindow.titleContent = new GUIContent(title);
            var browserType = (BrowserType)Settings.Current.Browser;

            if (browserType == BrowserType.UnityEmbedded && !IsWebViewAvailable)
            {
                browserType = BrowserType.SystemDefault;
            }
            switch (browserType)
            {
            case BrowserType.UnityEmbedded:
                editorWindow.LoadUrl(gameDataEditorUrl + reference);
                editorWindow.SetWebViewVisibility(true);
                editorWindow.Repaint();
                editorWindow.Focus();
                break;

            case BrowserType.Custom:
                if (string.IsNullOrEmpty(Settings.Current.BrowserPath))
                {
                    goto case BrowserType.SystemDefault;
                }
                Process.Start(Settings.Current.BrowserPath, gameDataEditorUrl + reference);
                editorWindow.isOffsiteBrowserLaunched = true;
                break;

            case BrowserType.SystemDefault:
                EditorUtility.OpenWithDefaultApp(gameDataEditorUrl + reference);
                editorWindow.isOffsiteBrowserLaunched = true;
                break;
            }
        }
예제 #13
0
        public UpdateWindow()
        {
            this.titleContent = new GUIContent(Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_TITLE);
            this.minSize      = new Vector2(380, 290);
            this.position     = new Rect(
                (Screen.width - this.minSize.x) / 2,
                (Screen.height - this.minSize.y) / 2,
                this.minSize.x,
                this.minSize.y
                );
            this.padding = new Rect(10, 10, 10, 10);

            this.rows = new[] {
                new ProductRow(UpdateServerCli.PRODUCT_CHARON, Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_CHARON_NAME, disabled: false)
                {
                    CurrentVersion  = CharonCli.GetVersionAsync().IgnoreFault(),
                    AllBuilds       = UpdateServerCli.GetBuilds(UpdateServerCli.PRODUCT_CHARON),
                    Location        = Path.GetFullPath(Settings.CharonPath),
                    ExpectedVersion = string.IsNullOrEmpty(Settings.Current.EditorVersion) ? default(Version) : new Version(Settings.Current.EditorVersion)
                },
                new ProductRow(UpdateServerCli.PRODUCT_CHARON_UNITY, Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_CHARON_UNITY_PLUGIN_NAME, disabled: !IsAssemblyLoaded(UpdateServerCli.PRODUCT_CHARON_UNITY_ASSEMBLY))
                {
                    CurrentVersion = Promise.FromResult(GetAssemblyVersion(UpdateServerCli.PRODUCT_CHARON_UNITY_ASSEMBLY)),
                    AllBuilds      = UpdateServerCli.GetBuilds(UpdateServerCli.PRODUCT_CHARON_UNITY),
                    Location       = GetAssemblyLocation(UpdateServerCli.PRODUCT_CHARON_UNITY_ASSEMBLY)
                },
                new ProductRow(UpdateServerCli.PRODUCT_EXPRESSIONS, Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_EXPRESSIONS_PLUGIN_NAME, disabled: !IsAssemblyLoaded(UpdateServerCli.PRODUCT_EXPRESSIONS_ASSEMBLY))
                {
                    CurrentVersion = Promise.FromResult(GetAssemblyVersion(UpdateServerCli.PRODUCT_EXPRESSIONS_ASSEMBLY)),
                    AllBuilds      = UpdateServerCli.GetBuilds(UpdateServerCli.PRODUCT_EXPRESSIONS),
                    Location       = GetAssemblyLocation(UpdateServerCli.PRODUCT_EXPRESSIONS_ASSEMBLY)
                },
                new ProductRow(UpdateServerCli.PRODUCT_TEXT_TEMPLATES, Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_TEXT_TRANSFORM_PLUGIN_NAME, disabled: !IsAssemblyLoaded(UpdateServerCli.PRODUCT_TEXT_TEMPLATES_ASSEMBLY))
                {
                    CurrentVersion = Promise.FromResult(GetAssemblyVersion(UpdateServerCli.PRODUCT_TEXT_TEMPLATES_ASSEMBLY)),
                    AllBuilds      = UpdateServerCli.GetBuilds(UpdateServerCli.PRODUCT_TEXT_TEMPLATES),
                    Location       = GetAssemblyLocation(UpdateServerCli.PRODUCT_TEXT_TEMPLATES_ASSEMBLY)
                }
            };
            this.columns = new[] {
                new ProductColumn(Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_PRODUCT_COLUMN_NAME, RenderProductCell)
                {
                    Flex = true, Width = 10
                },
                new ProductColumn(Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_CURRENT_VERSION_COLUMN_NAME, RenderCurrentVersionCell)
                {
                    Width = 100
                },
                new ProductColumn(Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_AVAILABLE_VERSION_COLUMN_NAME, RenderSelectedVersionCell)
                {
                    Width = 100
                },
                new ProductColumn(Resources.UI_UNITYPLUGIN_WINDOW_UPDATE_ACTION_COLUMN_NAME, RenderActionCell)
                {
                    Width = 80
                }
            };

            this.UpdateColumnWidths();

            for (var i = 0; i < this.rows.Length; i++)
            {
                var row = this.rows[i];
                if (row.CurrentVersion.IsCompleted == false)
                {
                    row.CurrentVersion.ContinueWith(this.ContinueWithRepaint);
                }
                if (row.AllBuilds.IsCompleted == false)
                {
                    row.AllBuilds.ContinueWith(this.ContinueWithRepaint);
                }

                Promise.WhenAll(row.CurrentVersion, row.AllBuilds)
                .ContinueWith(p => ChooseAction(row))
                .ContinueWith(this.ContinueWithRepaint);
            }
        }
예제 #14
0
        public static IEnumerable ValidateAsync(string path = null, Action <string, float> progressCallback = null)
        {
            var checkRequirements = CharonCli.CheckRequirementsAsync();

            yield return(checkRequirements);

            switch (checkRequirements.GetResult())
            {
            case RequirementsCheckResult.MissingRuntime: yield return(UpdateRuntimeWindow.ShowAsync()); break;

            case RequirementsCheckResult.WrongVersion:
            case RequirementsCheckResult.MissingExecutable: yield return(CharonCli.DownloadCharon(progressCallback)); break;

            case RequirementsCheckResult.Ok: break;

            default: throw new InvalidOperationException("Unknown Tools check result.");
            }

            var reports = new Dictionary <string, object>();
            var paths   = !string.IsNullOrEmpty(path) ? new[] { path } : GameDataTracker.All.ToArray();
            var total   = paths.Length;

            for (var i = 0; i < paths.Length; i++)
            {
                var gameDataPath = paths[i];
                if (File.Exists(gameDataPath) == false)
                {
                    continue;
                }
                if (progressCallback != null)
                {
                    progressCallback(string.Format(Resources.UI_UNITYPLUGIN_PROGRESS_CURRENT_TARGET_IS, gameDataPath), (float)i / total);
                }

                if (Settings.Current.Verbose)
                {
                    Debug.Log(string.Format("Validating GameData at '{0}'...", gameDataPath));
                }
                if (progressCallback != null)
                {
                    progressCallback(string.Format(Resources.UI_UNITYPLUGIN_VALIDATE_RUN_FOR, gameDataPath), (float)i / total);
                }

                var output          = CommandOutput.CaptureJson();
                var validateProcess = CharonCli.ValidateAsync(Path.GetFullPath(gameDataPath), ValidationOptions.None, output);
                yield return(validateProcess);

                using (var validateResult = validateProcess.GetResult())
                {
                    if (Settings.Current.Verbose)
                    {
                        Debug.Log(string.Format("Validation complete, exit code: '{0}'", validateResult.ExitCode));
                    }

                    if (validateResult.ExitCode != 0)
                    {
                        reports.Add(gameDataPath, validateProcess.GetResult().GetErrorData());
                        Debug.LogWarning(string.Format(Resources.UI_UNITYPLUGIN_VALIDATE_FAILED_DUE_ERRORS, gameDataPath, validateResult.GetErrorData()));
                    }
                    else
                    {
                        try
                        {
                            var report = output.ReadJsonAs <JsonObject>();
                            reports.Add(gameDataPath, report);
                            var success     = (bool)report["success"];
                            var totalErrors = 0;
                            if (!success)
                            {
                                var items = (JsonArray)report["items"];
                                System.Diagnostics.Debug.Assert(items != null, "items != null");
                                foreach (var record in items.Cast <JsonObject>())
                                {
                                    var errors = record.ContainsKey("errors") ? ((JsonArray)record["errors"]) : null;
                                    if (errors != null)
                                    {
                                        foreach (var error in errors.Cast <JsonObject>())
                                        {
                                            var id = record["id"] is JsonPrimitive?Convert.ToString(((JsonPrimitive)record["id"]).Value) : record["id"].Stringify();

                                            var entityName = (string)record["entityName"];
                                            var msg        = (string)error["msg"];
                                            var errorPath  = (string)error["path"];

                                            var validationException = new ValidationException(gameDataPath, id, entityName, errorPath, msg);

                                            var log = (Action <Exception>)Debug.LogException;
                                            log.BeginInvoke(validationException, null, null);
                                        }
                                        totalErrors += errors.Count;
                                    }
                                }
                            }

                            Debug.Log(string.Format(Resources.UI_UNITYPLUGIN_VALIDATE_COMPLETE, gameDataPath, success ? "success" : "failure", totalErrors));
                        }
                        catch (Exception e)
                        {
                            Debug.LogWarning(string.Format(Resources.UI_UNITYPLUGIN_VALIDATE_FAILED_DUE_ERRORS, gameDataPath, e));
                            reports[gameDataPath] = e.Unwrap().ToString();
                        }
                    }
                }
            }
            if (progressCallback != null)
            {
                progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1);
            }
            yield return(reports);
        }
예제 #15
0
        public static IEnumerable GenerateCodeAndAssetsAsync(string path = null, Action <string, float> progressCallback = null)
        {
            var checkRequirements = CharonCli.CheckRequirementsAsync();

            yield return(checkRequirements);

            switch (checkRequirements.GetResult())
            {
            case RequirementsCheckResult.MissingRuntime: yield return(UpdateRuntimeWindow.ShowAsync()); break;

            case RequirementsCheckResult.WrongVersion:
            case RequirementsCheckResult.MissingExecutable: yield return(CharonCli.DownloadCharon(progressCallback)); break;

            case RequirementsCheckResult.Ok: break;

            default: throw new InvalidOperationException("Unknown Tools check result.");
            }

            var paths             = !string.IsNullOrEmpty(path) ? new[] { path } : GameDataTracker.All.ToArray();
            var total             = paths.Length;
            var forceReImportList = new List <string>();

            for (var i = 0; i < paths.Length; i++)
            {
                var gameDataPath = paths[i];
                if (File.Exists(gameDataPath) == false)
                {
                    continue;
                }
                if (progressCallback != null)
                {
                    progressCallback(string.Format(Resources.UI_UNITYPLUGIN_PROGRESS_CURRENT_TARGET_IS, gameDataPath), (float)i / total);
                }

                var gameDataObj = AssetDatabase.LoadAssetAtPath(gameDataPath, typeof(UnityEngine.Object));
                var assetImport = AssetImporter.GetAtPath(gameDataPath);
                if (assetImport == null)
                {
                    continue;
                }

                var gameDataSettings   = GameDataSettings.Load(gameDataObj);
                var codeGenerationPath = FileAndPathUtils.MakeProjectRelative(gameDataSettings.CodeGenerationPath);
                if (gameDataSettings.Generator == (int)GameDataSettings.CodeGenerator.None)
                {
                    continue;
                }

                var generationOptions = gameDataSettings.Options;
                if (Array.IndexOf(Settings.SupportedExtensions, Settings.EXTENSION_FORMULAS) == -1)                 // no expression library installed
                {
                    generationOptions |= (int)CodeGenerationOptions.DisableFormulas;
                }

                // trying to touch gamedata file
                var touchGamedata = new Coroutine <FileStream>(TouchGameDataFile(gameDataPath));
                yield return(touchGamedata);

                if (touchGamedata.GetResult().Length == 0)
                {
                    continue;
                }
                touchGamedata.GetResult().Dispose();                 // release touched file

                var generator = (GameDataSettings.CodeGenerator)gameDataSettings.Generator;
                switch (generator)
                {
                case GameDataSettings.CodeGenerator.CSharpCodeAndAsset:
                    if (!string.IsNullOrEmpty(gameDataSettings.AssetGenerationPath))
                    {
                        AssetGenerator.AddPath(gameDataPath);
                        generationOptions &= ~(int)(CodeGenerationOptions.DisableJsonSerialization |
                                                    CodeGenerationOptions.DisableBsonSerialization |
                                                    CodeGenerationOptions.DisableMessagePackSerialization |
                                                    CodeGenerationOptions.DisableXmlSerialization
                                                    );
                    }
                    goto generateCSharpCode;

                case GameDataSettings.CodeGenerator.CSharp:
generateCSharpCode:
                    if (Settings.Current.Verbose)
                    {
                        Debug.Log(string.Format("Generating C# code for '{0}'...", gameDataPath));
                    }
                    if (progressCallback != null)
                    {
                        progressCallback(string.Format(Resources.UI_UNITYPLUGIN_GENERATE_CODE_FOR, gameDataPath), (float)i / total);
                    }

                    var generateProcess = generator == GameDataSettings.CodeGenerator.CSharp
                                                        ? CharonCli.GenerateCSharpCodeAsync
                                          (
                        gameDataPath,
                        Path.GetFullPath(codeGenerationPath),
                        (CodeGenerationOptions)generationOptions,
                        gameDataSettings.DocumentClassName,
                        gameDataSettings.GameDataClassName,
                        gameDataSettings.Namespace
                                          )
                                                        : CharonCli.GenerateUnityCSharpCodeAsync
                                          (
                        gameDataPath,
                        Path.GetFullPath(codeGenerationPath),
                        (CodeGenerationOptions)generationOptions,
                        gameDataSettings.DocumentClassName,
                        gameDataSettings.GameDataClassName,
                        gameDataSettings.Namespace
                                          );
                    yield return(generateProcess);

                    if (Settings.Current.Verbose)
                    {
                        Debug.Log(string.Format("Generation complete, exit code: '{0}'", generateProcess.GetResult().ExitCode));
                    }
                    using (var generateResult = generateProcess.GetResult())
                    {
                        if (generateResult.ExitCode != 0)
                        {
                            Debug.LogWarning(string.Format(Resources.UI_UNITYPLUGIN_GENERATE_FAILED_DUE_ERRORS, gameDataPath, generateResult.GetErrorData()));
                        }
                        else
                        {
                            if (Settings.Current.Verbose)
                            {
                                Debug.Log(string.Format("Code generation for '{0}' is complete.", gameDataPath));
                            }

                            forceReImportList.Add(codeGenerationPath);

                            if (gameDataSettings.LineEnding != 0 ||
                                gameDataSettings.Indentation != 0)
                            {
                                if (progressCallback != null)
                                {
                                    progressCallback(string.Format(Resources.UI_UNITYPLUGIN_GENERATE_REFORMAT_CODE, gameDataPath), (float)i / total);
                                }

                                var code = new StringBuilder(File.ReadAllText(codeGenerationPath));
                                switch ((GameDataSettings.LineEndings)gameDataSettings.LineEnding)
                                {
                                case GameDataSettings.LineEndings.Windows:
                                    // already windows
                                    break;

                                case GameDataSettings.LineEndings.Unix:
                                    code.Replace("\r\n", "\n");
                                    break;

                                default:
                                    throw new InvalidOperationException(string.Format("Unknown LineEnding value '{0}' is set for {1}", gameDataSettings.LineEnding, gameDataPath));
                                }
                                switch ((GameDataSettings.Indentations)gameDataSettings.Indentation)
                                {
                                case GameDataSettings.Indentations.Tab:
                                    // already tabs
                                    break;

                                case GameDataSettings.Indentations.FourSpaces:
                                    code.Replace("\t", "    ");
                                    break;

                                case GameDataSettings.Indentations.TwoSpaces:
                                    code.Replace("\t", "  ");
                                    break;

                                default:
                                    throw new InvalidOperationException(string.Format("Unknown indentation value '{0}' is set for {1}", gameDataSettings.Indentation, gameDataPath));
                                }
                                File.WriteAllText(codeGenerationPath, code.ToString());
                            }
                        }
                    }
                    break;

                default:
                    Debug.LogError("Unknown code/asset generator type " + (GameDataSettings.CodeGenerator)gameDataSettings.Generator + ".");
                    break;
                }
            }
            if (progressCallback != null)
            {
                progressCallback(Resources.UI_UNITYPLUGIN_GENERATE_REFRESHING_ASSETS, 0.99f);
            }
            foreach (var forceReImportPath in forceReImportList)
            {
                AssetDatabase.ImportAsset(forceReImportPath, ImportAssetOptions.ForceUpdate);
            }
            if (progressCallback != null)
            {
                progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1);
            }
        }
        private IEnumerable CompleteAsync()
        {
            GameDataEditorWindow.FindAllAndClose();

            this.versionDirectory.Refresh();
            if (this.versionDirectory.Exists == false)
            {
                Debug.LogError(string.Format("Unable to complete deployment because directory '{0}' with '{1}' product doesn't exists.", this.versionDirectory.Name, ProductInformation.PRODUCT_CHARON));
                yield break;
            }

            var extensionsToClean = new[] { ".exe", ".dll", ".config", ".xml", ".pdb", ".mdb", ".sha1" };

            foreach (var fileToClean in this.baseDirectory.GetFiles().Where(file => extensionsToClean.Contains(file.Extension, StringComparer.OrdinalIgnoreCase)))
            {
                try
                {
                    if (Settings.Current.Verbose)
                    {
                        Debug.Log(string.Format("Removing old file '{0}' of '{1}' product.", fileToClean.FullName, ProductInformation.PRODUCT_CHARON));
                    }

                    fileToClean.Delete();
                }
                catch (Exception error)
                {
                    Debug.LogWarning(error);
                }
            }

            this.versionDirectory.Refresh();
            foreach (var file in this.versionDirectory.GetFiles())
            {
                if (Settings.Current.Verbose)
                {
                    Debug.Log(string.Format("Copying target file '{0}' for product '{1}'.", file, ProductInformation.PRODUCT_CHARON));
                }

                try
                {
                    file.CopyTo(Path.Combine(Settings.ToolBasePath, file.Name), overwrite: true);
                }
                catch (Exception error)
                {
                    Debug.LogWarning(error);
                }
            }

            // ensure config file
            var charonConfigPath = new FileInfo(Settings.CharonExecutablePath + ".config");

            if (charonConfigPath.Exists)
            {
                try
                {
                    charonConfigPath.Delete();
                }
                catch (Exception error)
                {
                    Debug.LogWarning(error);
                }
            }
            var embeddedConfigStream = typeof(Menu).Assembly.GetManifestResourceStream("GameDevWare.Charon.Unity.Charon.exe.config");

            if (embeddedConfigStream != null)
            {
                using (embeddedConfigStream)
                    using (var configFileStream = charonConfigPath.Create())
                    {
                        var buffer = new byte[8 * 1024];
                        var read   = 0;
                        while ((read = embeddedConfigStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            configFileStream.Write(buffer, 0, read);
                        }
                    }
            }

            var currentVersion = default(SemanticVersion);

            if (File.Exists(Settings.CharonExecutablePath))
            {
                if (this.progressCallback != null)
                {
                    this.progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_CHECKING_TOOLS_VERSION, 0.95f);
                }

                var checkToolsVersion = CharonCli.GetVersionAsync();
                yield return(checkToolsVersion.IgnoreFault());

                currentVersion = checkToolsVersion.HasErrors ? default(SemanticVersion) : checkToolsVersion.GetResult();
            }

            Settings.Current.EditorVersion = currentVersion != null?currentVersion.ToString() : null;

            Settings.Current.Save();
        }