├── .gitignore ├── LICENSE ├── Loading screen pictures ├── Loading screen pictures.csproj └── LoadingScreenPictures.cs └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | Loading screen pictures/bin/ 2 | Loading screen pictures/obj/ 3 | .vs/ 4 | Loading screen pictures.sln 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright 2021 (C) MarkViews 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 6 | software and associated documentation files (the "Software"), to deal in the Software 7 | without restriction, including without limitation the rights to use, copy, modify, 8 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 14 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 15 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 16 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 17 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Loading screen pictures/Loading screen pictures.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {D4CF15C8-47C6-452B-9082-1DAB52F33964} 8 | Library 9 | Loading_screen_pictures 10 | LoadingScreenPictures 11 | v4.7.2 12 | 512 13 | true 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | False 35 | ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\VRChat\MelonLoader\Managed\Assembly-CSharp.dll 36 | 37 | 38 | ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\VRChat\MelonLoader\Managed\Il2Cppmscorlib.dll 39 | 40 | 41 | False 42 | ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\VRChat\MelonLoader\MelonLoader.dll 43 | 44 | 45 | 46 | 47 | ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\VRChat\MelonLoader\Managed\UnhollowerBaseLib.dll 48 | 49 | 50 | ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.CoreModule.dll 51 | 52 | 53 | False 54 | ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.ImageConversionModule.dll 55 | 56 | 57 | ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\VRChat\MelonLoader\Managed\UnityEngine.PhysicsModule.dll 58 | 59 | 60 | ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\VRChat\MelonLoader\Managed\VRCCore-Editor.dll 61 | 62 | 63 | ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\VRChat\MelonLoader\Managed\VRCCore-Standalone.dll 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /Loading screen pictures/LoadingScreenPictures.cs: -------------------------------------------------------------------------------- 1 | using Il2CppSystem; 2 | using MelonLoader; 3 | using System.IO; 4 | using UnityEngine; 5 | using Loading_screen_pictures; 6 | using System.Linq; 7 | using System.Collections; 8 | 9 | [assembly: MelonInfo(typeof(LoadingScreenPictures), "Loading Screen Pictures", "1.3.2", "MarkViews", "https://github.com/markviews/LoadingScreenPictures")] 10 | [assembly: MelonGame("VRChat", "VRChat")] 11 | 12 | namespace Loading_screen_pictures { 13 | internal class LoadingScreenPictures : MelonMod { 14 | 15 | private GameObject mainFrame; 16 | private GameObject cube; 17 | private Texture lastTexture; 18 | private Renderer screenRender, pic; 19 | private string folder_dir; 20 | private bool initUI = false; 21 | private bool enabled = true; 22 | private Vector3 originalSize; 23 | 24 | public override void OnApplicationStart() { 25 | MelonCoroutines.Start(UiManagerInitializer()); 26 | string default_dir = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) + @"\VRChat"; 27 | MelonPreferences.CreateCategory("LoadingScreenPictures", "Loading Screen Pictures"); 28 | MelonPreferences.CreateEntry("LoadingScreenPictures", "directory", default_dir, "Folder to get pictures from"); 29 | MelonPreferences.CreateEntry("LoadingScreenPictures", "enabled", true, "Enable"); 30 | folder_dir = MelonPreferences.GetEntryValue("LoadingScreenPictures", "directory"); 31 | enabled = MelonPreferences.GetEntryValue("LoadingScreenPictures", "enabled"); 32 | 33 | if (default_dir != folder_dir && !Directory.Exists(folder_dir)) { 34 | folder_dir = default_dir; 35 | MelonLogger.Msg("Couldn't find configured directory, using default directory"); 36 | } 37 | } 38 | 39 | public IEnumerator UiManagerInitializer() { 40 | while (VRCUiManager.prop_VRCUiManager_0 == null) yield return null; 41 | setup(); 42 | initUI = true; 43 | } 44 | 45 | public override void OnPreferencesSaved() { 46 | enabled = MelonPreferences.GetEntryValue("LoadingScreenPictures", "enabled"); 47 | if (enabled) setup(); 48 | else disable(); 49 | } 50 | 51 | private float wait = 0.0f; 52 | private bool hidden = false; 53 | 54 | public override void OnUpdate() { 55 | if (!enabled) return; 56 | 57 | if (Time.time > wait) { 58 | wait += 5f; 59 | if (hidden) { 60 | hidden = false; 61 | setup(); 62 | } 63 | } 64 | 65 | if (lastTexture == null) return; 66 | if (lastTexture == screenRender.material.mainTexture) return; 67 | lastTexture = screenRender.material.mainTexture; 68 | changePic(); 69 | } 70 | 71 | public override void OnSceneWasInitialized(int buildIndex, string sceneName) { 72 | switch (buildIndex) { 73 | case 1: 74 | case 2: 75 | break; 76 | default: //Causes this to run only once instead of multiple times. 77 | if (initUI && lastTexture == null) 78 | setup(); 79 | break; 80 | } 81 | } 82 | 83 | private void changePic() { 84 | Texture2D texture = new Texture2D(2, 2); 85 | ImageConversion.LoadImage(texture, File.ReadAllBytes(randImage())); 86 | pic.material.mainTexture = texture; 87 | if (pic.material.mainTexture.height > pic.material.mainTexture.width) { 88 | cube.transform.localScale = new Vector3(0.099f, 1, 0.175f); 89 | mainFrame.transform.localScale = new Vector3(10.80f, 19.20f, 1); 90 | } else { 91 | cube.transform.localScale = new Vector3(0.175f, 1, 0.099f); 92 | mainFrame.transform.localScale = new Vector3(19.20f, 10.80f, 1); 93 | } 94 | } 95 | 96 | private void disable() { 97 | MelonLogger.Msg("Disabled"); 98 | if (mainFrame) mainFrame.transform.localScale = originalSize; 99 | if (screenRender) screenRender.enabled = true; 100 | if (cube) GameObject.Destroy(cube); 101 | lastTexture = null; 102 | } 103 | 104 | private void setup() { 105 | if (!enabled || lastTexture != null) return; 106 | mainFrame = GameObject.Find("/UserInterface/MenuContent/Popups/LoadingPopup/3DElements/LoadingInfoPanel/InfoPanel_Template_ANIM/SCREEN/mainFrame"); 107 | originalSize = mainFrame.transform.localScale; 108 | 109 | GameObject screen = GameObject.Find("/UserInterface/MenuContent/Popups/LoadingPopup/3DElements/LoadingInfoPanel/InfoPanel_Template_ANIM/SCREEN/mainScreen"); 110 | //check if screenshots folder is empty 111 | String imageLink = randImage(); 112 | if (imageLink == null) { 113 | MelonLogger.Msg("No screenshots found in: " + folder_dir); 114 | return; 115 | } 116 | 117 | GameObject parentScreen = GameObject.Find("/UserInterface/MenuContent/Popups/LoadingPopup/3DElements/LoadingInfoPanel/InfoPanel_Template_ANIM/SCREEN"); 118 | screenRender = screen.GetComponent(); 119 | lastTexture = screenRender.material.mainTexture; 120 | 121 | //create new image 122 | cube = GameObject.CreatePrimitive(PrimitiveType.Plane); 123 | cube.transform.SetParent(parentScreen.transform); 124 | cube.transform.rotation = screen.transform.rotation; 125 | cube.transform.localPosition = new Vector3(0, 0, -0.19f); 126 | cube.GetComponent().enabled = false; 127 | cube.layer = LayerMask.NameToLayer("InternalUI"); 128 | Texture2D texture = new Texture2D(2, 2); 129 | ImageConversion.LoadImage(texture, File.ReadAllBytes(imageLink)); 130 | pic = cube.GetComponent(); 131 | pic.material.mainTexture = texture; 132 | 133 | //disable origial picture 134 | screenRender.enabled = false; 135 | 136 | //resize frame 137 | if (pic.material.mainTexture.height > pic.material.mainTexture.width) { 138 | cube.transform.localScale = new Vector3(0.099f, 1, 0.175f); 139 | mainFrame.transform.localScale = new Vector3(10.80f, 19.20f, 1); 140 | } else { 141 | cube.transform.localScale = new Vector3(0.175f, 1, 0.099f); 142 | mainFrame.transform.localScale = new Vector3(19.20f, 10.80f, 1); 143 | } 144 | 145 | //hide icon and title 146 | GameObject.Find("/UserInterface/MenuContent/Popups/LoadingPopup/3DElements/LoadingInfoPanel/InfoPanel_Template_ANIM/ICON").active = false; 147 | GameObject.Find("/UserInterface/MenuContent/Popups/LoadingPopup/3DElements/LoadingInfoPanel/InfoPanel_Template_ANIM/TITLE").active = false; 148 | 149 | MelonLogger.Msg("Setup Game Objects."); 150 | } 151 | 152 | private String randImage() { 153 | if (!Directory.Exists(folder_dir)) return null; 154 | string[] pics = Directory.GetFiles(folder_dir, "*.*", SearchOption.AllDirectories).Where(s => s.EndsWith(".png") || s.EndsWith(".jpeg")).ToArray(); 155 | if (pics.Length == 0) return null; 156 | int randPic = new Il2CppSystem.Random().Next(0, pics.Length); 157 | return pics[randPic].ToString(); 158 | } 159 | 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Loading Screen Pictures 2 | Replaces the tips in the loading screen with pictures from your VRChat screenshots folder!
3 |
4 | 5 | ### How to use 6 | 1. Download and install [MelonLoader](https://melonwiki.xyz/#/README) 7 | 2. Download [LoadingScreenPictures.dll](https://github.com/markviews/LoadingScreenPictures/releases) 8 | 3. Drag `LoadingScreenPictures.dll` into `VRChat/Mods` 9 | 4. Screenshots you take in game will show up in your loading screen! 10 | 11 | ### Notes 12 | * You can change the directory images are searched for in `VRChat/UserData/modprefs.ini` 13 | * Compatible with PhotoOrganization mod (searches subfolders) 14 | * Reads `.png` and `.jpeg` files 15 | 16 | ![Example picture](https://i.ibb.co/qgQTTRL/2020-11-03-22-55-24.png) 17 | 18 | ### Credits 19 | * HeyImRuu for adding vertical photo support 20 | * Arion-Kun for helping with error catching and optimization 21 | --------------------------------------------------------------------------------