This commit is contained in:
2026-04-26 04:39:59 +07:00
parent fdb2460c3b
commit 5b22d31259
81 changed files with 14099 additions and 277 deletions

View File

@@ -1,21 +1,70 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd">
<Style src="project:/Assets/UI/Styles/Global.uss" />
<ui:VisualElement class="screen-root">
<ui:VisualElement class="panel" style="width: 600px;">
<ui:Label text="LOBBY" class="header-text" />
<ui:Label text="Room Code: #H4L2" style="color: #AAAAAA; -unity-text-align: middle-center; margin-bottom: 10px;" />
<ui:VisualElement class="diagonal-container">
<!-- Left Pane: Transparent for 3D View (Character/Map) -->
<ui:VisualElement class="left-pane" />
<ui:ScrollView name="player-list" style="height: 300px; background-color: rgba(0,0,0,0.2); margin-bottom: 20px; padding: 10px;">
<!-- Placeholder players -->
<ui:Label text="Player 1 (Host)" style="color: #FFD700;" />
<ui:Label text="Player 2" />
<ui:Label text="Searching for players..." style="color: #666; font-style: italic;" />
</ui:ScrollView>
<!-- Right Pane: Frosted glass UI area -->
<ui:VisualElement class="right-pane-wrapper">
<ui:VisualElement class="right-pane-content">
<!-- Top Navigation (Always Visible) -->
<ui:VisualElement style="flex-direction: row; justify-content: space-between; margin-bottom: 30px;">
<ui:Button name="btn-back" class="slanted-button">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="&lt; BACK" style="font-size: 14px;" />
</ui:VisualElement>
</ui:Button>
<ui:Button name="btn-settings" class="slanted-button">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="SETTINGS" style="font-size: 14px;" />
</ui:VisualElement>
</ui:Button>
</ui:VisualElement>
<ui:VisualElement style="flex-direction: row; justify-content: space-between;">
<ui:Button text="LEAVE" name="btn-leave" class="button-primary button-danger" style="flex-grow: 1;" />
<ui:Button text="START GAME" name="btn-start" class="button-primary" style="flex-grow: 2;" />
<!-- STAGE 1: JOIN ROOM (Room Browser) -->
<ui:VisualElement name="join-view" display="Flex">
<ui:Label text="BROWSE ROOMS" class="header-text" style="font-size: 32px; -unity-text-align: upper-left; margin-bottom: 20px;" />
<!-- Search & Filters -->
<ui:VisualElement style="flex-direction: row; margin-bottom: 15px;">
<ui:TextField placeholder-text="Search room name..." name="search-field" style="flex-grow: 1; margin-right: 10px;" />
<ui:DropdownField name="sort-dropdown" choices="Ping,Name,Slots" value="Ping" style="width: 100px;" />
</ui:VisualElement>
<ui:ScrollView name="room-list" style="flex-grow: 1; height: 500px; background-color: rgba(0,0,0,0.4); padding: 10px; border-radius: 5px;">
<!-- Room items will be instantiated here via C# -->
<ui:Label text="No rooms found..." style="opacity: 0.5; -unity-text-align: middle-center; margin-top: 50px;" />
</ui:ScrollView>
</ui:VisualElement>
<!-- STAGE 2: CREATE ROOM (Configuration) -->
<ui:VisualElement name="create-view" display="None">
<ui:Label text="HOST NEW SESSION" class="header-text" style="font-size: 32px; -unity-text-align: upper-left; margin-bottom: 20px;" />
<ui:VisualElement style="margin-bottom: 20px;">
<ui:Label text="ROOM NAME" style="font-size: 12px; color: #888;" />
<ui:TextField name="field-room-name" value="SURVIVOR'S DEN" />
</ui:VisualElement>
<ui:VisualElement style="margin-bottom: 20px;">
<ui:Toggle label="REQUIRE PASSWORD" name="toggle-password" />
<ui:TextField name="field-password" password="true" display="None" />
</ui:VisualElement>
<ui:VisualElement style="margin-bottom: 40px;">
<ui:Label text="MAX PLAYERS: 2 (LOCKED)" style="font-size: 12px; color: #555;" />
</ui:VisualElement>
<ui:Button name="btn-create-confirm" class="slanted-button" style="height: 60px;">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="CREATE ROOM" style="font-size: 24px;" />
</ui:VisualElement>
</ui:Button>
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>

View File

@@ -0,0 +1,39 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd">
<Style src="project:/Assets/UI/Styles/Global.uss" />
<ui:VisualElement class="screen-root" style="justify-content: flex-start; align-items: stretch; width: 100%; height: 100%;">
<ui:VisualElement style="flex-direction: row; flex-grow: 1; width: 100%; height: 100%;">
<!-- Player 1 (Blue Tint) -->
<ui:VisualElement style="flex-grow: 1; background-color: rgba(59, 89, 152, 0.2); justify-content: flex-end; align-items: center; padding-bottom: 50px;">
<ui:Label text="HOST" style="color: white; font-size: 48px; -unity-font-style: bold;" />
<ui:Toggle label="READY" name="ready-host" class="slanted-button" style="width: 200px;" />
</ui:VisualElement>
<!-- Diagonal Slash Divider (simplified) -->
<ui:VisualElement style="width: 5px; background-color: #FFFFFF; rotate: 15deg;" />
<!-- Player 2 (Orange Tint) -->
<ui:VisualElement style="flex-grow: 1; background-color: rgba(255, 165, 0, 0.2); justify-content: flex-end; align-items: center; padding-bottom: 50px;">
<ui:Label text="GUEST" style="color: white; font-size: 48px; -unity-font-style: bold;" />
<ui:Toggle label="READY" name="ready-guest" class="slanted-button" style="width: 200px;" />
</ui:VisualElement>
</ui:VisualElement>
<!-- Start Button Overlaid -->
<ui:VisualElement style="position: absolute; bottom: 100px; width: 100%; align-items: center;" picking-mode="Ignore">
<ui:Button name="btn-start" class="slanted-button" style="width: 400px; height: 80px;">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="START GAME" style="font-size: 32px;" />
</ui:VisualElement>
</ui:Button>
</ui:VisualElement>
<!-- Nav Overlays -->
<ui:VisualElement style="position: absolute; top: 40px; left: 40px;" picking-mode="Ignore">
<ui:Button name="btn-back" class="slanted-button">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="&lt; LEAVE" />
</ui:VisualElement>
</ui:Button>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 1acf05b4c3eb7964b9b87b16b66c85f8
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -1,27 +1,56 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd">
<Style src="project:/Assets/UI/Styles/Global.uss" />
<ui:VisualElement style="flex-grow: 1; justify-content: flex-end; padding: 40px;">
<!-- Top Left: Stats -->
<ui:VisualElement style="position: absolute; top: 40px; left: 40px; background-color: rgba(0,0,0,0.5); padding: 15px; border-radius: 5px;">
<ui:Label name="health-text" text="HEALTH: 100/100" style="color: #ff4d4d; -unity-font-style: bold; margin-bottom: 5px;" />
<ui:VisualElement name="health-bar-bg" style="width: 200px; height: 12px; background-color: #333; border-radius: 3px; overflow: hidden; margin-bottom: 10px;">
<ui:VisualElement name="health-fill" style="width: 100%; height: 100%; background-color: #ff4d4d;" />
<!-- Root is fully transparent and ignores picking for gameplay -->
<ui:VisualElement style="flex-grow: 1; padding: 40px;" picking-mode="Ignore">
<!-- Area 2: Player Stats (Top Left) -->
<ui:VisualElement name="hud-stats" style="position: absolute; top: 40px; left: 40px; width: 300px;">
<ui:Label name="health-text" text="HEALTH" style="color: #ff4d4d; -unity-font-style: bold; margin-bottom: 5px;" />
<ui:VisualElement class="hud-bar-container" style="height: 20px;">
<ui:VisualElement name="health-fill" class="hud-bar-fill" style="width: 100%; background-color: #ff4d4d;" />
</ui:VisualElement>
<ui:Label text="STAMINA" style="color: #4da6ff; font-size: 12px; -unity-font-style: bold; margin-bottom: 3px;" />
<ui:VisualElement name="stamina-bar-bg" style="width: 150px; height: 8px; background-color: #333; border-radius: 2px; overflow: hidden;">
<ui:VisualElement name="stamina-fill" style="width: 100%; height: 100%; background-color: #4da6ff;" />
<ui:Label text="STAMINA" style="color: #4da6ff; -unity-font-style: bold; margin-top: 10px; margin-bottom: 5px;" />
<ui:VisualElement class="hud-bar-container" style="height: 12px;">
<ui:VisualElement name="stamina-fill" class="hud-bar-fill" style="width: 100%; background-color: #4da6ff;" />
</ui:VisualElement>
</ui:VisualElement>
<!-- Center: Interaction Prompt -->
<ui:VisualElement name="interaction-prompt" style="align-self: center; margin-bottom: 150px; background-color: rgba(0,0,0,0.6); padding: 10px 20px; border-radius: 20px; border-width: 1px; border-color: white; display: none;">
<!-- Area 3: Minimap (Top Right) -->
<ui:VisualElement name="hud-minimap" style="position: absolute; top: 40px; right: 40px; width: 200px; height: 200px; border-radius: 50%; background-color: rgba(0,0,0,0.4); border-width: 2px; border-color: white; overflow: hidden;">
<!-- Placeholder for map render texture -->
<ui:Label text="MAP" style="align-self: center; margin-top: 80px; opacity: 0.5;" />
</ui:VisualElement>
<!-- Area 4: Inventory (Bottom Left) -->
<ui:VisualElement name="hud-inventory" style="position: absolute; bottom: 40px; left: 40px; flex-direction: row; align-items: flex-end;">
<ui:VisualElement name="slot-holding" style="width: 100px; height: 100px; background-color: rgba(255,255,255,0.1); border-width: 2px; border-color: white; margin-right: 15px; justify-content: center; align-items: center;">
<ui:Label text="HAND" style="font-size: 10px;" />
</ui:VisualElement>
<ui:VisualElement style="flex-direction: row;">
<ui:VisualElement class="inv-slot" name="slot-1" style="width: 50px; height: 50px; background-color: rgba(0,0,0,0.5); border-width: 1px; border-color: #888; margin-right: 5px; justify-content: center; align-items: center;">
<ui:Label text="1" style="font-size: 8px; opacity: 0.5;" />
</ui:VisualElement>
<ui:VisualElement class="inv-slot" name="slot-2" style="width: 50px; height: 50px; background-color: rgba(0,0,0,0.5); border-width: 1px; border-color: #888; margin-right: 5px; justify-content: center; align-items: center;">
<ui:Label text="2" style="font-size: 8px; opacity: 0.5;" />
</ui:VisualElement>
<ui:VisualElement class="inv-slot" name="slot-3" style="width: 50px; height: 50px; background-color: rgba(0,0,0,0.5); border-width: 1px; border-color: #888; justify-content: center; align-items: center;">
<ui:Label text="3" style="font-size: 8px; opacity: 0.5;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
<!-- Area 5: Game Info (Bottom Center) -->
<ui:VisualElement name="hud-info" style="position: absolute; bottom: 20px; align-self: center; flex-direction: row;">
<ui:Label name="ping-label" text="PING: 20ms" style="color: #888; font-size: 12px; margin-right: 20px;" />
<ui:Label name="fps-label" text="FPS: 60" style="color: #888; font-size: 12px;" />
</ui:VisualElement>
<!-- Interaction Prompt (Center) -->
<ui:VisualElement name="interaction-prompt" style="align-self: center; margin-top: 600px; background-color: rgba(0,0,0,0.6); padding: 10px 20px; border-radius: 20px; border-width: 1px; border-color: white;" display="None">
<ui:Label name="interaction-text" text="Press [E] to Interact" style="color: white; font-size: 20px; -unity-text-align: middle-center;" />
</ui:VisualElement>
<!-- Bottom Center: Info -->
<ui:VisualElement style="align-self: center; background-color: rgba(0,0,0,0.3); padding: 5px 15px; border-radius: 10px;">
<ui:Label name="noise-label" text="NOISE: 0%" style="color: #00ff00; font-size: 14px; -unity-font-style: bold;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@@ -1,13 +1,55 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd">
<Style src="project:/Assets/UI/Styles/Global.uss" />
<ui:VisualElement class="screen-root">
<ui:VisualElement class="panel">
<ui:Label text="HALLUCINATE" class="header-text" />
<ui:Button text="CREATE ROOM" name="btn-create" class="button-primary" />
<ui:Button text="JOIN ROOM" name="btn-join" class="button-primary" />
<ui:Button text="SETTINGS" name="btn-settings" class="button-primary" />
<ui:Button text="PROFILE" name="btn-profile" class="button-primary" />
<ui:Button text="EXIT" name="btn-exit" class="button-primary button-danger" />
<ui:VisualElement name="menu-root" class="screen-root" style="justify-content: center; align-items: center;">
<!-- Background Blur Layer (Can be controlled via C#) -->
<ui:VisualElement name="bg-blur" style="position: absolute; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.4);" />
<!-- Logo Container (Idle position: Center) -->
<ui:VisualElement name="beat-logo-container" style="justify-content: center; align-items: center; width: 400px; height: 400px;">
<ui:VisualElement name="beat-logo" style="width: 300px; height: 300px; background-color: white; border-radius: 50%; box-shadow: 0 0 50px rgba(255, 255, 255, 0.3);" />
<ui:Label text="HALLUCINATE" style="position: absolute; color: black; -unity-font-style: bold; font-size: 32px; letter-spacing: 5px;" />
</ui:VisualElement>
<!-- Horizontal Ribbon (Slides out from center) -->
<ui:VisualElement name="menu-ribbon" style="position: absolute; flex-direction: row; justify-content: center; align-items: center; width: 100%; height: 120px; background-color: rgba(0, 0, 0, 0.8); border-top-width: 2px; border-bottom-width: 2px; border-color: rgba(255, 255, 255, 0.1); display: None;">
<!-- Left Side Buttons -->
<ui:VisualElement style="flex-direction: row; align-items: center; justify-content: flex-end; flex-grow: 1;">
<ui:Button name="btn-settings" class="slanted-button">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="SETTINGS" />
</ui:VisualElement>
</ui:Button>
</ui:VisualElement>
<!-- Spacer for Logo -->
<ui:VisualElement name="logo-placeholder" style="width: 250px;" />
<!-- Right Side Buttons -->
<ui:VisualElement style="flex-direction: row; align-items: center; justify-content: flex-start; flex-grow: 1;">
<ui:Button name="btn-create" class="slanted-button">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="CREATE" />
</ui:VisualElement>
</ui:Button>
<ui:Button name="btn-join" class="slanted-button">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="JOIN" />
</ui:VisualElement>
</ui:Button>
<ui:Button name="btn-profile" class="slanted-button">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="PROFILE" />
</ui:VisualElement>
</ui:Button>
<ui:Button name="btn-exit" class="slanted-button">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="EXIT" />
</ui:VisualElement>
</ui:Button>
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@@ -1,25 +1,57 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEngine.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd">
<Style src="project:/Assets/UI/Styles/Global.uss" />
<ui:VisualElement class="screen-root">
<ui:VisualElement class="panel">
<ui:Label text="PLAYER PROFILE" class="header-text" />
<ui:VisualElement style="flex-direction: row; margin-bottom: 20px;">
<ui:VisualElement style="width: 100px; height: 100px; background-color: #555; border-radius: 50%; margin-right: 20px;" />
<ui:VisualElement>
<ui:Label text="Username: PlayerOne" style="font-size: 24px; -unity-font-style: bold;" />
<ui:Label text="Level: 15" style="color: #AAAAAA;" />
<ui:VisualElement class="diagonal-container">
<!-- Left Pane: Character Profile View -->
<ui:VisualElement class="left-pane" />
<!-- Right Pane: Stats & Info -->
<ui:VisualElement class="right-pane-wrapper">
<ui:VisualElement class="right-pane-content">
<!-- Nav Bar -->
<ui:VisualElement style="flex-direction: row; justify-content: space-between; margin-bottom: 40px;">
<ui:Button name="btn-back" class="slanted-button" focusable="true">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="&lt; BACK" style="font-size: 14px;" />
</ui:VisualElement>
</ui:Button>
<ui:Button name="btn-settings" class="slanted-button" focusable="true">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="SETTINGS" style="font-size: 14px;" />
</ui:VisualElement>
</ui:Button>
</ui:VisualElement>
<ui:Label text="PROFILE" class="header-text" style="font-size: 40px; -unity-text-align: upper-left;" />
<!-- User Header -->
<ui:VisualElement style="flex-direction: row; align-items: center; margin-bottom: 40px;">
<ui:VisualElement name="avatar" style="width: 100px; height: 100px; border-radius: 50%; background-color: #555; border-width: 3px; border-color: white; margin-right: 20px;" />
<ui:VisualElement>
<ui:Label text="PLAYER ONE" style="font-size: 32px; -unity-font-style: bold;" />
<ui:Label text="RANK: SURVIVOR" style="color: #AAAAAA; font-size: 18px;" />
</ui:VisualElement>
</ui:VisualElement>
<!-- Stats Area -->
<ui:VisualElement style="background-color: rgba(0,0,0,0.3); padding: 20px; border-radius: 10px;">
<ui:Label text="STATISTICS" style="-unity-font-style: bold; margin-bottom: 10px;" />
<ui:Label text="WIN RATE: 75%" />
<ui:Label text="MATCHES: 124" />
<ui:Label text="ELO RATING: 1500" />
</ui:VisualElement>
<!-- Skins/Customization -->
<ui:Label text="CUSTOMIZATION" style="-unity-font-style: bold; margin-top: 30px; margin-bottom: 10px;" />
<ui:ScrollView style="height: 200px; background-color: rgba(0,0,0,0.2); padding: 10px;">
<ui:VisualElement style="flex-direction: row; flex-wrap: wrap;">
<ui:VisualElement style="width: 80px; height: 80px; background-color: #444; margin: 5px; border-radius: 5px;" />
<ui:VisualElement style="width: 80px; height: 80px; background-color: #444; margin: 5px; border-radius: 5px;" />
<ui:VisualElement style="width: 80px; height: 80px; background-color: #444; margin: 5px; border-radius: 5px;" />
</ui:VisualElement>
</ui:ScrollView>
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement style="background-color: rgba(0,0,0,0.2); padding: 15px; border-radius: 5px; margin-bottom: 20px;">
<ui:Label text="Stats" style="-unity-font-style: bold; margin-bottom: 10px;" />
<ui:Label text="Wins: 24" />
<ui:Label text="Losses: 10" />
<ui:Label text="K/D Ratio: 1.5" />
</ui:VisualElement>
<ui:Button text="CLOSE" name="btn-close" class="button-primary" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@@ -1,42 +1,31 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd">
<Style src="project:/Assets/UI/Styles/Global.uss" />
<ui:VisualElement class="screen-root" name="settings-root">
<ui:VisualElement class="panel" style="width: 800px; height: 600px;">
<ui:Label text="SETTINGS" name="title" class="header-text" />
<!-- TABS ROW -->
<ui:VisualElement class="tab-container">
<ui:VisualElement class="modal-backdrop" name="settings-overlay">
<ui:VisualElement class="modal-panel">
<ui:VisualElement style="flex-direction: row; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<ui:Label text="SETTINGS" class="header-text" style="font-size: 32px; margin-bottom: 0;" />
<ui:Button name="btn-close" class="slanted-button" focusable="true">
<ui:VisualElement class="slanted-button-inner">
<ui:Label text="X" />
</ui:VisualElement>
</ui:Button>
</ui:VisualElement>
<!-- TABS -->
<ui:VisualElement style="flex-direction: row; margin-bottom: 20px;">
<ui:Button text="GENERAL" name="tab-general" class="tab-button active-tab" />
<ui:Button text="GRAPHICS" name="tab-graphics" class="tab-button" />
<ui:Button text="AUDIO" name="tab-audio" class="tab-button" />
<ui:Button text="CONTROLS" name="tab-controls" class="tab-button" />
</ui:VisualElement>
<!-- CONTENT AREA -->
<ui:ScrollView class="tab-content">
<!-- Tab: General (Camera Settings) -->
<!-- CONTENT -->
<ui:ScrollView style="flex-grow: 1;">
<ui:VisualElement name="content-general">
<ui:Label text="Camera Settings" style="-unity-font-style: bold; margin-bottom: 10px;" />
<ui:Slider label="Field of View (FOV)" name="setting-fov" value="60" low-value="40" high-value="120" />
<ui:Slider label="Sensitivity" name="setting-sensitivity" value="5" low-value="0.1" high-value="20" />
<ui:DropdownField label="Language" name="setting-language" index="0" choices="English,Tiếng Việt" />
</ui:VisualElement>
<!-- Tab: Graphics (Dummy) -->
<ui:VisualElement name="content-graphics" style="display: none;">
<ui:DropdownField label="Quality" index="2" choices="Low,Medium,High,Ultra" />
<ui:Toggle label="Fullscreen" value="true" />
<ui:Toggle label="V-Sync" value="true" />
</ui:VisualElement>
<!-- Tab: Audio (Dummy) -->
<ui:VisualElement name="content-audio" style="display: none;">
<ui:Slider label="Master Volume" value="80" low-value="0" high-value="100" />
<ui:Slider label="Music Volume" value="50" low-value="0" high-value="100" />
<ui:Slider label="Field of View" name="setting-fov" value="60" low-value="40" high-value="120" />
<ui:Slider label="Mouse Sensitivity" name="setting-sensitivity" value="5" low-value="0.1" high-value="20" />
</ui:VisualElement>
</ui:ScrollView>
<ui:Button text="BACK" name="btn-back" class="button-primary" style="align-self: flex-end; margin-top: 20px;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,137 @@
# **Game UI/UX Architecture & Routing Specification (Unity UI Toolkit Edition)**
This document outlines the complete structural layout, visual design, animations, and routing logic for the game's user interface, specifically optimized for **Unity UI Toolkit**. It serves as a direct guide for the associated .uxml, .uss, and .cs controller files.
## **1\. Global Design System & Technical Approach**
To maintain consistency and reduce development overhead, the UI is built using UXML templates, styled with USS, and driven by specific C\# controllers mapped to your project structure.
### **Core UI Toolkit Architecture & File Mapping**
* **Controllers:** UI logic is managed by dedicated scripts (UIManager.cs, MainMenuController.cs, LobbyController.cs, ProfileController.cs, SettingsController.cs, HUDController.cs).
* **Views (UXML):** Layouts are defined in modular files (MainMenu.uxml, Lobby.uxml, Profile.uxml, Settings.uxml, MainGameHUD.uxml).
* **Styles (USS):** Global styling is handled in Global.uss.
### **Reusable UI Components & Visual Styles**
* **Cursorless Navigation (Focus-Based Selection):** The game does not display a standard OS cursor (Cursor.visible \= false). Instead, the UI interprets mouse movement natively to determine focus. As the hidden cursor moves, the nearest interactive element highlights and scales up. This provides a smart, "snapping" feel to UI selection without needing a visible pointer.
* **The "Osu-Style" Slanted Button:** A custom VisualElement utilizing USS transform: skew(...) properties to create angled edges. Contains an inner text element counter-skewed to remain horizontal.
* **Diagonal Split-Screen Container:** Used in Lobby and Profile screens. Instead of a boring vertical line, the split is a sharp diagonal line (like a lightning slash).
* *Implementation:* Achieved by applying a negative skew to the Right Pane's parent container, and a positive skew to its inner content to keep text readable.
* *Left Pane (approx. 60% width):* Transparent background, showing the Unity 3D Camera rendering the character model and procedural map.
* *Right Pane (approx. 40% width):* Frosted glass effect.
* **Right-Pane Navigation Bar (Top):** Unlike standard top bars, the navigation is contained *entirely within the Right Pane*.
* \[ \< Back \] button is pinned to the Top-Left of the right panel.
* \[ Settings \] button is pinned to the Top-Right of the right panel.
* **Modal Overlay Backdrop:** A full-screen VisualElement with a semi-transparent black USS background. Used to dim the screen and block inputs behind the Settings panel, Password Prompts, and Confirmation Dialogs.
## **2\. Screen-by-Screen Implementation Details**
### **2.1. Main Menu (MainMenu.uxml & MainMenuController.cs)**
Inspired by osu\!lazer, this screen is highly dynamic and relies on smooth, physics-based transitions.
* **State 1: Initial Load (Idle)**
* **Visuals:** The background is a heavily blurred, atmospheric map preview. The OS cursor is hidden. Dead center is the **Beat Logo**.
* **Animation:** The Beat Logo dynamically pulses (scales up and down) precisely in sync with the audio source's beat/BPM. There are no other UI elements visible.
* **State 2: Active Menu (Transition & Active State)**
* **Interaction:** The user moves the mouse toward the center, the logo snaps into focus (glows), and they click.
* **Smooth Transition:** 1\. The Beat Logo shrinks slightly and smoothly translates from the dead center to its designated position in the horizontal menu row.
2\. A horizontal VisualElement container (the ribbon) unfolds from behind the logo using an elastic/spring animation.
3\. The slanted buttons slide out from the logo's position horizontally: \[Settings\] to the left, and \[Create Room\], \[Join Room\], \[Profile\], \[Exit\] to the right. They fade in (opacity: 1\) with a staggered C\# coroutine delay to create a cascading reveal effect.
### **2.2. Lobby (Lobby.uxml & LobbyController.cs)**
* **View Setup:** Utilizes the Diagonal Split-Screen Container. The view is dynamic; the Right Pane content switches based on whether the user selected "Join Room" or "Create Room" from the Main Menu.
* **Left Pane (Transparent):** Shows the player model and live procedural background map generation.
* **Right Pane (Static UI Area) \- Divided into Two Stages:**
* **Navigation (Shared):** \[ \< Back \] (Top-Left) and \[ Settings \] (Top-Right) are always visible.
* **Stage 1: Join Room (Room Browser)**
* *Triggered when entering via the \[Join Room\] button.*
* **Filters & Search:** The top of this view includes a TextField for **Searching** by Room Name, and a DropdownField (or sort icons) for **Sorting** the list (e.g., by Ping, Name, or Open Slots).
* **Room List:** A ScrollView dynamically populated with active rooms via C\#. Each list item displays the Room Name, Host Name, Ping, and a clear "Lock" icon if the room requires a password.
* **Interaction Logic:**
* Clicking an unlocked room immediately joins it and transitions the player to the Lounge.
* Clicking a locked room triggers a Modal Overlay popup asking for the password (contains a TextField and \[Submit\] / \[Cancel\] buttons) before joining.
* **Stage 2: Create Room (Configuration Setup)**
* *Triggered when entering via the \[Create Room\] button.*
* **Content:** Dedicated input fields for setting up a new session. Uses TextField for Room Name and an optional Password. *Note: Max players is strictly locked to 2, so no dropdown field is necessary.*
* **Toggles:** A "Require password to join" checkbox/toggle is present to enable or disable the password field.
* **Action:** A large "CREATE ROOM" button sits at the bottom. Clicking this instantiates the room on the server and transitions the player to the Lounge as the Host.
### **2.3. Profile (Profile.uxml & ProfileController.cs)**
* **Layout:** Reuses the Diagonal Split-Screen structure. The 3D camera shifts to a "Profile Studio" lighting setup for the Left Pane.
* **Right Pane Content:**
* **Navigation:** \[ \< Back \] (Top-Left) and \[ Settings \] (Top-Right).
* **Header:** Player Avatar (circular mask), Username, and Rank/Level badge.
* **Statistics:** Text labels and progress bars for Win Rate, Matches Played, and current Elo/Rating.
* **Customization:** A scrollable grid view at the bottom for equipping character skins or banners.
### **2.4. Lounge / Pre-Match (Lobby.uxml extensions or new UXML)**
Since the game is strictly 2-player, the Lounge is an intimate VS screen.
* **Layout:** The screen is split directly down the middle via a diagonal slash. Player 1 (Host) is on the left, Player 2 (Guest) is on the right.
* **Visuals:** Each half has a distinctly tinted background color (e.g., Blue for Host, Red/Orange for Guest) behind the transparent 3D character models.
* **Navigation:** \[ \< Back \] (Top-Left) and \[ Settings \] (Top-Right) overlay the entire screen.
* **Confirmation Logic:** Clicking \[ \< Back \] triggers a Modal Overlay popup: "Are you sure you want to leave the room? \[Yes\] \[No\]".
* **Ready System:**
* Bottom of each player's panel has a Ready toggle.
* The Host has a large \[ START GAME \] button in the bottom center.
* **Logic:** The \[ START GAME \] button is greyed out (SetEnabled(false)) until *both* players have toggled their status to "Ready".
### **2.5. In-Game HUD (MainGameHUD.uxml & HUDController.cs)**
The HUD strictly follows a "Zero Obstruction" philosophy with specific interactive zones.
* **Area 1: The 3D World (Background)**
* The root UI element is fully transparent and set to picking-mode: ignore so all mouse inputs register for aiming/gameplay.
* **Area 2: Player Stats (Top Left)**
* **Visuals:** Liquid progress bars for Health and Stamina. Instead of standard flat bars, these utilize a UI Toolkit custom shader or animated sprite mask to look like fluid filling/draining from a container.
* **Area 3: Minimap (Top Right)**
* **Visuals:** The minimap continuously updates based on player position. It features a soft fade effect at its borders (achieved via an alpha gradient mask/texture applied to the VisualElement), seamlessly blending it into the gameplay view without harsh square borders.
* **Area 4: Inventory (Bottom Left)**
* **Structure:** 4 distinct slots: \[ Current Holding \] (larger, highlighted), and three quick-slots \[ I \], \[ II \], \[ III \].
* **Logic:** Pressing 1, 2, or 3 on the keyboard fires an event in HUDController.cs. The selected item's icon swaps into the \[ Current Holding \] slot, and the index updates visually to show what is equipped.
* **Area 5: Game Info (Bottom Center)**
* **Visuals:** Minimalist text displaying current Ping (ms) and FPS.
* **Auto-Hide Logic:**
* To maximize visibility, Area 2 (Stats), Area 4 (Inventory), and Area 5 (Game Info) dynamically fade out.
* In HUDController.cs, track input activity (mouse movement, ability use, damage taken). If Time.time \- lastActivityTime \> 5f (5 seconds), tween the opacity of these areas to 0 or 0.2. Any new interaction instantly fades them back to 1\.
### **2.6. Settings Menu (Settings.uxml & SettingsController.cs)**
* **Structure:** A floating, centered panel (e.g., occupies roughly 60% width and 70% height) rather than a full-screen view. It sits on top of a full-screen semi-transparent backdrop that blocks interactions with the underlying UI.
* **Global Shortcut:** The Settings menu can be toggled open or closed from anywhere in the game by pressing **Ctrl \+ O**.
* **Visuals:** The panel has rounded corners and distinct styling to elevate it from the background.
* **Layout:** Standard settings configuration (Audio sliders, Graphics toggles) using UI Toolkit elements, with a prominent \[ X Close \] button in the top right corner of the panel.
## **3\. C\# State Machine & Routing Logic (UIManager.cs)**
To manage UXML templates, UIManager.cs controls the flow using a stack-based approach.
\[Game Launch\]
|
\[Main Menu (Idle \-\> Active Logo Bar)\]
|
\+-------------------+-------------------+-------------------+
| | | |
v v v v
\[Lobby: Create\] \[Lobby: Join\] \[Profile\] \[Settings (Overlay)\]
| | | |
v v | |
\[Lounge (Host)\] \[Lounge (Guest)\] \+---(Back)----------+
| |
\+--- \[All Ready\] \---+
|
(Host Clicks Start)
|
v
\[IN-GAME HUD\]
### **UI Toolkit State Management Implementation**
1. **Screen Controller Pattern:** Each controller (MainMenuController, LobbyController, etc.) holds a reference to its root VisualElement defined in its corresponding .uxml file.
2. **Navigation Stack (Stack\<VisualElement\>):** UIManager.cs pushes screens to this stack. Pressing the Top-Left \[ \< Back \] button calls a method to pop the current state, hiding it (display: none) and showing the previous one (display: flex).
3. **Global Action Listeners (Ctrl \+ O):** UIManager.cs actively listens to the input system for Ctrl \+ O to instantly trigger SettingsController.ToggleSettings() without affecting the current navigation stack path.
4. **Cursorless Input Routing:** UIManager.cs constantly monitors Input.mousePosition. It calculates the nearest interactive element within the active screen and applies a .hover USS class to it, overriding default Unity pointer events.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6354ab3eece31da4ab644563d7a45612
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -18,7 +18,7 @@ MonoBehaviour:
m_RenderMode: 0
m_ColliderUpdateMode: 0
m_ColliderIsTrigger: 1
m_ScaleMode: 2
m_ScaleMode: 0
m_ReferenceSpritePixelsPerUnit: 100
m_PixelsPerUnit: 100
m_Scale: 1
@@ -26,7 +26,7 @@ MonoBehaviour:
m_FallbackDpi: 96
m_ReferenceResolution: {x: 1920, y: 1080}
m_ScreenMatchMode: 0
m_Match: 0
m_Match: 0.5
m_SortingOrder: 0
m_TargetDisplay: 0
m_BindingLogLevel: 0

View File

@@ -1,12 +1,25 @@
/* --- Global Design System --- */
:root {
--primary-color: #3B5998;
--primary-hover: #4C70BA;
--danger-color: #ff4d4d;
--panel-bg: rgba(45, 45, 45, 0.8);
--frosted-bg: rgba(255, 255, 255, 0.1);
--border-color: #4A4A4A;
--text-color: #E0E0E0;
--glass-blur: 15px;
}
/* Layout Containers */
.screen-root {
flex-grow: 1;
width: 100%;
height: 100%;
background-color: rgba(20, 20, 20, 0.95);
padding: 40px;
justify-content: center;
align-items: center;
/* Smooth Transition */
padding: 0;
justify-content: flex-start;
align-items: stretch;
transition-property: opacity, scale;
transition-duration: 0.3s;
transition-timing-function: ease-in-out;
@@ -20,70 +33,121 @@
display: none;
}
.panel {
background-color: rgba(45, 45, 45, 0.8);
border-width: 2px;
border-color: #4A4A4A;
border-radius: 10px;
padding: 20px;
min-width: 400px;
/* Diagonal Split-Screen Container */
.diagonal-container {
flex-grow: 1;
flex-direction: row;
width: 100%;
height: 100%;
overflow: hidden;
}
/* Tabs Settings Style */
.tab-container {
flex-direction: row;
margin-bottom: 20px;
border-bottom-width: 2px;
border-bottom-color: #333;
.left-pane {
width: 60%;
background-color: transparent;
}
.right-pane-wrapper {
width: 45%; /* Slightly larger to account for the skew overlap */
margin-left: -5%;
transform: skewX(-15deg);
background-color: var(--frosted-bg);
border-left-width: 4px;
border-left-color: white;
overflow: hidden;
}
.right-pane-content {
flex-grow: 1;
transform: skewX(15deg); /* Counter-skew content */
padding: 60px 40px;
background-color: rgba(0, 0, 0, 0.4); /* Darken for readability */
}
/* Modal Overlay Backdrop */
.modal-backdrop {
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
justify-content: center;
align-items: center;
padding: 100px;
}
.modal-panel {
background-color: var(--panel-bg);
border-width: 2px;
border-color: var(--border-color);
border-radius: 20px;
padding: 30px;
min-width: 600px;
min-height: 400px;
}
/* Osu-Style Slanted Button */
.slanted-button {
background-color: var(--primary-color);
padding: 0;
margin: 8px;
border-radius: 0;
border-width: 0;
transform: skewX(-20deg);
transition-duration: 0.1s;
overflow: hidden;
}
.slanted-button-inner {
flex-grow: 1;
padding: 12px 30px;
transform: skewX(20deg); /* Counter-skew text */
-unity-text-align: middle-center;
color: white;
font-size: 20px;
-unity-font-style: bold;
}
/* Cursorless Focus System */
.slanted-button.hover {
background-color: var(--primary-hover);
scale: 1.1;
border-width: 2px;
border-color: white;
}
/* HUD Components */
.hud-bar-container {
background-color: rgba(0, 0, 0, 0.5);
border-radius: 10px;
overflow: hidden;
margin-bottom: 5px;
}
.hud-bar-fill {
height: 100%;
transition-property: width;
transition-duration: 0.2s;
}
/* Typography */
.header-text {
font-size: 64px;
color: var(--text-color);
-unity-font-style: bold;
margin-bottom: 30px;
-unity-text-align: middle-center;
}
.tab-button {
flex-grow: 1;
background-color: rgba(60, 60, 60, 0.5);
border-radius: 5px 5px 0 0;
padding: 10px;
padding: 15px;
color: #888;
margin-right: 2px;
margin-right: 5px;
border-radius: 10px 10px 0 0;
}
.tab-button.active-tab {
background-color: #3B5998;
background-color: var(--primary-color);
color: white;
-unity-font-style: bold;
}
.tab-content {
flex-grow: 1;
padding: 10px;
}
/* Typography */
.header-text {
font-size: 48px;
color: #E0E0E0;
-unity-font-style: bold;
margin-bottom: 30px;
-unity-text-align: middle-center;
/* Để dùng font của bạn, hãy uncomment dòng dưới và thay đổi path */
/* -unity-font-definition: url("project:/Assets/Fonts/YourFont_SDF.asset"); */
}
/* Buttons */
.button-primary {
background-color: #3B5998;
color: white;
padding: 12px 24px;
margin: 8px;
border-radius: 5px;
font-size: 20px;
transition-duration: 0.2s;
}
.button-primary:hover {
background-color: #4C70BA;
scale: 1.05;
}
.button-primary:active {
background-color: #2D4373;
}