Image Component Updates

This commit is contained in:
2024-12-22 12:25:55 +02:00
parent a035902d8e
commit 7f3e851854
14 changed files with 369 additions and 230 deletions

View File

@@ -71,6 +71,7 @@ namespace VRCBoard
[UdonSynced, FieldChangeCallback(nameof(InstanceOwner))] private string _instanceOwner;
public string[] imageIdDownloadQueue = new string[0];
[PublicAPI]
public void SetInstanceOwner(string owner)
{
instanceOwnerOverride = owner;
@@ -265,13 +266,15 @@ namespace VRCBoard
if (token.TokenType != TokenType.DataDictionary) return null;
return token.DataDictionary;
}
public bool _GetImageAtlasTexture(string imageId, string uploader, out int atlasIndex, out Texture2D texture, out int position, out int size, out string type)
public bool _GetImageAtlasTexture(string imageId, string uploader, out int atlasIndex, out Texture2D texture, out int position, out int size, out string type, out string hash)
{
texture = null;
position = -1;
size = -1;
atlasIndex = -1;
type = null;
hash = null;
DataDictionary imageInfo = _GetImageIdInfo(imageId);
if (imageInfo == null)
{
@@ -348,6 +351,13 @@ namespace VRCBoard
}
texture = _downloadedAtlasTextures[atlasIndex];
position = (int)positionToken.Double;
bool hashSuccess = uploadInfo.TryGetValue("h", out DataToken hashToken);
if (!hashSuccess || hashToken.TokenType != TokenType.String)
{
return false;
}
hash = hashToken.String;
return true;
}
public void _RequestImageLoad(string imageId, string uploader, VRCBoardBaseComponent component)
@@ -365,7 +375,7 @@ namespace VRCBoard
string imageId = split[0];
string uploader = split[1];
bool success = _GetImageAtlasTexture(imageId, uploader, out int atlasIndex, out Texture2D texture,
out int position, out int size, out string type);
out int position, out int size, out string type, out string hash);
//Debug.Log("Try download image " + combinedImageId + " success: " + success);
if (!success) return;
DownloadAtlas(atlasIndex);
@@ -582,13 +592,83 @@ namespace VRCBoard
foreach (var component in vrcBoardComponents)
component._OnAtlasImageLoaded(index);
}
private static int NextPowerOf2(int value)
{
if (value <= 0)
return 1;
// Use bitwise manipulation to find the next power of 2
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
return value + 1;
}
private string[] textureCacheKeys = new string[0];
private Texture2D[] textureCacheTextures = new Texture2D[0];
private int textureCacheCurrentSize = 0;
public void AddToTextureCache(string key, Texture2D texture)
{
// If the store is full, resize the arrays
if (textureCacheCurrentSize >= textureCacheKeys.Length)
{
ResizeArrays(textureCacheCurrentSize + 1);
}
// Add the new key-value pair
textureCacheKeys[textureCacheCurrentSize-1] = key;
textureCacheTextures[textureCacheCurrentSize-1] = texture;
}
// Method to get a texture by its key
public Texture2D GetFromTextureCache(string key)
{
for (int i = 0; i < textureCacheCurrentSize; i++)
{
if (textureCacheKeys[i] == key)
{
return textureCacheTextures[i];
}
}
Debug.LogWarning("Key not found: " + key);
return null;
}
private void ResizeArrays(int newSize)
{
string[] newKeys = new string[newSize];
Texture2D[] newTextures = new Texture2D[newSize];
// Copy existing data to the new arrays
for (int i = 0; i < textureCacheCurrentSize; i++)
{
newKeys[i] = textureCacheKeys[i];
newTextures[i] = textureCacheTextures[i];
}
// Replace old arrays with the new resized arrays
textureCacheKeys = newKeys;
textureCacheTextures = newTextures;
textureCacheCurrentSize = newSize;
}
[PublicAPI]
public Texture2D GetTexture2D(string uploader, string imageId)
public Texture2D GetTexture2D(string uploader, string imageId, out string imageHash)
{
bool success = _GetImageAtlasTexture(imageId, uploader, out int atlasIndex, out Texture2D texture,
out int position, out int size, out string type);
out int position, out int size, out string type, out string hash);
imageHash = hash;
Texture2D cachedTexture = GetFromTextureCache(hash);
if (cachedTexture != null) return cachedTexture;
if (!success || atlasIndex == -1)
{
Debug.LogWarning("[VRCBoard] [GetTexture2D] Failed to get texture for " + uploader);
@@ -604,25 +684,51 @@ namespace VRCBoard
int blockSize = (int)Mathf.Floor((float)(texture.width) / (float)(size));
int startX = position % size;
int startY = size - (int)Mathf.Floor((float)position / (float)size) - 1;
float startX = position % size;
float startY = size - (int)Mathf.Floor((float)position / (float)size) - 1;
startX = startX / size;
startY = startY / size;
// Debug.Log("texture startX:" + startX + ", startY:" + startY);
Debug.Log("texture startX:" + startX + ", startY:" + startY);
int textureSize = 1024;
Texture2D newTexture = new Texture2D (textureSize, textureSize);
int blockWidth = blockSize;
int blockHeight = blockSize;
Texture2D newTexture = new Texture2D (blockWidth, blockHeight);
Color[] pixels = texture.GetPixels(startX * blockWidth, startY * blockHeight, blockWidth, blockHeight);
newTexture.SetPixels(pixels);
Color[] stretchedPixels = new Color[textureSize * textureSize];
for (int y = 0; y < textureSize; y++)
{
for (int x = 0; x < textureSize; x++)
{
// Get the corresponding pixel from the original texture
float u = startX + ((float)x / textureSize / size);
float v = startY + ((float)y / textureSize / size);
// Sample the original texture at the calculated UV coordinates
Color pixel = texture.GetPixelBilinear(u, v);
stretchedPixels[y * textureSize + x] = pixel;
}
}
//Color[] pixels = texture.GetPixels(startX * blockSize, startY * blockSize, blockSize, blockSize);
newTexture.SetPixels(stretchedPixels);
newTexture.wrapMode = TextureWrapMode.Clamp;
newTexture.filterMode = FilterMode.Trilinear;
newTexture.anisoLevel = 1;
//newTexture.alphaIsTransparency = true;
newTexture.Apply();
AddToTextureCache(hash, newTexture);
return newTexture;
}
[PublicAPI]
public Texture2D GetTexture2D(string uploader, string imageId)
{
return GetTexture2D(uploader, imageId, out string imageHash);
}
public override void OnImageLoadError(IVRCImageDownload result)
{
base.OnImageLoadError(result);
@@ -776,7 +882,7 @@ namespace VRCBoard
if (GUILayout.Button("Link all VRCBoard components"))
{
VRCBoardBaseComponent[] components = FindObjectsOfType<VRCBoardBaseComponent>();
VRCBoardBaseComponent[] components = FindObjectsOfType<VRCBoardBaseComponent>(true);
manager.vrcBoardComponents = components;
// mark the object as dirty
EditorUtility.SetDirty(manager);