修了不少东西
This commit is contained in:
@@ -36,8 +36,8 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: -51.2}
|
||||
m_SizeDelta: {x: 200, y: 32.156}
|
||||
m_AnchoredPosition: {x: 0, y: -49.6}
|
||||
m_SizeDelta: {x: 146, y: 56}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &5597810916468765611
|
||||
CanvasRenderer:
|
||||
@@ -67,8 +67,8 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 7621278097234006379, guid: 59df2390a598c904bab275d1ea743916, type: 3}
|
||||
m_Type: 1
|
||||
m_Sprite: {fileID: -2689630615245801869, guid: 2a46b5f36d286d447bd74d1db9a72cd7, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
@@ -157,8 +157,8 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: -9.196}
|
||||
m_SizeDelta: {x: 200, y: 110.402}
|
||||
m_AnchoredPosition: {x: 0, y: -49.6}
|
||||
m_SizeDelta: {x: 146, y: 56}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &5591616715459838773
|
||||
CanvasRenderer:
|
||||
@@ -188,8 +188,8 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 7919194353434859991, guid: b35fcaa46fa9f3e49b71c103f69df698, type: 3}
|
||||
m_Type: 1
|
||||
m_Sprite: {fileID: -566881566719626471, guid: 56ba1aaa875c6b7489f77555fd212d3e, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
@@ -355,8 +355,8 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 1.4682007}
|
||||
m_SizeDelta: {x: 0, y: -2.9365}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &3720672462226780915
|
||||
CanvasRenderer:
|
||||
@@ -379,7 +379,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
||||
m_Color: {r: 0.63529414, g: 0.3529412, b: 0.16862746, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
@@ -387,7 +387,7 @@ MonoBehaviour:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: bd4be44636ad6c24a9b117a7108a75e9, type: 3}
|
||||
m_Font: {fileID: 12800000, guid: d254d20d93651ae448ff13d10dff30ab, type: 3}
|
||||
m_FontSize: 24
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
@@ -456,7 +456,7 @@ MonoBehaviour:
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 4
|
||||
m_Spacing: 0
|
||||
m_Spacing: -100
|
||||
m_ChildForceExpandWidth: 1
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildControlWidth: 0
|
||||
@@ -500,8 +500,8 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: -171.99}
|
||||
m_SizeDelta: {x: 300, y: 40}
|
||||
m_AnchoredPosition: {x: 0, y: -171.1}
|
||||
m_SizeDelta: {x: 194.5543, y: 52.3284}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &6903183453437413057
|
||||
CanvasRenderer:
|
||||
@@ -531,8 +531,8 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 2561534620446350566, guid: 23a48ca1e983a4c47971fcf7eab26b89, type: 3}
|
||||
m_Type: 1
|
||||
m_Sprite: {fileID: -6405685121925378258, guid: 92151af6550eb214aa4daecf4ea48edb, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
@@ -622,7 +622,7 @@ RectTransform:
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 555, y: 264.2}
|
||||
m_SizeDelta: {x: 450, y: 230}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &7601750316680178786
|
||||
CanvasRenderer:
|
||||
@@ -652,7 +652,7 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 21300000, guid: 7f3b1220317607e44bbb8f0e1998044a, type: 3}
|
||||
m_Sprite: {fileID: 21300000, guid: a31ac6012ab10b146878694e7d720b11, type: 3}
|
||||
m_Type: 1
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
@@ -698,8 +698,8 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 16}
|
||||
m_SizeDelta: {x: 200, y: 60}
|
||||
m_AnchoredPosition: {x: -100.424805, y: 16}
|
||||
m_SizeDelta: {x: 346.8495, y: 60}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &67614290717671043
|
||||
CanvasRenderer:
|
||||
@@ -729,8 +729,8 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 4717104774431673990, guid: 2204c5120d209e24b8d8473101c0670f, type: 3}
|
||||
m_Type: 1
|
||||
m_Sprite: {fileID: 21300000, guid: 7edca03691f782d46ac361a681ce5685, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
@@ -874,8 +874,8 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: -2.8545, y: 2.3508}
|
||||
m_SizeDelta: {x: -5.7091, y: -4.7016}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &316840073610798188
|
||||
CanvasRenderer:
|
||||
@@ -898,7 +898,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_Color: {r: 0.63529414, g: 0.3529412, b: 0.16862746, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
@@ -906,8 +906,8 @@ MonoBehaviour:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: bd4be44636ad6c24a9b117a7108a75e9, type: 3}
|
||||
m_FontSize: 18
|
||||
m_Font: {fileID: 12800000, guid: d254d20d93651ae448ff13d10dff30ab, type: 3}
|
||||
m_FontSize: 24
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 1
|
||||
@@ -1104,8 +1104,8 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: -2.947403, y: 2.0960999}
|
||||
m_SizeDelta: {x: -5.8948, y: -4.1923}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &2489646231650356367
|
||||
CanvasRenderer:
|
||||
@@ -1128,7 +1128,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_Color: {r: 0.09803922, g: 0.32941177, b: 0.6, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
@@ -1136,8 +1136,8 @@ MonoBehaviour:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 12800000, guid: bd4be44636ad6c24a9b117a7108a75e9, type: 3}
|
||||
m_FontSize: 20
|
||||
m_Font: {fileID: 12800000, guid: d254d20d93651ae448ff13d10dff30ab, type: 3}
|
||||
m_FontSize: 24
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 1
|
||||
@@ -1148,7 +1148,7 @@ MonoBehaviour:
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: "\u521B\u5EFA\u623F\u95F4\u5E76\u4F5C\u4E3A\u623F\u4E3B"
|
||||
m_Text: "\u521B\u5EFA\u623F\u95F4"
|
||||
--- !u!1 &4714805719805124595
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -1373,8 +1373,8 @@ MonoBehaviour:
|
||||
m_Calls: []
|
||||
m_text: "\u200B"
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 452fa97492cae71479cf143f29930751, type: 2}
|
||||
m_sharedMaterial: {fileID: -346136068272202111, guid: 452fa97492cae71479cf143f29930751, type: 2}
|
||||
m_fontAsset: {fileID: 11400000, guid: 7cad3f54ac7b53d4885f00c16f1a6929, type: 2}
|
||||
m_sharedMaterial: {fileID: -346136068272202111, guid: 7cad3f54ac7b53d4885f00c16f1a6929, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
|
||||
@@ -942,7 +942,8 @@ public class globalChatSystem : MonoBehaviour
|
||||
playerMessagePrefab controller = instance.GetComponentInChildren<playerMessagePrefab>();
|
||||
if (controller != null)
|
||||
{
|
||||
controller.Bind(senderSteamId, avatarUrl, displayName, string.Empty, message.content, bubbleColor);
|
||||
string title = !string.IsNullOrWhiteSpace(message.player_title) ? message.player_title : string.Empty;
|
||||
controller.Bind(senderSteamId, avatarUrl, displayName, title, message.content, bubbleColor);
|
||||
}
|
||||
|
||||
return instance;
|
||||
|
||||
@@ -38,7 +38,7 @@ RectTransform:
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 323.75, y: 30}
|
||||
m_SizeDelta: {x: 380.56, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &2228420748506963945
|
||||
MonoBehaviour:
|
||||
@@ -83,7 +83,7 @@ MonoBehaviour:
|
||||
m_MinWidth: -1
|
||||
m_MinHeight: -1
|
||||
m_PreferredWidth: -1
|
||||
m_PreferredHeight: 30
|
||||
m_PreferredHeight: 0
|
||||
m_FlexibleWidth: -1
|
||||
m_FlexibleHeight: -1
|
||||
m_LayoutPriority: 2
|
||||
|
||||
@@ -100,6 +100,7 @@ public class roomAsk : MonoBehaviour
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogWarning($"[roomAsk] Create room failed: {ex.Message}");
|
||||
GameServer.Client.NetworkManager.ShowUserFacingNetworkError(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +126,7 @@ public class roomAsk : MonoBehaviour
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogWarning($"[roomAsk] Join room failed: {ex.Message}");
|
||||
GameServer.Client.NetworkManager.ShowUserFacingNetworkError(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,10 @@ public class roomDetails : MonoBehaviour
|
||||
public Text thisSongName;
|
||||
public Text thisSongDifficulty;
|
||||
|
||||
[Header("change songs")]
|
||||
public Dropdown songDropdown;
|
||||
public Dropdown difficultyDropdown;
|
||||
|
||||
[Header("objs")]
|
||||
public GameObject roommatePrefab;
|
||||
public Transform roommateParent;
|
||||
@@ -82,6 +86,11 @@ public class roomDetails : MonoBehaviour
|
||||
private readonly List<RectTransform> _pendingMessageLayoutDirtyRoots = new List<RectTransform>();
|
||||
private Coroutine _refocusChatInputCoroutine;
|
||||
private bool _refocusChatInputRequested;
|
||||
private readonly List<SongData> _selectableSongs = new List<SongData>();
|
||||
private readonly List<int> _selectableDifficulties = new List<int>();
|
||||
private Coroutine _songLibraryWaitRoutine;
|
||||
private bool _suppressSongDropdownEvents;
|
||||
private bool _isChangingRoomSong;
|
||||
|
||||
private const float ChatSendCooldownSeconds = 3f;
|
||||
private const int InitialHistoryLoadLimit = 20;
|
||||
@@ -162,6 +171,18 @@ public class roomDetails : MonoBehaviour
|
||||
sendMessageButton.onClick.AddListener(OnSendMessageClicked);
|
||||
}
|
||||
|
||||
if (songDropdown != null)
|
||||
{
|
||||
songDropdown.onValueChanged.RemoveListener(OnSongDropdownChanged);
|
||||
songDropdown.onValueChanged.AddListener(OnSongDropdownChanged);
|
||||
}
|
||||
|
||||
if (difficultyDropdown != null)
|
||||
{
|
||||
difficultyDropdown.onValueChanged.RemoveListener(OnDifficultyDropdownChanged);
|
||||
difficultyDropdown.onValueChanged.AddListener(OnDifficultyDropdownChanged);
|
||||
}
|
||||
|
||||
if (playerMessageInputField != null)
|
||||
{
|
||||
playerMessageInputField.onEndEdit.RemoveListener(OnChatInputEndEdit);
|
||||
@@ -185,6 +206,7 @@ public class roomDetails : MonoBehaviour
|
||||
_ = InitializeRoomChatAsync();
|
||||
|
||||
Refresh(_service.CurrentRoom);
|
||||
EnsureSongDropdownsReady();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
@@ -225,6 +247,16 @@ public class roomDetails : MonoBehaviour
|
||||
sendMessageButton.onClick.RemoveListener(OnSendMessageClicked);
|
||||
}
|
||||
|
||||
if (songDropdown != null)
|
||||
{
|
||||
songDropdown.onValueChanged.RemoveListener(OnSongDropdownChanged);
|
||||
}
|
||||
|
||||
if (difficultyDropdown != null)
|
||||
{
|
||||
difficultyDropdown.onValueChanged.RemoveListener(OnDifficultyDropdownChanged);
|
||||
}
|
||||
|
||||
if (playerMessageInputField != null)
|
||||
{
|
||||
playerMessageInputField.onEndEdit.RemoveListener(OnChatInputEndEdit);
|
||||
@@ -259,6 +291,12 @@ public class roomDetails : MonoBehaviour
|
||||
_refocusChatInputCoroutine = null;
|
||||
}
|
||||
|
||||
if (_songLibraryWaitRoutine != null)
|
||||
{
|
||||
StopCoroutine(_songLibraryWaitRoutine);
|
||||
_songLibraryWaitRoutine = null;
|
||||
}
|
||||
|
||||
RestoreDefaultChatPlaceholder();
|
||||
|
||||
if (_spawnedRoomRankingInstance != null)
|
||||
@@ -396,6 +434,7 @@ public class roomDetails : MonoBehaviour
|
||||
UpdateQuitButtonTexts(snapshot);
|
||||
UpdateReadyButton(snapshot);
|
||||
RenderParticipants(snapshot);
|
||||
RefreshSongDropdowns(snapshot);
|
||||
}
|
||||
|
||||
private IEnumerator UpdateRemainTime(ArenaRoomSnapshot snapshot)
|
||||
@@ -760,7 +799,7 @@ public class roomDetails : MonoBehaviour
|
||||
&& string.Equals(senderSteamId, localSteamId, StringComparison.Ordinal);
|
||||
Color bubbleColor = ResolveMessageBubbleColor(isSelf);
|
||||
string displayName = ResolveMessageDisplayName(message, isSelf);
|
||||
string title = ResolveMessageTitle();
|
||||
string title = ResolveMessageTitle(message);
|
||||
|
||||
GameObject instance = Instantiate(playerMessagePrefab, messageParent, false);
|
||||
playerMessagePrefab controller = instance.GetComponent<playerMessagePrefab>();
|
||||
@@ -1026,9 +1065,11 @@ public class roomDetails : MonoBehaviour
|
||||
return GameServer.Client.NetworkManager.ResolveDisplayName(message != null ? message.display_name : string.Empty, messageSteamId, false);
|
||||
}
|
||||
|
||||
private static string ResolveMessageTitle()
|
||||
private static string ResolveMessageTitle(ArenaRoomChatMessage message)
|
||||
{
|
||||
return string.Empty;
|
||||
return message != null && !string.IsNullOrWhiteSpace(message.player_title)
|
||||
? message.player_title
|
||||
: string.Empty;
|
||||
}
|
||||
|
||||
private static string GetMessageSenderSteamId(ArenaRoomChatMessage message)
|
||||
@@ -1387,6 +1428,405 @@ public class roomDetails : MonoBehaviour
|
||||
|| string.Equals(snapshot.status, "PLAYING", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private void EnsureSongDropdownsReady()
|
||||
{
|
||||
if (songDropdown == null && difficultyDropdown == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SongDataLibrary library = SongDataLibrary.Instance;
|
||||
if (library != null && library.IsLoaded)
|
||||
{
|
||||
RefreshSongDropdowns(_service != null ? _service.CurrentRoom : null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_songLibraryWaitRoutine == null)
|
||||
{
|
||||
_songLibraryWaitRoutine = StartCoroutine(WaitForSongLibraryAndRefresh());
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator WaitForSongLibraryAndRefresh()
|
||||
{
|
||||
float timeoutAt = Time.realtimeSinceStartup + 8f;
|
||||
while (Time.realtimeSinceStartup < timeoutAt)
|
||||
{
|
||||
SongDataLibrary library = SongDataLibrary.Instance;
|
||||
if (library != null && library.IsLoaded)
|
||||
{
|
||||
_songLibraryWaitRoutine = null;
|
||||
RefreshSongDropdowns(_service != null ? _service.CurrentRoom : null);
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
_songLibraryWaitRoutine = null;
|
||||
Debug.LogWarning("[roomDetails] SongDataLibrary was not ready; song dropdowns were left empty.");
|
||||
}
|
||||
|
||||
private void RefreshSongDropdowns(ArenaRoomSnapshot snapshot)
|
||||
{
|
||||
if (songDropdown == null && difficultyDropdown == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SongDataLibrary library = SongDataLibrary.Instance;
|
||||
if (library == null || !library.IsLoaded)
|
||||
{
|
||||
EnsureSongDropdownsReady();
|
||||
UpdateSongDropdownInteractable(snapshot);
|
||||
return;
|
||||
}
|
||||
|
||||
RebuildSelectableSongs(library);
|
||||
SongData selectedSong = ResolveSnapshotSong(snapshot);
|
||||
if (selectedSong == null && _selectableSongs.Count > 0)
|
||||
{
|
||||
selectedSong = _selectableSongs[0];
|
||||
}
|
||||
|
||||
int selectedDifficulty = ConvertDifficultyKeyToId(snapshot != null ? snapshot.difficulty : null);
|
||||
if (selectedSong != null)
|
||||
{
|
||||
RebuildSelectableDifficulties(selectedSong);
|
||||
if (!_selectableDifficulties.Contains(selectedDifficulty))
|
||||
{
|
||||
selectedDifficulty = _selectableDifficulties.Count > 0 ? _selectableDifficulties[0] : selectedDifficulty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectableDifficulties.Clear();
|
||||
}
|
||||
|
||||
_suppressSongDropdownEvents = true;
|
||||
try
|
||||
{
|
||||
PopulateSongDropdown(selectedSong);
|
||||
PopulateDifficultyDropdown(selectedSong, selectedDifficulty);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_suppressSongDropdownEvents = false;
|
||||
}
|
||||
|
||||
UpdateSongDropdownInteractable(snapshot);
|
||||
}
|
||||
|
||||
private void RebuildSelectableSongs(SongDataLibrary library)
|
||||
{
|
||||
_selectableSongs.Clear();
|
||||
|
||||
List<SongData> songs = library != null ? library.GetAllSongs() : null;
|
||||
if (songs == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
songs.Sort((left, right) =>
|
||||
{
|
||||
int idCompare = (left != null ? left.songID : int.MaxValue).CompareTo(right != null ? right.songID : int.MaxValue);
|
||||
if (idCompare != 0)
|
||||
{
|
||||
return idCompare;
|
||||
}
|
||||
|
||||
return string.Compare(left != null ? left.songName : string.Empty,
|
||||
right != null ? right.songName : string.Empty,
|
||||
StringComparison.CurrentCulture);
|
||||
});
|
||||
|
||||
foreach (SongData song in songs)
|
||||
{
|
||||
if (song != null && HasPlayableDifficulty(song))
|
||||
{
|
||||
_selectableSongs.Add(song);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SongData ResolveSnapshotSong(ArenaRoomSnapshot snapshot)
|
||||
{
|
||||
if (snapshot != null && int.TryParse(snapshot.song_id, out int songId))
|
||||
{
|
||||
for (int i = 0; i < _selectableSongs.Count; i++)
|
||||
{
|
||||
SongData song = _selectableSongs[i];
|
||||
if (song != null && song.songID == songId)
|
||||
{
|
||||
return song;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void RebuildSelectableDifficulties(SongData song)
|
||||
{
|
||||
_selectableDifficulties.Clear();
|
||||
if (song == null || song.chartFiles == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (ChartFileEntry entry in song.chartFiles)
|
||||
{
|
||||
if (entry == null || entry.chartFile == null || _selectableDifficulties.Contains(entry.difficulty))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_selectableDifficulties.Add(entry.difficulty);
|
||||
}
|
||||
|
||||
_selectableDifficulties.Sort();
|
||||
}
|
||||
|
||||
private void PopulateSongDropdown(SongData selectedSong)
|
||||
{
|
||||
if (songDropdown == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
songDropdown.ClearOptions();
|
||||
List<string> options = new List<string>();
|
||||
for (int i = 0; i < _selectableSongs.Count; i++)
|
||||
{
|
||||
SongData song = _selectableSongs[i];
|
||||
options.Add(song != null && !string.IsNullOrWhiteSpace(song.songName) ? song.songName : $"Song {song?.songID ?? 0}");
|
||||
}
|
||||
|
||||
songDropdown.AddOptions(options);
|
||||
int selectedIndex = selectedSong != null ? _selectableSongs.IndexOf(selectedSong) : -1;
|
||||
songDropdown.value = Mathf.Clamp(selectedIndex, 0, Mathf.Max(0, _selectableSongs.Count - 1));
|
||||
songDropdown.RefreshShownValue();
|
||||
}
|
||||
|
||||
private void PopulateDifficultyDropdown(SongData selectedSong, int selectedDifficulty)
|
||||
{
|
||||
if (difficultyDropdown == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
difficultyDropdown.ClearOptions();
|
||||
List<string> options = new List<string>();
|
||||
for (int i = 0; i < _selectableDifficulties.Count; i++)
|
||||
{
|
||||
options.Add(FormatDifficultyOption(selectedSong, _selectableDifficulties[i]));
|
||||
}
|
||||
|
||||
difficultyDropdown.AddOptions(options);
|
||||
int selectedIndex = _selectableDifficulties.IndexOf(selectedDifficulty);
|
||||
difficultyDropdown.value = Mathf.Clamp(selectedIndex, 0, Mathf.Max(0, _selectableDifficulties.Count - 1));
|
||||
difficultyDropdown.RefreshShownValue();
|
||||
}
|
||||
|
||||
private void UpdateSongDropdownInteractable(ArenaRoomSnapshot snapshot)
|
||||
{
|
||||
string localSteamId = NetworkManager.Instance != null ? NetworkManager.Instance.SteamId : string.Empty;
|
||||
bool canChange = !_isChangingRoomSong
|
||||
&& snapshot != null
|
||||
&& IsLocalHost(snapshot, localSteamId)
|
||||
&& !IsRoomStarted(snapshot)
|
||||
&& _selectableSongs.Count > 0;
|
||||
|
||||
if (songDropdown != null)
|
||||
{
|
||||
songDropdown.interactable = canChange;
|
||||
}
|
||||
|
||||
if (difficultyDropdown != null)
|
||||
{
|
||||
difficultyDropdown.interactable = canChange && _selectableDifficulties.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSongDropdownChanged(int index)
|
||||
{
|
||||
if (_suppressSongDropdownEvents || index < 0 || index >= _selectableSongs.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SongData song = _selectableSongs[index];
|
||||
int currentDifficulty = GetSelectedDifficultyId();
|
||||
RebuildSelectableDifficulties(song);
|
||||
if (!_selectableDifficulties.Contains(currentDifficulty))
|
||||
{
|
||||
currentDifficulty = _selectableDifficulties.Count > 0 ? _selectableDifficulties[0] : 2;
|
||||
}
|
||||
|
||||
_suppressSongDropdownEvents = true;
|
||||
try
|
||||
{
|
||||
PopulateDifficultyDropdown(song, currentDifficulty);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_suppressSongDropdownEvents = false;
|
||||
}
|
||||
|
||||
RequestChangeRoomSong(song, currentDifficulty);
|
||||
}
|
||||
|
||||
private void OnDifficultyDropdownChanged(int index)
|
||||
{
|
||||
if (_suppressSongDropdownEvents || index < 0 || index >= _selectableDifficulties.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SongData song = GetSelectedSong();
|
||||
RequestChangeRoomSong(song, _selectableDifficulties[index]);
|
||||
}
|
||||
|
||||
private async void RequestChangeRoomSong(SongData song, int difficultyId)
|
||||
{
|
||||
if (_service == null || song == null || _isChangingRoomSong)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ArenaRoomSnapshot snapshot = _service.CurrentRoom;
|
||||
string localSteamId = NetworkManager.Instance != null ? NetworkManager.Instance.SteamId : string.Empty;
|
||||
if (!IsLocalHost(snapshot, localSteamId) || IsRoomStarted(snapshot))
|
||||
{
|
||||
RefreshSongDropdowns(snapshot);
|
||||
return;
|
||||
}
|
||||
|
||||
string difficultyKey = ConvertDifficultyIdToKey(difficultyId);
|
||||
if (snapshot != null
|
||||
&& string.Equals(snapshot.song_id, song.songID.ToString(CultureInfo.InvariantCulture), StringComparison.Ordinal)
|
||||
&& string.Equals((snapshot.difficulty ?? string.Empty).Trim(), difficultyKey, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_isChangingRoomSong = true;
|
||||
UpdateSongDropdownInteractable(snapshot);
|
||||
try
|
||||
{
|
||||
await _service.ChangeRoomSong(
|
||||
song.songID.ToString(CultureInfo.InvariantCulture),
|
||||
song.songName,
|
||||
difficultyKey);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogWarning($"[roomDetails] Change room song failed: {ex.Message}");
|
||||
RefreshSongDropdowns(_service.CurrentRoom);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isChangingRoomSong = false;
|
||||
UpdateSongDropdownInteractable(_service.CurrentRoom);
|
||||
}
|
||||
}
|
||||
|
||||
private SongData GetSelectedSong()
|
||||
{
|
||||
if (songDropdown == null)
|
||||
{
|
||||
return ResolveSnapshotSong(_service != null ? _service.CurrentRoom : null);
|
||||
}
|
||||
|
||||
int index = songDropdown.value;
|
||||
return index >= 0 && index < _selectableSongs.Count ? _selectableSongs[index] : null;
|
||||
}
|
||||
|
||||
private int GetSelectedDifficultyId()
|
||||
{
|
||||
if (difficultyDropdown != null)
|
||||
{
|
||||
int index = difficultyDropdown.value;
|
||||
if (index >= 0 && index < _selectableDifficulties.Count)
|
||||
{
|
||||
return _selectableDifficulties[index];
|
||||
}
|
||||
}
|
||||
|
||||
return ConvertDifficultyKeyToId(_service != null && _service.CurrentRoom != null ? _service.CurrentRoom.difficulty : null);
|
||||
}
|
||||
|
||||
private static bool HasPlayableDifficulty(SongData song)
|
||||
{
|
||||
if (song == null || song.chartFiles == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (ChartFileEntry entry in song.chartFiles)
|
||||
{
|
||||
if (entry != null && entry.chartFile != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string FormatDifficultyOption(SongData song, int difficultyId)
|
||||
{
|
||||
string shortName = FormatDifficulty(ConvertDifficultyIdToKey(difficultyId));
|
||||
ChartFileEntry entry = song != null && song.chartFiles != null
|
||||
? song.chartFiles.Find(item => item != null && item.difficulty == difficultyId)
|
||||
: null;
|
||||
|
||||
if (entry != null && entry.difficultyLEVEL > 0f)
|
||||
{
|
||||
return $"{shortName} Lv.{entry.difficultyLEVEL:0.#}";
|
||||
}
|
||||
|
||||
return shortName;
|
||||
}
|
||||
|
||||
private static int ConvertDifficultyKeyToId(string difficultyKey)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(difficultyKey))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
switch (difficultyKey.Trim().ToLowerInvariant())
|
||||
{
|
||||
case "ez":
|
||||
return 0;
|
||||
case "hd":
|
||||
return 1;
|
||||
case "im":
|
||||
return 3;
|
||||
case "in":
|
||||
default:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
private static string ConvertDifficultyIdToKey(int difficultyId)
|
||||
{
|
||||
switch (difficultyId)
|
||||
{
|
||||
case 0:
|
||||
return "ez";
|
||||
case 1:
|
||||
return "hd";
|
||||
case 3:
|
||||
return "im";
|
||||
case 2:
|
||||
default:
|
||||
return "in";
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetButtonText(Button button, string text)
|
||||
{
|
||||
if (button == null)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user