Skip to content

Instantly share code, notes, and snippets.

@ShayBox
Last active April 27, 2023 02:09
Show Gist options
  • Save ShayBox/fdeb46ceeef3420aa962d0ee7ea900f3 to your computer and use it in GitHub Desktop.
Save ShayBox/fdeb46ceeef3420aa962d0ee7ea900f3 to your computer and use it in GitHub Desktop.
My custom VRChat avatar upload tool
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using VRC.SDK3.Avatars.Components;
using VRC.SDKBase.Editor;
namespace ShayBox {
public class ShaysUploadTool : EditorWindow {
#if UNITY_STANDALONE_WIN
public static readonly string PLATFORM = "PC";
public static readonly string SUFFIX = " (PC)";
#elif UNITY_ANDROID
public static readonly string PLATFORM = "Quest";
public static readonly string SUFFIX = " (Quest)";
#endif
[MenuItem(itemName: "Window/Shays Upload Tool")]
public static void ShowWindow() => GetWindow<ShaysUploadTool>(title: "Shays Upload Tool");
public void OnEnable() => EditorApplication.playModeStateChanged += PlayModeStateChanged;
public void OnDisable() => EditorApplication.playModeStateChanged -= PlayModeStateChanged;
public bool isWaitingForPlaymode = false;
public void PlayModeStateChanged(PlayModeStateChange state)
{
if (state is PlayModeStateChange.EnteredEditMode)
{
isWaitingForPlaymode = false;
}
}
public GameObject uploadObject = null;
// Window Render Loop
public void OnGUI() {
// Variables
Scene scene = SceneManager.GetActiveScene();
GameObject[] sceneAvatarObjects = scene.GetRootGameObjects()
.SelectMany(obj => obj.GetComponentsInChildren<VRCAvatarDescriptor>(includeInactive: false))
.Select(obj => obj.gameObject)
.Distinct()
.ToArray();
// Pre-conditions
if (sceneAvatarObjects.Length < 1) {
GUILayout.Label(text: "No Avatars Found");
return;
}
foreach (GameObject obj in sceneAvatarObjects) {
if (GUILayout.Button(text: "Build & Upload " + obj.name)) {
isWaitingForPlaymode = true;
uploadObject = obj;
VRC_SdkBuilder.RunExportAndUploadAvatarBlueprint(obj);
}
}
}
// Game Update Loop
public void Update() {
if (EditorApplication.isPlaying && EditorApplication.isPlayingOrWillChangePlaymode) {
// Play Mode
// Wait for VRCSDK to load
if (Time.frameCount < 500 && isWaitingForPlaymode) {
return;
}
// Variables
Scene scene = SceneManager.GetActiveScene();
GameObject[] sceneObjects = scene.GetRootGameObjects();
GameObject VRCSDK = sceneObjects.Where(predicate: obj => obj.name.Equals(value: "VRCSDK")).First();
// Pre-conditions
if (VRCSDK == null) {
GUILayout.Label(text: "No VRCSDK Found");
return;
}
Toggle[] toggles = VRCSDK.GetComponentsInChildren<Toggle>();
InputField[] inputFields = VRCSDK.GetComponentsInChildren<InputField>();
string input = uploadObject.name.Replace(oldValue: SUFFIX, newValue: "");
if (Time.frameCount == 500)
{
toggles.First(predicate: t => t.name.Equals(value: "ToggleWarrant")).isOn = true;
inputFields.First(predicate: f => f.name.Equals(value: "Name Input Field")).SetTextWithoutNotify(input);
inputFields.First(predicate: f => f.name.Equals(value: "Description Input Field")).SetTextWithoutNotify(input);
}
if (PLATFORM == "PC") {
GameObject gestureManager = sceneObjects.First(predicate: obj => obj.name.Equals(value: "GestureManager"));
if (gestureManager != null) {
Selection.SetActiveObjectWithContext(obj: gestureManager, context: null);
}
GameObject VRCCam = sceneObjects.First(predicate: obj => obj.name.Equals(value: "VRCCam"));
if (VRCCam == null) {
GUILayout.Label(text: "No VRCCam Found");
return;
}
Animator animator = uploadObject.GetComponent<Animator>();
Transform headTransform = animator.GetBoneTransform(humanBoneId: HumanBodyBones.Head);
VRCCam.transform.position = new Vector3(x: headTransform.position.x, y: headTransform.position.y, z: headTransform.localScale.z);
}
if (Time.frameCount == 600 && isWaitingForPlaymode)
{
if (PLATFORM == "PC")
{
toggles.First(predicate: t => t.name.Equals(value: "ImageUploadToggle")).isOn = true;
}
isWaitingForPlaymode = false;
Button[] buttons = VRCSDK.GetComponentsInChildren<Button>(includeInactive: true);
buttons.First(predicate: b => b.name.Equals(value: "UploadButton")).onClick.Invoke();
}
} else if (uploadObject != null) {
// Edit Mode
uploadObject.SetActive(value: false);
uploadObject = null;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment