939 lines
33 KiB
Lua
939 lines
33 KiB
Lua
--[[
|
|
|
|
!!!WARNING!!!
|
|
|
|
HORRIBLE, STUPID, HACKY AND PREFORMANCE DEGRADING CODE AHEAD
|
|
|
|
PROCEED WITH CAUTION
|
|
|
|
]]
|
|
|
|
RequestStreamedTextureDict("CommonMenu")
|
|
|
|
JayMenu = { }
|
|
|
|
-- Options
|
|
JayMenu.debug = false
|
|
|
|
-- Local variables
|
|
local menus = { }
|
|
local keys = {
|
|
up = 172,
|
|
down = 173,
|
|
left = 174,
|
|
right = 175,
|
|
select = 176,
|
|
back = 177,
|
|
mup = 181,
|
|
mdown = 180,
|
|
}
|
|
|
|
local optionCount = 0
|
|
|
|
local currentKey = nil
|
|
local currentDesc = nil
|
|
|
|
local currentMenu = nil
|
|
|
|
local menuWidth = 0.23
|
|
|
|
local titleHeight = 0.09
|
|
local titleYOffset = 0.02
|
|
local titleScale = 1.0
|
|
|
|
local buttonHeight = 0.038
|
|
local buttonFont = 0
|
|
local buttonScale = 0.365
|
|
local buttonTextXOffset = 0.005
|
|
local buttonTextYOffset = 0.005
|
|
|
|
local continuity = {}
|
|
|
|
local function HudColourToTable(r,g,b,a) return { r, g, b, a or 255 } end
|
|
|
|
-- Local functions
|
|
local function debugPrint(text)
|
|
if JayMenu.debug then
|
|
Citizen.Trace('[JayMenu] '..tostring(text))
|
|
end
|
|
end
|
|
|
|
local function setMenuProperty(id, property, value)
|
|
if id and menus[id] then
|
|
menus[id][property] = value
|
|
debugPrint(id..' menu property changed: { '..tostring(property)..', '..tostring(value)..' }')
|
|
end
|
|
end
|
|
|
|
local function isMenuVisible(id)
|
|
if id and menus[id] then
|
|
return menus[id].visible
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
--[[local function setMenuVisible(id, visible, holdCurrent)
|
|
if id and menus[id] then
|
|
setMenuProperty(id, 'visible', visible)
|
|
|
|
if not holdCurrent and menus[id] then
|
|
setMenuProperty(id, 'currentOption', 1)
|
|
end
|
|
|
|
if visible then
|
|
if id ~= currentMenu and isMenuVisible(currentMenu) then
|
|
setMenuVisible(currentMenu, false)
|
|
end
|
|
|
|
currentMenu = id
|
|
end
|
|
end
|
|
end]]
|
|
|
|
local function setMenuVisible(id, visible, holdCurrent)
|
|
if id and menus[id] then
|
|
setMenuProperty(id, 'visible', visible)
|
|
|
|
if visible then
|
|
if id ~= currentMenu and isMenuVisible(currentMenu) then
|
|
setMenuVisible(currentMenu, false, true)
|
|
else
|
|
setMenuProperty(id, 'currentOption', 1)
|
|
end
|
|
|
|
currentMenu = id
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function drawText(text, x, y, font, color, scale, center, shadow, alignRight)
|
|
BeginTextCommandDisplayText("STRING")
|
|
if color then
|
|
SetTextColour(color[1], color[2], color[3], color[4])
|
|
else
|
|
SetTextColour(255, 255, 255, 255)
|
|
end
|
|
SetTextFont(font)
|
|
SetTextScale(scale, scale)
|
|
|
|
if shadow then
|
|
SetTextDropShadow(2, 2, 0, 0, 0)
|
|
end
|
|
|
|
if menus[currentMenu] then
|
|
if center then
|
|
SetTextCentre(center)
|
|
elseif alignRight then
|
|
SetTextWrap(menus[currentMenu].x, menus[currentMenu].x + menuWidth - buttonTextXOffset)
|
|
SetTextRightJustify(true)
|
|
end
|
|
end
|
|
AddTextComponentSubstringPlayerName(text)
|
|
EndTextCommandDisplayText(x, y)
|
|
end
|
|
|
|
function getLineHeight(text, font, color, scale, center, shadow, alignRight)
|
|
BeginTextCommandLineCount("STRING")
|
|
if color then
|
|
SetTextColour(color[1], color[2], color[3], color[4])
|
|
else
|
|
SetTextColour(255, 255, 255, 255)
|
|
end
|
|
SetTextFont(font)
|
|
SetTextScale(scale, scale)
|
|
|
|
if shadow then
|
|
SetTextDropShadow(2, 2, 0, 0, 0)
|
|
end
|
|
|
|
if menus[currentMenu] then
|
|
SetTextWrap(menus[currentMenu].x, menus[currentMenu].x + menuWidth - buttonTextXOffset)
|
|
if center then
|
|
SetTextCentre(center)
|
|
elseif alignRight then
|
|
SetTextRightJustify(true)
|
|
end
|
|
end
|
|
AddTextComponentSubstringPlayerName(text)
|
|
return GetTextScreenLineCount(menus[currentMenu].x, menus[currentMenu].x + menuWidth - buttonTextXOffset)
|
|
end
|
|
|
|
function drawRect(x, y, width, height, color)
|
|
DrawRect(x, y, width, height, color[1], color[2], color[3], color[4])
|
|
end
|
|
|
|
function drawSprite(textDict, sprite, x, y, scale, color)
|
|
if HasStreamedTextureDictLoaded(textDict) then
|
|
DrawSprite(textDict, sprite, x, y, 0.0265, 0.05, 0, color[1], color[2], color[3], color[4])
|
|
else
|
|
RequestStreamedTextureDict(textDict, false)
|
|
end
|
|
end
|
|
|
|
local function drawTitle()
|
|
if menus[currentMenu] then
|
|
local x = menus[currentMenu].x + menuWidth / 2
|
|
local y = menus[currentMenu].y + titleHeight / 2
|
|
|
|
if menus[currentMenu].titleFont == "!sprite!" then
|
|
local color = menus[currentMenu].titleBackgroundColor
|
|
local textDict, sprite = table.unpack(menus[currentMenu].titleColor)
|
|
--print("txd:"..textDict.." spr:"..sprite.." col:"..color.r..","..color.g..","..color.b..","..color.a)
|
|
RequestStreamedTextureDict(textDict, false)
|
|
HasStreamedTextureDictLoaded(textDict)
|
|
DrawSprite(textDict, sprite, x, y, menuWidth, titleHeight, 0, color[1], color[2], color[3], color[4])
|
|
elseif menus[currentMenu].titleFont == "~sprite~" then
|
|
local color = menus[currentMenu].titleBackgroundColor
|
|
local textDict, sprite = table.unpack(menus[currentMenu].titleColor)
|
|
--print("txd:"..textDict.." spr:"..sprite.." col:"..color.r..","..color.g..","..color.b..","..color.a)
|
|
RequestStreamedTextureDict(textDict, false)
|
|
HasStreamedTextureDictLoaded(textDict)
|
|
DrawSprite(textDict, sprite, x, y, menuWidth, titleHeight, 0, color[1], color[2], color[3], color[4])
|
|
drawText(menus[currentMenu].title, x, y - titleHeight / 2 + titleYOffset, 1, {255, 255, 255, 255}, titleScale, true)
|
|
else
|
|
if HasStreamedTextureDictLoaded("CommonMenu") then
|
|
SetUiLayer(0)
|
|
DrawSprite("CommonMenu", "interaction_bgd", x, y, menuWidth, titleHeight, 0.0, 255, 255, 255, 255, 0)
|
|
end
|
|
--drawRect(x, y, menuWidth, titleHeight, menus[currentMenu].titleBackgroundColor)
|
|
drawText(menus[currentMenu].title, x, y - titleHeight / 2 + titleYOffset, menus[currentMenu].titleFont, menus[currentMenu].titleColor, titleScale, true)
|
|
end
|
|
|
|
local x,y,color,textDict,sprite = nil
|
|
end
|
|
end
|
|
|
|
-- local function drawSubTitle()
|
|
-- if menus[currentMenu] then
|
|
-- local x = menus[currentMenu].x + (menuWidth / 2)
|
|
-- local y = menus[currentMenu].y + (titleHeight + buttonHeight / 2)
|
|
|
|
-- local subTitleColor = { r = menus[currentMenu].titleBackgroundColor.r, g = menus[currentMenu].titleBackgroundColor.g, b = menus[currentMenu].titleBackgroundColor.b, a = 255 }
|
|
-- local subTitleColor = {255, 255, 255, 255}
|
|
|
|
-- drawRect(x, y, menuWidth, buttonHeight, menus[currentMenu].subTitleBackgroundColor)
|
|
-- drawText(menus[currentMenu].subTitle, menus[currentMenu].x + buttonTextXOffset, y - buttonHeight / 2 + buttonTextYOffset, buttonFont, false, buttonScale, false)
|
|
-- drawText(tostring(menus[currentMenu].currentOption)..' / '..tostring(optionCount), menus[currentMenu].x + menuWidth, y - buttonHeight / 2 + buttonTextYOffset, buttonFont, false, buttonScale, false, false, true)
|
|
|
|
-- local x,y,subTitleColor = nil
|
|
-- end
|
|
-- end
|
|
|
|
local function drawSubTitle()
|
|
if menus[currentMenu] then
|
|
local x = menus[currentMenu].x + (menuWidth / 2)
|
|
local y = menus[currentMenu].y + (titleHeight + buttonHeight / 2)
|
|
local subtitle = menus[currentMenu].subTitle
|
|
|
|
--local subTitleColor = { r = menus[currentMenu].titleBackgroundColor.r, g = menus[currentMenu].titleBackgroundColor.g, b = menus[currentMenu].titleBackgroundColor.b, a = 255 }
|
|
--local subTitleColor = {255, 255, 255, 255}
|
|
|
|
drawRect(x, y, menuWidth, buttonHeight, menus[currentMenu].subTitleBackgroundColor)
|
|
if subtitle:find("|") then
|
|
drawText(subtitle:sub(1,subtitle:find("|")-1), menus[currentMenu].x + buttonTextXOffset, y - buttonHeight / 2 + buttonTextYOffset, buttonFont, false, buttonScale, false)
|
|
drawText(subtitle:sub(subtitle:find("|")+1), menus[currentMenu].x + menuWidth, y - buttonHeight / 2 + buttonTextYOffset, buttonFont, false, buttonScale, false, false, true)
|
|
else
|
|
drawText(menus[currentMenu].subTitle, menus[currentMenu].x + buttonTextXOffset, y - buttonHeight / 2 + buttonTextYOffset, buttonFont, false, buttonScale, false)
|
|
drawText(tostring(menus[currentMenu].currentOption)..' / '..tostring(optionCount), menus[currentMenu].x + menuWidth, y - buttonHeight / 2 + buttonTextYOffset, buttonFont, false, buttonScale, false, false, true)
|
|
end
|
|
|
|
local x,y,subTitleColor = nil
|
|
end
|
|
end
|
|
|
|
local function drawDescription()
|
|
if menus[currentMenu] then
|
|
local x = menus[currentMenu].x + menuWidth / 2
|
|
local menuHeight = buttonHeight*(((optionCount <= menus[currentMenu].maxOptionCount) and optionCount or menus[currentMenu].maxOptionCount + 1) + 1)
|
|
|
|
local lines = getLineHeight(currentDesc, buttonFont, menus[currentMenu].menuTextColor, buttonScale, false, true)
|
|
|
|
local descriptionHeight = lines*(buttonTextYOffset*5) + buttonTextYOffset*2
|
|
local descriptionY = descriptionHeight/2
|
|
|
|
local y = menus[currentMenu].y + titleHeight + menuHeight + descriptionHeight/2 + buttonTextYOffset
|
|
local dividerY = y - descriptionHeight/2 + buttonTextYOffset/2
|
|
|
|
if HasStreamedTextureDictLoaded("CommonMenu") then
|
|
SetUiLayer(0)
|
|
|
|
DrawRect(x, dividerY, menuWidth, buttonTextYOffset, 0, 0, 0, 255)
|
|
DrawSprite("CommonMenu", "Gradient_Bgd", x, y, menuWidth, descriptionHeight, 0.0, 255, 255, 255, 220, 0)
|
|
|
|
drawText(currentDesc, menus[currentMenu].x + buttonTextXOffset, y - descriptionY + buttonTextYOffset, buttonFont, menus[currentMenu].menuTextColor, buttonScale, false, true)
|
|
else
|
|
RequestStreamedTextureDict("CommonMenu")
|
|
end
|
|
|
|
x,y,menuHeight = nil
|
|
end
|
|
end
|
|
|
|
local function drawMenuBackground()
|
|
if menus[currentMenu] then
|
|
local x = menus[currentMenu].x + menuWidth / 2
|
|
local menuHeight = buttonHeight*( (optionCount <= menus[currentMenu].maxOptionCount) and optionCount or menus[currentMenu].maxOptionCount )
|
|
local y = menus[currentMenu].y + titleHeight + buttonHeight + menuHeight / 2
|
|
|
|
if HasStreamedTextureDictLoaded("CommonMenu") then
|
|
SetUiLayer(0)
|
|
DrawSprite("CommonMenu", "Gradient_Bgd", x, y, menuWidth, menuHeight, 0.0, 255, 255, 255, 255, 0)
|
|
else
|
|
RequestStreamedTextureDict("CommonMenu")
|
|
end
|
|
|
|
local x,y,menuHeight = nil
|
|
end
|
|
end
|
|
|
|
local function drawArrows()
|
|
local x = menus[currentMenu].x + menuWidth / 2
|
|
local menuHeight = buttonHeight*(menus[currentMenu].maxOptionCount+1)
|
|
local y = menus[currentMenu].y + titleHeight + menuHeight + buttonHeight/2
|
|
|
|
if HasStreamedTextureDictLoaded("CommonMenu") then
|
|
local colour = menus[currentMenu].subTitleBackgroundColor
|
|
drawRect(x, y, menuWidth, buttonHeight, {colour[1], colour[2], colour[3], 182})
|
|
DrawSprite("CommonMenu", "shop_arrows_upanddown", x, y, 0.0265, 0.05, 0.0, 255, 255, 255, 255, 0)
|
|
else
|
|
RequestStreamedTextureDict("CommonMenu")
|
|
end
|
|
|
|
local x,menuHeight,y,color = nil
|
|
end
|
|
|
|
local function drawButton(text, subText)
|
|
local x = menus[currentMenu].x + menuWidth / 2
|
|
local multiplier = nil
|
|
|
|
if menus[currentMenu].currentOption <= menus[currentMenu].maxOptionCount and optionCount <= menus[currentMenu].maxOptionCount then
|
|
multiplier = optionCount
|
|
elseif optionCount > menus[currentMenu].currentOption - menus[currentMenu].maxOptionCount and optionCount <= menus[currentMenu].currentOption then
|
|
multiplier = optionCount - (menus[currentMenu].currentOption - menus[currentMenu].maxOptionCount)
|
|
end
|
|
|
|
if multiplier then
|
|
local y = menus[currentMenu].y + titleHeight + buttonHeight + (buttonHeight * multiplier) - buttonHeight / 2
|
|
local backgroundColor = nil
|
|
local textColor = nil
|
|
local subTextColor = nil
|
|
local shadow = false
|
|
|
|
if menus[currentMenu].currentOption == optionCount and text ~= "" then
|
|
backgroundColor = menus[currentMenu].menuFocusBackgroundColor
|
|
textColor = menus[currentMenu].menuFocusTextColor
|
|
subTextColor = menus[currentMenu].menuFocusTextColor
|
|
else
|
|
backgroundColor = menus[currentMenu].menuBackgroundColor
|
|
textColor = menus[currentMenu].menuTextColor
|
|
subTextColor = menus[currentMenu].menuSubTextColor
|
|
shadow = true
|
|
end
|
|
|
|
if text ~= "!!separator!!" then
|
|
if menus[currentMenu].currentOption == optionCount and HasStreamedTextureDictLoaded("CommonMenu") then
|
|
SetUiLayer(1)
|
|
DrawSprite("CommonMenu", "Gradient_Nav", x, y, menuWidth, buttonHeight, 0.0, 255, 255, 255, 255, 0)
|
|
end
|
|
--drawRect(x, y, menuWidth, buttonHeight, backgroundColor)
|
|
drawText(text, menus[currentMenu].x + buttonTextXOffset, y - (buttonHeight / 2) + buttonTextYOffset, buttonFont, textColor, buttonScale, false, shadow)
|
|
|
|
if subText then
|
|
drawText(subText, menus[currentMenu].x + buttonTextXOffset, y - buttonHeight / 2 + buttonTextYOffset, buttonFont, subTextColor, buttonScale, false, shadow, true)
|
|
end
|
|
end
|
|
end
|
|
|
|
local x,y,backgroundColor,textColor,subTextColor,shadow,multiplier = nil
|
|
end
|
|
|
|
local function drawDisabledButton(text, subText)
|
|
local x = menus[currentMenu].x + menuWidth / 2
|
|
local multiplier = nil
|
|
|
|
if menus[currentMenu].currentOption <= menus[currentMenu].maxOptionCount and optionCount <= menus[currentMenu].maxOptionCount then
|
|
multiplier = optionCount
|
|
elseif optionCount > menus[currentMenu].currentOption - menus[currentMenu].maxOptionCount and optionCount <= menus[currentMenu].currentOption then
|
|
multiplier = optionCount - (menus[currentMenu].currentOption - menus[currentMenu].maxOptionCount)
|
|
end
|
|
|
|
if multiplier then
|
|
local y = menus[currentMenu].y + titleHeight + buttonHeight + (buttonHeight * multiplier) - buttonHeight / 2
|
|
local backgroundColor = menus[currentMenu].menuBackgroundColor
|
|
local textColor = HudColourToTable(GetHudColour(5))
|
|
local subTextColor = HudColourToTable(GetHudColour(5))
|
|
local shadow = false
|
|
|
|
--[[if menus[currentMenu].currentOption == optionCount and HasStreamedTextureDictLoaded("CommonMenu") then
|
|
SetUiLayer(1)
|
|
DrawSprite("CommonMenu", "Gradient_Nav", x, y, menuWidth, buttonHeight, 0.0, 255, 255, 255, 255, 0)
|
|
end]]
|
|
--drawRect(x, y, menuWidth, buttonHeight, backgroundColor)
|
|
drawText(text, menus[currentMenu].x + buttonTextXOffset, y - (buttonHeight / 2) + buttonTextYOffset, buttonFont, textColor, buttonScale, false, shadow)
|
|
|
|
if subText then
|
|
drawText(subText, menus[currentMenu].x + buttonTextXOffset, y - buttonHeight / 2 + buttonTextYOffset, buttonFont, subTextColor, buttonScale, false, shadow, true)
|
|
end
|
|
end
|
|
|
|
local x,y,backgroundColor,textColor,subTextColor,shadow,multiplier = nil
|
|
end
|
|
|
|
local function drawSpriteButton(text, textDict, sprite, focusSprite)
|
|
local x = menus[currentMenu].x + menuWidth / 2
|
|
local multiplier = nil
|
|
|
|
if menus[currentMenu].currentOption <= menus[currentMenu].maxOptionCount and optionCount <= menus[currentMenu].maxOptionCount then
|
|
multiplier = optionCount
|
|
elseif optionCount > menus[currentMenu].currentOption - menus[currentMenu].maxOptionCount and optionCount <= menus[currentMenu].currentOption then
|
|
multiplier = optionCount - (menus[currentMenu].currentOption - menus[currentMenu].maxOptionCount)
|
|
end
|
|
|
|
if multiplier then
|
|
local y = menus[currentMenu].y + titleHeight + buttonHeight + (buttonHeight * multiplier) - buttonHeight / 2
|
|
local backgroundColor = nil
|
|
local textColor = nil
|
|
local subTextColor = nil
|
|
local shadow = false
|
|
|
|
if menus[currentMenu].currentOption == optionCount then
|
|
backgroundColor = menus[currentMenu].menuFocusBackgroundColor
|
|
textColor = menus[currentMenu].menuFocusTextColor
|
|
subTextColor = menus[currentMenu].menuFocusTextColor
|
|
else
|
|
backgroundColor = menus[currentMenu].menuBackgroundColor
|
|
textColor = menus[currentMenu].menuTextColor
|
|
subTextColor = menus[currentMenu].menuSubTextColor
|
|
shadow = true
|
|
end
|
|
|
|
if menus[currentMenu].currentOption == optionCount and HasStreamedTextureDictLoaded("CommonMenu") then
|
|
SetUiLayer(1)
|
|
DrawSprite("CommonMenu", "Gradient_Nav", x, y, menuWidth, buttonHeight, 0.0, 255, 255, 255, 255, 0)
|
|
end
|
|
|
|
drawText(text, menus[currentMenu].x + buttonTextXOffset, y - (buttonHeight / 2) + buttonTextYOffset, buttonFont, textColor, buttonScale, false, shadow)
|
|
|
|
if textDict and sprite then
|
|
if focusSprite then
|
|
if menus[currentMenu].currentOption == optionCount then
|
|
SetUiLayer(2)
|
|
drawSprite(textDict, focusSprite, menus[currentMenu].x + menuWidth - buttonTextXOffset*2 , y - buttonHeight / 2 + (buttonTextYOffset*3.75), buttonScale, menus[currentMenu].menuSubTextColor)
|
|
else
|
|
SetUiLayer(2)
|
|
drawSprite(textDict, sprite, menus[currentMenu].x + menuWidth - buttonTextXOffset*2 , y - buttonHeight / 2 + (buttonTextYOffset*3.75), buttonScale, subTextColor)
|
|
end
|
|
else
|
|
SetUiLayer(2)
|
|
drawSprite(textDict, sprite, menus[currentMenu].x + menuWidth - buttonTextXOffset*2 , y - buttonHeight / 2 + (buttonTextYOffset*3.75), buttonScale, subTextColor)
|
|
end
|
|
end
|
|
end
|
|
|
|
local x,y,backgroundColor,textColor,subTextColor,shadow,multiplier = nil
|
|
end
|
|
|
|
local function stopConflictingInputs()
|
|
-- isolates menu navigation buttons and stops jumping, weapon selection and opening of the pause menu
|
|
|
|
for _,key in pairs(keys) do
|
|
SetInputExclusive(0, key)
|
|
end
|
|
DisableControlAction(0, 22, true)
|
|
DisableControlAction(0, 37, true)
|
|
DisableControlAction(0, 38, true)
|
|
DisableControlAction(0, 200, true)
|
|
end
|
|
|
|
-- API
|
|
function JayMenu.CreateMenu(id, title, closeCallback)
|
|
-- Default settings
|
|
menus[id] = { }
|
|
menus[id].title = title
|
|
menus[id].subTitle = 'INTERACTION MENU'
|
|
|
|
menus[id].visible = false
|
|
|
|
menus[id].previousMenu = nil
|
|
|
|
menus[id].aboutToBeClosed = false
|
|
|
|
-- Top left corner
|
|
menus[id].x = 0.0145
|
|
menus[id].y = 0.075
|
|
|
|
menus[id].currentOption = 1
|
|
menus[id].maxOptionCount = 12
|
|
|
|
menus[id].titleFont = 1
|
|
menus[id].titleColor = {255, 255, 255, 255}
|
|
menus[id].titleBackgroundColor = {255, 255, 255, 255}
|
|
|
|
menus[id].menuTextColor = {255, 255, 255, 255}
|
|
menus[id].menuSubTextColor = {255, 255, 255, 255}
|
|
menus[id].menuFocusTextColor = {0, 0, 0, 255}
|
|
menus[id].menuFocusBackgroundColor = {245, 245, 245, 255}
|
|
menus[id].menuBackgroundColor = {0, 0, 0, 160}
|
|
|
|
menus[id].subTitleBackgroundColor = {menus[id].menuBackgroundColor[1], menus[id].menuBackgroundColor[2], menus[id].menuBackgroundColor[3], 255 }
|
|
|
|
menus[id].buttonPressedSound = { name = "SELECT", set = "HUD_FRONTEND_DEFAULT_SOUNDSET" } --https://pastebin.com/0neZdsZ5
|
|
|
|
menus[id].closeCallback = closeCallback or function() return true end
|
|
|
|
debugPrint(tostring(id)..' menu created')
|
|
end
|
|
|
|
|
|
function JayMenu.CreateSubMenu(id, parent, subTitle, closeCallback)
|
|
if menus[parent] then
|
|
JayMenu.CreateMenu(id, menus[parent].title)
|
|
|
|
-- Well it's copy constructor like :)
|
|
if subTitle then
|
|
setMenuProperty(id, 'subTitle', string.upper(subTitle))
|
|
else
|
|
setMenuProperty(id, 'subTitle', string.upper(menus[parent].subTitle))
|
|
end
|
|
|
|
setMenuProperty(id, 'previousMenu', parent)
|
|
|
|
setMenuProperty(id, 'x', menus[parent].x)
|
|
setMenuProperty(id, 'y', menus[parent].y)
|
|
setMenuProperty(id, 'maxOptionCount', menus[parent].maxOptionCount)
|
|
setMenuProperty(id, 'titleFont', menus[parent].titleFont)
|
|
setMenuProperty(id, 'titleColor', menus[parent].titleColor)
|
|
setMenuProperty(id, 'titleBackgroundColor', menus[parent].titleBackgroundColor)
|
|
setMenuProperty(id, 'menuTextColor', menus[parent].menuTextColor)
|
|
setMenuProperty(id, 'menuSubTextColor', menus[parent].menuSubTextColor)
|
|
setMenuProperty(id, 'menuFocusTextColor', menus[parent].menuFocusTextColor)
|
|
setMenuProperty(id, 'menuFocusBackgroundColor', menus[parent].menuFocusBackgroundColor)
|
|
setMenuProperty(id, 'menuBackgroundColor', menus[parent].menuBackgroundColor)
|
|
setMenuProperty(id, 'subTitleBackgroundColor', menus[parent].subTitleBackgroundColor)
|
|
setMenuProperty(id, 'closeCallback', closeCallback or function() return true end)
|
|
-- :(
|
|
else
|
|
debugPrint('Failed to create '..tostring(id)..' submenu: '..tostring(parent)..' parent menu doesn\'t exist')
|
|
end
|
|
end
|
|
|
|
|
|
function JayMenu.CurrentMenu()
|
|
return currentMenu
|
|
end
|
|
|
|
function JayMenu.MenuTable()
|
|
return menus
|
|
end
|
|
|
|
|
|
function JayMenu.OpenMenu(id)
|
|
if id and menus[id] then
|
|
PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
|
|
setMenuVisible(id, true)
|
|
|
|
-- continuity.lastPedWeapon = GetCurrentPedWeapon(PlayerPedId())
|
|
-- SetPedCurrentWeaponVisible(PlayerPedId(), false, true)
|
|
|
|
debugPrint(tostring(id)..' menu opened')
|
|
else
|
|
debugPrint('Failed to open '..tostring(id)..' menu: it doesn\'t exist')
|
|
end
|
|
end
|
|
|
|
|
|
function JayMenu.IsMenuOpened(id)
|
|
return isMenuVisible(id)
|
|
end
|
|
|
|
|
|
function JayMenu.IsAnyMenuOpened()
|
|
for id, _ in pairs(menus) do
|
|
if isMenuVisible(id) then return true end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function JayMenu.IsAnyMenuWithTitleOpened(subtitle)
|
|
for id, v in pairs(menus) do
|
|
if isMenuVisible(id) then
|
|
if v.title == subtitle then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function JayMenu.IsMenuAboutToBeClosed()
|
|
if menus[currentMenu] then
|
|
return menus[currentMenu].aboutToBeClosed
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function JayMenu.IsThisMenuAboutToBeClosed(id)
|
|
if menus[id] then
|
|
return menus[id].aboutToBeClosed
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
|
|
function JayMenu.CloseMenu()
|
|
if menus[currentMenu] then
|
|
if menus[currentMenu].aboutToBeClosed then
|
|
menus[currentMenu].aboutToBeClosed = false
|
|
setMenuVisible(currentMenu, false)
|
|
debugPrint(tostring(currentMenu)..' menu closed')
|
|
PlaySoundFrontend(-1, "QUIT", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
|
|
optionCount = 0
|
|
currentMenu = nil
|
|
currentKey = nil
|
|
currentDesc = nil
|
|
|
|
-- keep continuity
|
|
if continuity.lastPedWeapon then
|
|
SetCurrentPedWeapon(PlayerPedId(), continuity.lastPedWeapon, true)
|
|
end
|
|
|
|
continuity = {}
|
|
|
|
Citizen.CreateThread(function()
|
|
while IsDisabledControlPressed(0, 200) or IsDisabledControlJustReleased(0, 200) do
|
|
Citizen.Wait(0)
|
|
DisableControlAction(0, 200, true)
|
|
end
|
|
end)
|
|
else
|
|
if menus[currentMenu].closeCallback() then
|
|
menus[currentMenu].aboutToBeClosed = true
|
|
debugPrint(tostring(currentMenu)..' menu about to be closed')
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function JayMenu.Button(text, subText)
|
|
local buttonText = text
|
|
if subText then
|
|
buttonText = '{ '..tostring(buttonText)..', '..tostring(subText)..' }'
|
|
end
|
|
|
|
if menus[currentMenu] then
|
|
optionCount = optionCount + 1
|
|
|
|
local isCurrent = menus[currentMenu].currentOption == optionCount
|
|
|
|
drawButton(text, subText)
|
|
|
|
if isCurrent then
|
|
if text == "!!separator!!" then
|
|
if IsDisabledControlPressed(0, keys.up) then
|
|
menus[currentMenu].currentOption = menus[currentMenu].currentOption - 1
|
|
elseif IsDisabledControlPressed(0, keys.down) then
|
|
menus[currentMenu].currentOption = menus[currentMenu].currentOption + 1
|
|
end
|
|
elseif currentKey == keys.select then
|
|
if text ~= "" then PlaySoundFrontend(-1, menus[currentMenu].buttonPressedSound.name, menus[currentMenu].buttonPressedSound.set, true) end
|
|
debugPrint(buttonText..' button pressed')
|
|
return true, isCurrent
|
|
elseif currentKey == keys.left or currentKey == keys.right then
|
|
if text ~= "" then PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", true) end
|
|
end
|
|
end
|
|
|
|
return false, isCurrent
|
|
else
|
|
debugPrint('Failed to create '..buttonText..' button: '..tostring(currentMenu)..' menu doesn\'t exist')
|
|
|
|
return false
|
|
end
|
|
|
|
local buttonText,isCurrent = nil
|
|
end
|
|
|
|
function JayMenu.DisabledButton(text, subText)
|
|
local buttonText = text
|
|
if subText then
|
|
buttonText = '{ '..tostring(buttonText)..', '..tostring(subText)..' }'
|
|
end
|
|
|
|
if menus[currentMenu] then
|
|
optionCount = optionCount + 1
|
|
|
|
local isCurrent = menus[currentMenu].currentOption == optionCount
|
|
|
|
drawDisabledButton(text ~= "!!separator!!" and text or "", subText)
|
|
|
|
if isCurrent then
|
|
if IsDisabledControlPressed(0, 172) then
|
|
menus[currentMenu].currentOption = menus[currentMenu].currentOption - 1
|
|
elseif IsDisabledControlPressed(0, 173) then
|
|
menus[currentMenu].currentOption = menus[currentMenu].currentOption + 1
|
|
end
|
|
end
|
|
|
|
return false, isCurrent
|
|
else
|
|
debugPrint('Failed to create '..buttonText..' button: '..tostring(currentMenu)..' menu doesn\'t exist')
|
|
|
|
return false
|
|
end
|
|
|
|
local buttonText,isCurrent = nil
|
|
end
|
|
|
|
function JayMenu.SpriteButton(text, textDict, sprite, focusSprite)
|
|
local buttonText = text
|
|
|
|
if menus[currentMenu] then
|
|
optionCount = optionCount + 1
|
|
|
|
local isCurrent = menus[currentMenu].currentOption == optionCount
|
|
|
|
drawSpriteButton(text, textDict, sprite, focusSprite)
|
|
|
|
if isCurrent then
|
|
if currentKey == keys.select then
|
|
PlaySoundFrontend(-1, menus[currentMenu].buttonPressedSound.name, menus[currentMenu].buttonPressedSound.set, true)
|
|
debugPrint(buttonText..' button pressed')
|
|
return true, isCurrent
|
|
elseif currentKey == keys.left or currentKey == keys.right then
|
|
PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
|
|
end
|
|
end
|
|
|
|
return false, isCurrent
|
|
else
|
|
debugPrint('Failed to create '..buttonText..' button: '..tostring(currentMenu)..' menu doesn\'t exist')
|
|
|
|
return false, isCurrent
|
|
end
|
|
|
|
local buttonText,isCurrent = nil
|
|
end
|
|
|
|
function JayMenu.SpriteMenuButton(text, textDict, sprite, focusSprite, id)
|
|
if menus[id] then
|
|
local clicked, hovered = JayMenu.SpriteButton(text, textDict, sprite, focusSprite)
|
|
if clicked then
|
|
setMenuVisible(currentMenu, false)
|
|
setMenuVisible(id, true, true)
|
|
end
|
|
return clicked, hovered
|
|
else
|
|
debugPrint('Failed to create '..tostring(text)..' menu button: '..tostring(id)..' submenu doesn\'t exist')
|
|
end
|
|
|
|
local clicked,hovered = nil
|
|
end
|
|
|
|
function JayMenu.ComboBox(text, items, currentIndex, selectedIndex, callback, displaycb)
|
|
local itemsCount = #items
|
|
local isCurrent = menus[currentMenu].currentOption == (optionCount + 1)
|
|
local getDisplayText = displaycb or (function(t) return tostring(t or "") end)
|
|
local selectedItem = getDisplayText(items[currentIndex])
|
|
|
|
if itemsCount > 1 and isCurrent then
|
|
selectedItem = '← '..selectedItem..' →'
|
|
end
|
|
|
|
if JayMenu.Button(text, selectedItem) then
|
|
selectedIndex = currentIndex
|
|
callback(currentIndex, selectedIndex)
|
|
return true,isCurrent
|
|
elseif isCurrent then
|
|
if currentKey == keys.left then
|
|
if currentIndex > 1 then currentIndex = currentIndex - 1 else currentIndex = itemsCount end
|
|
elseif currentKey == keys.right then
|
|
if currentIndex < itemsCount then currentIndex = currentIndex + 1 else currentIndex = 1 end
|
|
end
|
|
else
|
|
currentIndex = selectedIndex
|
|
end
|
|
|
|
callback(currentIndex, selectedIndex)
|
|
-- local itemsCount,isCurrent,getDisplayText,selectedItem = nil
|
|
return false, isCurrent
|
|
end
|
|
|
|
function JayMenu.MenuButton(text, id, secondtext)
|
|
if menus[id] then
|
|
local clicked, hovered = JayMenu.Button(text, (secondtext and secondtext or "→"))
|
|
if clicked then
|
|
setMenuVisible(currentMenu, false)
|
|
setMenuVisible(id, true, true)
|
|
|
|
return true, true
|
|
end
|
|
|
|
return false, hovered
|
|
else
|
|
debugPrint('Failed to create '..tostring(text)..' menu button: '..tostring(id)..' submenu doesn\'t exist')
|
|
end
|
|
|
|
return false, false
|
|
end
|
|
|
|
function JayMenu.SwitchMenu(id)
|
|
setMenuVisible(currentMenu, false)
|
|
setMenuVisible(id, true, true)
|
|
end
|
|
|
|
function JayMenu.SetDescription(text)
|
|
currentDesc = tostring(text)
|
|
end
|
|
|
|
function JayMenu.CheckBox(text, bool, callback)
|
|
--[[local checked = '~r~Off'
|
|
if bool then
|
|
checked = '~g~On'
|
|
end]]
|
|
|
|
local sprite = bool and "shop_box_tick" or "shop_box_blank"
|
|
local focusSprite = bool and "shop_box_tickb" or "shop_box_blankb"
|
|
|
|
if JayMenu.SpriteButton(text, "commonmenu", sprite, focusSprite) then
|
|
bool = not bool
|
|
debugPrint(tostring(text)..' checkbox changed to '..tostring(bool))
|
|
callback(bool)
|
|
|
|
return true
|
|
end
|
|
|
|
local sprite,focusSprite = nil
|
|
|
|
return false
|
|
end
|
|
|
|
function JayMenu.Display()
|
|
if isMenuVisible(currentMenu) and not IsPauseMenuActive() then
|
|
|
|
stopConflictingInputs()
|
|
|
|
if menus[currentMenu].aboutToBeClosed then
|
|
JayMenu.CloseMenu()
|
|
else
|
|
ClearAllHelpMessages()
|
|
|
|
drawTitle()
|
|
drawSubTitle()
|
|
if currentDesc then
|
|
drawDescription()
|
|
end
|
|
drawMenuBackground()
|
|
if optionCount > menus[currentMenu].maxOptionCount then
|
|
drawArrows()
|
|
end
|
|
|
|
currentKey = nil
|
|
currentDesc = nil
|
|
|
|
if IsDisabledControlJustPressed(0, keys.down) or IsDisabledControlJustPressed(0, keys.mdown) then
|
|
PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
|
|
|
|
if menus[currentMenu].currentOption < optionCount then
|
|
menus[currentMenu].currentOption = menus[currentMenu].currentOption + 1
|
|
else
|
|
menus[currentMenu].currentOption = 1
|
|
end
|
|
elseif IsDisabledControlJustPressed(0, keys.up) or IsDisabledControlJustPressed(0, keys.mup) then
|
|
PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
|
|
|
|
if menus[currentMenu].currentOption > 1 then
|
|
menus[currentMenu].currentOption = menus[currentMenu].currentOption - 1
|
|
else
|
|
menus[currentMenu].currentOption = optionCount
|
|
end
|
|
elseif IsDisabledControlJustPressed(0, keys.left) then
|
|
currentKey = keys.left
|
|
elseif IsDisabledControlJustPressed(0, keys.right) then
|
|
currentKey = keys.right
|
|
elseif IsDisabledControlJustPressed(0, keys.select) then
|
|
currentKey = keys.select
|
|
elseif IsDisabledControlJustPressed(0, keys.back) then
|
|
if menus[menus[currentMenu].previousMenu] then
|
|
PlaySoundFrontend(-1, "BACK", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
|
|
menus[currentMenu].closeCallback()
|
|
setMenuVisible(menus[currentMenu].previousMenu, true)
|
|
else
|
|
JayMenu.CloseMenu()
|
|
end
|
|
end
|
|
|
|
optionCount = 0
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function JayMenu.SetMenuWidth(id, width)
|
|
setMenuProperty(id, 'width', width)
|
|
end
|
|
|
|
|
|
function JayMenu.SetMenuX(id, x)
|
|
setMenuProperty(id, 'x', x)
|
|
end
|
|
|
|
|
|
function JayMenu.SetMenuY(id, y)
|
|
setMenuProperty(id, 'y', y)
|
|
end
|
|
|
|
|
|
function JayMenu.SetMenuMaxOptionCountOnScreen(id, count)
|
|
setMenuProperty(id, 'maxOptionCount', count)
|
|
end
|
|
|
|
|
|
function JayMenu.SetTitleColor(id, r, g, b, a)
|
|
setMenuProperty(id, 'titleColor', { r, g, b, a or menus[id].titleColor[4] })
|
|
end
|
|
|
|
|
|
function JayMenu.SetTitleBackgroundColor(id, r, g, b, a)
|
|
setMenuProperty(id, 'titleBackgroundColor', { r, g, b, a or menus[id].titleBackgroundColor[4] })
|
|
end
|
|
|
|
|
|
function JayMenu.UseSpriteAsBackground(id, textDict, sprite, r, g, b, a, stillDrawText)
|
|
if stillDrawText then setMenuProperty(id, 'titleFont', "~sprite~") else setMenuProperty(id, 'titleFont', "!sprite!") end
|
|
setMenuProperty(id, 'titleColor', {textDict, sprite})
|
|
setMenuProperty(id, 'titleBackgroundColor', { r, g, b, a or menus[id].titleBackgroundColor[4] })
|
|
end
|
|
|
|
|
|
function JayMenu.SetSubTitle(id, text)
|
|
setMenuProperty(id, 'subTitle', string.upper(text))
|
|
end
|
|
|
|
|
|
function JayMenu.SetMenuBackgroundColor(id, r, g, b, a)
|
|
setMenuProperty(id, 'menuBackgroundColor', { r, g, b, a or menus[id].menuBackgroundColor[4] })
|
|
end
|
|
|
|
|
|
function JayMenu.SetMenuTextColor(id, r, g, b, a)
|
|
setMenuProperty(id, 'menuTextColor', { r, g, b, a or menus[id].menuTextColor[4] })
|
|
end
|
|
|
|
function JayMenu.SetMenuSubTextColor(id, r, g, b, a)
|
|
setMenuProperty(id, 'menuSubTextColor', { r, g, b, a or menus[id].menuSubTextColor[4] })
|
|
end
|
|
|
|
function JayMenu.SetMenuFocusColor(id, r, g, b, a)
|
|
setMenuProperty(id, 'menuFocusColor', { r, g, b, a or menus[id].menuFocusColor[4] })
|
|
end
|
|
|
|
|
|
function JayMenu.SetMenuButtonPressedSound(id, name, set)
|
|
setMenuProperty(id, 'buttonPressedSound', { ['name'] = name, ['set'] = set })
|
|
end |