Files
VRCBoard-Udon/Components/VRCBoardImage.cs

241 lines
9.0 KiB
C#

using System;
using UdonSharp;
using UnityEngine;
using UnityEngine.Serialization;
using VRC.SDK3.Data;
using UnityEditor;
namespace VRCBoard.Components
{
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class VRCBoardImage : VRCBoardBaseComponent
{
[Header("Uploader ID (only applies to images of 'shared' or 'instance' type)")]
public string uploaderIdOverride;
[Header("Material Override (Optional, if set the properties are applied globally to all renderers using the material)")]
public Material materialOverride;
[HideInInspector] public string[] imageIds = new string[0];
[HideInInspector] public string[] texturePropertyMappings = new string[0];
[HideInInspector] public Texture2D[] defaultTextures = new Texture2D[0];
private string _mainType = "";
private string _uploaderId = "";
protected override void OnRegister()
{
Debug.Log("Registering image component");
}
private string GetUploader()
{
string uploaderId = "";
if (string.IsNullOrEmpty(uploaderIdOverride) && imageIds.Length > 0)
{
string firstImageID = imageIds[0];
GetImageAtlasTexture(firstImageID, null, out Texture2D albedoTexture, out int albedoAtlasPosition, out int albedoAtlasSize, out string albedoType);
if (albedoType == null)
{
Debug.LogError("Failed to get image type for albedo image");
return "";
}
_mainType = albedoType;
if (_mainType == "shared")
{
uploaderId = GetRandomUploader(firstImageID);
}
else
{
DataDictionary ownerInfo = manager.GetSupporterDataFromPlayer(manager.instanceOwner);
if (ownerInfo == null)
{
Debug.LogWarning("Failed to get owner info, user has likely not linked their account.");
return "";
}
bool ownerSuccess = ownerInfo.TryGetValue("id", out DataToken ownerToken);
if (!ownerSuccess || ownerToken.TokenType != TokenType.String)
{
Debug.LogWarning("Failed to get owner ID from owner info.");
return "";
}
uploaderId = ownerToken.String;
}
Debug.Log("image uploader: " + uploaderId);
} else
{
uploaderId = uploaderIdOverride;
}
return uploaderId;
}
private void TryGetUploader()
{
if (!string.IsNullOrEmpty(_uploaderId)) return;
_uploaderId = GetUploader();
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);
}
}
protected override void OnInitialize()
{
TryGetUploader();
}
protected override void OnImageDataUpdate()
{
TryGetUploader();
}
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;
string propertyName = texturePropertyMappings[i];
Texture2D texture = manager.GetTexture2D(_uploaderId, imageIds[i]);
if (texture == null)
{
texture = defaultTextures[i];
if (texture == null) continue;
}
if (string.IsNullOrEmpty(propertyName)) continue;
propertyBlock.SetTexture(propertyName, texture);
if (materialOverride != null) materialOverride.SetTexture(propertyName, texture);
}
GetComponent<Renderer>().SetPropertyBlock(propertyBlock);
}
}
#if UNITY_EDITOR && !COMPILER_UDONSHARP
[CustomEditor(typeof(VRCBoardImage), true)]
public class VRCBoardImageComponentEditor : Editor
{
public override void OnInspectorGUI()
{
VRCBoardImage script = (VRCBoardImage)target;
Renderer renderer = script.GetComponent<Renderer>();
Material material = renderer.sharedMaterial;
if (script.materialOverride)
{
EditorGUILayout.HelpBox("Material override enabled", MessageType.Info);
material = script.materialOverride;
}
string[] materialPropertyNames = material.GetPropertyNames(MaterialPropertyType.Texture);
base.OnInspectorGUI();
bool equals =
Equals(script.imageIds.Length, script.defaultTextures.Length) &&
Equals(script.imageIds.Length, script.defaultTextures.Length);
EditorGUILayout.Separator();
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.materialOverride != null) script.materialOverride.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();
}
renderer.SetPropertyBlock(propertyBlock);
EditorGUILayout.EndHorizontal();
}
}
#endif
}