feat: add world chat UI
This commit is contained in:
@@ -38,6 +38,7 @@ namespace XGame
|
||||
private MiniGameNetChannel lobbyNet;
|
||||
private MiniGameHost gameHost;
|
||||
private LobbyWorldController lobbyWorld;
|
||||
private WorldChatModule worldChat;
|
||||
private readonly List<GameInfoMsg> games = new List<GameInfoMsg>();
|
||||
private bool lobbyActive;
|
||||
private bool openingLogin;
|
||||
@@ -120,6 +121,7 @@ namespace XGame
|
||||
{
|
||||
lobbyActive = false;
|
||||
lobbyWorld?.SendLeave();
|
||||
CloseWorldChat();
|
||||
lobbyNet = null;
|
||||
socket?.close();
|
||||
socket = null;
|
||||
@@ -581,6 +583,9 @@ namespace XGame
|
||||
}
|
||||
lobbyWorld?.HandleFrame(frame);
|
||||
break;
|
||||
case FrameworkOpcode.WorldChatMessage:
|
||||
worldChat?.HandleWorldChatMessage(WorldChatMessageMsg.Decode(frame.Payload));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,6 +595,7 @@ namespace XGame
|
||||
pendingGameVersion = 0;
|
||||
lobbyActive = false;
|
||||
lobbyWorld?.SendLeave();
|
||||
CloseWorldChat();
|
||||
lobbyNet = null;
|
||||
CloseWaiting();
|
||||
CloseLobby();
|
||||
@@ -668,6 +674,48 @@ namespace XGame
|
||||
GetLobbyPlayerId(),
|
||||
GetLobbyPlayerName(),
|
||||
0);
|
||||
EnsureWorldChatModule();
|
||||
}
|
||||
|
||||
private void EnsureWorldChatModule()
|
||||
{
|
||||
if (lobbyNet == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (worldChat == null)
|
||||
{
|
||||
worldChat = gameObject.GetComponent<WorldChatModule>();
|
||||
if (worldChat == null)
|
||||
{
|
||||
worldChat = gameObject.AddComponent<WorldChatModule>();
|
||||
}
|
||||
}
|
||||
worldChat.Initialize(GetLobbyPlayerId(), SendWorldChat);
|
||||
if (!worldChat.IsOpen)
|
||||
{
|
||||
XWCoroutine.StartCo(worldChat.OpenAsync());
|
||||
}
|
||||
}
|
||||
|
||||
private void SendWorldChat(string text)
|
||||
{
|
||||
text = (text ?? string.Empty).Trim();
|
||||
if (text.Length == 0 || lobbyNet == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lobbyNet.SendFramework(
|
||||
FrameworkOpcode.WorldChatSend,
|
||||
new WorldChatSendMsg { Text = text }.Encode());
|
||||
}
|
||||
|
||||
private void CloseWorldChat()
|
||||
{
|
||||
if (worldChat != null)
|
||||
{
|
||||
worldChat.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetLobbyPlayerName()
|
||||
|
||||
@@ -908,15 +908,14 @@ namespace XGame
|
||||
joystickRoot.gameObject.SetActive(joined);
|
||||
yield break;
|
||||
}
|
||||
// 摇杆是抬头 HUD → 挂到 UIRoot/HUD 层(见 UI 挂载规则);Main 未就绪时降级到本地 HUD 画布
|
||||
Transform parent = GetHudParent();
|
||||
GameObject prefabObj = prefab as GameObject;
|
||||
if (prefabObj == null)
|
||||
{
|
||||
Debug.LogError("[LobbyWorldController] load joystick prefab failed: " + JoystickPrefabPath);
|
||||
yield break;
|
||||
}
|
||||
rootObj = Instantiate(prefabObj, parent, false);
|
||||
rootObj = Instantiate(prefabObj);
|
||||
UIManager.AttachTo(UILayer.HUD, rootObj);
|
||||
|
||||
rootObj.name = "UI_LobbyJoystick";
|
||||
joystickRoot = rootObj.GetComponent<RectTransform>();
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace XGame
|
||||
private const string UIRootName = "UIRoot";
|
||||
private static readonly string[] LayerNames = { "HUD", "Normal", "Dialog", "Tips" };
|
||||
private static readonly Vector2 DesignResolution = new Vector2(2048f, 1024f);
|
||||
private static readonly int UiLayerId = LayerMask.NameToLayer("UI");
|
||||
|
||||
/// <summary>把 UI 挂到指定层(worldPositionStays=false 保留本地布局/锚点)。</summary>
|
||||
public static void AttachTo(UILayer layer, GameObject ui, bool worldPositionStays = false)
|
||||
@@ -39,6 +40,8 @@ namespace XGame
|
||||
if (layerRt != null)
|
||||
{
|
||||
ui.transform.SetParent(layerRt, worldPositionStays);
|
||||
ApplyUiLayer(ui.transform);
|
||||
EnsureVisibleAttachedRoot(ui);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +65,10 @@ namespace XGame
|
||||
if (go == null)
|
||||
{
|
||||
go = new GameObject(UIRootName, typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
|
||||
if (UiLayerId >= 0)
|
||||
{
|
||||
go.layer = UiLayerId;
|
||||
}
|
||||
Canvas canvas = go.GetComponent<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
canvas.sortingOrder = 100; // 位于主界面之上
|
||||
@@ -78,9 +85,45 @@ namespace XGame
|
||||
CreateFullStretchChild(go.transform, LayerNames[i]);
|
||||
}
|
||||
}
|
||||
ApplyUiLayer(go.transform);
|
||||
return go.transform;
|
||||
}
|
||||
|
||||
private static void EnsureVisibleAttachedRoot(GameObject ui)
|
||||
{
|
||||
RectTransform rt = ui == null ? null : ui.transform as RectTransform;
|
||||
if (rt == null || ui.GetComponent<Canvas>() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Mathf.Abs(rt.rect.width) > 0.01f || Mathf.Abs(rt.rect.height) > 0.01f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rt.anchorMin = Vector2.zero;
|
||||
rt.anchorMax = Vector2.one;
|
||||
rt.offsetMin = Vector2.zero;
|
||||
rt.offsetMax = Vector2.zero;
|
||||
rt.pivot = new Vector2(0.5f, 0.5f);
|
||||
rt.localScale = Vector3.one;
|
||||
}
|
||||
|
||||
private static void ApplyUiLayer(Transform root)
|
||||
{
|
||||
if (root == null || UiLayerId < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
root.gameObject.layer = UiLayerId;
|
||||
for (int i = 0; i < root.childCount; i++)
|
||||
{
|
||||
ApplyUiLayer(root.GetChild(i));
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureEventSystem()
|
||||
{
|
||||
if (EventSystem.current != null || Object.FindObjectOfType<EventSystem>() != null)
|
||||
@@ -93,6 +136,10 @@ namespace XGame
|
||||
private static Transform CreateFullStretchChild(Transform parent, string name)
|
||||
{
|
||||
GameObject go = new GameObject(name, typeof(RectTransform));
|
||||
if (UiLayerId >= 0)
|
||||
{
|
||||
go.layer = UiLayerId;
|
||||
}
|
||||
RectTransform rt = go.GetComponent<RectTransform>();
|
||||
rt.SetParent(parent, false);
|
||||
rt.anchorMin = Vector2.zero;
|
||||
|
||||
Reference in New Issue
Block a user