diff --git a/package/client/interface/radial.ts b/package/client/interface/radial.ts index c1190b82a..09e536f9f 100644 --- a/package/client/interface/radial.ts +++ b/package/client/interface/radial.ts @@ -19,6 +19,8 @@ export const registerRadial = (radial: { id: string; items: Omit exports.ox_lib.getCurrentRadialId(); +export const showRadialMenu = (menuId: string) => exports.ox_lib.showRadialMenu(menuId); + export const hideRadial = () => exports.ox_lib.hideRadial(); export const disableRadial = (state: boolean) => exports.ox_lib.disableRadial(state); diff --git a/resource/interface/client/radial.lua b/resource/interface/client/radial.lua index a66e3d69c..c411dd1eb 100644 --- a/resource/interface/client/radial.lua +++ b/resource/interface/client/radial.lua @@ -26,6 +26,8 @@ local isOpen = false +local isDisabled = false + ---@type table local menus = {} @@ -38,6 +40,10 @@ local menuHistory = {} ---@type RadialMenuProps? local currentRadial = nil +---The registered menu opened directly with lib.showRadialMenu. +---@type RadialMenuProps? +local rootRadial = nil + ---Open a the global radial menu or a registered radial submenu with the given id. ---@param id string? ---@param option number? @@ -65,7 +71,7 @@ local function showRadial(id, option) action = 'openRadialMenu', data = { items = radial and radial.items or menuItems, - sub = radial and true or nil, + sub = radial and radial ~= rootRadial or nil, option = option } }) @@ -110,6 +116,46 @@ local function refreshRadial(menuId) showRadial() end +---Validates requirements and shows the requested radial menu. +---@param id string? If not provided, the global radial menu will be shown. +local function onRadialOpen(id) + local radial = id and menus[id] + + if isDisabled or (id and not radial) then return end + + if isOpen then + if rootRadial == radial then + return lib.hideRadial() + end + + rootRadial = radial + table.wipe(menuHistory) + return showRadial(id) + end + + local items = radial and radial.items or menuItems + if #items == 0 or IsNuiFocused() or IsPauseMenuActive() then return end + + isOpen = true + rootRadial = radial + table.wipe(menuHistory) + + lib.setNuiFocus(true) + SetCursorLocation(0.5, 0.5) + + showRadial(id) + + while isOpen do + DisablePlayerFiring(cache.playerId, true) + DisableControlAction(0, 1, true) + DisableControlAction(0, 2, true) + DisableControlAction(0, 142, true) + DisableControlAction(2, 199, true) + DisableControlAction(2, 200, true) + Wait(0) + end +end + ---Registers a radial sub menu with predefined options. ---@param radial RadialMenuProps function lib.registerRadial(radial) @@ -138,6 +184,7 @@ function lib.hideRadial() isOpen = false currentRadial = nil + rootRadial = nil end ---Registers an item or array of items in the global radial menu. @@ -304,6 +351,7 @@ RegisterNUICallback('radialClose', function(_, cb) isOpen = false currentRadial = nil + rootRadial = nil end) RegisterNUICallback('radialTransition', function(_, cb) @@ -315,8 +363,6 @@ RegisterNUICallback('radialTransition', function(_, cb) cb(true) end) -local isDisabled = false - ---Disallow players from opening the radial menu. ---@param state boolean function lib.disableRadial(state) @@ -327,40 +373,18 @@ function lib.disableRadial(state) end end +---Shows a registered menu as root without affecting global menus. +---@param id string +function lib.showRadialMenu(id) + onRadialOpen(id) +end + lib.addKeybind({ name = 'ox_lib-radial', description = locale('open_radial_menu'), defaultKey = 'z', onPressed = function() - if isDisabled then return end - - 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 - } - }) - - lib.setNuiFocus(true) - SetCursorLocation(0.5, 0.5) - - while isOpen do - DisablePlayerFiring(cache.playerId, true) - DisableControlAction(0, 1, true) - DisableControlAction(0, 2, true) - DisableControlAction(0, 142, true) - DisableControlAction(2, 199, true) - DisableControlAction(2, 200, true) - Wait(0) - end + onRadialOpen() end, -- onReleased = lib.hideRadial, }) @@ -373,4 +397,4 @@ AddEventHandler('onClientResourceStop', function(resource) table.remove(menuItems, i) end end -end) +end) \ No newline at end of file