private static void CreateGameData(string extension) { if (extension == null) { throw new ArgumentNullException("extension"); } var location = Path.GetFullPath(AssetDatabase.GetAssetPath(Selection.activeObject)); if (File.Exists(location)) { location = Path.GetDirectoryName(location); } if (string.IsNullOrEmpty(location) || Directory.Exists(location) == false) { Debug.LogWarning("Unable to create GameData file because 'Selection.activeObject' is null or wrong asset. Select Folder in Project window and try again."); return; } var i = 1; var gameDataPath = Path.Combine(location, "GameData." + extension); while (File.Exists(gameDataPath)) { gameDataPath = Path.Combine(location, "GameData" + (i++) + "." + extension); } gameDataPath = FileAndPathUtils.MakeProjectRelative(gameDataPath); File.WriteAllText(gameDataPath, ""); AssetDatabase.Refresh(); }
public static void OnSelectionChanged() { if (Selection.activeObject == null) { return; } var assetPath = FileAndPathUtils.MakeProjectRelative(AssetDatabase.GetAssetPath(Selection.activeObject)); if (GameDataTracker.IsGameDataFile(assetPath) == false) { return; } try { var selectedAssetType = Selection.activeObject.GetType(); var inspectorWindowType = typeof(PopupWindow).Assembly.GetType("UnityEditor.InspectorWindow"); var inspectorWindow = EditorWindow.GetWindow(inspectorWindowType); var activeEditorTracker = inspectorWindow.HasProperty("tracker") ? inspectorWindow.GetPropertyValue("tracker") : inspectorWindow.GetFieldValue("m_Tracker"); var customEditorAttributesType = typeof(PopupWindow).Assembly.GetType("UnityEditor.CustomEditorAttributes"); var customEditorsList = (System.Collections.IList)customEditorAttributesType.GetFieldValue("kSCustomEditors"); var cachedCustomEditorsList = customEditorAttributesType.HasField("kCachedEditorForType") ? (Dictionary <Type, Type>)customEditorAttributesType.GetFieldValue("kCachedEditorForType") : null; foreach (var customEditor in customEditorsList) { if (customEditor == null || (Type)customEditor.GetFieldValue("m_InspectedType") != selectedAssetType) { continue; } var originalInspectorType = (Type)customEditor.GetFieldValue("m_InspectorType"); // override inspector customEditor.SetFieldValue("m_InspectorType", typeof(GameDataInspector)); if (cachedCustomEditorsList != null) { cachedCustomEditorsList[selectedAssetType] = typeof(GameDataInspector); } // force rebuild editor list activeEditorTracker.Invoke("ForceRebuild"); inspectorWindow.Repaint(); // restore original inspector customEditor.SetFieldValue("m_InspectorType", originalInspectorType); if (cachedCustomEditorsList != null) { cachedCustomEditorsList.Remove(selectedAssetType); } } } catch (Exception updateEditorError) { if (Settings.Current.Verbose) { Debug.LogError(updateEditorError); } } }
private static FileInfo DeployAtPath(FileInfo file, DirectoryInfo destinationDirectory) { if (destinationDirectory == null) { throw new ArgumentNullException("destinationDirectory"); } if (file == null) { throw new ArgumentNullException("file"); } destinationDirectory.Refresh(); var targetPath = Path.Combine(destinationDirectory.FullName, file.Name); if (Settings.Current.Verbose) { Debug.Log(string.Format("Copying '{0}' file to '{1}' directory.", file.Name, destinationDirectory.FullName)); } file.CopyTo(targetPath, overwrite: true); if (string.Equals(file.Extension, ".exe", StringComparison.OrdinalIgnoreCase) || string.Equals(file.Extension, ".dll", StringComparison.OrdinalIgnoreCase)) { if (Settings.Current.Verbose) { Debug.Log(string.Format("Computing SHA1 hash for '{0}' file in '{1}' directory.", file.Name, destinationDirectory.FullName)); } var targetPathHash = targetPath + ".sha1"; File.WriteAllText(targetPathHash, FileAndPathUtils.ComputeHash(targetPath, "SHA1")); } return(new FileInfo(targetPath)); }
private static void GameDataChanged(object sender, FileSystemEventArgs e) { var path = FileAndPathUtils.MakeProjectRelative(e.FullPath); lock (ChangedAssetPaths) ChangedAssetPaths.Add(path); }
// ReSharper disable once UnusedMember.Local // ReSharper disable once IdentifierTypo private static void OnPostprocessAllAssets(string[] _, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { if (Settings.Current == null) { return; } foreach (var deletedPath in deletedAssets) { if (!GameDataTracker.Untrack(deletedPath)) { continue; } if (Settings.Current.Verbose) { Debug.Log("GameData deleted: " + deletedPath); } GameDataHashByPath.Remove(deletedPath); } for (var i = 0; i < movedAssets.Length; i++) { var fromPath = FileAndPathUtils.MakeProjectRelative(movedFromAssetPaths[i]); var toPath = FileAndPathUtils.MakeProjectRelative(movedAssets[i]); if (fromPath == null || toPath == null) { continue; } if (!GameDataTracker.IsTracked(fromPath)) { continue; } GameDataTracker.Untrack(fromPath); GameDataTracker.Track(toPath); if (Settings.Current.Verbose) { Debug.Log("GameData moved: " + toPath + " from: " + fromPath); } GameDataHashByPath.Remove(fromPath); GameDataHashByPath.Remove(toPath); } }
private static bool IsUpdateSkipped(string releaseNotes) { try { var skippedUpdateHash = EditorPrefs.GetString(SKIPPED_UPDATE_PREFS_KEY); if (string.IsNullOrEmpty(skippedUpdateHash) || string.IsNullOrEmpty(releaseNotes)) { return(false); } return(string.Equals(skippedUpdateHash, FileAndPathUtils.ComputeNameHash(releaseNotes, "SHA1"))); } catch { return(false); } }
private static FileInfo DeployAtPath(FileInfo file, string destinationDirectory) { if (destinationDirectory == null) { throw new ArgumentNullException("destinationDirectory"); } if (file == null) { throw new ArgumentNullException("file"); } var targetPath = Path.Combine(destinationDirectory, file.Name); file.CopyTo(targetPath, overwrite: true); if (string.Equals(file.Extension, ".exe", StringComparison.OrdinalIgnoreCase) || string.Equals(file.Extension, ".dll", StringComparison.OrdinalIgnoreCase)) { var targetPathHash = targetPath + ".sha1"; File.WriteAllText(targetPathHash, FileAndPathUtils.ComputeHash(targetPath, "SHA1")); } return(new FileInfo(targetPath)); }
public static GameDataSettings Load(string gameDataPath) { if (gameDataPath == null) { throw new NullReferenceException("gameDataPath"); } var gameDataSettings = default(GameDataSettings); try { var gameDataSettingsJson = AssetImporter.GetAtPath(gameDataPath).userData; if (string.IsNullOrEmpty(gameDataSettingsJson) == false) { gameDataSettings = JsonValue.Parse(gameDataSettingsJson).As <GameDataSettings>(); } if (gameDataSettings != null) { gameDataSettings.CodeGenerationPath = FileAndPathUtils.MakeProjectRelative(gameDataSettings.CodeGenerationPath); gameDataSettings.AssetGenerationPath = FileAndPathUtils.MakeProjectRelative(gameDataSettings.AssetGenerationPath); if (string.IsNullOrEmpty(gameDataSettings.CodeGenerationPath)) { gameDataSettings.CodeGenerationPath = Path.ChangeExtension(gameDataPath, "cs"); } gameDataSettings.Validate(); } } catch (Exception e) { Debug.LogError("Failed to deserialize gamedata's settings: " + e); } if (gameDataSettings == null) { gameDataSettings = CreateDefault(gameDataPath); } return(gameDataSettings); }
protected static bool HasValidExecutableFiles(DirectoryInfo directoryInfo) { if (directoryInfo == null) { throw new ArgumentNullException("directoryInfo"); } var checkedFiles = 0; foreach (var file in directoryInfo.GetFiles()) { if (string.Equals(file.Extension, ".exe", StringComparison.OrdinalIgnoreCase) == false && string.Equals(file.Extension, ".dll", StringComparison.OrdinalIgnoreCase) == false) { continue; } var hashFilePath = new FileInfo(file.FullName + ".sha1"); if (hashFilePath.Exists == false) { return(false); // no hash file } var expectedHashValue = File.ReadAllText(hashFilePath.FullName).Trim(); var actualHashValue = FileAndPathUtils.ComputeHash(file.FullName, "SHA1"); if (string.Equals(expectedHashValue, actualHashValue, StringComparison.OrdinalIgnoreCase) == false) { return(false); // hash mismatch } checkedFiles++; } return(checkedFiles > 0); }
public override void OnInspectorGUI() { var gameDataAsset = (Object)this.target; var gameDataPath = FileAndPathUtils.MakeProjectRelative(AssetDatabase.GetAssetPath(gameDataAsset)); var assetPath = FileAndPathUtils.MakeProjectRelative(AssetDatabase.GetAssetPath(Selection.activeObject)); if (GameDataTracker.IsGameDataFile(assetPath) == false) { this.DrawDefaultInspector(); return; } if (this.lastAsset != gameDataAsset || this.gameDataSettings == null) { this.gameDataSettings = GameDataSettings.Load(gameDataPath); this.gameDataSettings.ScriptingAssemblies = this.gameDataSettings.ScriptingAssemblies ?? new string[0]; this.lastAsset = gameDataAsset; this.newScriptingAssembly = null; this.newScriptingAssemblyName = null; } GUI.enabled = true; GUILayout.Label(Path.GetFileName(gameDataPath), EditorStyles.boldLabel); this.gameDataSettings.Generator = (int)(GameDataSettings.CodeGenerator)EditorGUILayout.EnumPopup(Resources.UI_UNITYPLUGIN_INSPECTOR_CODE_GENERATOR, (GameDataSettings.CodeGenerator) this.gameDataSettings.Generator); if (this.gameDataSettings.Generator != (int)GameDataSettings.CodeGenerator.None) { this.codeGenerationFold = EditorGUILayout.Foldout(this.codeGenerationFold, Resources.UI_UNITYPLUGIN_INSPECTOR_CODE_GENERATION_LABEL); if (this.codeGenerationFold) { this.gameDataSettings.AutoGeneration = EditorGUILayout.Toggle(Resources.UI_UNITYPLUGIN_INSPECTOR_AUTO_GENERATION, this.gameDataSettings.AutoGeneration); var codeAsset = !string.IsNullOrEmpty(this.gameDataSettings.CodeGenerationPath) && File.Exists(this.gameDataSettings.CodeGenerationPath) ? AssetDatabase.LoadAssetAtPath <TextAsset>(this.gameDataSettings.CodeGenerationPath) : null; var assetAsset = !string.IsNullOrEmpty(this.gameDataSettings.AssetGenerationPath) && File.Exists(this.gameDataSettings.AssetGenerationPath) ? AssetDatabase.LoadAssetAtPath <ScriptableObject>(this.gameDataSettings.AssetGenerationPath) : null; if (codeAsset != null) { this.gameDataSettings.CodeGenerationPath = AssetDatabase.GetAssetPath(EditorGUILayout.ObjectField(Resources.UI_UNITYPLUGIN_INSPECTOR_CODE_GENERATION_PATH, codeAsset, typeof(TextAsset), false)); } else { this.gameDataSettings.CodeGenerationPath = EditorGUILayout.TextField(Resources.UI_UNITYPLUGIN_INSPECTOR_CODE_GENERATION_PATH, this.gameDataSettings.CodeGenerationPath); } if (this.gameDataSettings.Generator == (int)GameDataSettings.CodeGenerator.CSharpCodeAndAsset) { if (assetAsset != null) { this.gameDataSettings.AssetGenerationPath = AssetDatabase.GetAssetPath(EditorGUILayout.ObjectField(Resources.UI_UNITYPLUGIN_INSPECTOR_ASSET_GENERATION_PATH, assetAsset, typeof(ScriptableObject), false)); } else { this.gameDataSettings.AssetGenerationPath = EditorGUILayout.TextField(Resources.UI_UNITYPLUGIN_INSPECTOR_ASSET_GENERATION_PATH, this.gameDataSettings.AssetGenerationPath); } } if ((this.gameDataSettings.Generator == (int)GameDataSettings.CodeGenerator.CSharp || this.gameDataSettings.Generator == (int)GameDataSettings.CodeGenerator.CSharpCodeAndAsset) && Path.GetExtension(this.gameDataSettings.CodeGenerationPath) != ".cs") { this.gameDataSettings.CodeGenerationPath = Path.ChangeExtension(this.gameDataSettings.CodeGenerationPath, ".cs"); } if (this.gameDataSettings.Generator == (int)GameDataSettings.CodeGenerator.CSharpCodeAndAsset && Path.GetExtension(this.gameDataSettings.AssetGenerationPath) != ".asset") { this.gameDataSettings.AssetGenerationPath = Path.ChangeExtension(this.gameDataSettings.AssetGenerationPath, ".asset"); } this.gameDataSettings.Namespace = EditorGUILayout.TextField(Resources.UI_UNITYPLUGIN_INSPECTOR_CODE_NAMESPACE, this.gameDataSettings.Namespace); this.gameDataSettings.GameDataClassName = EditorGUILayout.TextField(Resources.UI_UNITYPLUGIN_INSPECTOR_CODE_API_CLASS_NAME, this.gameDataSettings.GameDataClassName); this.gameDataSettings.DocumentClassName = EditorGUILayout.TextField(Resources.UI_UNITYPLUGIN_INSPECTOR_CODE_DOCUMENT_CLASS_NAME, this.gameDataSettings.DocumentClassName); this.gameDataSettings.LineEnding = (int)(GameDataSettings.LineEndings)EditorGUILayout.EnumPopup( Resources.UI_UNITYPLUGIN_INSPECTOR_CODE_LINE_ENDINGS, (GameDataSettings.LineEndings) this.gameDataSettings.LineEnding); this.gameDataSettings.Indentation = (int)(GameDataSettings.Indentations)EditorGUILayout.EnumPopup( Resources.UI_UNITYPLUGIN_INSPECTOR_CODE_INDENTATION, (GameDataSettings.Indentations) this.gameDataSettings.Indentation); this.gameDataSettings.Options = (int)(CodeGenerationOptions)EditorGUILayout.EnumMaskField( Resources.UI_UNITYPLUGIN_INSPECTOR_CODE_OPTIONS, (CodeGenerationOptions)this.gameDataSettings.Options); } } this.scriptingAssembliesFold = EditorGUILayout.Foldout(this.scriptingAssembliesFold, Resources.UI_UNITYPLUGIN_INSPECTOR_SCRIPTING_ASSEMBLIES_LABEL); if (this.scriptingAssembliesFold) { for (var i = 0; i < this.gameDataSettings.ScriptingAssemblies.Length; i++) { var watchedAssetPath = this.gameDataSettings.ScriptingAssemblies[i]; var assetExists = !string.IsNullOrEmpty(watchedAssetPath) && (File.Exists(watchedAssetPath) || Directory.Exists(watchedAssetPath)); var watchedAsset = assetExists ? AssetDatabase.LoadMainAssetAtPath(watchedAssetPath) : null; if (watchedAsset != null) { this.gameDataSettings.ScriptingAssemblies[i] = AssetDatabase.GetAssetPath(EditorGUILayout.ObjectField(Resources.UI_UNITYPLUGIN_INSPECTOR_ASSET_LABEL, watchedAsset, typeof(Object), false)); } else { this.gameDataSettings.ScriptingAssemblies[i] = EditorGUILayout.TextField(Resources.UI_UNITYPLUGIN_INSPECTOR_NAME_LABEL, watchedAssetPath); } } EditorGUILayout.Space(); this.newScriptingAssembly = EditorGUILayout.ObjectField("<" + Resources.UI_UNITYPLUGIN_INSPECTOR_ADD_ASSET_BUTTON + ">", this.newScriptingAssembly, typeof(Object), false); if (Event.current.type == EventType.repaint && this.newScriptingAssembly != null) { var assemblies = new HashSet <string>(this.gameDataSettings.ScriptingAssemblies); assemblies.Remove(""); assemblies.Add(AssetDatabase.GetAssetPath(this.newScriptingAssembly)); this.gameDataSettings.ScriptingAssemblies = assemblies.ToArray(); this.newScriptingAssembly = null; GUI.changed = true; } EditorGUILayout.BeginHorizontal(); this.newScriptingAssemblyName = EditorGUILayout.TextField("<" + Resources.UI_UNITYPLUGIN_INSPECTOR_ADD_NAME_BUTTON + ">", this.newScriptingAssemblyName); if (GUILayout.Button(Resources.UI_UNITYPLUGIN_INSPECTOR_ADD_BUTTON, EditorStyles.toolbarButton, GUILayout.Width(70), GUILayout.Height(18))) { var assemblies = new HashSet <string>(this.gameDataSettings.ScriptingAssemblies); assemblies.Remove(""); assemblies.Add(this.newScriptingAssemblyName); this.gameDataSettings.ScriptingAssemblies = assemblies.ToArray(); this.newScriptingAssemblyName = null; GUI.changed = true; this.Repaint(); } GUILayout.Space(5); EditorGUILayout.EndHorizontal(); } EditorGUILayout.Space(); GUILayout.Label(Resources.UI_UNITYPLUGIN_INSPECTOR_ACTIONS_GROUP, EditorStyles.boldLabel); if (EditorApplication.isCompiling) { EditorGUILayout.HelpBox(Resources.UI_UNITYPLUGIN_COMPILING_WARNING, MessageType.Warning); } else if (CoroutineScheduler.IsRunning) { EditorGUILayout.HelpBox(Resources.UI_UNITYPLUGIN_COROUTINE_IS_RUNNIG_WARNING, MessageType.Warning); } EditorGUILayout.BeginHorizontal(); GUI.enabled = !CoroutineScheduler.IsRunning && !EditorApplication.isCompiling; if (GUILayout.Button(Resources.UI_UNITYPLUGIN_INSPECTOR_EDIT_BUTTON)) { AssetDatabase.OpenAsset(gameDataAsset); this.Repaint(); } if (this.gameDataSettings.Generator != (int)GameDataSettings.CodeGenerator.None && string.IsNullOrEmpty(this.gameDataSettings.CodeGenerationPath) == false) { if (GUILayout.Button(Resources.UI_UNITYPLUGIN_INSPECTOR_RUN_GENERATOR_BUTTON)) { CoroutineScheduler.Schedule(Menu.GenerateCodeAndAssetsAsync(gameDataPath, ProgressUtils.ReportToLog(Resources.UI_UNITYPLUGIN_INSPECTOR_GENERATION_PREFIX + " ")), "generation::" + gameDataPath) .ContinueWith(_ => this.Repaint()); } } GUI.enabled = !CoroutineScheduler.IsRunning && !EditorApplication.isCompiling; if (GUILayout.Button(Resources.UI_UNITYPLUGIN_INSPECTOR_VALIDATE_BUTTON)) { CoroutineScheduler.Schedule(Menu.ValidateAsync(gameDataPath, ProgressUtils.ReportToLog(Resources.UI_UNITYPLUGIN_INSPECTOR_VALIDATION_PREFIX + " ")), "validation::" + gameDataPath) .ContinueWith(_ => this.Repaint()); } if (GUILayout.Button(Resources.UI_UNITYPLUGIN_INSPECTOR_BACKUP_BUTTON)) { this.Backup(gameDataPath); } if (GUILayout.Button(Resources.UI_UNITYPLUGIN_INSPECTOR_RESTORE_BUTTON)) { this.Restore(gameDataPath); } EditorGUILayout.EndHorizontal(); GUI.enabled = true; if (GUI.changed) { this.gameDataSettings.Save(gameDataPath); } }
private IEnumerable CompleteAsync() { var extensionsToClean = new[] { ".exe", ".dll", ".config", ".xml", ".pdb", ".mdb", ".sha1" }; var filesToClean = extensionsToClean .Select(extension => new FileInfo(Path.ChangeExtension(this.targetFile.FullName, extension))) .Union(extensionsToClean.Select(extension => new FileInfo(this.targetFile.FullName + extension))); foreach (var fileToClean in filesToClean) { try { fileToClean.Refresh(); if (!fileToClean.Exists) { continue; } if (Settings.Current.Verbose) { Debug.Log(string.Format("Removing old file '{0}' of '{1}' product.", fileToClean.FullName, this.product)); } fileToClean.Delete(); } catch (Exception error) { Debug.LogWarning(error); } } foreach (var file in this.downloadDirectory.GetFiles()) { var targetFile = new FileInfo(Path.Combine(this.targetDirectory.FullName, file.Name)); if (targetFile.Exists) { if (Settings.Current.Verbose) { Debug.Log(string.Format("Replacing target file '{0}' with new content for product '{1}'.", targetFile, this.product)); } try { File.Replace(file.FullName, targetFile.FullName, null); } catch (Exception error) { Debug.LogWarning(error); } } else { if (Settings.Current.Verbose) { Debug.Log(string.Format("Adding new file '{0}' for product '{1}'.", targetFile, this.product)); } try { file.MoveTo(targetFile.FullName); } catch (Exception error) { Debug.LogWarning(error); } } this.changedAssets.Add(FileAndPathUtils.MakeProjectRelative(targetFile.FullName)); } yield break; }
public IEnumerable PerformUpdateAsync() { var artifacts = new string[this.rows.Length]; try { // downloading for (var i = 0; i < this.rows.Length; i++) { var row = this.rows[i]; if (row.Disabled || row.Action == ACTION_SKIP) { continue; } var downloadProgress = this.GetProgressReportFor(row, i + 1, this.rows.Length); var downloadAsync = new Coroutine <string>(DownloadAsync(row, downloadProgress)); yield return(downloadAsync.IgnoreFault()); if (downloadAsync.HasErrors) { Debug.LogWarning(string.Format("Failed to download build version '{1}' of '{0}' product. Error: {2}", row.Name, row.SelectedVersion, downloadAsync.Error.Unwrap())); continue; } artifacts[i] = downloadAsync.GetResult(); if (Settings.Current.Verbose) { Debug.Log(string.Format("Downloading '{0}' to '{1}'.", row.Name, artifacts[i])); } } // cleanup for (var i = 0; i < this.rows.Length; i++) { var row = this.rows[i]; if (row.Disabled || row.Action == ACTION_SKIP || artifacts[i] == null) { continue; } if (row.Id == UpdateServerCli.PRODUCT_CHARON) { PreCharonDeploy(row.Location); } } // deploy for (var i = 0; i < this.rows.Length; i++) { var row = this.rows[i]; if (row.Disabled || row.Action == ACTION_SKIP || artifacts[i] == null) { continue; } if (Settings.Current.Verbose) { Debug.Log(string.Format("Deploying '{0}' from '{1}' to '{2}'.", row.Name, artifacts[i], row.Location)); } try { File.Delete(row.Location); File.Move(artifacts[i], row.Location); } catch (Exception moveError) { Debug.LogError(string.Format("Failed to move downloaded file to new location '{0}'.", row.Location)); Debug.LogError(moveError.Unwrap()); } var deployProgress = this.GetProgressReportFor(row, i + 1, this.rows.Length); if (row.Id == UpdateServerCli.PRODUCT_CHARON && artifacts[i] != null) { yield return(new Coroutine <object>(PostCharonDeployAsync(row.Location, deployProgress)).IgnoreFault()); } } // post deploy for (var i = 0; i < this.rows.Length; i++) { var row = this.rows[i]; if (row.Disabled || row.Action == ACTION_SKIP || artifacts[i] == null) { continue; } var assetLocation = FileAndPathUtils.MakeProjectRelative(row.Location); if (string.IsNullOrEmpty(assetLocation)) { continue; } AssetDatabase.ImportAsset(assetLocation, ImportAssetOptions.ForceUpdate); } this.updateStatus = Resources.UI_UNITYPLUGIN_PROGRESS_DONE; } finally { foreach (var tempFile in artifacts) { try { File.Delete(tempFile); } catch { /*ignore delete error*/ } } } this.Close(); // re-load window if not 'Close' button was pressed if (this.rows.All(r => r.Action == ACTION_SKIP) == false) { Promise.Delayed(TimeSpan.FromSeconds(1)).ContinueWith(_ => EditorWindow.GetWindow <UpdateWindow>(utility: true)); } }
private static void ChooseAction(ProductRow row) { var currentVersion = row.CurrentVersion.GetResult(); var builds = row.AllBuilds.HasErrors ? default(BuildInfo[]) : row.AllBuilds.GetResult(); if (builds == null || builds.Length == 0) { return; } var versions = Array.ConvertAll(builds, b => b.Version); Array.Sort(versions); Array.Reverse(versions); row.AllVersions = versions; var lastVersion = versions.FirstOrDefault(); if (string.IsNullOrEmpty(row.Location) || lastVersion == null) { // no local artifacts row.SelectedVersion = null; row.Action = ACTION_SKIP; row.ActionMask = (1 << Array.IndexOf(Actions, ACTION_SKIP)); return; } var expectedBuild = builds.FirstOrDefault(b => b.Version == row.ExpectedVersion); var currentBuild = builds.FirstOrDefault(b => b.Version == currentVersion); if (expectedBuild == null && currentVersion != null && currentVersion > lastVersion) { // current installed build is the last one row.SelectedVersion = currentVersion; row.Action = ACTION_SKIP; row.ActionMask = (1 << Array.IndexOf(Actions, ACTION_SKIP)); } else if (File.Exists(row.Location) == false || (expectedBuild != null && currentBuild != expectedBuild)) { // missing file or invalid version is installed row.SelectedVersion = expectedBuild != null ? expectedBuild.Version : currentVersion ?? lastVersion; row.Action = ACTION_DOWNLOAD; row.ActionMask = (1 << Array.IndexOf(Actions, ACTION_DOWNLOAD)) | (1 << Array.IndexOf(Actions, ACTION_SKIP)); } else if (currentBuild == null && currentVersion != null) { // current installed build is not found row.SelectedVersion = lastVersion; row.Action = ACTION_DOWNLOAD; row.ActionMask = (1 << Array.IndexOf(Actions, ACTION_DOWNLOAD)) | (1 << Array.IndexOf(Actions, ACTION_SKIP)); } else { var actualHash = FileAndPathUtils.ComputeHash(row.Location, currentBuild.HashAlgorithm); if (string.Equals(currentBuild.Hash, actualHash, StringComparison.OrdinalIgnoreCase) == false) { if (Settings.Current.Verbose) { Debug.LogWarning(string.Format("File's '{0}' {1} hash '{2}' differs from expected '{3}'. File should be repaired.", row.Location, currentBuild.HashAlgorithm, actualHash, currentBuild.Hash)); } // corrupted file row.SelectedVersion = lastVersion; row.Action = ACTION_REPAIR; row.ActionMask = (1 << Array.IndexOf(Actions, ACTION_REPAIR)) | (1 << Array.IndexOf(Actions, ACTION_UPDATE)) | (1 << Array.IndexOf(Actions, ACTION_SKIP)); } else if (currentVersion < lastVersion) { // outdated version row.SelectedVersion = lastVersion; row.Action = ACTION_UPDATE; row.ActionMask = (1 << Array.IndexOf(Actions, ACTION_UPDATE)) | (1 << Array.IndexOf(Actions, ACTION_SKIP)); } else { // actual version row.SelectedVersion = currentVersion ?? lastVersion; row.Action = ACTION_SKIP; row.ActionMask = (1 << Array.IndexOf(Actions, ACTION_SKIP)); } } }
public static void OnSelectionChanged() { if (Selection.activeObject == null) { return; } var assetPath = FileAndPathUtils.MakeProjectRelative(AssetDatabase.GetAssetPath(Selection.activeObject)); if (GameDataTracker.IsGameDataFile(assetPath) == false) { return; } try { var selectedAssetType = Selection.activeObject.GetType(); var inspectorWindowType = typeof(PopupWindow).Assembly.GetType("UnityEditor.InspectorWindow"); var inspectorWindow = EditorWindow.GetWindow(inspectorWindowType); var activeEditorTracker = inspectorWindow.HasProperty("tracker") ? inspectorWindow.GetPropertyValue("tracker") : inspectorWindow.GetFieldValue("m_Tracker"); var customEditorAttributesType = typeof(PopupWindow).Assembly.GetType("UnityEditor.CustomEditorAttributes"); var customEditorsList = customEditorAttributesType.GetFieldValue("kSCustomEditors") as IList; var customEditorsDictionary = customEditorAttributesType.GetFieldValue("kSCustomEditors") as IDictionary; var monoEditorType = customEditorAttributesType.GetNestedType("MonoEditorType", BindingFlags.NonPublic); // after unity 2018.* if (customEditorsDictionary != null) { foreach (IEnumerable customEditors in customEditorsDictionary.Values) { foreach (var customEditor in customEditors) { if (customEditor == null || (Type)customEditor.GetFieldValue("m_InspectedType") != selectedAssetType) { continue; } var originalInspectorType = (Type)customEditor.GetFieldValue("m_InspectorType"); // override inspector customEditor.SetFieldValue("m_InspectorType", typeof(GameDataInspector)); // force rebuild editor list activeEditorTracker.Invoke("ForceRebuild"); inspectorWindow.Repaint(); // restore original inspector customEditor.SetFieldValue("m_InspectorType", originalInspectorType); break; } } var newMonoEditorType = Activator.CreateInstance(monoEditorType); newMonoEditorType.SetFieldValue("m_InspectedType", selectedAssetType); newMonoEditorType.SetFieldValue("m_InspectorType", typeof(GameDataInspector)); newMonoEditorType.SetFieldValue("m_EditorForChildClasses", false); if (monoEditorType.HasField("m_IsFallback")) { newMonoEditorType.SetFieldValue("m_IsFallback", false); } var newMonoEditorTypeList = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(monoEditorType)); newMonoEditorTypeList.Add(newMonoEditorType); // override inspector customEditorsDictionary[selectedAssetType] = newMonoEditorTypeList; // force rebuild editor list activeEditorTracker.Invoke("ForceRebuild"); inspectorWindow.Repaint(); // restore original inspector customEditorsDictionary.Remove(selectedAssetType); } // prior to unity 2018.* else if (customEditorsList != null) { var cachedCustomEditorsByType = customEditorAttributesType.HasField("kCachedEditorForType") ? (IDictionary <Type, Type>)customEditorAttributesType.GetFieldValue("kCachedEditorForType") : null; foreach (var customEditor in customEditorsList) { if (customEditor == null || (Type)customEditor.GetFieldValue("m_InspectedType") != selectedAssetType) { continue; } var originalInspectorType = (Type)customEditor.GetFieldValue("m_InspectorType"); // override inspector customEditor.SetFieldValue("m_InspectorType", typeof(GameDataInspector)); if (cachedCustomEditorsByType != null) { cachedCustomEditorsByType[selectedAssetType] = typeof(GameDataInspector); } // force rebuild editor list activeEditorTracker.Invoke("ForceRebuild"); inspectorWindow.Repaint(); // restore original inspector customEditor.SetFieldValue("m_InspectorType", originalInspectorType); if (cachedCustomEditorsByType != null) { cachedCustomEditorsByType.Remove(selectedAssetType); } break; } var newMonoEditorType = Activator.CreateInstance(monoEditorType); newMonoEditorType.SetFieldValue("m_InspectedType", selectedAssetType); newMonoEditorType.SetFieldValue("m_InspectorType", typeof(GameDataInspector)); newMonoEditorType.SetFieldValue("m_EditorForChildClasses", false); if (monoEditorType.HasField("m_IsFallback")) { newMonoEditorType.SetFieldValue("m_IsFallback", false); } // override inspector customEditorsList.Insert(0, newMonoEditorType); if (cachedCustomEditorsByType != null) { cachedCustomEditorsByType[selectedAssetType] = typeof(GameDataInspector); } // force rebuild editor list activeEditorTracker.Invoke("ForceRebuild"); inspectorWindow.Repaint(); // restore original inspector customEditorsList.Remove(newMonoEditorType); if (cachedCustomEditorsByType != null) { cachedCustomEditorsByType.Remove(selectedAssetType); } } } catch (Exception updateEditorError) { if (Settings.Current.Verbose) { Debug.LogError(updateEditorError); } } }
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 ); } } }
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); } }
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 gameDataType = Type.GetType(gameDataSettings.Namespace + "." + gameDataSettings.GameDataClassName + ", Assembly-CSharp", throwOnError: false) ?? Type.GetType(gameDataSettings.Namespace + "." + gameDataSettings.GameDataClassName + ", Assembly-CSharp-firstpass", throwOnError: false) ?? Type.GetType(gameDataSettings.Namespace + "." + gameDataSettings.GameDataClassName + ", Assembly-CSharp-Editor", throwOnError: false); if (gameDataType == 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(gameDataType); gameDataAsset.SetFieldValue("dataBytes", gameDataBytes); gameDataAsset.SetFieldValue("format", 0); 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); } }
internal static string GetLocalUserDataPath() { return(Path.Combine(Path.Combine(AppDataPath, "Users"), FileAndPathUtils.SanitizeFileName(Environment.UserName ?? "Default"))); }
public static void SkipUpdates(string releaseNotes) { EditorPrefs.SetString(SKIPPED_UPDATE_PREFS_KEY, FileAndPathUtils.ComputeNameHash(releaseNotes, "SHA1")); }