Created
May 1, 2024 08:23
-
-
Save JLChnToZ/aaaf2c03f63bbb665b3f8270fbeb8348 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if UNITY_EDITOR | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.UI; | |
using TMPro; | |
using UnityEditor; | |
using QvPen.UdonScript; | |
using QvPen.UdonScript.UI; | |
public class QvPenTMProMigrator { | |
readonly TMProSimpleReplacer migrator = new TMProSimpleReplacer(); | |
[MenuItem("CONTEXT/QvPen_Settings/Migrate to TextMeshPro")] | |
[MenuItem("CONTEXT/QvPen_PenManager/Migrate to TextMeshPro")] | |
[MenuItem("CONTEXT/QvPen_EraserManager/Migrate to TextMeshPro")] | |
[MenuItem("CONTEXT/QvPen_ResetAllButton/Migrate to TextMeshPro")] | |
static void Migrate(MenuCommand cmd) { | |
var migrator = new QvPenTMProMigrator(); | |
if (cmd.context is QvPen_Settings settings) | |
migrator.Migrate(settings); | |
else if (cmd.context is QvPen_PenManager penManager) | |
migrator.Migrate(penManager); | |
else if (cmd.context is QvPen_EraserManager eraserManager) | |
migrator.Migrate(eraserManager); | |
else if (cmd.context is QvPen_ResetAllButton resetAllButton) | |
migrator.Migrate(resetAllButton); | |
var group = Undo.GetCurrentGroup(); | |
Undo.SetCurrentGroupName("Migrate QvPen to TextMeshPro"); | |
Undo.CollapseUndoOperations(group); | |
} | |
public void Migrate(QvPen_Settings settings) { | |
Transform pensParent = null, erasersParent = null; | |
using (var so = new SerializedObject(settings)) { | |
pensParent = so.FindProperty("pensParent").objectReferenceValue as Transform; | |
erasersParent = so.FindProperty("erasersParent").objectReferenceValue as Transform; | |
if (Migrate(so, "information")) | |
so.ApplyModifiedProperties(); | |
} | |
if (pensParent != null) | |
foreach (var pen in pensParent.GetComponentsInChildren<QvPen_PenManager>(true)) | |
Migrate(pen); | |
if (erasersParent != null) | |
foreach (var eraser in erasersParent.GetComponentsInChildren<QvPen_EraserManager>(true)) | |
Migrate(eraser); | |
var parent = settings.transform.parent; | |
if (parent != null) { | |
var resetAllButton = parent.GetComponentInChildren<QvPen_ResetAllButton>(true); | |
if (resetAllButton != null) | |
Migrate(resetAllButton); | |
} | |
} | |
public void Migrate(QvPen_PenManager penManager) { | |
using (var so = new SerializedObject(penManager)) | |
if (Migrate(so, "textInUse")) | |
so.ApplyModifiedProperties(); | |
} | |
public void Migrate(QvPen_EraserManager eraserManager) { | |
using (var so = new SerializedObject(eraserManager)) | |
if (Migrate(so, "textInUse")) | |
so.ApplyModifiedProperties(); | |
} | |
public void Migrate(QvPen_ResetAllButton resetAllButton) { | |
using (var so = new SerializedObject(resetAllButton)) | |
if (Migrate(so, "message")) | |
so.ApplyModifiedProperties(); | |
} | |
bool Migrate(SerializedObject serializedObject, string fieldPrefix) { | |
var tmpProperty = serializedObject.FindProperty($"{fieldPrefix}TMP"); | |
if (tmpProperty.objectReferenceValue != null) return false; | |
var tmpuProperty = serializedObject.FindProperty($"{fieldPrefix}TMPU"); | |
if (tmpuProperty.objectReferenceValue != null) return false; | |
var textProperty = serializedObject.FindProperty(fieldPrefix); | |
var text = textProperty.objectReferenceValue as Text; | |
if (text == null) return false; | |
var tmpu = migrator.Migrate(text); | |
if (tmpu == null) return false; | |
tmpuProperty.objectReferenceValue = tmpu; | |
textProperty.objectReferenceValue = null; | |
return true; | |
} | |
} | |
public class TMProSimpleReplacer { | |
readonly Dictionary<Font, TMP_FontAsset> fontAssetMapping = new Dictionary<Font, TMP_FontAsset>(); | |
public TMProSimpleReplacer() { | |
foreach (var guid in AssetDatabase.FindAssets("t:TMP_FontAsset", new[] { "Assets", "Packages" })) { | |
var path = AssetDatabase.GUIDToAssetPath(guid); | |
var fontAsset = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>(path); | |
if (fontAsset == null) continue; | |
var font = fontAsset.sourceFontFile; | |
if (font == null) { | |
using (var so = new SerializedObject(fontAsset)) | |
font = so.FindProperty("m_SourceFontFile_EditorRef").objectReferenceValue as Font; | |
if (font == null) continue; | |
} | |
fontAssetMapping[font] = fontAsset; | |
} | |
} | |
public TextMeshProUGUI Migrate(Text textComponent) { | |
if (textComponent == null) return null; | |
var text = textComponent.text; | |
var font = textComponent.font; | |
var fontSize = textComponent.fontSize; | |
var fontStyle = textComponent.fontStyle; | |
var alignment = textComponent.alignment; | |
var alignByGeometry = textComponent.alignByGeometry; | |
var color = textComponent.color; | |
var lineSpacing = textComponent.lineSpacing; | |
var richText = textComponent.supportRichText; | |
var vertOverflow = textComponent.verticalOverflow; | |
var horzOverflow = textComponent.horizontalOverflow; | |
var bestFit = textComponent.resizeTextForBestFit; | |
var minSize = textComponent.resizeTextMinSize; | |
var maxSize = textComponent.resizeTextMaxSize; | |
var raycastTarget = textComponent.raycastTarget; | |
var gameObject = textComponent.gameObject; | |
Undo.DestroyObjectImmediate(textComponent); | |
var tmpComponent = Undo.AddComponent<TextMeshProUGUI>(gameObject); | |
if (tmpComponent == null) return null; | |
tmpComponent.text = text; | |
if (font == null || !fontAssetMapping.TryGetValue(font, out var fontAsset)) | |
fontAsset = TMP_Settings.GetFontAsset(); | |
if (fontAsset != null) tmpComponent.font = fontAsset; | |
tmpComponent.fontSize = fontSize; | |
switch (fontStyle) { | |
case FontStyle.Bold: tmpComponent.fontStyle = FontStyles.Bold; break; | |
case FontStyle.Italic: tmpComponent.fontStyle = FontStyles.Italic; break; | |
case FontStyle.BoldAndItalic: tmpComponent.fontStyle = FontStyles.Bold | FontStyles.Italic; break; | |
default: tmpComponent.fontStyle = FontStyles.Normal; break; | |
} | |
switch (alignment) { | |
case TextAnchor.UpperLeft: tmpComponent.alignment = TextAlignmentOptions.TopLeft; break; | |
case TextAnchor.UpperCenter: tmpComponent.alignment = alignByGeometry ? TextAlignmentOptions.TopGeoAligned : TextAlignmentOptions.Top; break; | |
case TextAnchor.UpperRight: tmpComponent.alignment = TextAlignmentOptions.TopRight; break; | |
case TextAnchor.MiddleLeft: tmpComponent.alignment = TextAlignmentOptions.Left; break; | |
case TextAnchor.MiddleCenter: tmpComponent.alignment = alignByGeometry ? TextAlignmentOptions.CenterGeoAligned : TextAlignmentOptions.Center; break; | |
case TextAnchor.MiddleRight: tmpComponent.alignment = TextAlignmentOptions.Right; break; | |
case TextAnchor.LowerLeft: tmpComponent.alignment = TextAlignmentOptions.BottomLeft; break; | |
case TextAnchor.LowerCenter: tmpComponent.alignment = alignByGeometry ? TextAlignmentOptions.BottomGeoAligned : TextAlignmentOptions.Bottom; break; | |
case TextAnchor.LowerRight: tmpComponent.alignment = TextAlignmentOptions.BottomRight; break; | |
default: tmpComponent.alignment = alignByGeometry ? TextAlignmentOptions.MidlineGeoAligned : TextAlignmentOptions.Center; break; | |
} | |
tmpComponent.color = color; | |
tmpComponent.lineSpacing = (lineSpacing - 1) * 100; | |
tmpComponent.richText = richText; | |
tmpComponent.overflowMode = vertOverflow == VerticalWrapMode.Truncate ? TextOverflowModes.Truncate : TextOverflowModes.Overflow; | |
tmpComponent.enableWordWrapping = horzOverflow == HorizontalWrapMode.Wrap; | |
tmpComponent.enableAutoSizing = bestFit; | |
tmpComponent.fontSizeMin = minSize; | |
tmpComponent.fontSizeMax = maxSize; | |
tmpComponent.raycastTarget = raycastTarget; | |
return tmpComponent; | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment