Files
GaCy-GO/scripts/hide_ui.lua
T

280 lines
12 KiB
Lua

-- 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("<color=#FF00FF>[UI Toggle Script]</color> HUD-only HideUI loaded! Press 'ฃ' to toggle UI.")
else
CS.UnityEngine.Debug.Log("[GaC HideUI] Could not register a render callback.")
end
end