Pular para o conteúdo

Convenções de UI / NUI

Cada recurso tem a sua própria página NUI (ui_page 'html/index.html'). O bs_ui é o HUD, as notificações e as partes partilhadas.

Um painel de cada vez: bs:ui:opened / bs:ui:closed

Seção intitulada “Um painel de cada vez: bs:ui:opened / bs:ui:closed”

Quando o teu painel abre, anuncias isso. Todos os outros painéis ouvem e fecham-se. Quando o teu fecha, anuncias também. Código real do bs_config:

local function close()
if not isOpen then return end
isOpen = false
SetNuiFocus(false, false)
SendNUIMessage({ action = 'close' })
TriggerEvent('bs:ui:closed', 'config')
end
local function open()
if isOpen then return close() end
isOpen = true
SetNuiFocus(true, true)
SendNUIMessage({ action = 'open', data = data })
TriggerEvent('bs:ui:opened', 'config')
end
-- another UI took over: step aside
AddEventHandler('bs:ui:opened', function(what)
if what ~= 'config' and isOpen then close() end
end)
AddEventHandler('onResourceStop', function(res)
if res == GetCurrentResourceName() and isOpen then
SetNuiFocus(false, false)
TriggerEvent('bs:ui:closed', 'config')
end
end)

Regras:

  • Passa o nome do teu painel nos dois eventos. Os handlers verificam-no; um handler que reagia a qualquer fecho estragou o mapa de campo durante meses.
  • Emparelha-os em todas as saídas: botão de fechar, Esc, tecla de alternar, outra UI a abrir, paragem do recurso. Falha uma e o jogador fica preso com um cursor de rato e sem jogo.
  • Anuncia opened depois de estares aberto, e fecha-te a partir do teu próprio handler, não assumas que os outros o farão.

O /refreshui (bs_ui) é o botão de pânico: fecha tudo, larga o foco e dispara bs:ui:closed com nil.

-- client
TriggerEvent('bs:ui:notify', { type = 'info', title = 'Radio', message = 'Signal found.', duration = 3000 })
-- server
TriggerClientEvent('bs:ui:notify', src, { type = 'error', title = 'Denied', message = 'Nope.' })

Tipos usados no código: info, success, error.

As páginas são desenhadas para 1920x1080. Inclui o scaler partilhado para se ajustarem a qualquer resolução:

<script src="https://cfx-nui-bs_ui/html/shared/scale.js"></script>

Escala o <body> com um transform: --ui-scale = clamp(min(w/1920, h/1080), 0.6, 1.25). Os jogadores podem alterá-lo (0.6 a 1.4) nas definições.

O que deves saber ao usá-lo:

  • No CSS da página escreve vh/vw como calc(Nvh / var(--ui-scale, 1)), para continuarem a ser frações reais do viewport.
  • O JS que define style.left/top a partir de clientX/clientY ou de um bounding rect tem de dividir por BSScale.get(). BSScale.w() / BSScale.h() dão o viewport local.
  • Desativa com <html data-bs-noscale>.
  • html, body { background: transparent !important; } em todas as páginas. Caso contrário aparece um ecrã preto sobre o jogo.
  • Sem mensagens NUI a cada frame em idle. Envia quando muda, ou limita (o HUD do drone envia a cada 150 ms a voar, é mais ou menos o máximo).
  • A paleta é âmbar / ferrugem / osso / pó sobre quase-preto. Reutiliza os tokens CSS do bs_ui e o bs_menu/html/css/faction-hub.css. Sem fontes externas nem CDNs: os jogadores podem não ter acesso à internet para elas, e é uma questão de privacidade de qualquer forma.
  • Ícones: ícones de linha em bs_ui/html/js/icons.js.
  • Sons: bs_ui/html/js/sound.js trata dos sons posicionais (maxDistance, panning).