Skip to content

Instantly share code, notes, and snippets.

@JLChnToZ
Created May 1, 2024 08:23
Show Gist options
  • Save JLChnToZ/aaaf2c03f63bbb665b3f8270fbeb8348 to your computer and use it in GitHub Desktop.
Save JLChnToZ/aaaf2c03f63bbb665b3f8270fbeb8348 to your computer and use it in GitHub Desktop.
#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