Skip to content

Instantly share code, notes, and snippets.

@FairlySadPanda
Last active October 19, 2024 19:31
Show Gist options
  • Save FairlySadPanda/c8b81c50c7f6e9ce9e4f4c434a795d37 to your computer and use it in GitHub Desktop.
Save FairlySadPanda/c8b81c50c7f6e9ce9e4f4c434a795d37 to your computer and use it in GitHub Desktop.
Some handy editor scripting for working with UI text and buttons in VRChat Udon development
using System.Linq;
using TMPro;
using TMPro.EditorUtilities;
using UnityEditor;
using UnityEditor.Events;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.UI;
using VRC.Udon;
// Adds automation so the text on the button matches the button's name.
[CustomEditor(typeof(Button))]
public class ButtonEditorEnhancer : UnityEditor.UI.ButtonEditor
{
[SerializeField] private UdonBehaviour buttonOnClickUdonTarget;
private int selectedEvent;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
// Get the selected object. Update its text so it matches the name of the object.
// This is a grotty script.
var obj = Selection.activeGameObject;
if (!obj)
{
return;
}
var text = Selection.activeGameObject.GetComponentInChildren<TMP_Text>();
if (text)
{
text.text = obj.name;
}
buttonOnClickUdonTarget = (UdonBehaviour)EditorGUILayout.ObjectField("Target Udon Behaviour:", buttonOnClickUdonTarget, typeof(UdonBehaviour), true);
if (!buttonOnClickUdonTarget)
{
return;
}
// If we've provided an UdonTarget, set the button via some fun tricks, so we don't have to manually look up the name of the string corresponding to the exported Custom Event.
// Get the event names via an utter nonsense lookup.
var program = buttonOnClickUdonTarget.programSource.SerializedProgramAsset.RetrieveProgram();
if (program == null)
{
return;
}
var events = program.EntryPoints.GetExportedSymbols();
// Get the user to pick an event via a dropdown menu. This is an int; stash it.
selectedEvent = EditorGUILayout.Popup("Selected Event", selectedEvent, events.ToArray());
var buttonTarget = (Button) target;
// Clear all instances of the UdonBehaviour from the OnClick listener list.
// This means if you're using this automation you can't use the same UdonBehaviour twice in the same OnClick.
// Frankly, if you, are, skill issue. 🎃. Just write a single function that calls both internally. If you're
// doing something exceptionally cursed, just manually input the events!
for (var i = 0; i < buttonTarget.onClick.GetPersistentEventCount(); i++)
{
if (buttonTarget.onClick.GetPersistentTarget(i) != buttonOnClickUdonTarget)
{
continue;
}
UnityEventTools.RemovePersistentListener(buttonTarget.onClick, i);
}
// Stick a string persistent listener that directs to trigger SCE on the UB using the event the user picked.
UnityEventTools.AddStringPersistentListener(buttonTarget.onClick, buttonOnClickUdonTarget.SendCustomEvent, events[selectedEvent]);
// Write to the object. Note that once we close this inspector window, the behaviour we used for this automation
// will be cleared if we re-open the window. Which is totally a feature and not a limitation.
// Leaving this here in case we mess with the serialized object in an update to this script.
// serializedObject.ApplyModifiedProperties();
Undo.RecordObject(buttonTarget, "modified on-click events");
PrefabUtility.RecordPrefabInstancePropertyModifications(buttonTarget);
}
}
// Adds automation so the name of the text object matches the text of the object.
[CustomEditor(typeof(TextMeshProUGUI))]
public class TMProTextEnhancer : TMP_EditorPanelUI
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
// Get the selected object. Update its name so it matches the text of the object.
// This is a grotty script.
var obj = Selection.activeGameObject;
if (!obj)
{
return;
}
var text = Selection.activeGameObject.GetComponent<TMP_Text>();
if (text)
{
obj.name = text.text;
}
}
}
@FairlySadPanda
Copy link
Author

The above code is hereby declared as part of the public domain; the original author declares no ownership over it. No relationship is assumed between original author and user.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment