From 7d5444fbeeaf611ddf06cbb389b7fb9a29fa77aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?PUM4CH3=D0=98?= <18906012399@163.com> Date: Mon, 14 Aug 2023 18:59:52 +0800 Subject: [PATCH] Tor Processor (#2) * TOR Processor --------- Co-authored-by: chenjunbiao --- Editor/API/HDAProcessor.cs | 4 +- Editor/API/TORLibrary.cs | 45 ++++++ Editor/API/TORLibrary.cs.meta | 11 ++ Editor/API/TORProcessor.cs | 136 ++++++++++++++++++ Editor/API/TORProcessor.cs.meta | 11 ++ Editor/Parm.cs | 92 ++++++++++-- Editor/ParmTemplate.cs | 16 ++- Editor/ScriptableObject/HDAProcessorPreset.cs | 2 +- Editor/Window/HDAProcessorWindow.cs | 6 +- Editor/Window/TORProcessorWindow.cs | 130 +++++++++++++++++ Editor/Window/TORProcessorWindow.cs.meta | 11 ++ 11 files changed, 439 insertions(+), 25 deletions(-) create mode 100644 Editor/API/TORLibrary.cs create mode 100644 Editor/API/TORLibrary.cs.meta create mode 100644 Editor/API/TORProcessor.cs create mode 100644 Editor/API/TORProcessor.cs.meta create mode 100644 Editor/Window/TORProcessorWindow.cs create mode 100644 Editor/Window/TORProcessorWindow.cs.meta diff --git a/Editor/API/HDAProcessor.cs b/Editor/API/HDAProcessor.cs index dd0d897..c33179e 100644 --- a/Editor/API/HDAProcessor.cs +++ b/Editor/API/HDAProcessor.cs @@ -64,7 +64,7 @@ public static void ProcessHDAAsync(this HDAProcessorPreset preset, Action parms, Action completed, + public static void ProcessHDAAsync(string hda, IEnumerable parms, Action completed, Action failed = null, int timeout = 3000) { Uri uri = GetUri(hda); @@ -97,7 +97,7 @@ public static void ProcessHDAAsync(string hda, IEnumerable parms, Actio }); } - public static IEnumerator ProcessHDARoutine(string hda, IEnumerable parms, Action completed, + public static IEnumerator ProcessHDARoutine(string hda, IEnumerable parms, Action completed, Action failed = null, int timeout = 300) { Uri uri = GetUri(hda); diff --git a/Editor/API/TORLibrary.cs b/Editor/API/TORLibrary.cs new file mode 100644 index 0000000..5b2f287 --- /dev/null +++ b/Editor/API/TORLibrary.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Harpoon.Utils; +using Newtonsoft.Json; +using UnityEditor; +using UnityEngine; +using UnityEngine.Networking; + +namespace Harpoon +{ + public static class TORLibrary + { + /*public static string[] TorLibrary() + { + GetTORLibraryAsync((tors) => + { + foreach (var tor in tors) + { + Debug.Log(tor); + } + }); + }*/ + + public static void GetTORLibraryAsync(Action completed, Action failed = null) + { + Uri uri = new Uri(HarpoonUriBuilder.Root, "api/torlibrary"); + UnityWebRequest request = UnityWebRequest.Get(uri); + request.SendWebRequest((request) => + { + if (request.result == UnityWebRequest.Result.Success) + { + dynamic torLibrary = JsonConvert.DeserializeObject(request.downloadHandler.text); + string[] tors = torLibrary.ToObject(); + completed?.Invoke(tors); + } + else + { + Debug.Log(request.error); + failed?.Invoke(); + } + }); + } + } +} diff --git a/Editor/API/TORLibrary.cs.meta b/Editor/API/TORLibrary.cs.meta new file mode 100644 index 0000000..98e097e --- /dev/null +++ b/Editor/API/TORLibrary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4cbae77d104a5c14aaffebab6247b396 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/API/TORProcessor.cs b/Editor/API/TORProcessor.cs new file mode 100644 index 0000000..0229aae --- /dev/null +++ b/Editor/API/TORProcessor.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.IO; +using System.IO.Compression; +using Newtonsoft.Json; +using Unity.EditorCoroutines.Editor; +using UnityEditor; +using UnityEditor.PackageManager.Requests; +using UnityEngine; +using UnityEngine.Networking; +using Harpoon.Utils; +using UnityEditor.PackageManager; + +namespace Harpoon +{ + public static class TORProcessor + { + private static Uri GetUri(string torName) + { + return new Uri(HarpoonUriBuilder.Root, $"api/torprocessor/{torName}"); + } + + public static void GetTORHeaderAsync(string torName, Action completed, Action failed = null) + { + Uri uri = GetUri(torName); + UnityWebRequest request = UnityWebRequest.Get(uri); + request.SendWebRequest((request) => + { + if (request.result == UnityWebRequest.Result.Success) + { + completed?.Invoke(JsonConvert.DeserializeObject(request.downloadHandler.text)); + } + else + { + Debug.LogError(request.error); + failed?.Invoke(); + } + }); + } + + public static IEnumerator GetTORHeaderRoutine(string torName, Action completed, Action failed = null) + { + Uri uri = GetUri(torName); + using (UnityWebRequest get = UnityWebRequest.Get(uri)) + { + var request = get.SendWebRequest(); + while (!request.isDone) + yield return null; + if (get.result != UnityWebRequest.Result.Success) + { + if (failed == null) + Debug.LogError(get.error); + else + failed?.Invoke(); + } + completed?.Invoke(JsonConvert.DeserializeObject(get.downloadHandler.text)); + } + } + + /*public static void ProcessTORAsync(this TORProcessorPreset preset, Action completed, Action failed = null, int timeout = 300) + { + ProcessTORAsync(preset.tor, preset.parms, completed, failed, timeout); + }*/ + + public static void ProcessTORAsync(string tor, IEnumerable parms, Action completed, + Action failed = null, int timeout = 3000) + { + Uri uri = GetUri(tor); + List formData = new List(); + foreach (var parm in parms) + { + formData.Add(parm.formSection); + } + + string downloadedFile = Path.Combine(Path.GetDirectoryName(Application.temporaryCachePath), "Temp", $"Harpoon_Response{DateTime.Now.Ticks}.zip"); + UnityWebRequest post = UnityWebRequest.Post(uri, formData); + post.useHttpContinue = false; + post.timeout = timeout; + post.downloadHandler = new DownloadHandlerFile(downloadedFile); + post.SendWebRequest((request) => + { + if (request.result == UnityWebRequest.Result.Success) + { + using (var zipArchive = ZipFile.OpenRead(downloadedFile)) + { + completed?.Invoke(zipArchive); + } + + File.Delete(downloadedFile); + } + else + { + failed?.Invoke(); + } + }); + } + + public static IEnumerator ProcessTORRoutine(string tor, IEnumerable parms, Action completed, + Action failed = null, int timeout = 300) + { + Uri uri = GetUri(tor); + List formData = new List(); + foreach (var parm in parms) + { + formData.Add(parm.formSection); + } + string downloadedFile = Path.Combine(Path.GetDirectoryName(Application.temporaryCachePath), "Temp", $"Harpoon_Response{DateTime.Now.Ticks}.zip"); + using (UnityWebRequest post = UnityWebRequest.Post(uri, formData)) + { + post.useHttpContinue = false; + post.timeout = timeout; + post.downloadHandler = new DownloadHandlerFile(downloadedFile); + var request = post.SendWebRequest(); + while (!request.isDone) + yield return null; + if (post.result == UnityWebRequest.Result.Success) + { + using (var zipArchive = ZipFile.OpenRead(downloadedFile)) + { + completed?.Invoke(zipArchive); + } + } + else + { + if (failed == null) + Debug.LogError(post.error); + else + failed?.Invoke(); + } + File.Delete(downloadedFile); + } + } + } +} diff --git a/Editor/API/TORProcessor.cs.meta b/Editor/API/TORProcessor.cs.meta new file mode 100644 index 0000000..f914b48 --- /dev/null +++ b/Editor/API/TORProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9b10b10cc579c0f4699e0b5d04b1f049 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Parm.cs b/Editor/Parm.cs index 367833d..8e20743 100644 --- a/Editor/Parm.cs +++ b/Editor/Parm.cs @@ -14,7 +14,7 @@ namespace Harpoon { [Serializable] - public abstract class HouParm + public abstract class Parm { public abstract ParmTemplate parmTemplate { get; } public abstract void GUILayout(); @@ -22,14 +22,12 @@ public abstract class HouParm public abstract IMultipartFormSection formSection { get; } public string name => parmTemplate.name; - public static IEnumerable CreateParms(dynamic hdaHeader) + public static IEnumerable CreateParms(dynamic parmTemplateGroup) { - IEnumerable parmTemplates = hdaHeader.parmTemplateGroup.parmTemplates; + IEnumerable parmTemplates = parmTemplateGroup.parmTemplates; foreach (var parmTemplate in parmTemplates) { ParmTemplate template = parmTemplate.ToObject(); - if (template.isHidden) - continue; switch (template.dataType) { case (ParmData.Int): @@ -53,7 +51,7 @@ public static IEnumerable CreateParms(dynamic hdaHeader) } [Serializable] - public class FloatParm : HouParm + public class FloatParm : Parm { public override ParmTemplate parmTemplate => template; public FloatParmTemplate template; @@ -68,11 +66,43 @@ public FloatParm(FloatParmTemplate template) public override void GUILayout() { + if(template.isHidden) + return; EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(template.label); - for (int i = 0; i < template.numComponents; ++i) + if (template.numComponents == 1) { - value[i] = EditorGUILayout.FloatField(value[i]); + if (template.minIsStrict && template.maxIsStrict) + { + value[0] = EditorGUILayout.Slider(value[0], template.minValue, template.maxValue); + } + else + { + value[0] = EditorGUILayout.FloatField(value[0]); + } + if (template.minIsStrict) + { + value[0] = Mathf.Max(value[0], template.minValue); + } + if (template.maxIsStrict) + { + value[0] = Mathf.Min(value[0], template.maxValue); + } + } + else + { + for (int i = 0; i < template.numComponents; ++i) + { + value[i] = EditorGUILayout.FloatField(value[i]); + if (template.minIsStrict) + { + value[i] = Mathf.Max(value[i], template.minValue); + } + if (template.maxIsStrict) + { + value[i] = Mathf.Min(value[i], template.maxValue); + } + } } EditorGUILayout.EndHorizontal(); } @@ -84,7 +114,7 @@ public override IMultipartFormSection formSection } [Serializable] - public class IntParm : HouParm + public class IntParm : Parm { public override ParmTemplate parmTemplate => template; public IntParmTemplate template; @@ -103,18 +133,54 @@ public override IMultipartFormSection formSection public override void GUILayout() { + if(template.isHidden) + return; EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(template.label); - for (int i = 0; i < template.numComponents; ++i) + if (template.numComponents == 1) + { + if (template.menuItems != null && template.menuItems.Length > 0) + { + value[0] = EditorGUILayout.Popup(value[0], template.menuLabels); + } + else if (template.minIsStrict && template.maxIsStrict) + { + value[0] = EditorGUILayout.IntSlider(value[0], template.minValue, template.maxValue); + } + else + { + value[0] = EditorGUILayout.IntField(value[0]); + } + if (template.minIsStrict) + { + value[0] = Mathf.Max(value[0], template.minValue); + } + if (template.maxIsStrict) + { + value[0] = Mathf.Min(value[0], template.maxValue); + } + } + else { - value[i] = EditorGUILayout.IntField(value[i]); + for (int i = 0; i < template.numComponents; ++i) + { + value[i] = EditorGUILayout.IntField(value[i]); + if (template.minIsStrict) + { + value[i] = Mathf.Max(value[i], template.minValue); + } + if (template.maxIsStrict) + { + value[i] = Mathf.Min(value[i], template.maxValue); + } + } } EditorGUILayout.EndHorizontal(); } } [Serializable] - public class StringParm : HouParm + public class StringParm : Parm { public override ParmTemplate parmTemplate => template; public StringParmTemplate template; @@ -136,6 +202,8 @@ public StringParm(StringParmTemplate template) public override void GUILayout() { + if(template.isHidden) + return; switch (template.stringType) { case StringParmType.FileReference: diff --git a/Editor/ParmTemplate.cs b/Editor/ParmTemplate.cs index 73e5f76..a21e7dd 100644 --- a/Editor/ParmTemplate.cs +++ b/Editor/ParmTemplate.cs @@ -26,7 +26,7 @@ public class ParmTemplate public bool joinsWithNext; // public string disableWhen; // public string conditionals; - public Dictionary tags; + //public Dictionary tags; // public string scriptCallback; // public string scriptCallbackLanguage; } @@ -55,9 +55,11 @@ public class IntParmTemplate : ParmTemplate public bool maxIsStrict; //public string itemGeneratorScript; //public string itemGeneratorScriptLanguage; - [JsonConverter(typeof(StringEnumConverter))] - public MenuType menuType; - public bool menuUseToken; + //[JsonConverter(typeof(StringEnumConverter))] + //public MenuType menuType; + public string[] menuItems; + public string[] menuLabels; + //public bool menuUseToken; } [Serializable] @@ -75,8 +77,8 @@ public class StringParmTemplate : ParmTemplate //public string[] iconNames; //public string itemGeneratorScript; //public string itemGeneratorScriptLanguage; - [JsonConverter(typeof(StringEnumConverter))] - public MenuType menuType; - public bool menuUseToken; + //[JsonConverter(typeof(StringEnumConverter))] + //public MenuType menuType; + //public bool menuUseToken; } } \ No newline at end of file diff --git a/Editor/ScriptableObject/HDAProcessorPreset.cs b/Editor/ScriptableObject/HDAProcessorPreset.cs index f360ba4..0389469 100644 --- a/Editor/ScriptableObject/HDAProcessorPreset.cs +++ b/Editor/ScriptableObject/HDAProcessorPreset.cs @@ -13,7 +13,7 @@ public class HDAProcessorPreset : ScriptableObject public StringParm[] stringParms; public int timeout = 3000; - public IEnumerable parms + public IEnumerable parms { get { diff --git a/Editor/Window/HDAProcessorWindow.cs b/Editor/Window/HDAProcessorWindow.cs index 5c79d03..edcdf1f 100644 --- a/Editor/Window/HDAProcessorWindow.cs +++ b/Editor/Window/HDAProcessorWindow.cs @@ -19,7 +19,7 @@ public class HDAProcessorWindow : EditorWindow private int hdaIdx = 0; private string[] hdas = new string[0]; private string[] hdaNames = new string[0]; - private HouParm[] parms; + private Parm[] parms; private float progress = 1.0f; private static int timeout = 3000; @@ -52,7 +52,7 @@ void UpdateHDAParms() { HDAProcessor.GetHDAHeaderAsync(hda, (hdaHeader) => { - IEnumerable _parms = HouParm.CreateParms(hdaHeader); + IEnumerable _parms = Parm.CreateParms(hdaHeader.parmTemplateGroup); parms = _parms.ToArray(); }); } @@ -118,7 +118,7 @@ void Cook() zip => { string outputDir = EditorUtility.SaveFolderPanel("Output Dir", Application.dataPath, "Output"); - if (outputDir != null) + if (!string.IsNullOrEmpty(outputDir)) { zip.ExtractToDirectory(outputDir, true); AssetDatabase.Refresh(); diff --git a/Editor/Window/TORProcessorWindow.cs b/Editor/Window/TORProcessorWindow.cs new file mode 100644 index 0000000..958338a --- /dev/null +++ b/Editor/Window/TORProcessorWindow.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Runtime.Remoting.Messaging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Unity.EditorCoroutines.Editor; +using UnityEngine; +using UnityEditor; +using UnityEngine.Networking; + +namespace Harpoon +{ + public class TORProcessorWindow : EditorWindow + { + private int torIdx = 0; + private string[] tors = new string[0]; + private string[] torNames = new string[0]; + private Parm[] parms; + private float progress = 1.0f; + private static int timeout = 3000; + + private string tor => tors[torIdx]; + + [MenuItem("Harpoon/TORProcessor")] + public static void Open() + { + TORProcessorWindow window = CreateWindow(); + window.titleContent = new GUIContent("TOR Processor"); + window.Show(); + } + + private void OnEnable() + { + TORLibrary.GetTORLibraryAsync(torLibrary => + { + tors = new string[torLibrary.Length]; + torNames = new string[torLibrary.Length]; + for (int i = 0; i < torLibrary.Length; ++i) + { + tors[i] = torLibrary[i]; + torNames[i] = Path.GetFileNameWithoutExtension(torLibrary[i]); + } + UpdateTORParms(); + }); + } + + void UpdateTORParms() + { + TORProcessor.GetTORHeaderAsync(tor, (torHeader) => + { + IEnumerable _parms = Parm.CreateParms(torHeader); + parms = _parms.ToArray(); + }); + } + + private void OnGUI() + { + int selectedIdx = EditorGUILayout.Popup("TOR", torIdx, torNames); + if (selectedIdx != torIdx) + { + torIdx = selectedIdx; + UpdateTORParms(); + } + + if (parms != null) + { + foreach (var parm in parms) + { + parm.GUILayout(); + } + } + + timeout = Mathf.Max(30, EditorGUILayout.IntField("Timeout(s)", timeout)); + + if (GUILayout.Button("Save As Preset")) + { + //CreateTORProcessorPreset(); + } + + if (progress < 1.0f) + { + Rect rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight); + EditorGUI.ProgressBar(rect, progress, "Cooking"); + } + else if (GUILayout.Button("Cook")) + { + Cook(); + } + } + + /*void CreateTORProcessorPreset() + { + var torProcessorJob = ScriptableObject.CreateInstance(); + torProcessorJob.intParms = parms.Where(p => p is IntParm).Select(p => p as IntParm).ToArray(); + torProcessorJob.floatParms = parms.Where(p => p is FloatParm).Select(p => p as FloatParm).ToArray(); + torProcessorJob.stringParms = parms.Where(p => p is StringParm).Select(p => p as StringParm).ToArray(); + torProcessorJob.tor = tor; + string fileName = EditorUtility.SaveFilePanelInProject( + "Save TOR Processor Preset", + $"{Path.GetFileNameWithoutExtension(tor)}", "asset", ""); + if (string.IsNullOrEmpty(fileName)) + return; + if (!string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(fileName))) + { + AssetDatabase.DeleteAsset(fileName); + } + AssetDatabase.CreateAsset(torProcessorJob, fileName); + }*/ + + void Cook() + { + progress = 0.0f; + TORProcessor.ProcessTORAsync(tor, parms, + zip => + { + string outputDir = EditorUtility.SaveFolderPanel("Output Dir", Application.dataPath, "Output"); + if (!string.IsNullOrEmpty(outputDir)) + { + zip.ExtractToDirectory(outputDir, true); + AssetDatabase.Refresh(); + } + progress = 1.0f; + }, timeout: timeout); + } + } +} \ No newline at end of file diff --git a/Editor/Window/TORProcessorWindow.cs.meta b/Editor/Window/TORProcessorWindow.cs.meta new file mode 100644 index 0000000..cfa3644 --- /dev/null +++ b/Editor/Window/TORProcessorWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ddf5f10823ff7b94f924527c19761a32 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: