mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-17 15:06:02 +01:00
Store an array containing the history of opened menus, and restore the previous menu when closing out of nested menus. Added lib.getCurrentRadialId and improved types.
216 lines
4.7 KiB
Lua
216 lines
4.7 KiB
Lua
---@class RadialMenuItem
|
|
---@field id string
|
|
---@field icon string
|
|
---@field label string
|
|
---@field menu? string
|
|
---@field onSelect? function
|
|
|
|
---@class RadialMenuProps
|
|
---@field id string
|
|
---@field items RadialMenuItem[]
|
|
|
|
local isOpen = false
|
|
|
|
---@type table<string, RadialMenuProps>
|
|
local menus = {}
|
|
|
|
---@type RadialMenuItem[]
|
|
local menuItems = {}
|
|
|
|
---@type string[]
|
|
local menuHistory = {}
|
|
|
|
---@type RadialMenuProps?
|
|
local currentRadial = nil
|
|
|
|
---Registers a radial sub menu with predefined options.
|
|
---@param radial RadialMenuProps
|
|
function lib.registerRadial(radial)
|
|
menus[radial.id] = radial
|
|
end
|
|
|
|
function lib.getCurrentRadialId()
|
|
return currentRadial and currentRadial.id
|
|
end
|
|
|
|
---Open a registered radial submenu with the given id.
|
|
---@param id string
|
|
local function showRadial(id)
|
|
local radial = menus[id]
|
|
|
|
if not radial then return error('No radial menu with such id found.') end
|
|
|
|
currentRadial = radial
|
|
|
|
-- Hide current menu and allow for transition
|
|
SendNUIMessage({
|
|
action = 'openRadialMenu',
|
|
data = false
|
|
})
|
|
|
|
Wait(100)
|
|
|
|
-- If menu was closed during transition, don't open the submenu
|
|
if not isOpen then return end
|
|
|
|
SendNUIMessage({
|
|
action = 'openRadialMenu',
|
|
data = {
|
|
items = radial.items,
|
|
sub = true
|
|
}
|
|
})
|
|
end
|
|
|
|
function lib.hideRadial()
|
|
if not isOpen then return end
|
|
|
|
SendNUIMessage({
|
|
action = 'openRadialMenu',
|
|
data = false
|
|
})
|
|
|
|
SetNuiFocus(false, false)
|
|
table.wipe(menuHistory)
|
|
|
|
isOpen = false
|
|
currentRadial = nil
|
|
end
|
|
|
|
---Registers an item or array of items in the global radial menu.
|
|
---@param items RadialMenuItem | RadialMenuItem[]
|
|
function lib.addRadialItem(items)
|
|
local menuSize = #menuItems
|
|
local invokingResource = GetInvokingResource()
|
|
|
|
if table.type(items) == 'array' then
|
|
for i = 1, #items do
|
|
local item = items[i]
|
|
item.resource = invokingResource
|
|
menuSize += 1
|
|
menuItems[menuSize] = item
|
|
end
|
|
else
|
|
items.resource = invokingResource
|
|
menuItems[menuSize + 1] = items
|
|
end
|
|
|
|
if isOpen and not currentRadial then
|
|
SendNUIMessage({
|
|
action = 'refreshItems',
|
|
data = menuItems
|
|
})
|
|
end
|
|
end
|
|
|
|
---Removes an item from the global radial menu with the given id.
|
|
---@param id string
|
|
function lib.removeRadialItem(id)
|
|
for i = 1, #menuItems do
|
|
local item = menuItems[i]
|
|
if item.id == id then
|
|
table.remove(menuItems, i)
|
|
break
|
|
end
|
|
end
|
|
if isOpen and not currentRadial then
|
|
SendNUIMessage({
|
|
action = 'refreshItems',
|
|
data = menuItems
|
|
})
|
|
end
|
|
end
|
|
|
|
RegisterNUICallback('radialClick', function(index, cb)
|
|
cb(1)
|
|
|
|
local item = (currentRadial and currentRadial.items or menuItems)[index + 1]
|
|
|
|
if item.menu then
|
|
if currentRadial then
|
|
menuHistory[#menuHistory + 1] = currentRadial.id
|
|
end
|
|
|
|
showRadial(item.menu)
|
|
else
|
|
lib.hideRadial()
|
|
end
|
|
|
|
if item.onSelect then item.onSelect() end
|
|
end)
|
|
|
|
RegisterNUICallback('radialBack', function(_, cb)
|
|
cb(1)
|
|
|
|
local numHistory = #menuHistory
|
|
local lastMenu = numHistory > 0 and menuHistory[numHistory]
|
|
|
|
if lastMenu then
|
|
menuHistory[numHistory] = nil
|
|
return showRadial(lastMenu)
|
|
end
|
|
|
|
currentRadial = nil
|
|
|
|
SendNUIMessage({
|
|
action = 'openRadialMenu',
|
|
data = {
|
|
items = menuItems
|
|
}
|
|
})
|
|
end)
|
|
|
|
RegisterNUICallback('radialClose', function(_, cb)
|
|
cb(1)
|
|
|
|
if not isOpen then return end
|
|
|
|
SetNuiFocus(false, false)
|
|
|
|
isOpen = false
|
|
currentRadial = nil
|
|
end)
|
|
|
|
lib.addKeybind({
|
|
name = 'ox_lib-radial',
|
|
description = 'Open radial menu',
|
|
defaultKey = 'z',
|
|
onPressed = function()
|
|
if isOpen then
|
|
return lib.hideRadial()
|
|
end
|
|
|
|
if #menuItems == 0 or IsNuiFocused() or IsPauseMenuActive() then return end
|
|
|
|
isOpen = true
|
|
|
|
SendNUIMessage({
|
|
action = 'openRadialMenu',
|
|
data = {
|
|
items = menuItems
|
|
}
|
|
})
|
|
SetNuiFocus(true, true)
|
|
SetNuiFocusKeepInput(true)
|
|
SetCursorLocation(0.5, 0.5)
|
|
|
|
while isOpen do
|
|
DisablePlayerFiring(cache.playerId, true)
|
|
DisableControlAction(0, 1, true)
|
|
DisableControlAction(0, 2, true)
|
|
Wait(0)
|
|
end
|
|
end,
|
|
-- onReleased = lib.hideRadial,
|
|
})
|
|
|
|
AddEventHandler('onClientResourceStop', function(resource)
|
|
for i = #menuItems, 1, -1 do
|
|
local item = menuItems[i]
|
|
|
|
if item.resource == resource then
|
|
table.remove(menuItems, i)
|
|
end
|
|
end
|
|
end)
|