EVERYTHING
This commit is contained in:
@@ -0,0 +1,1160 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using BlockSpace.Account;
|
||||
using BlockSpace.Worlds;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BlockSpace.Voxels
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class InventoryController : MonoBehaviour
|
||||
{
|
||||
private enum InventoryMode
|
||||
{
|
||||
Avatars = 0,
|
||||
Creations = 1
|
||||
}
|
||||
|
||||
private const float ButtonPressCooldown = 0.2f;
|
||||
|
||||
private const float ButtonShrinkDuration = 0.08f;
|
||||
|
||||
private const float ButtonSettleDuration = 0.12f;
|
||||
|
||||
private const float ButtonPressedScale = 0.84f;
|
||||
|
||||
private const float ButtonOvershootScale = 1.04f;
|
||||
|
||||
private const string ButtonThockResourcePath = "Thock";
|
||||
|
||||
private const float AvatarVoxelSizeScale = 0.5f;
|
||||
|
||||
private const float CreationPreviewMaxSize = 3f;
|
||||
|
||||
[SerializeField]
|
||||
private VoxelGroupManager groupManager;
|
||||
|
||||
[SerializeField]
|
||||
private VRVoxelBrush voxelBrush;
|
||||
|
||||
[SerializeField]
|
||||
private string backendBaseUrl = "https://blockspacebackend-production.up.railway.app";
|
||||
|
||||
[Header("Buttons")]
|
||||
[SerializeField]
|
||||
private Collider avatarsButton;
|
||||
|
||||
[SerializeField]
|
||||
private Collider creationsButton;
|
||||
|
||||
[SerializeField]
|
||||
private Collider backButton;
|
||||
|
||||
[SerializeField]
|
||||
private Collider nextButton;
|
||||
|
||||
[SerializeField]
|
||||
private Collider saveButton;
|
||||
|
||||
[SerializeField]
|
||||
private Collider loadButton;
|
||||
|
||||
[Header("Previews")]
|
||||
[SerializeField]
|
||||
private Transform creationPreviewRoot;
|
||||
|
||||
[SerializeField]
|
||||
private Transform previewHead;
|
||||
|
||||
[SerializeField]
|
||||
private Transform previewLeft;
|
||||
|
||||
[SerializeField]
|
||||
private Transform previewRight;
|
||||
|
||||
[SerializeField]
|
||||
private AudioClip buttonThockClip;
|
||||
|
||||
[SerializeField]
|
||||
private bool debugLogs;
|
||||
|
||||
private readonly Dictionary<Transform, Vector3> buttonBaseScales = new Dictionary<Transform, Vector3>();
|
||||
|
||||
private readonly Dictionary<Transform, Coroutine> buttonAnimationCoroutines = new Dictionary<Transform, Coroutine>();
|
||||
|
||||
private readonly Dictionary<string, Transform> transformCache = new Dictionary<string, Transform>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private InventoryMode mode;
|
||||
|
||||
private readonly List<string> ids = new List<string>();
|
||||
|
||||
private int slotIndex;
|
||||
|
||||
private string equippedAvatarId = string.Empty;
|
||||
|
||||
private bool slotsDirty = true;
|
||||
|
||||
private float nextButtonPressTime;
|
||||
|
||||
private bool avatarsInsidePrev;
|
||||
|
||||
private bool creationsInsidePrev;
|
||||
|
||||
private bool backInsidePrev;
|
||||
|
||||
private bool nextInsidePrev;
|
||||
|
||||
private bool saveInsidePrev;
|
||||
|
||||
private bool loadInsidePrev;
|
||||
|
||||
private VoxelGroup previewCreationGroup;
|
||||
|
||||
private readonly List<VoxelGroup> previewCreationGroups = new List<VoxelGroup>();
|
||||
|
||||
private VoxelGroup previewHeadGroup;
|
||||
|
||||
private VoxelGroup previewLeftGroup;
|
||||
|
||||
private VoxelGroup previewRightGroup;
|
||||
|
||||
private bool warnedMissingAvatarPreviewRoots;
|
||||
|
||||
private bool warnedMissingCreationPreviewRoot;
|
||||
|
||||
private InventoryBackendClient client;
|
||||
|
||||
private int previewRequestToken;
|
||||
|
||||
public void Configure(VoxelGroupManager manager, VRVoxelBrush brush)
|
||||
{
|
||||
if (manager != null)
|
||||
{
|
||||
groupManager = manager;
|
||||
}
|
||||
if (brush != null)
|
||||
{
|
||||
voxelBrush = brush;
|
||||
}
|
||||
ResolveSceneReferences();
|
||||
EnsureButtonAudioAssigned();
|
||||
EnsurePreviewGroups();
|
||||
client = new InventoryBackendClient(backendBaseUrl);
|
||||
slotsDirty = true;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
ResolveSceneReferences();
|
||||
EnsureButtonAudioAssigned();
|
||||
EnsurePreviewGroups();
|
||||
client = new InventoryBackendClient(backendBaseUrl);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
StopAllCoroutines();
|
||||
ResetAllButtonScales();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
ResolveSceneReferences();
|
||||
EnsurePreviewGroups();
|
||||
if (!(groupManager == null))
|
||||
{
|
||||
HandleButton(avatarsButton, ref avatarsInsidePrev, delegate
|
||||
{
|
||||
SwitchMode(InventoryMode.Avatars);
|
||||
});
|
||||
HandleButton(creationsButton, ref creationsInsidePrev, delegate
|
||||
{
|
||||
SwitchMode(InventoryMode.Creations);
|
||||
});
|
||||
HandleButton(backButton, ref backInsidePrev, PrevSlot);
|
||||
HandleButton(nextButton, ref nextInsidePrev, NextSlot);
|
||||
HandleButton(saveButton, ref saveInsidePrev, SaveCurrentSlot);
|
||||
HandleButton(loadButton, ref loadInsidePrev, LoadCurrentSlot);
|
||||
if (slotsDirty)
|
||||
{
|
||||
slotsDirty = false;
|
||||
StartCoroutine(RefreshSlots());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SwitchMode(InventoryMode newMode)
|
||||
{
|
||||
if (mode != newMode)
|
||||
{
|
||||
mode = newMode;
|
||||
slotIndex = 0;
|
||||
if (mode == InventoryMode.Avatars)
|
||||
{
|
||||
ApplyEmptyCreationPreview();
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyEmptyAvatarPreview();
|
||||
}
|
||||
slotsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void PrevSlot()
|
||||
{
|
||||
if (ids.Count <= 0)
|
||||
{
|
||||
slotIndex = 0;
|
||||
return;
|
||||
}
|
||||
slotIndex = (slotIndex - 1 + ids.Count) % ids.Count;
|
||||
UpdatePreviewsForSelectedSlot();
|
||||
}
|
||||
|
||||
private void NextSlot()
|
||||
{
|
||||
if (ids.Count <= 0)
|
||||
{
|
||||
slotIndex = 0;
|
||||
return;
|
||||
}
|
||||
slotIndex = (slotIndex + 1) % ids.Count;
|
||||
UpdatePreviewsForSelectedSlot();
|
||||
}
|
||||
|
||||
private void SaveCurrentSlot()
|
||||
{
|
||||
string userFolderId = BlockSpaceAccountPrefs.GetUserFolderId();
|
||||
if (string.IsNullOrEmpty(userFolderId) || client == null || (mode == InventoryMode.Creations && (groupManager == null || !groupManager.CreatorMode || groupManager.EditingLocked)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
string orCreateSelectedId = GetOrCreateSelectedId();
|
||||
if (!string.IsNullOrEmpty(orCreateSelectedId))
|
||||
{
|
||||
if (mode == InventoryMode.Avatars)
|
||||
{
|
||||
StartCoroutine(SaveAvatarSlot(userFolderId, orCreateSelectedId));
|
||||
}
|
||||
else
|
||||
{
|
||||
StartCoroutine(SaveCreationSlot(userFolderId, orCreateSelectedId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadCurrentSlot()
|
||||
{
|
||||
string userFolderId = BlockSpaceAccountPrefs.GetUserFolderId();
|
||||
if (!string.IsNullOrEmpty(userFolderId) && client != null && (mode != InventoryMode.Creations || (!(groupManager == null) && groupManager.CreatorMode && !groupManager.EditingLocked)) && TryGetSelectedId(out var id) && !string.IsNullOrEmpty(id))
|
||||
{
|
||||
if (mode == InventoryMode.Avatars)
|
||||
{
|
||||
StartCoroutine(LoadAndEquipAvatar(userFolderId, id));
|
||||
}
|
||||
else
|
||||
{
|
||||
StartCoroutine(LoadCreationIntoWorld(userFolderId, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator RefreshSlots()
|
||||
{
|
||||
string playerId = BlockSpaceAccountPrefs.GetUserFolderId();
|
||||
if (string.IsNullOrEmpty(playerId) || client == null)
|
||||
{
|
||||
ids.Clear();
|
||||
yield break;
|
||||
}
|
||||
InventoryBackendClient.ListResponse response = null;
|
||||
if (mode == InventoryMode.Avatars)
|
||||
{
|
||||
yield return client.ListAvatars(playerId, delegate(InventoryBackendClient.ListResponse r)
|
||||
{
|
||||
response = r;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return client.ListCreations(playerId, delegate(InventoryBackendClient.ListResponse r)
|
||||
{
|
||||
response = r;
|
||||
});
|
||||
}
|
||||
ids.Clear();
|
||||
if (response != null && response.ok && response.ids != null)
|
||||
{
|
||||
ids.AddRange(response.ids);
|
||||
}
|
||||
ids.Add(string.Empty);
|
||||
equippedAvatarId = ((response != null) ? (response.equippedId ?? string.Empty) : string.Empty);
|
||||
if (debugLogs)
|
||||
{
|
||||
Debug.Log($"InventoryController: mode={mode} playerIdLen={playerId.Length} ids={ids.Count} equipped={equippedAvatarId}");
|
||||
}
|
||||
slotIndex = Mathf.Clamp(slotIndex, 0, Mathf.Max(0, ids.Count - 1));
|
||||
UpdatePreviewsForSelectedSlot();
|
||||
if (mode != InventoryMode.Avatars || !BlockSpaceAccountPrefs.IsLinked)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
bool flag = false;
|
||||
for (int num = 0; num < ids.Count; num++)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ids[num]))
|
||||
{
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag || !AvatarVoxelStorage.TryLoadLocal(out var localPayload) || !AvatarPayloadHasVoxels(localPayload))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
string newId = MakeNewId();
|
||||
InventoryBackendClient.PutResponse put = null;
|
||||
yield return client.UploadAvatar(playerId, newId, AvatarVoxelStorage.Serialize(localPayload), delegate(InventoryBackendClient.PutResponse r)
|
||||
{
|
||||
put = r;
|
||||
});
|
||||
if (put != null && put.ok && put.saved)
|
||||
{
|
||||
InventoryBackendClient.EquipResponse equip = null;
|
||||
yield return client.EquipAvatar(playerId, newId, delegate(InventoryBackendClient.EquipResponse r)
|
||||
{
|
||||
equip = r;
|
||||
});
|
||||
PhotonVoxelAvatar localOwnedInstance = PhotonVoxelAvatar.LocalOwnedInstance;
|
||||
if (localOwnedInstance != null)
|
||||
{
|
||||
localOwnedInstance.ApplyAndBroadcastAvatar(localPayload);
|
||||
}
|
||||
if (PlayerPrefs.HasKey("BlockSpace.Avatar.Payload"))
|
||||
{
|
||||
PlayerPrefs.DeleteKey("BlockSpace.Avatar.Payload");
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
slotsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool AvatarPayloadHasVoxels(AvatarVoxelPayload payload)
|
||||
{
|
||||
if (payload == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!GroupDataHasVoxels(payload.headBody) && !GroupDataHasVoxels(payload.left))
|
||||
{
|
||||
return GroupDataHasVoxels(payload.right);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool AvatarPayloadHasAnyBase64(AvatarVoxelPayload payload)
|
||||
{
|
||||
if (payload == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrEmpty(payload.headBody?.voxelsBase64) && string.IsNullOrEmpty(payload.left?.voxelsBase64))
|
||||
{
|
||||
return !string.IsNullOrEmpty(payload.right?.voxelsBase64);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int AvatarPayloadBase64TotalLength(AvatarVoxelPayload payload)
|
||||
{
|
||||
if (payload == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (payload.headBody?.voxelsBase64 ?? string.Empty).Length + (payload.left?.voxelsBase64 ?? string.Empty).Length + (payload.right?.voxelsBase64 ?? string.Empty).Length;
|
||||
}
|
||||
|
||||
private static bool GroupDataHasVoxels(AvatarVoxelGroupData group)
|
||||
{
|
||||
if (group == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (group.sizeX <= 0 || group.sizeY <= 0 || group.sizeZ <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerator SaveAvatarSlot(string playerId, string avatarId)
|
||||
{
|
||||
AvatarCustomizerController avatarCustomizerController = UnityEngine.Object.FindObjectOfType<AvatarCustomizerController>();
|
||||
PhotonVoxelAvatar runtime = PhotonVoxelAvatar.LocalOwnedInstance;
|
||||
AvatarVoxelPayload editorPayload = null;
|
||||
VoxelGroup headBody = null;
|
||||
VoxelGroup left = null;
|
||||
VoxelGroup right = null;
|
||||
if (avatarCustomizerController != null && avatarCustomizerController.TryGetEditorGroups(out headBody, out left, out right))
|
||||
{
|
||||
editorPayload = AvatarVoxelStorage.CapturePayload(headBody, left, right);
|
||||
}
|
||||
AvatarVoxelPayload avatarVoxelPayload = ((runtime != null) ? runtime.CaptureRuntimePayload() : null);
|
||||
AvatarVoxelPayload payload;
|
||||
AvatarVoxelPayload localPayload = (AvatarVoxelStorage.TryLoadLocal(out payload) ? payload : null);
|
||||
AvatarVoxelPayload payload2 = (AvatarPayloadHasAnyBase64(editorPayload) ? editorPayload : (AvatarPayloadHasAnyBase64(avatarVoxelPayload) ? avatarVoxelPayload : (AvatarPayloadHasAnyBase64(localPayload) ? localPayload : (AvatarPayloadHasVoxels(editorPayload) ? editorPayload : (AvatarPayloadHasVoxels(avatarVoxelPayload) ? avatarVoxelPayload : (AvatarPayloadHasVoxels(localPayload) ? localPayload : (editorPayload ?? avatarVoxelPayload ?? localPayload ?? AvatarVoxelStorage.CreateEmptyPayload())))))));
|
||||
if (runtime != null && AvatarPayloadBase64TotalLength(payload2) <= 0 && !runtime.HasRuntimeGroups)
|
||||
{
|
||||
float waited = 0f;
|
||||
while (waited < 1.5f && !runtime.HasRuntimeGroups)
|
||||
{
|
||||
waited += 0.1f;
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
}
|
||||
avatarVoxelPayload = runtime.CaptureRuntimePayload();
|
||||
if (AvatarPayloadHasAnyBase64(avatarVoxelPayload))
|
||||
{
|
||||
payload2 = avatarVoxelPayload;
|
||||
}
|
||||
else if (AvatarPayloadHasAnyBase64(localPayload))
|
||||
{
|
||||
payload2 = localPayload;
|
||||
}
|
||||
}
|
||||
string text = AvatarVoxelStorage.Serialize(payload2);
|
||||
if (text == "{}" || text.Length <= 4 || AvatarPayloadBase64TotalLength(payload2) <= 0)
|
||||
{
|
||||
Debug.LogWarning($"InventoryController: refusing to upload empty avatar payload slot={avatarId} jsonLen={text.Length} base64Total={AvatarPayloadBase64TotalLength(payload2)}");
|
||||
yield break;
|
||||
}
|
||||
if (debugLogs)
|
||||
{
|
||||
int num = ((headBody != null && headBody.voxels != null) ? headBody.voxels.Length : 0);
|
||||
int num2 = ((left != null && left.voxels != null) ? left.voxels.Length : 0);
|
||||
int num3 = ((right != null && right.voxels != null) ? right.voxels.Length : 0);
|
||||
int num4 = Mathf.Max(0, payload2.headBody?.sizeX ?? 0) * Mathf.Max(0, payload2.headBody?.sizeY ?? 0) * Mathf.Max(0, payload2.headBody?.sizeZ ?? 0);
|
||||
int num5 = Mathf.Max(0, payload2.left?.sizeX ?? 0) * Mathf.Max(0, payload2.left?.sizeY ?? 0) * Mathf.Max(0, payload2.left?.sizeZ ?? 0);
|
||||
int num6 = Mathf.Max(0, payload2.right?.sizeX ?? 0) * Mathf.Max(0, payload2.right?.sizeY ?? 0) * Mathf.Max(0, payload2.right?.sizeZ ?? 0);
|
||||
int length = (payload2.headBody?.voxelsBase64 ?? string.Empty).Length;
|
||||
int num7 = AvatarPayloadBase64TotalLength(payload2);
|
||||
string text2 = ((payload2 == editorPayload) ? "editor" : ((payload2 == avatarVoxelPayload) ? "runtime" : ((payload2 == localPayload) ? "local" : "other")));
|
||||
Debug.Log($"InventoryController: saving avatar slot={avatarId} chosen={text2} editor(head={num},left={num2},right={num3}) payloadExpected(head={num4},left={num5},right={num6}) headB64Len={length} b64Total={num7} jsonLen={text.Length}");
|
||||
}
|
||||
AvatarVoxelStorage.SaveLocal(payload2);
|
||||
InventoryBackendClient.PutResponse put = null;
|
||||
yield return client.UploadAvatar(playerId, avatarId, text, delegate(InventoryBackendClient.PutResponse r)
|
||||
{
|
||||
put = r;
|
||||
});
|
||||
if (put != null && put.ok && put.saved)
|
||||
{
|
||||
slotsDirty = true;
|
||||
if (debugLogs)
|
||||
{
|
||||
string roundTrip = string.Empty;
|
||||
yield return client.DownloadAvatar(playerId, avatarId, delegate(string t)
|
||||
{
|
||||
roundTrip = t;
|
||||
});
|
||||
int num8 = ((roundTrip != null) ? Encoding.UTF8.GetByteCount(roundTrip) : 0);
|
||||
int num9 = 0;
|
||||
if (!string.IsNullOrEmpty(roundTrip) && AvatarVoxelStorage.TryDeserialize(roundTrip, out var payload3))
|
||||
{
|
||||
num9 = (payload3.headBody?.voxelsBase64 ?? string.Empty).Length;
|
||||
}
|
||||
Debug.Log($"InventoryController: avatar roundtrip bytes={num8} headB64Len={num9}");
|
||||
}
|
||||
}
|
||||
else if (debugLogs)
|
||||
{
|
||||
Debug.LogWarning(string.Format("InventoryController: UploadAvatar failed ok={0} saved={1} err={2}", put != null && put.ok, put != null && put.saved, (put != null) ? put.error : "null"));
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator LoadAndEquipAvatar(string playerId, string avatarId)
|
||||
{
|
||||
string json = string.Empty;
|
||||
yield return client.DownloadAvatar(playerId, avatarId, delegate(string t)
|
||||
{
|
||||
json = t;
|
||||
});
|
||||
if (!string.IsNullOrWhiteSpace(json) && AvatarVoxelStorage.TryDeserialize(json, out var payload))
|
||||
{
|
||||
AvatarCustomizerController avatarCustomizerController = UnityEngine.Object.FindObjectOfType<AvatarCustomizerController>();
|
||||
if (avatarCustomizerController != null && avatarCustomizerController.TryGetEditorGroups(out var headBody, out var left, out var right))
|
||||
{
|
||||
AvatarVoxelStorage.ApplyPayload(payload, headBody, left, right, groupManager, useLocalGridTransform: true);
|
||||
}
|
||||
PhotonVoxelAvatar localOwnedInstance = PhotonVoxelAvatar.LocalOwnedInstance;
|
||||
if (localOwnedInstance != null)
|
||||
{
|
||||
localOwnedInstance.ApplyAndBroadcastAvatar(payload);
|
||||
}
|
||||
InventoryBackendClient.EquipResponse equip = null;
|
||||
yield return client.EquipAvatar(playerId, avatarId, delegate(InventoryBackendClient.EquipResponse r)
|
||||
{
|
||||
equip = r;
|
||||
});
|
||||
slotsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator SaveCreationSlot(string playerId, string creationId)
|
||||
{
|
||||
VRGroupSelector instance = VRGroupSelector.Instance;
|
||||
List<VoxelGroup> list = ((instance != null) ? instance.GetSelectedGroupsSnapshot() : new List<VoxelGroup>());
|
||||
NodeGraphManager instance2 = NodeGraphManager.Instance;
|
||||
List<Node> list2 = ((instance2 != null) ? instance2.GetSelectedNodesSnapshot() : new List<Node>());
|
||||
bool num = list != null && list.Count > 0;
|
||||
bool flag = list2 != null && list2.Count > 0;
|
||||
if (!num && !flag)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
HashSet<int> hashSet = null;
|
||||
if (flag)
|
||||
{
|
||||
hashSet = new HashSet<int>();
|
||||
for (int i = 0; i < list2.Count; i++)
|
||||
{
|
||||
if (list2[i] != null)
|
||||
{
|
||||
hashSet.Add(list2[i].NodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
byte[] gzipBytes = WorldGroupsCodec.EncodeGzip(list, (instance2 != null) ? instance2.BuildWorldNodeRecords(hashSet) : null, (instance2 != null) ? instance2.BuildWorldWireRecords(hashSet, BuildGroupSaveIndexMap(list)) : null);
|
||||
InventoryBackendClient.PutResponse put = null;
|
||||
yield return client.UploadCreation(playerId, creationId, gzipBytes, delegate(InventoryBackendClient.PutResponse r)
|
||||
{
|
||||
put = r;
|
||||
});
|
||||
if (put != null && put.ok && put.saved)
|
||||
{
|
||||
slotsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator LoadCreationIntoWorld(string playerId, string creationId)
|
||||
{
|
||||
byte[] gzip = null;
|
||||
yield return client.DownloadCreation(playerId, creationId, delegate(byte[] b)
|
||||
{
|
||||
gzip = b;
|
||||
});
|
||||
if (gzip == null)
|
||||
{
|
||||
gzip = Array.Empty<byte>();
|
||||
}
|
||||
if (!WorldGroupsCodec.TryDecodeGzip(gzip, out WorldGroupsCodec.WorldSaveData saveData) || groupManager == null || !TryGetSpawnGridPosition(out var gridPosition))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
List<WorldGroupsCodec.WorldGroupRecord> list = saveData.groupRecords ?? new List<WorldGroupsCodec.WorldGroupRecord>();
|
||||
List<WorldGroupsCodec.WorldNodeRecord> list2 = saveData.nodeRecords ?? new List<WorldGroupsCodec.WorldNodeRecord>();
|
||||
if (list.Count == 0 && list2.Count == 0)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
float voxelSize = groupManager.VoxelSize;
|
||||
Vector3 vector = ((list.Count > 0) ? new Vector3((float)list[0].position.x * voxelSize, (float)list[0].position.y * voxelSize, (float)list[0].position.z * voxelSize) : list2[0].position);
|
||||
for (int num = 1; num < list.Count; num++)
|
||||
{
|
||||
Vector3 rhs = new Vector3((float)list[num].position.x * voxelSize, (float)list[num].position.y * voxelSize, (float)list[num].position.z * voxelSize);
|
||||
vector = Vector3.Min(vector, rhs);
|
||||
}
|
||||
for (int num2 = 0; num2 < list2.Count; num2++)
|
||||
{
|
||||
vector = Vector3.Min(vector, list2[num2].position);
|
||||
}
|
||||
Dictionary<int, int> dictionary = new Dictionary<int, int>();
|
||||
for (int num3 = 0; num3 < list.Count; num3++)
|
||||
{
|
||||
WorldGroupsCodec.WorldGroupRecord worldGroupRecord = list[num3];
|
||||
VoxelGroupManager.SavedGroupData data = new VoxelGroupManager.SavedGroupData
|
||||
{
|
||||
position = worldGroupRecord.position,
|
||||
packedRotation = worldGroupRecord.packedRotation,
|
||||
size = worldGroupRecord.size,
|
||||
voxels = worldGroupRecord.voxels
|
||||
};
|
||||
Vector3 vector2 = new Vector3((float)worldGroupRecord.position.x * voxelSize, (float)worldGroupRecord.position.y * voxelSize, (float)worldGroupRecord.position.z * voxelSize);
|
||||
Vector3Int vector3Int = new Vector3Int(Mathf.RoundToInt((vector2.x - vector.x) / voxelSize), Mathf.RoundToInt((vector2.y - vector.y) / voxelSize), Mathf.RoundToInt((vector2.z - vector.z) / voxelSize));
|
||||
VoxelGroup voxelGroup = groupManager.SpawnSavedGroup(data, gridPosition + vector3Int);
|
||||
if (voxelGroup != null)
|
||||
{
|
||||
dictionary[num3] = voxelGroup.id;
|
||||
}
|
||||
}
|
||||
if (list2.Count > 0)
|
||||
{
|
||||
NodeGraphManager instance = NodeGraphManager.Instance;
|
||||
if (instance != null)
|
||||
{
|
||||
instance.ApplySavedGraph(positionOffset: new Vector3((float)gridPosition.x * voxelSize, (float)gridPosition.y * voxelSize, (float)gridPosition.z * voxelSize) - vector, nodeRecords: list2, wireRecords: saveData.wireRecords, clearExisting: false, broadcast: true, savedGroupIndexToRuntimeId: dictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<int, int> BuildGroupSaveIndexMap(IList<VoxelGroup> groups)
|
||||
{
|
||||
Dictionary<int, int> dictionary = new Dictionary<int, int>();
|
||||
if (groups == null)
|
||||
{
|
||||
return dictionary;
|
||||
}
|
||||
for (int i = 0; i < groups.Count; i++)
|
||||
{
|
||||
VoxelGroup voxelGroup = groups[i];
|
||||
if (voxelGroup != null)
|
||||
{
|
||||
dictionary[voxelGroup.id] = i;
|
||||
}
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
private void UpdatePreviewsForSelectedSlot()
|
||||
{
|
||||
previewRequestToken++;
|
||||
if (mode == InventoryMode.Avatars)
|
||||
{
|
||||
ApplyEmptyAvatarPreview();
|
||||
StartCoroutine(UpdateAvatarPreviews());
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyEmptyCreationPreview();
|
||||
StartCoroutine(UpdateCreationPreview());
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator UpdateAvatarPreviews()
|
||||
{
|
||||
EnsurePreviewGroups();
|
||||
int token = previewRequestToken;
|
||||
string userFolderId = BlockSpaceAccountPrefs.GetUserFolderId();
|
||||
if (string.IsNullOrEmpty(userFolderId) || client == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
if (!TryGetSelectedId(out var id) || string.IsNullOrEmpty(id))
|
||||
{
|
||||
ApplyEmptyAvatarPreview();
|
||||
yield break;
|
||||
}
|
||||
ApplyEmptyAvatarPreview();
|
||||
string json = string.Empty;
|
||||
yield return client.DownloadAvatar(userFolderId, id, delegate(string t)
|
||||
{
|
||||
json = t;
|
||||
});
|
||||
if (token != previewRequestToken)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(json) || !AvatarVoxelStorage.TryDeserialize(json, out var payload))
|
||||
{
|
||||
if (debugLogs)
|
||||
{
|
||||
string text = json ?? string.Empty;
|
||||
if (text.Length > 120)
|
||||
{
|
||||
text = text.Substring(0, 120);
|
||||
}
|
||||
Debug.LogWarning($"InventoryController: avatar download/parse failed id={id} jsonLen={(json ?? string.Empty).Length} snippet={text}");
|
||||
}
|
||||
ApplyEmptyAvatarPreview();
|
||||
yield break;
|
||||
}
|
||||
if (debugLogs)
|
||||
{
|
||||
int num = Mathf.Max(0, payload.headBody?.sizeX ?? 0) * Mathf.Max(0, payload.headBody?.sizeY ?? 0) * Mathf.Max(0, payload.headBody?.sizeZ ?? 0);
|
||||
int num2 = Mathf.Max(0, payload.left?.sizeX ?? 0) * Mathf.Max(0, payload.left?.sizeY ?? 0) * Mathf.Max(0, payload.left?.sizeZ ?? 0);
|
||||
int num3 = Mathf.Max(0, payload.right?.sizeX ?? 0) * Mathf.Max(0, payload.right?.sizeY ?? 0) * Mathf.Max(0, payload.right?.sizeZ ?? 0);
|
||||
Debug.Log($"InventoryController: avatarId={id} headExpected={num} leftExpected={num2} rightExpected={num3} headB64Len={(payload.headBody?.voxelsBase64 ?? string.Empty).Length}");
|
||||
}
|
||||
ApplyAvatarPreviewPayload(payload);
|
||||
}
|
||||
|
||||
private IEnumerator UpdateCreationPreview()
|
||||
{
|
||||
EnsurePreviewGroups();
|
||||
int token = previewRequestToken;
|
||||
string userFolderId = BlockSpaceAccountPrefs.GetUserFolderId();
|
||||
if (string.IsNullOrEmpty(userFolderId) || client == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
if (!TryGetSelectedId(out var id) || string.IsNullOrEmpty(id))
|
||||
{
|
||||
ApplyEmptyCreationPreview();
|
||||
yield break;
|
||||
}
|
||||
ApplyEmptyCreationPreview();
|
||||
byte[] gzip = null;
|
||||
yield return client.DownloadCreation(userFolderId, id, delegate(byte[] b)
|
||||
{
|
||||
gzip = b;
|
||||
});
|
||||
if (token == previewRequestToken)
|
||||
{
|
||||
if (gzip == null)
|
||||
{
|
||||
gzip = Array.Empty<byte>();
|
||||
}
|
||||
if (!WorldGroupsCodec.TryDecodeGzip(gzip, out WorldGroupsCodec.WorldSaveData saveData) || saveData.groupRecords == null || saveData.groupRecords.Count == 0)
|
||||
{
|
||||
ApplyEmptyCreationPreview();
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyCreationPreviewRecords(saveData.groupRecords);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyCreationPreviewRecords(List<WorldGroupsCodec.WorldGroupRecord> records)
|
||||
{
|
||||
if (creationPreviewRoot == null || groupManager == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
EnsurePreviewGroups();
|
||||
Vector3Int vector3Int = records[0].position;
|
||||
Vector3Int vector3Int2 = records[0].position + records[0].size;
|
||||
for (int i = 1; i < records.Count; i++)
|
||||
{
|
||||
Vector3Int position = records[i].position;
|
||||
Vector3Int rhs = records[i].position + records[i].size;
|
||||
vector3Int = Vector3Int.Min(vector3Int, position);
|
||||
vector3Int2 = Vector3Int.Max(vector3Int2, rhs);
|
||||
}
|
||||
while (previewCreationGroups.Count < records.Count)
|
||||
{
|
||||
int count = previewCreationGroups.Count;
|
||||
GameObject obj = new GameObject($"CreationGroupPreview_{count}");
|
||||
obj.transform.SetParent(creationPreviewRoot, worldPositionStays: false);
|
||||
VoxelGroup voxelGroup = obj.AddComponent<VoxelGroup>();
|
||||
voxelGroup.id = (ushort)(62500 + count);
|
||||
voxelGroup.SetOwner(groupManager);
|
||||
voxelGroup.SetUseLocalGridTransform(useLocalGrid: true);
|
||||
voxelGroup.SetColliderGeneration(enabled: false);
|
||||
previewCreationGroups.Add(voxelGroup);
|
||||
}
|
||||
for (int j = records.Count; j < previewCreationGroups.Count; j++)
|
||||
{
|
||||
if (previewCreationGroups[j] != null)
|
||||
{
|
||||
previewCreationGroups[j].OverwriteData(Vector3Int.zero, 0, Vector3Int.zero, new byte[0], queueRebuild: false);
|
||||
previewCreationGroups[j].SetVoxelSizeScale(1f, rebuild: false);
|
||||
previewCreationGroups[j].RebuildMesh();
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < records.Count; k++)
|
||||
{
|
||||
WorldGroupsCodec.WorldGroupRecord worldGroupRecord = records[k];
|
||||
VoxelGroup voxelGroup2 = previewCreationGroups[k];
|
||||
if (!(voxelGroup2 == null))
|
||||
{
|
||||
Vector3Int gridPosition = worldGroupRecord.position - vector3Int;
|
||||
voxelGroup2.SetUseLocalGridTransform(useLocalGrid: true);
|
||||
voxelGroup2.SetColliderGeneration(enabled: false);
|
||||
voxelGroup2.SetOwner(groupManager);
|
||||
voxelGroup2.OverwriteData(gridPosition, worldGroupRecord.packedRotation, worldGroupRecord.size, worldGroupRecord.voxels, queueRebuild: false);
|
||||
voxelGroup2.SetVoxelSizeScale(1f, rebuild: false);
|
||||
voxelGroup2.RebuildMesh();
|
||||
}
|
||||
}
|
||||
Vector3 vector = vector3Int2 - vector3Int;
|
||||
float num = ((groupManager != null) ? groupManager.VoxelSize : 0.125f);
|
||||
float num2 = Mathf.Max(vector.x, Mathf.Max(vector.y, vector.z)) * num;
|
||||
float num3 = ((num2 > 0.0001f) ? Mathf.Min(1f, 3f / num2) : 1f);
|
||||
creationPreviewRoot.localScale = Vector3.one * num3;
|
||||
}
|
||||
|
||||
private void ApplyEmptyCreationPreview()
|
||||
{
|
||||
for (int i = 0; i < previewCreationGroups.Count; i++)
|
||||
{
|
||||
if (previewCreationGroups[i] != null)
|
||||
{
|
||||
previewCreationGroups[i].OverwriteData(Vector3Int.zero, 0, Vector3Int.zero, new byte[0], queueRebuild: false);
|
||||
previewCreationGroups[i].RebuildMesh();
|
||||
}
|
||||
}
|
||||
if (creationPreviewRoot != null)
|
||||
{
|
||||
creationPreviewRoot.localScale = Vector3.one;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyAvatarPreviewPayload(AvatarVoxelPayload payload)
|
||||
{
|
||||
if (!(groupManager == null))
|
||||
{
|
||||
EnsurePreviewGroups();
|
||||
if (previewHeadGroup != null)
|
||||
{
|
||||
AvatarVoxelStorage.ApplyGroupData(previewHeadGroup, payload.headBody, groupManager, useLocalGridTransform: true);
|
||||
}
|
||||
if (previewLeftGroup != null)
|
||||
{
|
||||
AvatarVoxelStorage.ApplyGroupData(previewLeftGroup, payload.left, groupManager, useLocalGridTransform: true);
|
||||
}
|
||||
if (previewRightGroup != null)
|
||||
{
|
||||
AvatarVoxelStorage.ApplyGroupData(previewRightGroup, payload.right, groupManager, useLocalGridTransform: true);
|
||||
}
|
||||
if (previewHeadGroup != null)
|
||||
{
|
||||
previewHeadGroup.SetVoxelSizeScale(0.5f, rebuild: false);
|
||||
previewHeadGroup.RebuildMesh();
|
||||
}
|
||||
if (previewLeftGroup != null)
|
||||
{
|
||||
previewLeftGroup.SetVoxelSizeScale(0.5f, rebuild: false);
|
||||
previewLeftGroup.RebuildMesh();
|
||||
}
|
||||
if (previewRightGroup != null)
|
||||
{
|
||||
previewRightGroup.SetVoxelSizeScale(0.5f, rebuild: false);
|
||||
previewRightGroup.RebuildMesh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyEmptyAvatarPreview()
|
||||
{
|
||||
EnsurePreviewGroups();
|
||||
if (!(previewHeadGroup == null))
|
||||
{
|
||||
previewHeadGroup.OverwriteData(Vector3Int.zero, 0, Vector3Int.zero, new byte[0], queueRebuild: false);
|
||||
previewLeftGroup.OverwriteData(Vector3Int.zero, 0, Vector3Int.zero, new byte[0], queueRebuild: false);
|
||||
previewRightGroup.OverwriteData(Vector3Int.zero, 0, Vector3Int.zero, new byte[0], queueRebuild: false);
|
||||
previewHeadGroup.RebuildMesh();
|
||||
previewLeftGroup.RebuildMesh();
|
||||
previewRightGroup.RebuildMesh();
|
||||
}
|
||||
}
|
||||
|
||||
private void ResolveSceneReferences()
|
||||
{
|
||||
if (groupManager == null)
|
||||
{
|
||||
groupManager = ((VoxelGroupManager.Instance != null) ? VoxelGroupManager.Instance : UnityEngine.Object.FindObjectOfType<VoxelGroupManager>());
|
||||
}
|
||||
if (voxelBrush == null)
|
||||
{
|
||||
voxelBrush = ((VRVoxelBrush.Instance != null) ? VRVoxelBrush.Instance : UnityEngine.Object.FindObjectOfType<VRVoxelBrush>());
|
||||
}
|
||||
if (avatarsButton == null)
|
||||
{
|
||||
avatarsButton = FindCollider("Avatars");
|
||||
}
|
||||
if (creationsButton == null)
|
||||
{
|
||||
creationsButton = FindCollider("Creations");
|
||||
}
|
||||
if (backButton == null)
|
||||
{
|
||||
backButton = FindCollider("Back");
|
||||
}
|
||||
if (nextButton == null)
|
||||
{
|
||||
nextButton = FindCollider("Next");
|
||||
}
|
||||
if (saveButton == null)
|
||||
{
|
||||
saveButton = FindCollider("Save");
|
||||
}
|
||||
if (loadButton == null)
|
||||
{
|
||||
loadButton = FindCollider("Load");
|
||||
}
|
||||
if (creationPreviewRoot == null)
|
||||
{
|
||||
creationPreviewRoot = FindTransform("Preview");
|
||||
}
|
||||
if (previewRight == null)
|
||||
{
|
||||
previewRight = FindTransform("PrevR");
|
||||
}
|
||||
if (previewHead == null)
|
||||
{
|
||||
previewHead = FindTransform("PrevH");
|
||||
}
|
||||
if (previewLeft == null)
|
||||
{
|
||||
previewLeft = FindTransform("PrevL");
|
||||
}
|
||||
}
|
||||
|
||||
private Collider FindCollider(string name)
|
||||
{
|
||||
Transform transform = base.transform.Find("UI/" + name);
|
||||
if (transform == null)
|
||||
{
|
||||
GameObject gameObject = GameObject.Find(name);
|
||||
transform = ((gameObject != null) ? gameObject.transform : null);
|
||||
}
|
||||
if (!(transform != null))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return transform.GetComponent<Collider>();
|
||||
}
|
||||
|
||||
private Transform FindTransform(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (transformCache.TryGetValue(name, out var value) && value != null)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
Transform transform = base.transform.Find(name);
|
||||
if (transform != null)
|
||||
{
|
||||
transformCache[name] = transform;
|
||||
return transform;
|
||||
}
|
||||
Transform[] componentsInChildren = GetComponentsInChildren<Transform>(includeInactive: true);
|
||||
foreach (Transform transform2 in componentsInChildren)
|
||||
{
|
||||
if (transform2 != null && string.Equals(transform2.name, name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
transformCache[name] = transform2;
|
||||
return transform2;
|
||||
}
|
||||
}
|
||||
GameObject gameObject = GameObject.Find(name);
|
||||
if (gameObject != null)
|
||||
{
|
||||
transformCache[name] = gameObject.transform;
|
||||
return gameObject.transform;
|
||||
}
|
||||
Transform[] array = UnityEngine.Object.FindObjectsOfType<Transform>(includeInactive: true);
|
||||
foreach (Transform transform3 in array)
|
||||
{
|
||||
if (transform3 != null && string.Equals(transform3.name, name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
transformCache[name] = transform3;
|
||||
return transform3;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void EnsureButtonAudioAssigned()
|
||||
{
|
||||
if (!(buttonThockClip != null))
|
||||
{
|
||||
buttonThockClip = Resources.Load<AudioClip>("Thock");
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsurePreviewGroups()
|
||||
{
|
||||
if (!(groupManager == null))
|
||||
{
|
||||
if (creationPreviewRoot == null)
|
||||
{
|
||||
creationPreviewRoot = FindTransform("Preview");
|
||||
}
|
||||
if (previewRight == null)
|
||||
{
|
||||
previewRight = FindTransform("PrevR");
|
||||
}
|
||||
if (previewHead == null)
|
||||
{
|
||||
previewHead = FindTransform("PrevH");
|
||||
}
|
||||
if (previewLeft == null)
|
||||
{
|
||||
previewLeft = FindTransform("PrevL");
|
||||
}
|
||||
if (creationPreviewRoot != null && previewCreationGroups.Count == 0)
|
||||
{
|
||||
GameObject gameObject = new GameObject("CreationGroupPreview_0");
|
||||
gameObject.transform.SetParent(creationPreviewRoot, worldPositionStays: false);
|
||||
previewCreationGroup = gameObject.AddComponent<VoxelGroup>();
|
||||
previewCreationGroup.id = 62500;
|
||||
previewCreationGroup.SetOwner(groupManager);
|
||||
previewCreationGroup.SetUseLocalGridTransform(useLocalGrid: true);
|
||||
previewCreationGroup.SetColliderGeneration(enabled: false);
|
||||
previewCreationGroups.Add(previewCreationGroup);
|
||||
}
|
||||
else if (creationPreviewRoot == null && !warnedMissingCreationPreviewRoot)
|
||||
{
|
||||
warnedMissingCreationPreviewRoot = true;
|
||||
Debug.LogWarning("InventoryController: could not find Creation Preview root named 'Preview'. Creation previews will be hidden until it exists.");
|
||||
}
|
||||
previewHeadGroup = EnsurePreviewGroupOn(previewHead, previewHeadGroup, 62000);
|
||||
previewLeftGroup = EnsurePreviewGroupOn(previewLeft, previewLeftGroup, 62001);
|
||||
previewRightGroup = EnsurePreviewGroupOn(previewRight, previewRightGroup, 62002);
|
||||
if (!warnedMissingAvatarPreviewRoots && (previewHead == null || previewLeft == null || previewRight == null))
|
||||
{
|
||||
warnedMissingAvatarPreviewRoots = true;
|
||||
Debug.LogWarning("InventoryController: could not find one or more avatar preview roots ('PrevH', 'PrevL', 'PrevR'). Avatar previews will be hidden until they exist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private VoxelGroup EnsurePreviewGroupOn(Transform root, VoxelGroup existing, ushort id)
|
||||
{
|
||||
if (root == null || groupManager == null)
|
||||
{
|
||||
return existing;
|
||||
}
|
||||
VoxelGroup voxelGroup = ((existing != null) ? existing : root.GetComponent<VoxelGroup>());
|
||||
if (voxelGroup == null)
|
||||
{
|
||||
voxelGroup = root.gameObject.AddComponent<VoxelGroup>();
|
||||
}
|
||||
voxelGroup.id = id;
|
||||
voxelGroup.SetOwner(groupManager);
|
||||
voxelGroup.SetUseLocalGridTransform(useLocalGrid: true);
|
||||
voxelGroup.SetColliderGeneration(enabled: false);
|
||||
voxelGroup.SetVoxelSizeScale(0.5f);
|
||||
return voxelGroup;
|
||||
}
|
||||
|
||||
private void HandleButton(Collider button, ref bool insidePrevious, Action action)
|
||||
{
|
||||
bool flag = IsHandInside(button, (voxelBrush != null) ? voxelBrush.LeftHandAnchor : null) || IsHandInside(button, (voxelBrush != null) ? voxelBrush.RightHandAnchor : null);
|
||||
if (flag && !insidePrevious)
|
||||
{
|
||||
PlayButtonEnterAnimation(button);
|
||||
if (Time.unscaledTime >= nextButtonPressTime)
|
||||
{
|
||||
nextButtonPressTime = Time.unscaledTime + 0.2f;
|
||||
PlayButtonClickFeedback(button);
|
||||
action?.Invoke();
|
||||
}
|
||||
}
|
||||
insidePrevious = flag;
|
||||
}
|
||||
|
||||
private static bool IsHandInside(Collider button, Transform hand)
|
||||
{
|
||||
if (button == null || hand == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return button.bounds.Contains(hand.position);
|
||||
}
|
||||
|
||||
private void PlayButtonEnterAnimation(Collider button)
|
||||
{
|
||||
if (!(button == null))
|
||||
{
|
||||
Transform transform = button.transform;
|
||||
if (!buttonBaseScales.TryGetValue(transform, out var value))
|
||||
{
|
||||
value = transform.localScale;
|
||||
buttonBaseScales.Add(transform, value);
|
||||
}
|
||||
if (buttonAnimationCoroutines.TryGetValue(transform, out var value2) && value2 != null)
|
||||
{
|
||||
StopCoroutine(value2);
|
||||
}
|
||||
transform.localScale = value;
|
||||
buttonAnimationCoroutines[transform] = StartCoroutine(AnimateButtonScale(transform, value));
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator AnimateButtonScale(Transform buttonTransform, Vector3 baseScale)
|
||||
{
|
||||
if (!(buttonTransform == null))
|
||||
{
|
||||
float startTime = Time.unscaledTime;
|
||||
while (Time.unscaledTime - startTime < 0.08f)
|
||||
{
|
||||
float t = Mathf.Clamp01((Time.unscaledTime - startTime) / 0.08f);
|
||||
buttonTransform.localScale = Vector3.Lerp(baseScale, baseScale * 0.84f, t);
|
||||
yield return null;
|
||||
}
|
||||
startTime = Time.unscaledTime;
|
||||
while (Time.unscaledTime - startTime < 0.12f)
|
||||
{
|
||||
float num = Mathf.Clamp01((Time.unscaledTime - startTime) / 0.12f);
|
||||
float num2 = Mathf.Sin(num * MathF.PI);
|
||||
Vector3 a = Vector3.Lerp(baseScale * 0.84f, baseScale, num);
|
||||
buttonTransform.localScale = Vector3.LerpUnclamped(a, baseScale * 1.04f, num2 * 0.15f);
|
||||
yield return null;
|
||||
}
|
||||
buttonTransform.localScale = baseScale;
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayButtonClickFeedback(Collider button)
|
||||
{
|
||||
if (!(buttonThockClip == null) && !(button == null))
|
||||
{
|
||||
AudioSource.PlayClipAtPoint(buttonThockClip, button.bounds.center, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetAllButtonScales()
|
||||
{
|
||||
foreach (KeyValuePair<Transform, Vector3> buttonBaseScale in buttonBaseScales)
|
||||
{
|
||||
if (buttonBaseScale.Key != null)
|
||||
{
|
||||
buttonBaseScale.Key.localScale = buttonBaseScale.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetSelectedId(out string id)
|
||||
{
|
||||
id = string.Empty;
|
||||
if (slotIndex < 0 || slotIndex >= ids.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
id = ids[slotIndex] ?? string.Empty;
|
||||
return true;
|
||||
}
|
||||
|
||||
private string GetOrCreateSelectedId()
|
||||
{
|
||||
if (!TryGetSelectedId(out var id))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
return id;
|
||||
}
|
||||
string text = MakeNewId();
|
||||
ids[slotIndex] = text;
|
||||
return text;
|
||||
}
|
||||
|
||||
private static string MakeNewId()
|
||||
{
|
||||
return DateTime.UtcNow.ToString("yyyyMMddHHmmssfff");
|
||||
}
|
||||
|
||||
private bool TryGetSpawnGridPosition(out Vector3Int gridPosition)
|
||||
{
|
||||
gridPosition = Vector3Int.zero;
|
||||
VRVoxelBrush vRVoxelBrush = ((voxelBrush != null) ? voxelBrush : VRVoxelBrush.Instance);
|
||||
if (vRVoxelBrush != null && vRVoxelBrush.TryGetSpawnGridPosition(out gridPosition))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
float num = ((groupManager != null) ? groupManager.VoxelSize : 0.125f);
|
||||
Vector3 vector = ((Camera.main != null) ? Camera.main.transform.position : base.transform.position) + ((Camera.main != null) ? Camera.main.transform.forward : base.transform.forward).normalized * 2f;
|
||||
gridPosition = new Vector3Int(Mathf.RoundToInt(vector.x / num), Mathf.RoundToInt(vector.y / num), Mathf.RoundToInt(vector.z / num));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user