Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Lua: Ported RadialMenu to the Project in sync with its c# counterpart
- Loading branch information
Showing
3 changed files
with
399 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,239 @@ | ||
| RadialMenu = setmetatable({}, RadialMenu) | ||
| RadialMenu.__index = RadialMenu | ||
| RadialMenu.__call = function() | ||
| return "RadialMenu" | ||
| end | ||
|
|
||
| function RadialMenu.New(x, y) | ||
| local X, Y = tonumber(x) or 0, tonumber(y) or 0 | ||
| local _rad = { | ||
| _visible = false, | ||
| currentSelection = 1, | ||
| oldAngle = 0, | ||
| changed = false, | ||
| enable3D = true, | ||
| offset = {x=X, y=Y}, | ||
| Segments = { | ||
| RadialSegment.New(1), | ||
| RadialSegment.New(2), | ||
| RadialSegment.New(3), | ||
| RadialSegment.New(4), | ||
| RadialSegment.New(5), | ||
| RadialSegment.New(6), | ||
| RadialSegment.New(7), | ||
| RadialSegment.New(8), | ||
| }, | ||
| InstructionalButtons = { | ||
| InstructionalButton.New(GetLabelText("HUD_INPUT2"), -1, 176, 176, -1), | ||
| InstructionalButton.New(GetLabelText("HUD_INPUT3"), -1, 177, 177, -1) | ||
| }, | ||
| OnMenuOpen = function(menu, data) | ||
| end, | ||
| OnMenuClose = function(menu) | ||
| end, | ||
| OnSegmentHighlight = function(segment) | ||
| end, | ||
| OnSegmentIndexChange = function(segment, index) | ||
| end, | ||
| OnSegmentSelect = function(segment) | ||
| end | ||
| } | ||
| local meta = setmetatable(_rad, RadialMenu) | ||
| meta.Segments[1].Parent = meta | ||
| meta.Segments[2].Parent = meta | ||
| meta.Segments[3].Parent = meta | ||
| meta.Segments[4].Parent = meta | ||
| meta.Segments[5].Parent = meta | ||
| meta.Segments[6].Parent = meta | ||
| meta.Segments[7].Parent = meta | ||
| meta.Segments[8].Parent = meta | ||
| return meta | ||
| end | ||
|
|
||
| ---AddInstructionButton | ||
| ---@param button InstructionalButton | ||
| function RadialMenu:AddInstructionButton(button) | ||
| if type(button) == "table" then | ||
| self.InstructionalButtons[#self.InstructionalButtons + 1] = button | ||
| if self:Visible() and not ScaleformUI.Scaleforms.Warning:IsShowing() then | ||
| ScaleformUI.Scaleforms.InstructionalButtons:SetInstructionalButtons(self.InstructionalButtons) | ||
| end | ||
| end | ||
| end | ||
|
|
||
| ---RemoveInstructionButton | ||
| ---@param button table | ||
| function RadialMenu:RemoveInstructionButton(button) | ||
| if type(button) == "table" then | ||
| for i = 1, #self.InstructionalButtons do | ||
| if button == self.InstructionalButtons[i] then | ||
| table.remove(self.InstructionalButtons, i) | ||
| break | ||
| end | ||
| end | ||
| else | ||
| if tonumber(button) then | ||
| if self.InstructionalButtons[tonumber(button)] then | ||
| table.remove(self.InstructionalButtons, tonumber(button)) | ||
| end | ||
| end | ||
| end | ||
| if self:Visible() and not ScaleformUI.Scaleforms.Warning:IsShowing() then | ||
| ScaleformUI.Scaleforms.InstructionalButtons:SetInstructionalButtons(self.InstructionalButtons) | ||
| end | ||
| end | ||
|
|
||
|
|
||
| function RadialMenu:Enable3D(enable) | ||
| if enable ~= nil then | ||
| self.enable3D = enable | ||
| if self:Visible() then | ||
| ScaleformUI.Scaleforms._radialMenu:CallFunction("ENABLE_3D", false, enable) | ||
| end | ||
| else | ||
| return self.enable3D | ||
| end | ||
| end | ||
|
|
||
| function RadialMenu:CurrentSelection(index) | ||
| if index ~= nil then | ||
| self.currentSelection = index | ||
| if self:Visible() then | ||
| ScaleformUI.Scaleforms._radialMenu:CallFunction("SET_POINTER", false, (index - 1), true) | ||
| end | ||
| else | ||
| return self.currentSelection or 1 | ||
| end | ||
| end | ||
|
|
||
| function RadialMenu:Visible(bool) | ||
| if bool ~= nil then | ||
| self._visible = bool | ||
| if bool then | ||
| self:BuildMenu() | ||
| MenuHandler._currentMenu = self | ||
| MenuHandler.ableToDraw = true | ||
| self.OnMenuOpen(self) | ||
| if BreadcrumbsHandler:Count() == 0 then | ||
| BreadcrumbsHandler:Forward(self) | ||
| end | ||
| else | ||
| ScaleformUI.Scaleforms.InstructionalButtons:ClearButtonList() | ||
| self.OnMenuClose(self) | ||
| ScaleformUI.Scaleforms._radialMenu:CallFunction("CLEAR_ALL", false) | ||
| MenuHandler._currentMenu = nil | ||
| MenuHandler.ableToDraw = false | ||
| end | ||
| else | ||
| return self._visible | ||
| end | ||
| end | ||
|
|
||
| function RadialMenu:BuildMenu() | ||
| ScaleformUI.Scaleforms._radialMenu:CallFunction("CREATE_MENU", false, self:Enable3D(), (1280 / 2) + self.offset.x, ((720 / 2) - 60) + self.offset.y) | ||
| for i=1, 8 do | ||
| local seg = self.Segments[i] | ||
| for j=1, #seg.Items do | ||
| local item = seg.Items[j] | ||
| ScaleformUI.Scaleforms._radialMenu:CallFunction("ADD_ITEM", false, i-1, item:Label(), item:Description(), item:TextureDict(), item:TextureName(), item:TextureWidth(), item:TextureHeight(), item:Color(), item.qtty, item.max) | ||
| end | ||
| end | ||
| ScaleformUI.Scaleforms._radialMenu:CallFunction("LOAD_MENU", false, self.currentSelection-1, self.Segments[1]:CurrentSelection()-1, self.Segments[2]:CurrentSelection()-1, self.Segments[3]:CurrentSelection()-1, self.Segments[4]:CurrentSelection()-1, self.Segments[5]:CurrentSelection()-1, self.Segments[6]:CurrentSelection()-1, self.Segments[7]:CurrentSelection()-1, self.Segments[8]:CurrentSelection()-1) | ||
| end | ||
|
|
||
| function RadialMenu:ProcessMouse() | ||
| end | ||
|
|
||
| function RadialMenu:ProcessControl() | ||
| if not self:Visible() then | ||
| return | ||
| end | ||
| if UpdateOnscreenKeyboard() == 0 or IsWarningMessageActive() or ScaleformUI.Scaleforms.Warning:IsShowing() or BreadcrumbsHandler.SwitchInProgress then return end | ||
|
|
||
| Controls:ToggleAll(false) | ||
| DisableControlAction(0, 1, true) | ||
| DisableControlAction(0, 2, true) | ||
|
|
||
| local x = math.floor(GetDisabledControlNormal(2, 13) * 1000) | ||
| local y = math.floor(GetDisabledControlNormal(2, 12) * 1000) | ||
|
|
||
| if x > 0 and y == 0 then y = 1 end | ||
| local angle = 0 | ||
| local normalized_angle = 0 | ||
| local finalizedAngle = -1 | ||
| if x > 400 or y > 400 or x < -400 or y < -400 then | ||
| angle = math.atan(y, x) * (180 / math.pi) | ||
| if angle == 0 then | ||
| normalized_angle = 0 | ||
| else | ||
| normalized_angle = (angle + 450) % 360 | ||
| end | ||
| if angle == 0 then | ||
| finalizedAngle = -1 | ||
| else | ||
| finalizedAngle = math.floor(normalized_angle / 45) | ||
| end | ||
|
|
||
| if self.currentSelection ~= finalizedAngle + 1 and finalizedAngle ~= -1 and (normalized_angle > self.oldAngle + 45 or normalized_angle < self.oldAngle - 45) then | ||
| if not self.changed then | ||
| self.Segments[self.currentSelection].Selected = false | ||
| self.currentSelection = finalizedAngle + 1 | ||
| self.oldAngle = normalized_angle | ||
| self.changed = true | ||
| end | ||
| end | ||
|
|
||
| if self.changed then | ||
| self.Segments[self.currentSelection].Selected = true | ||
| self.OnSegmentHighlight(self.Segments[self.currentSelection]) | ||
| ScaleformUI.Scaleforms._radialMenu:CallFunction("SET_POINTER", false, finalizedAngle, true) | ||
| self.changed = false | ||
| end | ||
| end | ||
|
|
||
| if IsDisabledControlJustPressed(0, 15) then | ||
| Citizen.CreateThread(function() | ||
| local sel = self.Segments[self.currentSelection]:CycleItems(-1) | ||
| self.OnSegmentIndexChange(self.Segments[self.currentSelection], sel) | ||
| end) | ||
|
|
||
| end | ||
|
|
||
| if IsDisabledControlJustPressed(0, 14) then | ||
| Citizen.CreateThread(function() | ||
| local sel = self.Segments[self.currentSelection]:CycleItems(1) | ||
| self.OnSegmentIndexChange(self.Segments[self.currentSelection], sel) | ||
| end) | ||
| end | ||
|
|
||
| if IsDisabledControlJustPressed(0, 202) then | ||
| self:GoBack() | ||
| end | ||
|
|
||
| if IsDisabledControlJustPressed(0, 201) then | ||
| self:Select() | ||
| end | ||
| end | ||
|
|
||
| function RadialMenu:GoBack() | ||
| if BreadcrumbsHandler:CurrentDepth() == 1 then | ||
| self:Visible(false) | ||
| BreadcrumbsHandler:Clear() | ||
| else | ||
| BreadcrumbsHandler.SwitchInProgress = true | ||
| local prevMenu = BreadcrumbsHandler:PreviousMenu() | ||
| BreadcrumbsHandler:Backwards() | ||
| self:Visible(false) | ||
| prevMenu:Visible(true) | ||
| BreadcrumbsHandler.SwitchInProgress = false | ||
| end | ||
| end | ||
|
|
||
| function RadialMenu:Select() | ||
| self.OnSegmentSelect(self.Segments[self.currentSelection]) | ||
| end | ||
|
|
||
| function RadialMenu:Draw() | ||
| HideHudComponentThisFrame(19) | ||
| ScaleformUI.Scaleforms._radialMenu:Render2D() | ||
| end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| RadialSegment = setmetatable({}, RadialSegment) | ||
| RadialSegment.__index = RadialSegment | ||
| RadialSegment.__call = function() | ||
| return "RadialSegment" | ||
| end | ||
|
|
||
| function RadialSegment.New(idx, _parent) | ||
| local _seg = { | ||
| Index = idx or -1, | ||
| Items = {}, | ||
| Parent = _parent or nil, | ||
| _selected = false, | ||
| currentSelection = 1, | ||
| OnIndexChanged = function(index) | ||
| end | ||
| } | ||
| return setmetatable(_seg, RadialSegment) | ||
| end | ||
|
|
||
| function RadialSegment:CurrentSelection() | ||
| return self.currentSelection or 1 | ||
| end | ||
|
|
||
| function RadialSegment:AddItem(item) | ||
| item.Parent = self | ||
| table.insert(self.Items, item) | ||
| if self.Parent ~= nil and self.Parent:Visible() then | ||
| ScaleformUI.Scaleforms._radialMenu:CallFunction("ADD_ITEM", false, self.Index-1, item:Label(), item:Description(), item:TextureDict(), item:TextureName(), item:TextureWidth(), item:TextureHeight(), item:Color(), item.qtty, item.max) | ||
| end | ||
| end | ||
|
|
||
| function RadialSegment:RemoveItem(item) | ||
| if item == "number" then | ||
| table.remove(self.Items, item) | ||
| elseif item == "table" then | ||
| table.remove(self.Items, IndexOf(self.Items, item)) | ||
| end | ||
| end | ||
|
|
||
| function RadialSegment:CycleItems(dir) | ||
| local retVal = 0 | ||
| if dir == -1 then | ||
| retVal = ScaleformUI.Scaleforms._radialMenu:CallFunction("SET_INPUT_EVENT", true, 10) | ||
| else | ||
| retVal = ScaleformUI.Scaleforms._radialMenu:CallFunction("SET_INPUT_EVENT", true, 11) | ||
| end | ||
| while not IsScaleformMovieMethodReturnValueReady(retVal) do | ||
| Citizen.Wait(0) | ||
| end | ||
| self.currentSelection = GetScaleformMovieMethodReturnValueInt(retVal) + 1 | ||
|
|
||
| self.OnIndexChanged(self.currentSelection) | ||
| return self:CurrentSelection() | ||
| end |
Oops, something went wrong.