diff --git a/Packages/src/Editor/AssetModification.meta b/Packages/src/Editor/AssetModification.meta new file mode 100644 index 0000000..e7c46c4 --- /dev/null +++ b/Packages/src/Editor/AssetModification.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1006234332be4f329fc1830319b31aaa +timeCreated: 1704502465 \ No newline at end of file diff --git a/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AbsoluteMode.cs b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AbsoluteMode.cs new file mode 100644 index 0000000..0008c52 --- /dev/null +++ b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AbsoluteMode.cs @@ -0,0 +1,31 @@ +using Coffee.UIExtensions; +using Coffee.UIParticleInternal.AssetModification; +using UnityEditor; + +#pragma warning disable CS0612 // Type or member is obsolete + +namespace Coffee.UIParticleInternal +{ + internal class UIParticleComponentModifier_AbsoluteMode : ComponentModifier + { + protected override bool ModifyComponent(UIParticle uip, bool dryRun) + { + if (!uip.m_AbsoluteMode) return false; + + uip.m_AbsoluteMode = false; + uip.positionMode = UIParticle.PositionMode.Absolute; + + if (!dryRun) + { + EditorUtility.SetDirty(uip); + } + + return true; + } + + public override string Report() + { + return " -> UIParticle.absoluteMode is obsolete. Use UIParticle.positionMode instead.\n"; + } + } +} diff --git a/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AbsoluteMode.cs.meta b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AbsoluteMode.cs.meta new file mode 100644 index 0000000..7ed542c --- /dev/null +++ b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AbsoluteMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d3378b5e701274218b04cb5588b8a3bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AutoScaling.cs b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AutoScaling.cs new file mode 100644 index 0000000..f1f8314 --- /dev/null +++ b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AutoScaling.cs @@ -0,0 +1,36 @@ +using Coffee.UIExtensions; +using Coffee.UIParticleInternal.AssetModification; +using UnityEditor; +using UnityEngine; + +#pragma warning disable CS0612 // Type or member is obsolete + +namespace Coffee.UIParticleInternal +{ + internal class UIParticleComponentModifier_AutoScaling : ComponentModifier + { + protected override bool ModifyComponent(UIParticle uip, bool dryRun) + { + if (!uip.m_AutoScaling) return false; + + uip.m_AutoScaling = false; + uip.autoScalingMode = UIParticle.AutoScalingMode.Transform; + uip.transform.localScale = Vector3.one; + + if (!dryRun) + { + EditorUtility.SetDirty(uip); + EditorUtility.SetDirty(uip.transform); + } + + return true; + } + + public override string Report() + { + return + " -> UIParticle.ignoreCanvasScaler and UIParticle.autoScaling are obsolete." + + " Use UIParticle.autoScalingMode instead.\n"; + } + } +} diff --git a/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AutoScaling.cs.meta b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AutoScaling.cs.meta new file mode 100644 index 0000000..08f5c03 --- /dev/null +++ b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_AutoScaling.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3d6d0ca7ae8c641aa98b66fd91c05264 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/AssetModification/UIParticleComponentModifier_IsTrail.cs b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_IsTrail.cs new file mode 100644 index 0000000..1041679 --- /dev/null +++ b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_IsTrail.cs @@ -0,0 +1,31 @@ +using Coffee.UIExtensions; +using Coffee.UIParticleInternal.AssetModification; +using UnityEditor; +using UnityEngine; + +#pragma warning disable CS0612 // Type or member is obsolete + +namespace Coffee.UIParticleInternal +{ + internal class UIParticleComponentModifier_IsTrail : ComponentModifier + { + protected override bool ModifyComponent(UIParticle uip, bool dryRun) + { + if (!uip.m_IsTrail) return false; + + if (!dryRun) + { + var go = uip.gameObject; + Object.DestroyImmediate(uip); + EditorUtility.SetDirty(go); + } + + return true; + } + + public override string Report() + { + return " -> UIParticle for trail is no longer needed. Removed."; + } + } +} diff --git a/Packages/src/Editor/AssetModification/UIParticleComponentModifier_IsTrail.cs.meta b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_IsTrail.cs.meta new file mode 100644 index 0000000..5a5825a --- /dev/null +++ b/Packages/src/Editor/AssetModification/UIParticleComponentModifier_IsTrail.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dfbc9e244a2a040179e7f5b58ec0b978 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/AssetModification/UIParticleModifierRunner.cs b/Packages/src/Editor/AssetModification/UIParticleModifierRunner.cs new file mode 100644 index 0000000..5b29798 --- /dev/null +++ b/Packages/src/Editor/AssetModification/UIParticleModifierRunner.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using Coffee.UIParticleInternal.AssetModification; +using UnityEditor; + +namespace Coffee.UIParticleInternal +{ + internal class UIParticleModifierRunner : Runner + { + public UIParticleModifierRunner() + : base("UIParticle v5", new List<(string, Func)> + { + (".unity", x => new SceneModifier + { + path = x, + componentModifiers = new IComponentModifier[] + { + new UIParticleRendererComponentModifier(), + new UIParticleComponentModifier_AutoScaling(), + new UIParticleComponentModifier_AbsoluteMode(), + new UIParticleComponentModifier_IsTrail() + } + }), + (".prefab", x => new PrefabModifier + { + path = x, + componentModifiers = new IComponentModifier[] + { + new UIParticleRendererComponentModifier(), + new UIParticleComponentModifier_AutoScaling(), + new UIParticleComponentModifier_AbsoluteMode(), + new UIParticleComponentModifier_IsTrail() + } + }) + }) + { + } + + [MenuItem("UIParticleModifierRunner/Run")] + private static void Run() + { + new UIParticleModifierRunner().RunIfUserWantsTo(); + } + } +} diff --git a/Packages/src/Editor/AssetModification/UIParticleModifierRunner.cs.meta b/Packages/src/Editor/AssetModification/UIParticleModifierRunner.cs.meta new file mode 100644 index 0000000..545fbfd --- /dev/null +++ b/Packages/src/Editor/AssetModification/UIParticleModifierRunner.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: edd678db452e49869caeca7e7d269e5d +timeCreated: 1704502476 \ No newline at end of file diff --git a/Packages/src/Editor/AssetModification/UIParticleRendererComponentModifier.cs b/Packages/src/Editor/AssetModification/UIParticleRendererComponentModifier.cs new file mode 100644 index 0000000..8dc04ce --- /dev/null +++ b/Packages/src/Editor/AssetModification/UIParticleRendererComponentModifier.cs @@ -0,0 +1,29 @@ +using Coffee.UIExtensions; +using Coffee.UIParticleInternal.AssetModification; +using UnityEditor; +using UnityEngine; + +namespace Coffee.UIParticleInternal +{ + internal class UIParticleRendererComponentModifier : ComponentModifier + { + protected override bool ModifyComponent(UIParticleRenderer c, bool dryRun) + { + if (c.hideFlags.HasFlag(HideFlags.DontSave | HideFlags.NotEditable)) return false; + + if (!dryRun) + { + var go = c.gameObject; + Object.DestroyImmediate(c); + EditorUtility.SetDirty(go); + } + + return true; + } + + public override string Report() + { + return " -> UIParticleRenderer component is now auto-generated object. Remove them.\n"; + } + } +} diff --git a/Packages/src/Editor/AssetModification/UIParticleRendererComponentModifier.cs.meta b/Packages/src/Editor/AssetModification/UIParticleRendererComponentModifier.cs.meta new file mode 100644 index 0000000..d72e25b --- /dev/null +++ b/Packages/src/Editor/AssetModification/UIParticleRendererComponentModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b2a025408e4a7486a941102775d2c73b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/Internal/AssetModification.meta b/Packages/src/Editor/Internal/AssetModification.meta new file mode 100644 index 0000000..6ab72f6 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 269bcefd175184eebbfa31421171fadf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/Internal/AssetModification/ComponentModifier.cs b/Packages/src/Editor/Internal/AssetModification/ComponentModifier.cs new file mode 100644 index 0000000..ac6bcab --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/ComponentModifier.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Coffee.UIParticleInternal.AssetModification +{ + internal abstract class ComponentModifier : IComponentModifier where T : Component + { + private static readonly List s_Components = new List(); + + public bool isModified { get; private set; } + + public bool ModifyComponent(GameObject root, bool dryRun) + { + root.GetComponentsInChildren(true, s_Components); + foreach (var c in s_Components) + { + if (PrefabUtility.IsPartOfAnyPrefab(c.gameObject)) continue; + + if (ModifyComponent(c, dryRun)) + { + isModified = true; + } + } + + return isModified; + } + + public abstract string Report(); + + protected abstract bool ModifyComponent(T component, bool dryRun); + } +} diff --git a/Packages/src/Editor/Internal/AssetModification/ComponentModifier.cs.meta b/Packages/src/Editor/Internal/AssetModification/ComponentModifier.cs.meta new file mode 100644 index 0000000..68a483e --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/ComponentModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 338da2d8cec784add924489fc4a7bb01 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/Internal/AssetModification/GameObjectModifier.cs b/Packages/src/Editor/Internal/AssetModification/GameObjectModifier.cs new file mode 100644 index 0000000..7b4a11c --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/GameObjectModifier.cs @@ -0,0 +1,43 @@ +using System.Linq; +using System.Text; +using UnityEngine; + +namespace Coffee.UIParticleInternal.AssetModification +{ + internal abstract class GameObjectModifier : Modifier + { + private static readonly StringBuilder s_ReportLog = new StringBuilder(); + public IComponentModifier[] componentModifiers; + + protected bool ModifyGameObject(GameObject root, bool dryRun) + { + foreach (var modifier in componentModifiers) + { + modifier.ModifyComponent(root, dryRun); + } + + return componentModifiers.Any(x => x.isModified); + } + + protected override string ModificationReport() + { + if (!hasUpgraded) return string.Empty; + + s_ReportLog.Length = 0; + foreach (var componentModifier in componentModifiers) + { + if (componentModifier.isModified) + { + s_ReportLog.Append(componentModifier.Report()); + } + } + + if (0 < s_ReportLog.Length) + { + s_ReportLog.Length--; + } + + return s_ReportLog.ToString(); + } + } +} diff --git a/Packages/src/Editor/Internal/AssetModification/GameObjectModifier.cs.meta b/Packages/src/Editor/Internal/AssetModification/GameObjectModifier.cs.meta new file mode 100644 index 0000000..862c22a --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/GameObjectModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f16bc447ca4934ca3b9329d1d870440a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/Internal/AssetModification/IComponentModifier.cs b/Packages/src/Editor/Internal/AssetModification/IComponentModifier.cs new file mode 100644 index 0000000..c67592c --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/IComponentModifier.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace Coffee.UIParticleInternal.AssetModification +{ + internal interface IComponentModifier + { + bool isModified { get; } + bool ModifyComponent(GameObject root, bool dryRun); + string Report(); + } +} diff --git a/Packages/src/Editor/Internal/AssetModification/IComponentModifier.cs.meta b/Packages/src/Editor/Internal/AssetModification/IComponentModifier.cs.meta new file mode 100644 index 0000000..23eb2f0 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/IComponentModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e50323d0799f4daf8ef476f7bf403a4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/Internal/AssetModification/ITextModifier.cs b/Packages/src/Editor/Internal/AssetModification/ITextModifier.cs new file mode 100644 index 0000000..bcfe547 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/ITextModifier.cs @@ -0,0 +1,9 @@ +using System.Text; + +namespace Coffee.UIParticleInternal.AssetModification +{ + internal interface ITextModifier + { + bool ModifyText(StringBuilder sb, string text); + } +} diff --git a/Packages/src/Editor/Internal/AssetModification/ITextModifier.cs.meta b/Packages/src/Editor/Internal/AssetModification/ITextModifier.cs.meta new file mode 100644 index 0000000..967a444 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/ITextModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2ad967b4f039b4deba09ed0c1401cf83 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/Internal/AssetModification/Modifier.cs b/Packages/src/Editor/Internal/AssetModification/Modifier.cs new file mode 100644 index 0000000..ec9c74c --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/Modifier.cs @@ -0,0 +1,41 @@ +using System; + +namespace Coffee.UIParticleInternal.AssetModification +{ + internal abstract class Modifier + { + private string _error; + public string path; + + protected abstract string id { get; } + protected bool hasUpgraded { private set; get; } + + public void Modify(bool dryRun) + { + try + { + hasUpgraded = RunModify(dryRun); + } + catch (Exception e) + { + _error = e.Message; + } + } + + public string GetModificationReport() + { + return !string.IsNullOrEmpty(_error) + ? $"[{id} (Error)] {path} {_error}\n" + : hasUpgraded + ? $"[{id}] {path} {ModificationReport()}\n" + : string.Empty; + } + + protected abstract bool RunModify(bool dryRun); + + protected virtual string ModificationReport() + { + return string.Empty; + } + } +} diff --git a/Packages/src/Editor/Internal/AssetModification/Modifier.cs.meta b/Packages/src/Editor/Internal/AssetModification/Modifier.cs.meta new file mode 100644 index 0000000..09dc316 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/Modifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c716fe53d75054d309923c577f5059a4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/Internal/AssetModification/PrefabModifier.cs b/Packages/src/Editor/Internal/AssetModification/PrefabModifier.cs new file mode 100644 index 0000000..d0eccad --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/PrefabModifier.cs @@ -0,0 +1,48 @@ +using System; +using UnityEditor; +using UnityEngine; + +namespace Coffee.UIParticleInternal.AssetModification +{ + internal class PrefabModifier : GameObjectModifier + { + protected override string id => "Prefab"; + + protected override bool RunModify(bool dryRun) + { + using (var scope = new EditScope(path)) + { + var changed = ModifyGameObject(scope.root, dryRun); + + if (!dryRun && changed) + { + scope.Save(); + } + + return changed; + } + } + + private readonly struct EditScope : IDisposable + { + private readonly string _path; + public readonly GameObject root; + + public EditScope(string path) + { + _path = path; + root = PrefabUtility.LoadPrefabContents(path); + } + + public void Dispose() + { + PrefabUtility.UnloadPrefabContents(root); + } + + public void Save() + { + PrefabUtility.SaveAsPrefabAsset(root, _path); + } + } + } +} diff --git a/Packages/src/Editor/Internal/AssetModification/PrefabModifier.cs.meta b/Packages/src/Editor/Internal/AssetModification/PrefabModifier.cs.meta new file mode 100644 index 0000000..7bb9475 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/PrefabModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a50643d4fde75458cae1f0d4ef9549ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/Internal/AssetModification/Runner.cs b/Packages/src/Editor/Internal/AssetModification/Runner.cs new file mode 100644 index 0000000..521f842 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/Runner.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; + +namespace Coffee.UIParticleInternal.AssetModification +{ + internal class Runner + { + private readonly List<(string ext, Func create)> _factory; + private readonly string _name; + + protected Runner(string name, List<(string ext, Func create)> factory) + { + _name = name; + _factory = factory; + } + + private Modifier CreateFromPath(string assetPath) + { + var ext = Path.GetExtension(assetPath); + return _factory + .FirstOrDefault(x => x.ext == ext) + .create?.Invoke(assetPath); + } + + private Modifier[] GetModifiers(string[] assetPaths) + { + return assetPaths + .Where(x => x.StartsWith("Assets/", StringComparison.Ordinal)) + .Select(CreateFromPath) + .Where(x => x != null) + .OrderBy(x => Path.GetExtension(x.path)) + .ToArray(); + } + + public void RunIfUserWantsTo() + { + var select = EditorUtility.DisplayDialogComplex($"Upgrade {_name}", + "Upgrade all assets in this project?\n\n" + + "'Go Ahead': Upgrades all assets in this project using the old APIs. You should make a backup before proceeding.\n\n" + + "'Dry Run': Outputs the upgrade summary to the console without changing.", "I Made a Backup. Go Ahead!", + "No Thanks", "Dry Run"); + if (select == 1) return; + + if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) return; + + var assetPaths = AssetDatabase.GetAllAssetPaths(); + var dryRun = select == 2; + Run(assetPaths, dryRun); + } + + public void Run(string[] assetPaths, bool dryRun) + { + var modifiers = GetModifiers(assetPaths); + var canceled = false; + + try + { + AssetDatabase.StartAssetEditing(); + EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); + + for (var i = 0; i < modifiers.Length; i++) + { + var percentage = (float)i / modifiers.Length; + var m = modifiers[i]; + if (EditorUtility.DisplayCancelableProgressBar("Upgrading...", m.path, percentage)) + { + canceled = true; + break; + } + + m.Modify(dryRun); + } + } + catch (Exception e) + { + Debug.LogException(e); + } + finally + { + var sb = new StringBuilder(); + sb.Append(dryRun ? "[DryRun] " : ""); + sb.AppendLine($"Modify '{_name}' is {(canceled ? "canceled" : "completed")}."); + sb.AppendLine("==== Modifications ===="); + Debug.Log(modifiers.Aggregate(sb, (x, m) => x.Append(m.GetModificationReport()))); + EditorUtility.ClearProgressBar(); + AssetDatabase.StopAssetEditing(); + AssetDatabase.Refresh(); + } + } + } +} diff --git a/Packages/src/Editor/Internal/AssetModification/Runner.cs.meta b/Packages/src/Editor/Internal/AssetModification/Runner.cs.meta new file mode 100644 index 0000000..b941c9e --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/Runner.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f28067cf4bfca4d92bd5262ac5c7a652 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/Internal/AssetModification/SceneModifier.cs b/Packages/src/Editor/Internal/AssetModification/SceneModifier.cs new file mode 100644 index 0000000..8267207 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/SceneModifier.cs @@ -0,0 +1,53 @@ +using System; +using UnityEditor.SceneManagement; +using UnityEngine.SceneManagement; + +namespace Coffee.UIParticleInternal.AssetModification +{ + internal class SceneModifier : GameObjectModifier + { + protected override string id => "Scene"; + + protected override bool RunModify(bool dryRun) + { + using (var scope = new EditScope(path)) + { + var changed = false; + foreach (var root in scope.scene.GetRootGameObjects()) + { + if (ModifyGameObject(root, dryRun)) + { + changed = true; + } + } + + if (!dryRun && changed) + { + scope.Save(); + } + + return changed; + } + } + + private readonly struct EditScope : IDisposable + { + public readonly Scene scene; + + public EditScope(string path) + { + scene = EditorSceneManager.OpenScene(path, OpenSceneMode.Additive); + } + + public void Dispose() + { + EditorSceneManager.CloseScene(scene, true); + } + + public void Save() + { + EditorSceneManager.SaveScene(scene); + } + } + } +} diff --git a/Packages/src/Editor/Internal/AssetModification/SceneModifier.cs.meta b/Packages/src/Editor/Internal/AssetModification/SceneModifier.cs.meta new file mode 100644 index 0000000..e43cbaa --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/SceneModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6764c0c6fd61a4f66a8b0e3467be420d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/Internal/AssetModification/TextAssetModifier.cs b/Packages/src/Editor/Internal/AssetModification/TextAssetModifier.cs new file mode 100644 index 0000000..cf43857 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/TextAssetModifier.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Coffee.UIParticleInternal.AssetModification +{ + internal class TextAssetModifier : Modifier + { + public ITextModifier[] textModifiers; + protected override string id => "Text"; + protected virtual string savePath => path; + + protected override bool RunModify(bool dryRun) + { + var changed = false; + using (var scope = new EditScope(path, savePath)) + { + foreach (var line in scope.lines) + { + if (ModifyLine(scope.sb, line)) + { + changed = true; + } + else + { + scope.sb.AppendLine(line); + } + } + + if (!dryRun && changed) + { + scope.Save(); + } + + return changed; + } + } + + private bool ModifyLine(StringBuilder sb, string line) + { + foreach (var modifier in textModifiers) + { + if (modifier.ModifyText(sb, line)) + { + return true; + } + } + + return false; + } + + private readonly struct EditScope : IDisposable + { + private static readonly StringBuilder s_File = new StringBuilder(); + private readonly string _path; + private readonly string _savePath; + public IEnumerable lines => File.ReadLines(_path); + public StringBuilder sb => s_File; + + public EditScope(string path, string savePath) + { + s_File.Length = 0; + _path = path; + _savePath = savePath; + } + + public void Dispose() + { + } + + public void Save() + { + File.WriteAllText(_savePath, sb.ToString()); + } + } + } +} diff --git a/Packages/src/Editor/Internal/AssetModification/TextAssetModifier.cs.meta b/Packages/src/Editor/Internal/AssetModification/TextAssetModifier.cs.meta new file mode 100644 index 0000000..cc24bf2 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/TextAssetModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 431e5b95f2f5c4f19926a7fc5342e118 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/src/Editor/Internal/AssetModification/TextReplaceModifier.cs b/Packages/src/Editor/Internal/AssetModification/TextReplaceModifier.cs new file mode 100644 index 0000000..4dd1e65 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/TextReplaceModifier.cs @@ -0,0 +1,25 @@ +using System.Text; +using System.Text.RegularExpressions; + +namespace Coffee.UIParticleInternal.AssetModification +{ + internal class TextReplaceModifier : ITextModifier + { + private readonly Regex _pattern; + private readonly string _replace; + + public TextReplaceModifier(string pattern, string replace) + { + _pattern = new Regex(pattern); + _replace = replace; + } + + public bool ModifyText(StringBuilder sb, string text) + { + if (!_pattern.IsMatch(text)) return false; + + sb.AppendLine(_pattern.Replace(text, _replace)); + return true; + } + } +} diff --git a/Packages/src/Editor/Internal/AssetModification/TextReplaceModifier.cs.meta b/Packages/src/Editor/Internal/AssetModification/TextReplaceModifier.cs.meta new file mode 100644 index 0000000..fe35ab6 --- /dev/null +++ b/Packages/src/Editor/Internal/AssetModification/TextReplaceModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: afc6ba9550e5e4c25951b03db43a4fd0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: