using System; using UdonSharp; using UnityEngine; using UnityEngine.Serialization; using VRC.SDK3.Data; using UnityEditor; using VRC.SDKBase; namespace VRCBoard.Components { [UdonBehaviourSyncMode(BehaviourSyncMode.None)] public class VRCBoardImage : VRCBoardImageBaseComponent { [HideInInspector] public int materialIndex; [HideInInspector] public string[] imageIds = new string[0]; [HideInInspector] public string[] texturePropertyMappings = new string[0]; [HideInInspector] public Texture2D[] defaultTextures = new Texture2D[0]; private string _uploaderId = ""; private Renderer _renderer; private void Start() { _renderer = GetComponent(); OnImageLoaded(); } protected override void OnRegister() { Debug.Log("Registering image component"); OnImageLoaded(); } private void TryGetUploader() { if (!string.IsNullOrEmpty(_uploaderId)) return; if (imageIds.Length == 0) return; _uploaderId = GetUploader(imageIds[0]); if (string.IsNullOrEmpty(_uploaderId)) { Debug.LogError("Failed to get uploader ID"); return; } for (int i = 0; i < imageIds.Length; i++) { string imageId = imageIds[i]; RequestImageLoad(imageId, _uploaderId); } OnImageLoaded(); } protected override void OnInitialize() { TryGetUploader(); OnImageLoaded(); } protected override void OnImageDataUpdate() { // OnImageLoaded(); } protected override void OnSupporterDataUpdate() { TryGetUploader(); } protected override void OnImageLoaded() { //Debug.Log("Image loaded VRCBoardImage"); //bool textureSuccess = GetImageAtlasTexture(albedoImageId, _uploaderId, out Texture2D texture, out int atlasPosition, out int atlasSize, out string type1); MaterialPropertyBlock propertyBlock = new MaterialPropertyBlock(); for (int i = 0; i < imageIds.Length; i++) { if (i >= texturePropertyMappings.Length) continue; if (i >= defaultTextures.Length) continue; string propertyName = texturePropertyMappings[i]; Texture2D texture = manager ? manager.GetTexture2D(_uploaderId, imageIds[i]) : defaultTextures[i]; if (texture == null) { Debug.Log("texture was null, using default texture"); texture = defaultTextures[i]; } if (string.IsNullOrEmpty(propertyName)) continue; if (texture != null) propertyBlock.SetTexture(propertyName, texture); } if (_renderer) _renderer.SetPropertyBlock(propertyBlock,materialIndex); } } #if UNITY_EDITOR && !COMPILER_UDONSHARP [CustomEditor(typeof(VRCBoardImage), true)] public class VRCBoardImageComponentEditor : Editor { public void OnDisable() { VRCBoardImage script = (VRCBoardImage)target; Renderer renderer = script.GetComponent(); int materialCount = renderer.sharedMaterials.Length; MaterialPropertyBlock propertyBlock = new MaterialPropertyBlock(); for (int i = 0; i < materialCount; i++) { renderer.SetPropertyBlock(propertyBlock, i); } } public override void OnInspectorGUI() { base.OnInspectorGUI(); VRCBoardImage script = (VRCBoardImage)target; Renderer renderer = script.GetComponent(); if (renderer == null) { EditorGUILayout.HelpBox("No renderer, did you intend to use material override?", MessageType.Warning); return; } bool equals = Equals(script.imageIds.Length, script.defaultTextures.Length) && Equals(script.imageIds.Length, script.defaultTextures.Length); EditorGUILayout.Separator(); int materialCount = renderer.sharedMaterials.Length; int newMaterialIndex = materialCount > 1 ? EditorGUILayout.IntSlider("Material Slot", script.materialIndex, 0, materialCount - 1) : 0; newMaterialIndex = Mathf.Clamp(newMaterialIndex, 0, materialCount); if (newMaterialIndex != script.materialIndex) { script.materialIndex = newMaterialIndex; OnDisable(); EditorUtility.SetDirty(script); } if (renderer.sharedMaterials.Length == 0) { EditorGUILayout.HelpBox("Material has no material slots.", MessageType.Error); return; } Material material = renderer.sharedMaterials[newMaterialIndex]; if (material == null) { EditorGUILayout.HelpBox("No material assigned to material slot ("+newMaterialIndex+")", MessageType.Error); return; } string[] materialPropertyNames = material.GetPropertyNames(MaterialPropertyType.Texture); GUILayout.BeginVertical("Images", "window"); int newSize = script.imageIds.Length; GUILayout.BeginHorizontal(); if (GUILayout.Button("+")) { newSize++; } if (GUILayout.Button("-")) { newSize--; } GUILayout.EndHorizontal(); if (newSize != script.imageIds.Length || !equals) { Debug.Log("Resized arrays to"+newSize); Array.Resize(ref script.imageIds, newSize); Array.Resize(ref script.texturePropertyMappings, newSize); Array.Resize(ref script.defaultTextures, newSize); EditorUtility.SetDirty(script); } MaterialPropertyBlock propertyBlock = new MaterialPropertyBlock(); for (int i = 0; i < script.imageIds.Length; i++) { EditorGUILayout.Space(); GUILayout.BeginVertical("Image "+i, "window"); string imageId = script.imageIds[i]; string propertyName = script.texturePropertyMappings[i]; Texture2D defaultImage = script.defaultTextures[i]; imageId = EditorGUILayout.TextField("Image Id:", imageId); int selectedIndex = Array.IndexOf(materialPropertyNames, propertyName); selectedIndex = EditorGUILayout.Popup("Material Property:", selectedIndex, materialPropertyNames); bool propertyExists = Array.Exists(materialPropertyNames, materialProperty => materialProperty == propertyName); if (propertyExists) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Default Texture:"); defaultImage = EditorGUILayout.ObjectField(defaultImage, typeof(Texture2D), false) as Texture2D; EditorGUILayout.EndHorizontal(); if (defaultImage != null) propertyBlock.SetTexture(propertyName, defaultImage); } if (script.defaultTextures[i] != defaultImage) { script.defaultTextures[i] = defaultImage; EditorUtility.SetDirty(script); } if (script.imageIds[i] != imageId) { script.imageIds[i] = imageId; EditorUtility.SetDirty(script); } if (selectedIndex >= 0 && selectedIndex < materialPropertyNames.Length && script.texturePropertyMappings[i] != materialPropertyNames[selectedIndex]) { script.texturePropertyMappings[i] = materialPropertyNames[selectedIndex]; EditorUtility.SetDirty(script); } GUILayout.EndVertical(); } if (renderer && !Application.isPlaying) renderer.SetPropertyBlock(propertyBlock,script.materialIndex); EditorGUILayout.EndVertical(); } } #endif }