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()); } } }
private static IEnumerable DownloadCharonAsync(Action <string, float> progressCallback = null) { var checkRequirements = CharonCli.CheckRequirementsAsync(); yield return(checkRequirements); var checkResult = checkRequirements.GetResult(); if (checkResult == RequirementsCheckResult.MissingRuntime) { yield return(UpdateRuntimeWindow.ShowAsync()); } var currentVersion = default(Version); var charonPath = Path.GetFullPath(Settings.CharonPath); var toolName = Path.GetFileNameWithoutExtension(Path.GetFileName(charonPath)); if (File.Exists(charonPath)) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_CHECKING_TOOLS_VERSION, 0.05f); } var checkToolsVersion = CharonCli.GetVersionAsync(); yield return(checkToolsVersion.IgnoreFault()); currentVersion = checkToolsVersion.HasErrors ? default(Version) : checkToolsVersion.GetResult(); } if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_GETTING_AVAILABLE_BUILDS, 0.10f); } var getBuildsAsync = UpdateServerCli.GetBuilds(UpdateServerCli.PRODUCT_CHARON); yield return(getBuildsAsync.IgnoreFault()); if (getBuildsAsync.HasErrors) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } Debug.LogError(string.Format("Failed to get builds list from server. Error: {0}", getBuildsAsync.Error.Unwrap().Message)); yield break; } var builds = getBuildsAsync.GetResult(); var buildsByVersion = builds.ToDictionary(b => b.Version); var lastBuild = builds.OrderByDescending(b => b.Version).FirstOrDefault(); if (lastBuild == null) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } if (Settings.Current.Verbose) { Debug.Log(string.Format("No builds of {0} are available.", toolName)); } yield break; } var currentBuild = currentVersion != null?builds.FirstOrDefault(b => b.Version == currentVersion) : null; var lastVersion = lastBuild.Version; var isMissing = File.Exists(charonPath); var actualHash = isMissing || currentBuild == null ? null : FileAndPathUtils.ComputeHash(charonPath, currentBuild.HashAlgorithm); var isCorrupted = currentBuild != null && string.Equals(currentBuild.Hash, actualHash, StringComparison.OrdinalIgnoreCase) == false; var expectedVersion = string.IsNullOrEmpty(Settings.Current.EditorVersion) ? default(Version) : new Version(Settings.Current.EditorVersion); if (!isMissing && !isCorrupted && expectedVersion == currentVersion && currentVersion != null) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } if (Settings.Current.Verbose) { Debug.Log(string.Format("{0} version '{1}' is expected and file is not corrupted.", toolName, currentVersion)); } yield break; } var versionToDownload = expectedVersion ?? lastVersion; if (buildsByVersion.ContainsKey(versionToDownload) == false) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } Debug.LogError(string.Format("Build of {0} with version '{1}' is not available to download.", toolName, versionToDownload)); yield break; } if (progressCallback != null) { progressCallback(string.Format(Resources.UI_UNITYPLUGIN_PROGRESS_DOWNLOADINGS, 0, 0), 0.10f); } var downloadPath = Path.GetTempFileName(); var downloadAsync = UpdateServerCli.DownloadBuild(UpdateServerCli.PRODUCT_CHARON, versionToDownload, downloadPath, progressCallback); yield return(downloadAsync.IgnoreFault()); if (downloadAsync.HasErrors) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } Debug.LogError(string.Format("Failed to download build of {0} with version '{1}'.{2}{3}", toolName, versionToDownload, Environment.NewLine, downloadAsync.Error.Unwrap())); yield break; } GameDataEditorWindow.FindAllAndClose(); try { if (File.Exists(charonPath)) { File.Delete(charonPath); } if (Directory.Exists(charonPath)) { Directory.Delete(charonPath); } var toolsDirectory = Path.GetDirectoryName(charonPath) ?? ""; if (Directory.Exists(toolsDirectory) == false) { Directory.CreateDirectory(toolsDirectory); } File.Move(downloadPath, charonPath); // 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); } } } } } catch (Exception moveError) { Debug.LogWarning(string.Format("Failed to move downloaded file from '{0}' to {1}. {2}.", downloadPath, charonPath, moveError.Message)); Debug.LogError(moveError); } finally { try { if (File.Exists(downloadPath)) { File.Delete(downloadPath); } } catch { /* ignore */ } } 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(); Debug.Log(string.Format("{1} version is '{0}'. Download is complete.", currentVersion, Path.GetFileName(charonPath))); if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } }
private static IEnumerable DownloadCharonAsync(Action <string, float> progressCallback = null) { var checkRequirements = CharonCli.CheckRequirementsAsync(); yield return(checkRequirements); var checkResult = checkRequirements.GetResult(); if (checkResult == RequirementsCheckResult.MissingRuntime) { yield return(UpdateRuntimeWindow.ShowAsync()); } var currentVersion = default(SemanticVersion); var charonPath = Path.GetFullPath(Settings.CharonExecutablePath); var toolName = Path.GetFileNameWithoutExtension(Path.GetFileName(charonPath)); if (File.Exists(charonPath)) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_CHECKING_TOOLS_VERSION, 0.05f); } var checkToolsVersion = CharonCli.GetVersionAsync(); yield return(checkToolsVersion.IgnoreFault()); currentVersion = checkToolsVersion.HasErrors ? default(SemanticVersion) : checkToolsVersion.GetResult(); } if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_GETTING_AVAILABLE_BUILDS, 0.10f); } var getBuildsAsync = PackageManager.GetVersions(ProductInformation.PRODUCT_CHARON); yield return(getBuildsAsync.IgnoreFault()); if (getBuildsAsync.HasErrors) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } Debug.LogError(string.Format("Failed to get builds list from server. Error: {0}", getBuildsAsync.Error.Unwrap().Message)); yield break; } var builds = getBuildsAsync.GetResult(); var buildsByVersion = builds.ToDictionary(b => b.Version); var lastBuild = builds.OrderByDescending(b => b.Version).FirstOrDefault(); if (lastBuild == null) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } if (Settings.Current.Verbose) { Debug.Log(string.Format("No builds of {0} are available.", toolName)); } yield break; } var currentBuild = currentVersion != null?builds.FirstOrDefault(b => b.Version == currentVersion) : null; var lastVersion = lastBuild.Version; var isMissing = File.Exists(charonPath); var hashFileName = currentBuild == null ? null : Path.Combine(Path.Combine(Settings.ToolBasePath, currentVersion.ToString()), Path.GetFileName(charonPath) + ".sha1"); var actualHash = isMissing || currentBuild == null ? null : FileAndPathUtils.ComputeHash(charonPath, "SHA1"); var expectedHash = isMissing || hashFileName == null || File.Exists(hashFileName) == false ? null : File.ReadAllText(hashFileName); var isCorrupted = currentBuild != null && string.Equals(expectedHash, actualHash, StringComparison.OrdinalIgnoreCase) == false; var expectedVersion = string.IsNullOrEmpty(Settings.Current.EditorVersion) ? default(SemanticVersion) : new SemanticVersion(Settings.Current.EditorVersion); if (!isMissing && !isCorrupted && expectedVersion == currentVersion && currentVersion != null) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } if (Settings.Current.Verbose) { Debug.Log(string.Format("{0} version '{1}' is expected and file hash is matching.", toolName, currentVersion)); } yield break; } var versionToDeploy = expectedVersion ?? lastVersion; if (buildsByVersion.ContainsKey(versionToDeploy) == false) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } Debug.LogError(string.Format("Package of {0} with version '{1}' is not available to download.", toolName, versionToDeploy)); yield break; } if (progressCallback != null) { progressCallback(string.Format(Resources.UI_UNITYPLUGIN_PROGRESS_DOWNLOADING, 0, 0, ProductInformation.PRODUCT_CHARON), 0.10f); } var deployAction = new CharonDeploymentAction(versionToDeploy, progressCallback); var prepareAsync = deployAction.Prepare(); yield return(prepareAsync.IgnoreFault()); if (prepareAsync.HasErrors) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } Debug.LogError(string.Format("Failed to download package of {0} with version '{1}'.{2}{3}", toolName, versionToDeploy, Environment.NewLine, prepareAsync.Error.Unwrap())); deployAction.Complete(); yield break; } var deployAsync = deployAction.Complete(); yield return(deployAsync.IgnoreFault()); if (deployAsync.HasErrors) { if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } Debug.LogError(string.Format("Failed to deploy package of {0} with version '{1}'.{2}{3}", toolName, versionToDeploy, Environment.NewLine, deployAsync.Error.Unwrap())); deployAction.Complete(); yield break; } // cleanup resources deployAction.Complete(); 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(SemanticVersion) : checkToolsVersion.GetResult(); } Settings.Current.EditorVersion = currentVersion != null?currentVersion.ToString() : null; Settings.Current.Save(); Debug.Log(string.Format("{1} version is '{0}'. Update is completed.", currentVersion, Path.GetFileName(charonPath))); if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1.0f); } }
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); }
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 static void CheckRuntime() { UpdateRuntimeWindow.ShowAsync(autoClose: false); }