Scripts/resources/[standalone]/ox_lib/resource/interface/client/menu.lua

197 lines
5.0 KiB
Lua
Raw Normal View History

2024-12-29 20:02:43 +00:00
---@type { [string]: MenuProps }
local registeredMenus = {}
---@type MenuProps | nil
local openMenu
---@alias MenuPosition 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
---@alias MenuChangeFunction fun(selected: number, scrollIndex?: number, args?: any, checked?: boolean)
---@class MenuOptions
---@field label string
---@field progress? number
---@field colorScheme? string
---@field icon? string | {[1]: IconProp, [2]: string};
---@field iconColor? string
---@field values? table<string | { label: string, description: string }>
---@field checked? boolean
---@field description? string
---@field defaultIndex? number
---@field args? {[any]: any}
---@field close? boolean
---@class MenuProps
---@field id string
---@field title string
---@field options MenuOptions[]
---@field position? MenuPosition
---@field disableInput? boolean
---@field canClose? boolean
---@field onClose? fun(keyPressed?: 'Escape' | 'Backspace')
---@field onSelected? MenuChangeFunction
---@field onSideScroll? MenuChangeFunction
---@field onCheck? MenuChangeFunction
---@field cb? MenuChangeFunction
---@param data MenuProps
---@param cb? MenuChangeFunction
function lib.registerMenu(data, cb)
if not data.id then error('No menu id was provided.') end
if not data.title then error('No menu title was provided.') end
if not data.options then error('No menu options were provided.') end
data.cb = cb
registeredMenus[data.id] = data
end
---@param id string
---@param startIndex? number
function lib.showMenu(id, startIndex)
local menu = registeredMenus[id]
if not menu then
error(('No menu with id %s was found'):format(id))
end
if not openMenu then
local control = cache.game == 'fivem' and 140 or 0xE30CD707
CreateThread(function()
while openMenu do
if openMenu.disableInput == nil or openMenu.disableInput then
DisablePlayerFiring(cache.playerId, true)
if cache.game == 'fivem' then
HudWeaponWheelIgnoreSelection() -- Not a REDM native
end
DisableControlAction(0, control, true)
end
Wait(0)
end
end)
end
openMenu = menu
lib.setNuiFocus(not menu.disableInput, true)
SendNUIMessage({
action = 'setMenu',
data = {
position = menu.position,
canClose = menu.canClose,
title = menu.title,
items = menu.options,
startItemIndex = startIndex and startIndex - 1 or 0
}
})
end
---@param onExit boolean?
function lib.hideMenu(onExit)
local menu = openMenu
openMenu = nil
if not menu then return end
lib.resetNuiFocus()
if onExit and menu.onClose then
menu.onClose()
end
SendNUIMessage({
action = 'closeMenu'
})
end
---@param id string
---@param options MenuOptions | MenuOptions[]
---@param index? number
function lib.setMenuOptions(id, options, index)
if index then
registeredMenus[id].options[index] = options
else
if not options[1] then error('Invalid override format used, expected table of options.') end
registeredMenus[id].options = options
end
end
---@return string?
function lib.getOpenMenu() return openMenu and openMenu.id end
RegisterNUICallback('confirmSelected', function(data, cb)
cb(1)
data[1] += 1 -- selected
if data[2] then
data[2] += 1 -- scrollIndex
end
local menu = openMenu
if not menu then return end
if menu.options[data[1]].close ~= false then
lib.resetNuiFocus()
openMenu = nil
end
if menu.cb then
menu.cb(data[1], data[2], menu.options[data[1]].args, data[3])
end
end)
RegisterNUICallback('changeIndex', function(data, cb)
cb(1)
if not openMenu or not openMenu.onSideScroll then return end
data[1] += 1 -- selected
if data[2] then
data[2] += 1 -- scrollIndex
end
openMenu.onSideScroll(data[1], data[2], openMenu.options[data[1]].args)
end)
RegisterNUICallback('changeSelected', function(data, cb)
cb(1)
if not openMenu or not openMenu.onSelected then return end
data[1] += 1 -- selected
local args = openMenu.options[data[1]].args
if args and type(args) ~= 'table' then
return error("Menu args must be passed as a table")
end
if not args then args = {} end
if data[2] then args[data[3]] = true end
if data[2] and not args.isCheck then
data[2] += 1 -- scrollIndex
end
openMenu.onSelected(data[1], data[2], args)
end)
RegisterNUICallback('changeChecked', function(data, cb)
cb(1)
if not openMenu or not openMenu.onCheck then return end
data[1] += 1 -- selected
openMenu.onCheck(data[1], data[2], openMenu.options[data[1]].args)
end)
RegisterNUICallback('closeMenu', function(data, cb)
cb(1)
lib.resetNuiFocus()
local menu = openMenu
if not menu then return end
openMenu = nil
if menu.onClose then
menu.onClose(data --[[@as 'Escape' | 'Backspace' | nil]])
end
end)