Skip to content

Instantly share code, notes, and snippets.

@Slaynash
Last active February 7, 2022 21:17
Show Gist options
  • Save Slaynash/018d6de4e8d27faf08c0fe4a6c2854de to your computer and use it in GitHub Desktop.
Save Slaynash/018d6de4e8d27faf08c0fe4a6c2854de to your computer and use it in GitHub Desktop.
[VRChat] QuickMod Tab sample
public static class QuickModeUtils
{
public static (Transform tab, Transform menu) CreateNotificationTab(string name, string text, Color color, string imageDataBase64 = null)
{
List<GameObject> existingTabs = Resources.FindObjectsOfTypeAll<MonoBehaviourPublicObCoGaCoObCoObCoUnique>()[0].field_Public_ArrayOf_GameObject_0.ToList();
QuickMenu quickMenu = Resources.FindObjectsOfTypeAll<QuickMenu>()[0];
// Tab
MonoBehaviourPublicObCoGaCoObCoObCoUnique quickModeTabs = quickMenu.transform.Find("QuickModeTabs").GetComponent<MonoBehaviourPublicObCoGaCoObCoObCoUnique>();
Transform newTab = GameObject.Instantiate(quickModeTabs.transform.Find("NotificationsTab"), quickModeTabs.transform);
newTab.name = name + "Tab";
GameObject.DestroyImmediate(newTab.GetComponent<MonoBehaviourPublicGaTeSiSiUnique>());
SetTabIndex(newTab, (MonoBehaviourPublicObCoGaCoObCoObCoUnique.EnumNPublicSealedvaHoNoPl4vUnique)existingTabs.Count);
newTab.Find("Badge").GetComponent<RawImage>().color = color;
newTab.Find("Badge/NotificationsText").GetComponent<Text>().text = text;
existingTabs.Add(newTab.gameObject);
Resources.FindObjectsOfTypeAll<MonoBehaviourPublicObCoGaCoObCoObCoUnique>()[0].field_Public_ArrayOf_GameObject_0 = existingTabs.ToArray();
if (imageDataBase64 != null)
newTab.Find("Icon").GetComponent<Image>().sprite = CreateSpriteFromBase64(imageDataBase64);
else
newTab.Find("Icon").gameObject.SetActive(false);
// Menu
Transform quickModeMenus = quickMenu.transform.Find("QuickModeMenus");
RectTransform newMenu = new GameObject(name + "Menu", new Il2CppSystem.Type[] { Il2CppType.Of<RectTransform>() }).GetComponent<RectTransform>();
newMenu.SetParent(quickModeMenus, false);
newMenu.anchorMin = new Vector2(0, 1);
newMenu.anchorMax = new Vector2(0, 1);
newMenu.sizeDelta = new Vector2(1680f, 1200f);
newMenu.pivot = new Vector2(0.5f, 0.5f);
newMenu.anchoredPosition = new Vector2(0, 200f);
newMenu.gameObject.SetActive(false);
//Image menuBG = newMenu.gameObject.AddComponent<Image>();
//menuBG.color = new Color(0.2f, 0.2f, 0.22f);
// Tab interaction
newTab.GetComponent<Button>().onClick.AddListener((Action)(() =>
{
QuickMenu.prop_QuickMenu_0.field_Private_GameObject_6.SetActive(false);
QuickMenu.prop_QuickMenu_0.field_Private_GameObject_6 = newMenu.gameObject;
newMenu.gameObject.SetActive(true);
}));
return (newTab, newMenu);
}
private static void SetTabIndex(Transform tab, MonoBehaviourPublicObCoGaCoObCoObCoUnique.EnumNPublicSealedvaHoNoPl4vUnique value)
{
MonoBehaviour tabDescriptor = tab.GetComponents<MonoBehaviour>().First(c => c.GetIl2CppType().GetMethod("ShowTabContent") != null);
tabDescriptor.GetIl2CppType().GetFields().First(f => f.FieldType.IsEnum).SetValue(tabDescriptor, new Il2CppSystem.Int32 { m_value = (int)value }.BoxIl2CppObject());
}
private static Sprite CreateSpriteFromBase64(string data)
{
Texture2D t = new Texture2D(2, 2);
ImageConversion.LoadImage(t, Convert.FromBase64String(data));
Rect rect = new Rect(0.0f, 0.0f, t.width, t.height);
Vector2 pivot = new Vector2(0.5f, 0.5f);
Vector4 border = Vector4.zero;
Sprite s = Sprite.CreateSprite_Injected(t, ref rect, ref pivot, 100.0f, 0, SpriteMeshType.Tight, ref border, false);
return s;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment