-- Backslash toggles HUD only. Keep pages, dialogs and UI cameras visible. local Input = CS.UnityEngine.Input local KeyCode = CS.UnityEngine.KeyCode local Time = CS.UnityEngine.Time local GameObject = CS.UnityEngine.GameObject local CanvasGroup = CS.UnityEngine.CanvasGroup local Camera = CS.UnityEngine.Camera -- Names observed under UIRoot in this Client, plus the existing battle HUD. -- Never target an ancestor shared by HUD and character/reward dialogs. local HUD_PATHS = { "UIRoot/Page/MazeMainPage(Clone)", -- Fallback for clients where the phase's private HudPage field is absent -- or does not include every battle overlay. "UIRoot/Page/BattleGamePhaseUI(Clone)", "UIRoot/BelowPage/AdventureWaypointsPage(Clone)", "UIRoot/BelowPage/MazeJumpingText(Clone)", "UIRoot/BelowPage/MazeMonsterWarningPage(Clone)", -- Character controls observed under AvatarMainPage/Root. Keep RankPanel -- and dialogs intact so Eidolon illustrations are not hidden with menus. "UIRoot/Page/AvatarMainPage(Clone)/Root/AvatarSubMenuPanel_Vertical", "UIRoot/Page/AvatarMainPage(Clone)/Root/AvatarDetailPanel", "UIRoot/Page/AvatarMainPage(Clone)/Root/AvatarTopListPanel", "UIRoot/Page/AvatarMainPage(Clone)/Root/AvatarListPanel", "UIRoot/Page/AvatarMainPage(Clone)/Root/BtnClose", "UIRoot/Page/AvatarMainPage(Clone)/Root/TopBarArea", } -- The old script did not record CanvasGroup state. Undo its blanket hide once -- on live upgrade; a fresh Client session avoids any lost legacy fade state. if _G.__HIDE_UI_REGISTERED and (_G.__HIDE_UI_SCHEMA or 0) < 2 and _G.__HIDE_UI_ENABLED then pcall(function() local cams = Camera.allCameras for i = 0, cams.Length - 1 do local mask = (_G.__ORIG_CAM_MASKS or {})[cams[i]:GetInstanceID()] if mask ~= nil then cams[i].cullingMask = mask end end local function restore(obj) if obj then local cg = obj:GetComponent(typeof(CanvasGroup)) if cg then cg.alpha = 1; cg.blocksRaycasts = true; cg.interactable = true end end end local root = GameObject.Find("UIRoot") if root then restore(root) local t = root.transform for i = 0, t.childCount - 1 do local c = t:GetChild(i); restore(c.gameObject) for j = 0, c.childCount - 1 do restore(c:GetChild(j).gameObject) end end end local canvases = GameObject.FindObjectsOfType(typeof(CS.UnityEngine.Canvas)) for i = 0, canvases.Length - 1 do restore(canvases[i].gameObject) end end) end _G.__HIDE_UI_ENABLED = _G.__HIDE_UI_ENABLED or false _G.__HIDE_UI_TARGETS = _G.__HIDE_UI_TARGETS or {} local function restore_hud() for id, state in pairs(_G.__HIDE_UI_TARGETS) do pcall(function() if state.group then if state.added then CS.UnityEngine.Object.Destroy(state.group) else state.group.alpha = state.alpha state.group.blocksRaycasts = state.raycast state.group.interactable = state.interactable end end end) _G.__HIDE_UI_TARGETS[id] = nil end end local function protected_name(name) local n = string.lower(tostring(name)) return string.find(n, "uid", 1, true) ~= nil and string.find(n, "guide", 1, true) == nil or n == "versiontext" or n == "betahintdialog(clone)" end local function hide_object(obj) if not obj or protected_name(obj.name) then return end local id = obj:GetInstanceID() local state = _G.__HIDE_UI_TARGETS[id] if not state then local group = obj:GetComponent(typeof(CanvasGroup)) local added = not group if added then group = obj:AddComponent(typeof(CanvasGroup)) end state = {group=group, added=added, alpha=group.alpha, raycast=group.blocksRaycasts, interactable=group.interactable} _G.__HIDE_UI_TARGETS[id] = state end state.group.alpha = 0 state.group.blocksRaycasts = false state.group.interactable = false end -- Keep UID/branding subtrees visible even if they belong to a HUD container. local function hide_hud_tree(obj) if not obj then return end local protected = {} local ts = obj:GetComponentsInChildren(typeof(CS.UnityEngine.Transform), true) for i = 0, ts.Length - 1 do if protected_name(ts[i].name) then local t = ts[i] while t do protected[t:GetInstanceID()] = true if t == obj.transform then break end t = t.parent end end end local function visit(t) if protected_name(t.name) then return end if not protected[t:GetInstanceID()] then hide_object(t.gameObject) -- Battle HUD widgets have their own CanvasGroups and some ignore -- their parent's alpha. Hide those groups too, preserving each -- original state for restoration when the toggle is disabled. local groups = t:GetComponentsInChildren(typeof(CanvasGroup), true) for i = 0, groups.Length - 1 do hide_object(groups[i].gameObject) end return end for i = 0, t.childCount - 1 do visit(t:GetChild(i)) end end visit(obj.transform) end -- EX/Eidolon artwork is an image. Hide interactive controls and labels, -- never the page's Canvas/camera or the illustration's parent container. local function hide_control_components(root, kind) local ok, controls = pcall(function() return root:GetComponentsInChildren(kind, true) end) if not ok or not controls then return end for i = 0, controls.Length - 1 do local component = controls[i] if component and component.gameObject and not protected_name(component.gameObject.name) then -- Hiding each control directly avoids rescanning its entire -- subtree for every Button/LocalizedText pair on the page. hide_object(component.gameObject) end end end local function hide_rank_controls(root) if not root or not root.activeInHierarchy then return end hide_control_components(root, typeof(CS.RPG.Client.LocalizedText)) -- Selectable includes buttons, toggles, sliders, dropdowns and scrollbars; -- some rank-page controls have no text or Button component of their own. hide_control_components(root, typeof(CS.UnityEngine.UI.Selectable)) -- Skill icons use SkillIcon sprites; illustrations use separate portrait -- assets. Do not hide arbitrary images or the illustration container. local images = root:GetComponentsInChildren(typeof(CS.UnityEngine.UI.Image), true) for i = 0, images.Length - 1 do local sprite = images[i].sprite if sprite and string.lower(tostring(sprite.name)):find("skillicon",1,true) then hide_object(images[i].gameObject) end end end local function hide_hud() for _, path in ipairs(HUD_PATHS) do pcall(function() hide_hud_tree(GameObject.Find(path)) end) end local ok, err = pcall(function() local flags = CS.System.Enum.ToObject(typeof(CS.System.Reflection.BindingFlags), 60) _G.__HIDE_UI_PHASE_FIELD = _G.__HIDE_UI_PHASE_FIELD or typeof(CS.RPG.Client.GamePhaseManager):GetField("_CurrentPhase", flags) _G.__HIDE_UI_BATTLE_HUD_FIELD = _G.__HIDE_UI_BATTLE_HUD_FIELD or typeof(CS.RPG.Client.BattleGamePhase):GetField("_HudPage", flags) local manager = CS.RPG.Client.GlobalVars.s_GamePhaseManager local phase = manager and _G.__HIDE_UI_PHASE_FIELD:GetValue(manager) if phase and typeof(CS.RPG.Client.BattleGamePhase):IsInstanceOfType(phase) then local hud = _G.__HIDE_UI_BATTLE_HUD_FIELD:GetValue(phase) if hud and hud.Trans then hide_hud_tree(hud.Trans.gameObject) end if hud and hud.ChildDialogs then local dialogs = hud.ChildDialogs for i = 0, dialogs.Count - 1 do if dialogs[i].Trans then hide_hud_tree(dialogs[i].Trans.gameObject) end end end end end) if not ok and _G.__HIDE_UI_LAST_ERROR ~= tostring(err) then _G.__HIDE_UI_LAST_ERROR = tostring(err) CS.UnityEngine.Debug.Log("[GaC HideUI] Battle HUD: " .. tostring(err)) end pcall(function() local ui = CS.RPG.Client.GlobalVars.s_UIManager local pages = ui:GetAllPageNames() for i = 0, pages.Count - 1 do local name = tostring(pages[i]); local lower = string.lower(name) local page = ui:GetPageByName(name) if page and page.ChildDialogs then for j = 0, page.ChildDialogs.Count - 1 do local dialog = page.ChildDialogs[j] local dialogName = string.lower(tostring(dialog.Name)) if dialog.Trans and (dialogName:find("rank",1,true) or dialogName:find("eidolon",1,true)) then hide_rank_controls(dialog.Trans.gameObject) end end end if lower:find("battle",1,true) then local page = ui:GetPageByName(name) if page and page.Trans and page.Trans.gameObject.activeInHierarchy then hide_hud_tree(page.Trans.gameObject) end end if lower:find("rank",1,true) or lower:find("eidolon",1,true) then local page = ui:GetPageByName(name) if page and page.Trans then hide_rank_controls(page.Trans.gameObject) end end end hide_rank_controls(GameObject.Find("UIRoot/Page/AvatarMainPage(Clone)/Root/AvatarRankPanel")) end) end function _G.__HIDE_UI_TICK() pcall(function() local frame = Time.frameCount if _G.__HIDE_UI_LAST_FRAME == frame then return end _G.__HIDE_UI_LAST_FRAME = frame local toggled = Input.GetKeyDown(KeyCode.Backslash) if toggled then _G.__HIDE_UI_ENABLED = not _G.__HIDE_UI_ENABLED if not _G.__HIDE_UI_ENABLED then restore_hud() end end -- The page/child scan walks Unity UI trees, so keep it to once a second. -- New pages/dialogs never inherit a hidden UIRoot or UI camera. if _G.__HIDE_UI_ENABLED then local now = Time.unscaledTime if toggled or now >= (_G.__HIDE_UI_NEXT_SCAN or 0) then _G.__HIDE_UI_NEXT_SCAN = now + 1.0 hide_hud() end end end) end -- Restore targets from the previous policy (including VersionText) on upgrade. if _G.__HIDE_UI_SCHEMA ~= 5 then restore_hud() _G.__HIDE_UI_SCHEMA = 5 _G.__HIDE_UI_NEXT_SCAN = 0 end -- Use one render callback. Registering all camera events plus before-render -- made the toggle callback run redundantly several times per frame. if not _G.__HIDE_UI_REGISTERED then local callback = function() _G.__HIDE_UI_TICK() end local ok = pcall(function() CS.UnityEngine.Application.onBeforeRender('+', callback) end) if not ok then ok = pcall(function() CS.UnityEngine.Application.onBeforeRender = CS.UnityEngine.Application.onBeforeRender + callback end) end if not ok then ok = pcall(function() Camera.onPostRender('+', callback) end) if not ok then ok = pcall(function() Camera.onPostRender = Camera.onPostRender + callback end) end end _G.__HIDE_UI_REGISTERED = ok if ok then CS.UnityEngine.Debug.Log("[UI Toggle Script] HUD-only HideUI loaded! Press 'ฃ' to toggle UI.") else CS.UnityEngine.Debug.Log("[GaC HideUI] Could not register a render callback.") end end