public static GameDataSettings CreateDefault(string gameDataPath) { if (gameDataPath == null) { throw new ArgumentNullException("gameDataPath"); } var settings = new GameDataSettings(); settings.Generator = (int)CodeGenerator.CSharp; settings.AutoGeneration = true; settings.LineEnding = (int)LineEndings.Windows; settings.Indentation = (int)Indentations.Tab; settings.AssetGenerationPath = Path.ChangeExtension(gameDataPath, ".asset"); settings.CodeGenerationPath = Path.ChangeExtension(gameDataPath, ".cs"); settings.GameDataClassName = Path.GetFileNameWithoutExtension(gameDataPath); settings.Namespace = (Path.GetDirectoryName(gameDataPath) ?? "").Replace("\\", ".").Replace("/", "."); settings.DocumentClassName = "Document"; settings.Options = (int)(CodeGenerationOptions.HideLocalizedStrings | CodeGenerationOptions.HideReferences | CodeGenerationOptions.SuppressDataContractAttributes); return(settings); }
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) { if (Settings.Current.Verbose) { Debug.LogWarning(string.Format("Code generation was skipped for an empty file '{0}'.", gameDataPath)); } 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 ); var assetCodeGenerationPath = Path.Combine(Path.GetDirectoryName(gameDataSettings.CodeGenerationPath) ?? "", gameDataSettings.GameDataClassName + "Asset.cs"); var assetCodeGenerator = new AssetLoaderGenerator(); assetCodeGenerator.AssetClassName = gameDataSettings.GameDataClassName + "Asset"; assetCodeGenerator.GameDataClassName = gameDataSettings.Namespace + "." + gameDataSettings.GameDataClassName; assetCodeGenerator.Namespace = gameDataSettings.Namespace; var assetCode = assetCodeGenerator.TransformText(); File.WriteAllText(assetCodeGenerationPath, assetCode); forceReImportList.Add(assetCodeGenerationPath); } 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 = CharonCli.GenerateCSharpCodeAsync ( 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); } }
public static IEnumerable GenerateAssetsAsync(string[] paths, Action <string, float> progressCallback = null) { 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); } var gameDataObj = AssetDatabase.LoadAssetAtPath(gameDataPath, typeof(UnityEngine.Object)); var assetImport = AssetImporter.GetAtPath(gameDataPath); if (assetImport == null) { continue; } var gameDataSettings = GameDataSettings.Load(gameDataObj); var assetGenerationPath = FileAndPathUtils.MakeProjectRelative(gameDataSettings.AssetGenerationPath); if (string.IsNullOrEmpty(assetGenerationPath)) { continue; } // trying to touch gamedata file var touchGamedata = new Coroutine <FileStream>(TouchGameDataFile(gameDataPath)); yield return(touchGamedata); if (touchGamedata.GetResult().Length == 0) { continue; } using (var file = touchGamedata.GetResult()) { var gameDataBytes = new byte[file.Length]; int read, offset = 0; while ((read = file.Read(gameDataBytes, offset, gameDataBytes.Length - offset)) > 0) { offset += read; } var gameDataAssetType = Type.GetType(gameDataSettings.Namespace + "." + gameDataSettings.GameDataClassName + "Asset, Assembly-CSharp", throwOnError: false) ?? Type.GetType(gameDataSettings.Namespace + "." + gameDataSettings.GameDataClassName + "Asset, Assembly-CSharp-firstpass", throwOnError: false) ?? Type.GetType(gameDataSettings.Namespace + "." + gameDataSettings.GameDataClassName + "Asset, Assembly-CSharp-Editor", throwOnError: false); if (gameDataAssetType == null) { Debug.LogError(Resources.UI_UNITYPLUGIN_GENERATE_ASSET_CANT_FIND_GAMEDATA_CLASS); continue; } var assetDirectory = Path.GetDirectoryName(assetGenerationPath); if (assetDirectory != null && !Directory.Exists(assetDirectory)) { Directory.CreateDirectory(assetDirectory); } var gameDataAsset = ScriptableObject.CreateInstance(gameDataAssetType); gameDataAsset.SetFieldValue("dataBytes", gameDataBytes); gameDataAsset.SetFieldValue("extension", Path.GetExtension(gameDataPath)); AssetDatabase.CreateAsset(gameDataAsset, assetGenerationPath); AssetDatabase.SaveAssets(); } } if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_GENERATE_REFRESHING_ASSETS, 0.99f); } AssetDatabase.Refresh(ImportAssetOptions.Default); if (progressCallback != null) { progressCallback(Resources.UI_UNITYPLUGIN_PROGRESS_DONE, 1); } }
private static void Update() { if (Settings.Current == null) { return; } if (LastWatchedGameDataTrackerVersion != GameDataTracker.Version) { var gameDataPaths = new HashSet <string>(GameDataTracker.All); foreach (var gameDataPath in gameDataPaths) { if (Watchers.ContainsKey(gameDataPath) || File.Exists(gameDataPath) == false) { continue; } try { var fullPath = Path.GetFullPath(gameDataPath); var directoryName = Path.GetDirectoryName(fullPath); var watcher = new FileSystemWatcher(directoryName) { NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size }; watcher.Filter = Path.GetFileName(fullPath); watcher.Changed += GameDataChanged; Watchers.Add(gameDataPath, watcher); try { GameDataHashByPath[gameDataPath] = FileAndPathUtils.ComputeHash(gameDataPath); } catch { // ignored } watcher.EnableRaisingEvents = true; } catch (Exception e) { Debug.LogError("Failed to create FileSystemWatcher for GameData " + gameDataPath + ": " + e); } } foreach (var gameDataPath in Watchers.Keys.ToArray()) { if (gameDataPaths.Contains(gameDataPath)) { continue; } var watcher = Watchers[gameDataPath]; Watchers.Remove(gameDataPath); try { watcher.Dispose(); } catch (Exception e) { Debug.LogError("Failed to dispose FileSystemWatcher of GameData: " + e); } } LastWatchedGameDataTrackerVersion = GameDataTracker.Version; } var changedAssetsCopy = default(string[]); lock (ChangedAssetPaths) { if (ChangedAssetPaths.Count > 0) { changedAssetsCopy = ChangedAssetPaths.ToArray(); ChangedAssetPaths.Clear(); } } if (changedAssetsCopy != null) { foreach (var changedAsset in changedAssetsCopy) { if (Settings.Current.Verbose) { Debug.Log("Changed Asset: " + changedAsset); } if (!File.Exists(changedAsset) || GameDataTracker.IsTracked(changedAsset) == false) { continue; } var gameDataSettings = GameDataSettings.Load(changedAsset); if (!gameDataSettings.AutoGeneration) { continue; } var assetHash = default(string); try { assetHash = FileAndPathUtils.ComputeHash(changedAsset); } catch (Exception e) { Debug.LogWarning("Failed to compute hash of " + changedAsset + ": " + e); continue; } var oldAssetHash = default(string); if (GameDataHashByPath.TryGetValue(changedAsset, out oldAssetHash) && assetHash == oldAssetHash) { continue; // not changed } if (EditorApplication.isUpdating) { continue; } if (Settings.Current.Verbose) { Debug.Log("Asset's " + changedAsset + " hash has changed from " + (oldAssetHash ?? "<none>") + " to " + assetHash); } GameDataHashByPath[changedAsset] = assetHash; CoroutineScheduler.Schedule ( Menu.GenerateCodeAndAssetsAsync( path: changedAsset, progressCallback: ProgressUtils.ReportToLog("Generation(Auto): ")), "generation::" + changedAsset ); } } }