├── .github └── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── feature-request.md │ └── feature_request.md ├── CHANGES.md ├── License & More ├── CODE_OF_CONDUCT.md ├── LICENSE └── _config.yml ├── NativeUI from Frazzle ├── MenuPool.lua ├── NativeUI.lua ├── UIMenu.lua ├── Utils.lua ├── __resource.lua ├── elements │ ├── Badge.lua │ ├── Colours.lua │ ├── Sprite.lua │ ├── StringMeasurer.lua │ ├── UIResRectangle.lua │ └── UIResText.lua ├── items │ ├── UIMenuCheckboxItem.lua │ ├── UIMenuColouredItem.lua │ ├── UIMenuItem.lua │ ├── UIMenuListItem.lua │ ├── UIMenuProgressItem.lua │ └── UIMenuSliderItem.lua ├── panels │ ├── UIMenuColourPanel.lua │ ├── UIMenuGridPanel.lua │ └── UIMenuPercentagePanel.lua └── windows │ └── UIMenuHeritageWindow.lua ├── README.md ├── SimpleMenu.lua ├── Tutorial.html ├── __resource.lua ├── perms └── perms.lua ├── tutorial.html └── version.lua /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | --------------- 2 | Newest Updates: 3 | --------------- 4 | 5 | * Added Version Checker 6 | 7 | * UI Changes 8 | 9 | * Cleaner UI (SubMenus in SubMenus) 10 | 11 | * UPDATE LINK: https://github.com/Thymester/SimpleMenu/releases 12 | 13 | * Past Update(s) Link: https://github.com/Thymester/SimpleMenu/releases 14 | -------------------------------------------------------------------------------- /License & More/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at zieonngaming@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /License & More/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [2019] [Tyler] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /License & More/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-time-machine -------------------------------------------------------------------------------- /NativeUI from Frazzle/MenuPool.lua: -------------------------------------------------------------------------------- 1 | MenuPool = setmetatable({}, MenuPool) 2 | MenuPool.__index = MenuPool 3 | 4 | function MenuPool.New() 5 | local _MenuPool = { 6 | Menus = {} 7 | } 8 | return setmetatable(_MenuPool, MenuPool) 9 | end 10 | 11 | function MenuPool:AddSubMenu(Menu, Text, Description, KeepPosition, KeepBanner) 12 | if Menu() == "UIMenu" then 13 | local Item = UIMenuItem.New(tostring(Text), Description or "") 14 | Menu:AddItem(Item) 15 | local SubMenu 16 | if KeepPosition then 17 | SubMenu = UIMenu.New(Menu.Title:Text(), Text, Menu.Position.X, Menu.Position.Y) 18 | else 19 | SubMenu = UIMenu.New(Menu.Title:Text(), Text) 20 | end 21 | if KeepBanner then 22 | if Menu.Logo ~= nil then 23 | SubMenu.Logo = Menu.Logo 24 | else 25 | SubMenu.Logo = nil 26 | SubMenu.Banner = Menu.Banner 27 | end 28 | end 29 | self:Add(SubMenu) 30 | Menu:BindMenuToItem(SubMenu, Item) 31 | return SubMenu 32 | end 33 | end 34 | 35 | function MenuPool:Add(Menu) 36 | if Menu() == "UIMenu" then 37 | table.insert(self.Menus, Menu) 38 | end 39 | end 40 | 41 | function MenuPool:MouseEdgeEnabled(bool) 42 | if bool ~= nil then 43 | for _, Menu in pairs(self.Menus) do 44 | Menu.Settings.MouseEdgeEnabled = tobool(bool) 45 | end 46 | end 47 | end 48 | 49 | function MenuPool:ControlDisablingEnabled(bool) 50 | if bool ~= nil then 51 | for _, Menu in pairs(self.Menus) do 52 | Menu.Settings.ControlDisablingEnabled = tobool(bool) 53 | end 54 | end 55 | end 56 | 57 | function MenuPool:ResetCursorOnOpen(bool) 58 | if bool ~= nil then 59 | for _, Menu in pairs(self.Menus) do 60 | Menu.Settings.ResetCursorOnOpen = tobool(bool) 61 | end 62 | end 63 | end 64 | 65 | function MenuPool:MultilineFormats(bool) 66 | if bool ~= nil then 67 | for _, Menu in pairs(self.Menus) do 68 | Menu.Settings.MultilineFormats = tobool(bool) 69 | end 70 | end 71 | end 72 | 73 | function MenuPool:Audio(Attribute, Setting) 74 | if Attribute ~= nil and Setting ~= nil then 75 | for _, Menu in pairs(self.Menus) do 76 | if Menu.Settings.Audio[Attribute] then 77 | Menu.Settings.Audio[Attribute] = Setting 78 | end 79 | end 80 | end 81 | end 82 | 83 | function MenuPool:WidthOffset(offset) 84 | if tonumber(offset) then 85 | for _, Menu in pairs(self.Menus) do 86 | Menu:SetMenuWidthOffset(tonumber(offset)) 87 | end 88 | end 89 | end 90 | 91 | function MenuPool:CounterPreText(str) 92 | if str ~= nil then 93 | for _, Menu in pairs(self.Menus) do 94 | Menu.PageCounter.PreText = tostring(str) 95 | end 96 | end 97 | end 98 | 99 | function MenuPool:DisableInstructionalButtons(bool) 100 | if bool ~= nil then 101 | for _, Menu in pairs(self.Menus) do 102 | Menu.Settings.InstructionalButtons = tobool(bool) 103 | end 104 | end 105 | end 106 | 107 | function MenuPool:MouseControlsEnabled(bool) 108 | if bool ~= nil then 109 | for _, Menu in pairs(self.Menus) do 110 | Menu.Settings.MouseControlsEnabled = tobool(bool) 111 | end 112 | end 113 | end 114 | 115 | function MenuPool:RefreshIndex() 116 | for _, Menu in pairs(self.Menus) do 117 | Menu:RefreshIndex() 118 | end 119 | end 120 | 121 | function MenuPool:ProcessMenus() 122 | self:ProcessControl() 123 | self:ProcessMouse() 124 | self:Draw() 125 | end 126 | 127 | function MenuPool:ProcessControl() 128 | for _, Menu in pairs(self.Menus) do 129 | if Menu:Visible() then 130 | Menu:ProcessControl() 131 | end 132 | end 133 | end 134 | 135 | function MenuPool:ProcessMouse() 136 | for _, Menu in pairs(self.Menus) do 137 | if Menu:Visible() then 138 | Menu:ProcessMouse() 139 | end 140 | end 141 | end 142 | 143 | function MenuPool:Draw() 144 | for _, Menu in pairs(self.Menus) do 145 | if Menu:Visible() then 146 | Menu:Draw() 147 | end 148 | end 149 | end 150 | 151 | function MenuPool:IsAnyMenuOpen() 152 | local open = false 153 | for _, Menu in pairs(self.Menus) do 154 | if Menu:Visible() then 155 | open = true 156 | break 157 | end 158 | end 159 | return open 160 | end 161 | 162 | function MenuPool:CloseAllMenus() 163 | for _, Menu in pairs(self.Menus) do 164 | if Menu:Visible() then 165 | Menu:Visible(false) 166 | Menu.OnMenuClosed(Menu) 167 | end 168 | end 169 | end 170 | 171 | function MenuPool:SetBannerSprite(Sprite) 172 | if Sprite() == "Sprite" then 173 | for _, Menu in pairs(self.Menus) do 174 | Menu:SetBannerSprite(Sprite) 175 | end 176 | end 177 | end 178 | 179 | function MenuPool:SetBannerRectangle(Rectangle) 180 | if Rectangle() == "Rectangle" then 181 | for _, Menu in pairs(self.Menus) do 182 | Menu:SetBannerRectangle(Rectangle) 183 | end 184 | end 185 | end 186 | 187 | function MenuPool:TotalItemsPerPage(Value) 188 | if tonumber(Value) then 189 | for _, Menu in pairs(self.Menus) do 190 | Menu.Pagination.Total = Value - 1 191 | end 192 | end 193 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/UIMenu.lua: -------------------------------------------------------------------------------- 1 | UIMenu = setmetatable({}, UIMenu) 2 | UIMenu.__index = UIMenu 3 | UIMenu.__call = function() return "UIMenu" end 4 | 5 | function UIMenu.New(Title, Subtitle, X, Y, TxtDictionary, TxtName) 6 | local X, Y = tonumber(X) or 0, tonumber(Y) or 0 7 | if Title ~= nil then Title = tostring(Title) or "" else Title = "" end 8 | if Subtitle ~= nil then Subtitle = tostring(Subtitle) or "" else Subtitle = "" end 9 | if TxtDictionary ~= nil then TxtDictionary = tostring(TxtDictionary) or "commonmenu" else TxtDictionary = "commonmenu" end 10 | if TxtName ~= nil then TxtName = tostring(TxtName) or "interaction_bgd" else TxtName = "interaction_bgd" end 11 | local _UIMenu = { 12 | Logo = Sprite.New(TxtDictionary, TxtName, 0 + X, 0 + Y, 431, 107), 13 | Banner = nil, 14 | Title = UIResText.New(Title, 215 + X, 20 + Y, 1.15, 255, 255, 255, 255, 1, 1), 15 | Subtitle = {ExtraY = 0}, 16 | WidthOffset = 0, 17 | Position = {X = X, Y = Y}, 18 | Pagination = {Min = 0, Max = 9, Total = 9}, 19 | PageCounter = {PreText = ""}, 20 | Extra = {}, 21 | Description = {}, 22 | Items = {}, 23 | Windows = {}, 24 | Children = {}, 25 | Controls = { 26 | Back = { 27 | Enabled = true, 28 | }, 29 | Select = { 30 | Enabled = true, 31 | }, 32 | Left = { 33 | Enabled = true, 34 | }, 35 | Right = { 36 | Enabled = true, 37 | }, 38 | Up = { 39 | Enabled = true, 40 | }, 41 | Down = { 42 | Enabled = true, 43 | }, 44 | }, 45 | ParentMenu = nil, 46 | ParentItem = nil, 47 | _Visible = false, 48 | ActiveItem = 1000, 49 | Dirty = false; 50 | ReDraw = true, 51 | InstructionalScaleform = RequestScaleformMovie("INSTRUCTIONAL_BUTTONS"), 52 | InstructionalButtons = {}, 53 | OnIndexChange = function(menu, newindex) end, 54 | OnListChange = function(menu, list, newindex) end, 55 | OnSliderChange = function(menu, slider, newindex) end, 56 | OnProgressChange = function(menu, progress, newindex) end, 57 | OnCheckboxChange = function(menu, item, checked) end, 58 | OnListSelect = function(menu, list, index) end, 59 | OnSliderSelect = function(menu, slider, index) end, 60 | OnProgressSelect = function(menu, progress, index) end, 61 | OnItemSelect = function(menu, item, index) end, 62 | OnMenuChanged = function(menu, newmenu, forward) end, 63 | OnMenuClosed = function(menu) end, 64 | Settings = { 65 | InstructionalButtons = true, 66 | MultilineFormats = true, 67 | ScaleWithSafezone = true, 68 | ResetCursorOnOpen = true, 69 | MouseControlsEnabled = true, 70 | MouseEdgeEnabled = true, 71 | ControlDisablingEnabled = true, 72 | Audio = { 73 | Library = "HUD_FRONTEND_DEFAULT_SOUNDSET", 74 | UpDown = "NAV_UP_DOWN", 75 | LeftRight = "NAV_LEFT_RIGHT", 76 | Select = "SELECT", 77 | Back = "BACK", 78 | Error = "ERROR", 79 | }, 80 | EnabledControls = { 81 | Controller = { 82 | {0, 2}, -- Look Up and Down 83 | {0, 1}, -- Look Left and Right 84 | {0, 25}, -- Aim 85 | {0, 24}, -- Attack 86 | }, 87 | Keyboard = { 88 | {0, 201}, -- Select 89 | {0, 195}, -- X axis 90 | {0, 196}, -- Y axis 91 | {0, 187}, -- Down 92 | {0, 188}, -- Up 93 | {0, 189}, -- Left 94 | {0, 190}, -- Right 95 | {0, 202}, -- Back 96 | {0, 217}, -- Select 97 | {0, 242}, -- Scroll down 98 | {0, 241}, -- Scroll up 99 | {0, 239}, -- Cursor X 100 | {0, 240}, -- Cursor Y 101 | {0, 31}, -- Move Up and Down 102 | {0, 30}, -- Move Left and Right 103 | {0, 21}, -- Sprint 104 | {0, 22}, -- Jump 105 | {0, 23}, -- Enter 106 | {0, 75}, -- Exit Vehicle 107 | {0, 71}, -- Accelerate Vehicle 108 | {0, 72}, -- Vehicle Brake 109 | {0, 59}, -- Move Vehicle Left and Right 110 | {0, 89}, -- Fly Yaw Left 111 | {0, 9}, -- Fly Left and Right 112 | {0, 8}, -- Fly Up and Down 113 | {0, 90}, -- Fly Yaw Right 114 | {0, 76}, -- Vehicle Handbrake 115 | }, 116 | }, 117 | } 118 | } 119 | 120 | if Subtitle ~= "" and Subtitle ~= nil then 121 | _UIMenu.Subtitle.Rectangle = UIResRectangle.New(0 + _UIMenu.Position.X, 107 + _UIMenu.Position.Y, 431, 37, 0, 0, 0, 255) 122 | _UIMenu.Subtitle.Text = UIResText.New(Subtitle, 8 + _UIMenu.Position.X, 110 + _UIMenu.Position.Y, 0.35, 245, 245, 245, 255, 0) 123 | _UIMenu.Subtitle.BackupText = Subtitle 124 | _UIMenu.Subtitle.Formatted = false 125 | if string.starts(Subtitle, "~") then 126 | _UIMenu.PageCounter.PreText = string.sub(Subtitle, 1, 3) 127 | end 128 | _UIMenu.PageCounter.Text = UIResText.New("", 425 + _UIMenu.Position.X, 110 + _UIMenu.Position.Y, 0.35, 245, 245, 245, 255, 0, "Right") 129 | _UIMenu.Subtitle.ExtraY = 37 130 | end 131 | 132 | _UIMenu.ArrowSprite = Sprite.New("commonmenu", "shop_arrows_upanddown", 190 + _UIMenu.Position.X, 147 + 37 * (_UIMenu.Pagination.Total + 1) + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 50, 50) 133 | _UIMenu.Extra.Up = UIResRectangle.New(0 + _UIMenu.Position.X, 144 + 38 * (_UIMenu.Pagination.Total + 1) + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 431, 18, 0, 0, 0, 200) 134 | _UIMenu.Extra.Down = UIResRectangle.New(0 + _UIMenu.Position.X, 144 + 18 + 38 * (_UIMenu.Pagination.Total + 1) + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 431, 18, 0, 0, 0, 200) 135 | 136 | _UIMenu.Description.Bar = UIResRectangle.New(_UIMenu.Position.X, 123, 431, 4, 0, 0, 0, 255) 137 | _UIMenu.Description.Rectangle = Sprite.New("commonmenu", "gradient_bgd", _UIMenu.Position.X, 127, 431, 30) 138 | _UIMenu.Description.Text = UIResText.New("Description", _UIMenu.Position.X + 5, 125, 0.35) 139 | 140 | _UIMenu.Background = Sprite.New("commonmenu", "gradient_bgd", _UIMenu.Position.X, 144 + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 290, 25) 141 | 142 | Citizen.CreateThread(function() 143 | if not HasScaleformMovieLoaded(_UIMenu.InstructionalScaleform) then 144 | _UIMenu.InstructionalScaleform = RequestScaleformMovie("INSTRUCTIONAL_BUTTONS") 145 | while not HasScaleformMovieLoaded(_UIMenu.InstructionalScaleform) do 146 | Citizen.Wait(0) 147 | end 148 | end 149 | end) 150 | return setmetatable(_UIMenu, UIMenu) 151 | end 152 | 153 | function UIMenu:SetMenuWidthOffset(Offset) 154 | if tonumber(Offset) then 155 | self.WidthOffset = math.floor(tonumber(Offset)) 156 | self.Logo:Size(431 + self.WidthOffset, 107) 157 | self.Title:Position(((self.WidthOffset + 431)/2) + self.Position.X, 20 + self.Position.Y) 158 | if self.Subtitle.Rectangle ~= nil then 159 | self.Subtitle.Rectangle:Size(431 + self.WidthOffset + 100, 37) 160 | self.PageCounter.Text:Position(425 + self.Position.X + self.WidthOffset, 110 + self.Position.Y) 161 | end 162 | if self.Banner ~= nil then 163 | self.Banner:Size(431 + self.WidthOffset, 107) 164 | end 165 | end 166 | end 167 | 168 | function UIMenu:DisEnableControls(bool) 169 | if bool then 170 | EnableAllControlActions(2) 171 | else 172 | DisableAllControlActions(2) 173 | end 174 | 175 | if bool then 176 | return 177 | else 178 | if Controller() then 179 | for Index = 1, #self.Settings.EnabledControls.Controller do 180 | EnableControlAction(self.Settings.EnabledControls.Controller[Index][1], self.Settings.EnabledControls.Controller[Index][2], true) 181 | end 182 | else 183 | for Index = 1, #self.Settings.EnabledControls.Keyboard do 184 | EnableControlAction(self.Settings.EnabledControls.Keyboard[Index][1], self.Settings.EnabledControls.Keyboard[Index][2], true) 185 | end 186 | end 187 | end 188 | end 189 | 190 | function UIMenu:InstructionalButtons(bool) 191 | if bool ~= nil then 192 | self.Settings.InstrucitonalButtons = tobool(bool) 193 | end 194 | end 195 | 196 | function UIMenu:SetBannerSprite(Sprite, IncludeChildren) 197 | if Sprite() == "Sprite" then 198 | self.Logo = Sprite 199 | self.Logo:Size(431 + self.WidthOffset, 107) 200 | self.Logo:Position(self.Position.X, self.Position.Y) 201 | self.Banner = nil 202 | if IncludeChildren then 203 | for Item, Menu in pairs(self.Children) do 204 | Menu.Logo = Sprite 205 | Menu.Logo:Size(431 + self.WidthOffset, 107) 206 | Menu.Logo:Position(self.Position.X, self.Position.Y) 207 | Menu.Banner = nil 208 | end 209 | end 210 | end 211 | end 212 | 213 | function UIMenu:SetBannerRectangle(Rectangle, IncludeChildren) 214 | if Rectangle() == "Rectangle" then 215 | self.Banner = Rectangle 216 | self.Banner:Size(431 + self.WidthOffset, 107) 217 | self.Banner:Position(self.Position.X, self.Position.Y) 218 | self.Logo = nil 219 | if IncludeChildren then 220 | for Item, Menu in pairs(self.Children) do 221 | Menu.Banner = Rectangle 222 | Menu.Banner:Size(431 + self.WidthOffset, 107) 223 | Menu:Position(self.Position.X, self.Position.Y) 224 | Menu.Logo = nil 225 | end 226 | end 227 | end 228 | end 229 | 230 | function UIMenu:CurrentSelection(value) 231 | if tonumber(value) then 232 | if #self.Items == 0 then 233 | self.ActiveItem = 0 234 | end 235 | 236 | self.Items[self:CurrentSelection()]:Selected(false) 237 | self.ActiveItem = 1000000 - (1000000 % #self.Items) + tonumber(value) 238 | 239 | if self:CurrentSelection() > self.Pagination.Max then 240 | self.Pagination.Min = self:CurrentSelection() - self.Pagination.Total 241 | self.Pagination.Max = self:CurrentSelection() 242 | elseif self:CurrentSelection() < self.Pagination.Min then 243 | self.Pagination.Min = self:CurrentSelection() 244 | self.Pagination.Max = self:CurrentSelection() + self.Pagination.Total 245 | end 246 | else 247 | if #self.Items == 0 then 248 | return 1 249 | else 250 | if self.ActiveItem % #self.Items == 0 then 251 | return 1 252 | else 253 | return self.ActiveItem % #self.Items + 1 254 | end 255 | end 256 | end 257 | end 258 | 259 | function UIMenu:CalculateWindowHeight() 260 | local Height = 0 261 | for i = 1, #self.Windows do 262 | Height = Height + self.Windows[i].Background:Size().Height 263 | end 264 | return Height 265 | end 266 | 267 | function UIMenu:CalculateItemHeightOffset(Item) 268 | if Item.Base then 269 | return Item.Base.Rectangle.Height 270 | else 271 | return Item.Rectangle.Height 272 | end 273 | end 274 | 275 | function UIMenu:CalculateItemHeight() 276 | local ItemOffset = 0 + self.Subtitle.ExtraY - 37 277 | for i = self.Pagination.Min + 1, self.Pagination.Max do 278 | local Item = self.Items[i] 279 | if Item ~= nil then 280 | ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item) 281 | end 282 | end 283 | return ItemOffset 284 | end 285 | 286 | function UIMenu:RecalculateDescriptionPosition() 287 | local WindowHeight = self:CalculateWindowHeight() 288 | self.Description.Bar:Position(self.Position.X, 149 + self.Position.Y + WindowHeight) 289 | self.Description.Rectangle:Position(self.Position.X, 149 + self.Position.Y + WindowHeight) 290 | self.Description.Text:Position(self.Position.X + 8, 155 + self.Position.Y + WindowHeight) 291 | 292 | self.Description.Bar:Size(431 + self.WidthOffset, 4) 293 | self.Description.Rectangle:Size(431 + self.WidthOffset, 30) 294 | 295 | self.Description.Bar:Position(self.Position.X, self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + self.Description.Bar:Position().Y) 296 | self.Description.Rectangle:Position(self.Position.X, self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + self.Description.Rectangle:Position().Y) 297 | self.Description.Text:Position(self.Position.X + 8, self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + self.Description.Text:Position().Y) 298 | end 299 | 300 | function UIMenu:CaclulatePanelPosition(HasDescription) 301 | local Height = self:CalculateWindowHeight() + 149 + self.Position.Y 302 | 303 | if HasDescription then 304 | Height = Height + self.Description.Rectangle:Size().Height + 5 305 | end 306 | 307 | return self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + Height 308 | end 309 | 310 | function UIMenu:AddWindow(Window) 311 | if Window() == "UIMenuWindow" then 312 | Window:SetParentMenu(self) 313 | Window:Offset(self.Position.X, self.Position.Y) 314 | table.insert(self.Windows, Window) 315 | self.ReDraw = true 316 | self:RecalculateDescriptionPosition() 317 | end 318 | end 319 | 320 | function UIMenu:RemoveWindowAt(Index) 321 | if tonumber(Index) then 322 | if self.Windows[Index] then 323 | table.remove(self.Windows, Index) 324 | self.ReDraw = true 325 | self:RecalculateDescriptionPosition() 326 | end 327 | end 328 | end 329 | 330 | function UIMenu:AddItem(Item) 331 | if Item() == "UIMenuItem" then 332 | local SelectedItem = self:CurrentSelection() 333 | Item:SetParentMenu(self) 334 | Item:Offset(self.Position.X, self.Position.Y) 335 | Item:Position((#self.Items * 25) - 37 + self.Subtitle.ExtraY) 336 | table.insert(self.Items, Item) 337 | self:RecalculateDescriptionPosition() 338 | self:CurrentSelection(SelectedItem) 339 | end 340 | end 341 | 342 | function UIMenu:RemoveItemAt(Index) 343 | if tonumber(Index) then 344 | if self.Items[Index] then 345 | local SelectedItem = self:CurrentSelection() 346 | if #self.Items > self.Pagination.Total and self.Pagination.Max == #self.Items - 1 then 347 | self.Pagination.Min = self.Pagination.Min - 1 348 | self.Pagination.Max = self.Pagination.Max + 1 349 | end 350 | table.remove(self.Items, tonumber(Index)) 351 | self:RecalculateDescriptionPosition() 352 | self:CurrentSelection(SelectedItem) 353 | end 354 | end 355 | end 356 | 357 | function UIMenu:RefreshIndex() 358 | if #self.Items == 0 then 359 | self.ActiveItem = 1000 360 | self.Pagination.Max = self.Pagination.Total + 1 361 | self.Pagination.Min = 0 362 | return 363 | end 364 | self.Items[self:CurrentSelection()]:Selected(false) 365 | self.ActiveItem = 1000 - (1000 % #self.Items) 366 | self.Pagination.Max = self.Pagination.Total + 1 367 | self.Pagination.Min = 0 368 | self.ReDraw = true 369 | end 370 | 371 | function UIMenu:Clear() 372 | self.Items = {} 373 | self.ReDraw = true 374 | self:RecalculateDescriptionPosition() 375 | end 376 | 377 | function UIMenu:MultilineFormat(str) 378 | if tostring(str) then 379 | 380 | local PixelPerLine = 425 + self.WidthOffset 381 | local AggregatePixels = 0 382 | local output = "" 383 | local words = string.split(tostring(str), " ") 384 | 385 | for i = 1, #words do 386 | local offset = MeasureStringWidth(words[i], 0, 0.35) 387 | AggregatePixels = AggregatePixels + offset 388 | if AggregatePixels > PixelPerLine then 389 | output = output .. "\n" .. words[i] .. " " 390 | AggregatePixels = offset + MeasureString(" ") 391 | else 392 | output = output .. words[i] .. " " 393 | AggregatePixels = AggregatePixels + MeasureString(" ") 394 | end 395 | end 396 | return output 397 | end 398 | end 399 | 400 | function UIMenu:DrawCalculations() 401 | local WindowHeight = self:CalculateWindowHeight() 402 | 403 | if self.Settings.MultilineFormats then 404 | if self.Subtitle.Rectangle and not self.Subtitle.Formatted then 405 | self.Subtitle.Formatted = true 406 | self.Subtitle.Text:Text(self:MultilineFormat(self.Subtitle.Text:Text())) 407 | 408 | local Linecount = #string.split(self.Subtitle.Text:Text(), "\n") 409 | self.Subtitle.ExtraY = ((Linecount == 1) and 37 or ((Linecount + 1) * 22)) 410 | self.Subtitle.Rectangle:Size(431 + self.WidthOffset, self.Subtitle.ExtraY) 411 | end 412 | elseif self.Subtitle.Formatted then 413 | self.Subtitle.Formatted = false 414 | self.Subtitle.ExtraY = 37 415 | self.Subtitle.Rectangle:Size(431 + self.WidthOffset, self.Subtitle.ExtraY) 416 | self.Subtitle.Text:Text(self.Subtitle.BackupText) 417 | end 418 | 419 | self.Background:Size(431 + self.WidthOffset, self:CalculateItemHeight() + WindowHeight + ((self.Subtitle.ExtraY > 0) and 0 or 37)) 420 | 421 | self.Extra.Up:Size(431 + self.WidthOffset, 18) 422 | self.Extra.Down:Size(431 + self.WidthOffset, 18) 423 | 424 | self.Extra.Up:Position(self.Position.X, 144 + self:CalculateItemHeight() + self.Position.Y + WindowHeight) 425 | self.Extra.Down:Position(self.Position.X, 144 + 18 + self:CalculateItemHeight() + self.Position.Y + WindowHeight) 426 | 427 | if self.WidthOffset > 0 then 428 | self.ArrowSprite:Position(190 + self.Position.X + (self.WidthOffset / 2), 137 + self:CalculateItemHeight() + self.Position.Y + WindowHeight) 429 | else 430 | self.ArrowSprite:Position(190 + self.Position.X + self.WidthOffset, 137 + self:CalculateItemHeight() + self.Position.Y + WindowHeight) 431 | end 432 | 433 | self.ReDraw = false 434 | 435 | if #self.Items ~= 0 and self.Items[self:CurrentSelection()]:Description() ~= "" then 436 | self:RecalculateDescriptionPosition() 437 | 438 | local description = self.Items[self:CurrentSelection()]:Description() 439 | if self.Settings.MultilineFormats then 440 | self.Description.Text:Text(self:MultilineFormat(description)) 441 | else 442 | self.Description.Text:Text(description) 443 | end 444 | 445 | local Linecount = #string.split(self.Description.Text:Text(), "\n") 446 | self.Description.Rectangle:Size(431 + self.WidthOffset, ((Linecount == 1) and 37 or ((Linecount + 1) * 22))) 447 | end 448 | end 449 | 450 | function UIMenu:Visible(bool) 451 | if bool ~= nil then 452 | self._Visible = tobool(bool) 453 | self.JustOpened = tobool(bool) 454 | self.Dirty = tobool(bool) 455 | self:UpdateScaleform() 456 | if self.ParentMenu ~= nil or tobool(bool) == false then 457 | return 458 | end 459 | if self.Settings.ResetCursorOnOpen then 460 | local W, H = GetScreenResolution() 461 | SetCursorLocation(W / 2, H / 2) 462 | SetCursorSprite(1) 463 | end 464 | else 465 | return self._Visible 466 | end 467 | end 468 | 469 | function UIMenu:ProcessControl() 470 | if not self._Visible then 471 | return 472 | end 473 | 474 | if self.JustOpened then 475 | self.JustOpened = false 476 | return 477 | end 478 | 479 | if self.Controls.Back.Enabled and (IsDisabledControlJustReleased(0, 177) or IsDisabledControlJustReleased(1, 177) or IsDisabledControlJustReleased(2, 177) or IsDisabledControlJustReleased(0, 199) or IsDisabledControlJustReleased(1, 199) or IsDisabledControlJustReleased(2, 199)) then 480 | self:GoBack() 481 | end 482 | 483 | if #self.Items == 0 then 484 | return 485 | end 486 | 487 | if not self.UpPressed then 488 | if self.Controls.Up.Enabled and (IsDisabledControlJustPressed(0, 172) or IsDisabledControlJustPressed(1, 172) or IsDisabledControlJustPressed(2, 172) or IsDisabledControlJustPressed(0, 241) or IsDisabledControlJustPressed(1, 241) or IsDisabledControlJustPressed(2, 241) or IsDisabledControlJustPressed(2, 241)) then 489 | Citizen.CreateThread(function() 490 | self.UpPressed = true 491 | if #self.Items > self.Pagination.Total + 1 then 492 | self:GoUpOverflow() 493 | else 494 | self:GoUp() 495 | end 496 | self:UpdateScaleform() 497 | Citizen.Wait(175) 498 | while self.Controls.Up.Enabled and (IsDisabledControlPressed(0, 172) or IsDisabledControlPressed(1, 172) or IsDisabledControlPressed(2, 172) or IsDisabledControlPressed(0, 241) or IsDisabledControlPressed(1, 241) or IsDisabledControlPressed(2, 241) or IsDisabledControlPressed(2, 241)) do 499 | if #self.Items > self.Pagination.Total + 1 then 500 | self:GoUpOverflow() 501 | else 502 | self:GoUp() 503 | end 504 | self:UpdateScaleform() 505 | Citizen.Wait(125) 506 | end 507 | self.UpPressed = false 508 | end) 509 | end 510 | end 511 | 512 | if not self.DownPressed then 513 | if self.Controls.Down.Enabled and (IsDisabledControlJustPressed(0, 173) or IsDisabledControlJustPressed(1, 173) or IsDisabledControlJustPressed(2, 173) or IsDisabledControlJustPressed(0, 242) or IsDisabledControlJustPressed(1, 242) or IsDisabledControlJustPressed(2, 242)) then 514 | Citizen.CreateThread(function() 515 | self.DownPressed = true 516 | if #self.Items > self.Pagination.Total + 1 then 517 | self:GoDownOverflow() 518 | else 519 | self:GoDown() 520 | end 521 | self:UpdateScaleform() 522 | Citizen.Wait(175) 523 | while self.Controls.Down.Enabled and (IsDisabledControlPressed(0, 173) or IsDisabledControlPressed(1, 173) or IsDisabledControlPressed(2, 173) or IsDisabledControlPressed(0, 242) or IsDisabledControlPressed(1, 242) or IsDisabledControlPressed(2, 242)) do 524 | if #self.Items > self.Pagination.Total + 1 then 525 | self:GoDownOverflow() 526 | else 527 | self:GoDown() 528 | end 529 | self:UpdateScaleform() 530 | Citizen.Wait(125) 531 | end 532 | self.DownPressed = false 533 | end) 534 | end 535 | end 536 | 537 | if not self.LeftPressed then 538 | if self.Controls.Left.Enabled and (IsDisabledControlPressed(0, 174) or IsDisabledControlPressed(1, 174) or IsDisabledControlPressed(2, 174)) then 539 | Citizen.CreateThread(function() 540 | self.LeftPressed = true 541 | self:GoLeft() 542 | Citizen.Wait(175) 543 | while self.Controls.Left.Enabled and (IsDisabledControlPressed(0, 174) or IsDisabledControlPressed(1, 174) or IsDisabledControlPressed(2, 174)) do 544 | self:GoLeft() 545 | Citizen.Wait(125) 546 | end 547 | self.LeftPressed = false 548 | end) 549 | end 550 | end 551 | 552 | if not self.RightPressed then 553 | if self.Controls.Right.Enabled and (IsDisabledControlPressed(0, 175) or IsDisabledControlPressed(1, 175) or IsDisabledControlPressed(2, 175)) then 554 | Citizen.CreateThread(function() 555 | self.RightPressed = true 556 | self:GoRight() 557 | Citizen.Wait(175) 558 | while self.Controls.Right.Enabled and (IsDisabledControlPressed(0, 175) or IsDisabledControlPressed(1, 175) or IsDisabledControlPressed(2, 175)) do 559 | self:GoRight() 560 | Citizen.Wait(125) 561 | end 562 | self.RightPressed = false 563 | end) 564 | end 565 | end 566 | 567 | if self.Controls.Select.Enabled and (IsDisabledControlJustPressed(0, 201) or IsDisabledControlJustPressed(1, 201) or IsDisabledControlJustPressed(2, 201)) then 568 | self:SelectItem() 569 | end 570 | end 571 | 572 | function UIMenu:GoUpOverflow() 573 | if #self.Items <= self.Pagination.Total + 1 then 574 | return 575 | end 576 | 577 | if self:CurrentSelection() <= self.Pagination.Min + 1 then 578 | if self:CurrentSelection() == 1 then 579 | self.Pagination.Min = #self.Items - (self.Pagination.Total + 1) 580 | self.Pagination.Max = #self.Items 581 | self.Items[self:CurrentSelection()]:Selected(false) 582 | self.ActiveItem = 1000 - (1000 % #self.Items) 583 | self.ActiveItem = self.ActiveItem + (#self.Items - 1) 584 | self.Items[self:CurrentSelection()]:Selected(true) 585 | else 586 | self.Pagination.Min = self.Pagination.Min - 1 587 | self.Pagination.Max = self.Pagination.Max - 1 588 | self.Items[self:CurrentSelection()]:Selected(false) 589 | self.ActiveItem = self.ActiveItem - 1 590 | self.Items[self:CurrentSelection()]:Selected(true) 591 | end 592 | else 593 | self.Items[self:CurrentSelection()]:Selected(false) 594 | self.ActiveItem = self.ActiveItem - 1 595 | self.Items[self:CurrentSelection()]:Selected(true) 596 | end 597 | PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true) 598 | self.OnIndexChange(self, self:CurrentSelection()) 599 | self.ReDraw = true 600 | end 601 | 602 | function UIMenu:GoUp() 603 | if #self.Items > self.Pagination.Total + 1 then 604 | return 605 | end 606 | self.Items[self:CurrentSelection()]:Selected(false) 607 | self.ActiveItem = self.ActiveItem - 1 608 | self.Items[self:CurrentSelection()]:Selected(true) 609 | PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true) 610 | self.OnIndexChange(self, self:CurrentSelection()) 611 | self.ReDraw = true 612 | end 613 | 614 | function UIMenu:GoDownOverflow() 615 | if #self.Items <= self.Pagination.Total + 1 then 616 | return 617 | end 618 | 619 | if self:CurrentSelection() >= self.Pagination.Max then 620 | if self:CurrentSelection() == #self.Items then 621 | self.Pagination.Min = 0 622 | self.Pagination.Max = self.Pagination.Total + 1 623 | self.Items[self:CurrentSelection()]:Selected(false) 624 | self.ActiveItem = 1000 - (1000 % #self.Items) 625 | self.Items[self:CurrentSelection()]:Selected(true) 626 | else 627 | self.Pagination.Max = self.Pagination.Max + 1 628 | self.Pagination.Min = self.Pagination.Max - (self.Pagination.Total + 1) 629 | self.Items[self:CurrentSelection()]:Selected(false) 630 | self.ActiveItem = self.ActiveItem + 1 631 | self.Items[self:CurrentSelection()]:Selected(true) 632 | end 633 | else 634 | self.Items[self:CurrentSelection()]:Selected(false) 635 | self.ActiveItem = self.ActiveItem + 1 636 | self.Items[self:CurrentSelection()]:Selected(true) 637 | end 638 | PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true) 639 | self.OnIndexChange(self, self:CurrentSelection()) 640 | self.ReDraw = true 641 | end 642 | 643 | function UIMenu:GoDown() 644 | if #self.Items > self.Pagination.Total + 1 then 645 | return 646 | end 647 | 648 | self.Items[self:CurrentSelection()]:Selected(false) 649 | self.ActiveItem = self.ActiveItem + 1 650 | self.Items[self:CurrentSelection()]:Selected(true) 651 | PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true) 652 | self.OnIndexChange(self, self:CurrentSelection()) 653 | self.ReDraw = true 654 | end 655 | 656 | function UIMenu:GoLeft() 657 | local type, subtype = self.Items[self:CurrentSelection()]() 658 | if subtype ~= "UIMenuListItem" and subtype ~= "UIMenuSliderItem" and subtype ~= "UIMenuProgressItem" then 659 | return 660 | end 661 | 662 | if not self.Items[self:CurrentSelection()]:Enabled() then 663 | PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) 664 | return 665 | end 666 | 667 | if subtype == "UIMenuListItem" then 668 | local Item = self.Items[self:CurrentSelection()] 669 | Item:Index(Item._Index - 1) 670 | self.OnListChange(self, Item, Item._Index) 671 | Item.OnListChanged(self, Item, Item._Index) 672 | PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) 673 | elseif subtype == "UIMenuSliderItem" then 674 | local Item = self.Items[self:CurrentSelection()] 675 | Item:Index(Item._Index - 1) 676 | self.OnSliderChange(self, Item, Item:Index()) 677 | Item.OnSliderChanged(self, Item, Item._Index) 678 | PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) 679 | elseif subtype == "UIMenuProgressItem" then 680 | local Item = self.Items[self:CurrentSelection()] 681 | Item:Index(Item.Data.Index - 1) 682 | self.OnProgressChange(self, Item, Item.Data.Index) 683 | Item.OnProgressChanged(self, Item, Item.Data.Index) 684 | PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) 685 | end 686 | end 687 | 688 | function UIMenu:GoRight() 689 | local type, subtype = self.Items[self:CurrentSelection()]() 690 | if subtype ~= "UIMenuListItem" and subtype ~= "UIMenuSliderItem" and subtype ~= "UIMenuProgressItem" then 691 | return 692 | end 693 | 694 | if not self.Items[self:CurrentSelection()]:Enabled() then 695 | PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) 696 | return 697 | end 698 | 699 | if subtype == "UIMenuListItem" then 700 | local Item = self.Items[self:CurrentSelection()] 701 | Item:Index(Item._Index + 1) 702 | self.OnListChange(self, Item, Item._Index) 703 | Item.OnListChanged(self, Item, Item._Index) 704 | PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) 705 | elseif subtype == "UIMenuSliderItem" then 706 | local Item = self.Items[self:CurrentSelection()] 707 | Item:Index(Item._Index + 1) 708 | self.OnSliderChange(self, Item, Item:Index()) 709 | Item.OnSliderChanged(self, Item, Item._Index) 710 | PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) 711 | elseif subtype == "UIMenuProgressItem" then 712 | local Item = self.Items[self:CurrentSelection()] 713 | Item:Index(Item.Data.Index + 1) 714 | self.OnProgressChange(self, Item, Item.Data.Index) 715 | Item.OnProgressChanged(self, Item, Item.Data.Index) 716 | PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true) 717 | end 718 | end 719 | 720 | function UIMenu:SelectItem() 721 | if not self.Items[self:CurrentSelection()]:Enabled() then 722 | PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) 723 | return 724 | end 725 | local Item = self.Items[self:CurrentSelection()] 726 | local type, subtype = Item() 727 | if subtype == "UIMenuCheckboxItem" then 728 | Item.Checked = not Item.Checked 729 | PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true) 730 | self.OnCheckboxChange(self, Item, Item.Checked) 731 | Item.CheckboxEvent(self, Item, Item.Checked) 732 | elseif subtype == "UIMenuListItem" then 733 | PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true) 734 | self.OnListSelect(self, Item, Item._Index) 735 | Item.OnListSelected(self, Item, Item._Index) 736 | elseif subtype == "UIMenuSliderItem" then 737 | PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true) 738 | self.OnSliderSelect(self, Item, Item._Index) 739 | Item.OnSliderSelected(Item._Index) 740 | elseif subtype == "UIMenuProgressItem" then 741 | PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true) 742 | self.OnProgressSelect(self, Item, Item.Data.Index) 743 | Item.OnProgressSelected(Item.Data.Index) 744 | else 745 | PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true) 746 | self.OnItemSelect(self, Item, self:CurrentSelection()) 747 | Item.Activated(self, Item) 748 | if not self.Children[Item] then 749 | return 750 | end 751 | self:Visible(false) 752 | self.Children[Item]:Visible(true) 753 | self.OnMenuChanged(self, self.Children[self.Items[self:CurrentSelection()]], true) 754 | end 755 | end 756 | 757 | function UIMenu:GoBack() 758 | PlaySoundFrontend(-1, self.Settings.Audio.Back, self.Settings.Audio.Library, true) 759 | self:Visible(false) 760 | if self.ParentMenu ~= nil then 761 | self.ParentMenu:Visible(true) 762 | self.OnMenuChanged(self, self.ParentMenu, false) 763 | if self.Settings.ResetCursorOnOpen then 764 | local W, H = GetActiveScreenResolution() 765 | SetCursorLocation(W / 2, H / 2) 766 | end 767 | end 768 | self.OnMenuClosed(self) 769 | end 770 | 771 | function UIMenu:BindMenuToItem(Menu, Item) 772 | if Menu() == "UIMenu" and Item() == "UIMenuItem" then 773 | Menu.ParentMenu = self 774 | Menu.ParentItem = Item 775 | self.Children[Item] = Menu 776 | end 777 | end 778 | 779 | function UIMenu:ReleaseMenuFromItem(Item) 780 | if Item() == "UIMenuItem" then 781 | if not self.Children[Item] then 782 | return false 783 | end 784 | self.Children[Item].ParentMenu = nil 785 | self.Children[Item].ParentItem = nil 786 | self.Children[Item] = nil 787 | return true 788 | end 789 | end 790 | 791 | function UIMenu:Draw() 792 | if not self._Visible then 793 | return 794 | end 795 | 796 | HideHudComponentThisFrame(19) 797 | 798 | if self.Settings.ControlDisablingEnabled then 799 | self:DisEnableControls(false) 800 | end 801 | 802 | if self.Settings.InstructionalButtons then 803 | DrawScaleformMovieFullscreen(self.InstructionalScaleform, 255, 255, 255, 255, 0) 804 | end 805 | 806 | if self.Settings.ScaleWithSafezone then 807 | ScreenDrawPositionBegin(76, 84) 808 | ScreenDrawPositionRatio(0, 0, 0, 0) 809 | end 810 | 811 | if self.ReDraw then 812 | self:DrawCalculations() 813 | end 814 | 815 | if self.Logo then 816 | self.Logo:Draw() 817 | elseif self.Banner then 818 | self.Banner:Draw() 819 | end 820 | 821 | self.Title:Draw() 822 | 823 | if self.Subtitle.Rectangle then 824 | self.Subtitle.Rectangle:Draw() 825 | self.Subtitle.Text:Draw() 826 | end 827 | 828 | if #self.Items ~= 0 or #self.Windows ~= 0 then 829 | self.Background:Draw() 830 | end 831 | 832 | if #self.Windows ~= 0 then 833 | local WindowOffset = 0 834 | for index = 1, #self.Windows do 835 | if self.Windows[index - 1] then 836 | WindowOffset = WindowOffset + self.Windows[index - 1].Background:Size().Height 837 | end 838 | local Window = self.Windows[index] 839 | Window:Position(WindowOffset + self.Subtitle.ExtraY - 37) 840 | Window:Draw() 841 | end 842 | end 843 | 844 | if #self.Items == 0 then 845 | if self.Settings.ScaleWithSafezone then 846 | ScreenDrawPositionEnd() 847 | end 848 | return 849 | end 850 | 851 | local CurrentSelection = self:CurrentSelection() 852 | self.Items[CurrentSelection]:Selected(true) 853 | 854 | if self.Items[CurrentSelection]:Description() ~= "" then 855 | self.Description.Bar:Draw() 856 | self.Description.Rectangle:Draw() 857 | self.Description.Text:Draw() 858 | end 859 | 860 | if self.Items[CurrentSelection].Panels ~= nil then 861 | if #self.Items[CurrentSelection].Panels ~= 0 then 862 | local PanelOffset = self:CaclulatePanelPosition(self.Items[CurrentSelection]:Description() ~= "") 863 | for index = 1, #self.Items[CurrentSelection].Panels do 864 | if self.Items[CurrentSelection].Panels[index - 1] then 865 | PanelOffset = PanelOffset + self.Items[CurrentSelection].Panels[index - 1].Background:Size().Height + 5 866 | end 867 | self.Items[CurrentSelection].Panels[index]:Position(PanelOffset) 868 | self.Items[CurrentSelection].Panels[index]:Draw() 869 | end 870 | end 871 | end 872 | 873 | local WindowHeight = self:CalculateWindowHeight() 874 | 875 | if #self.Items <= self.Pagination.Total + 1 then 876 | local ItemOffset = self.Subtitle.ExtraY - 37 + WindowHeight 877 | for index = 1, #self.Items do 878 | Item = self.Items[index] 879 | Item:Position(ItemOffset) 880 | Item:Draw() 881 | ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item) 882 | end 883 | else 884 | local ItemOffset = self.Subtitle.ExtraY - 37 + WindowHeight 885 | for index = self.Pagination.Min + 1, self.Pagination.Max, 1 do 886 | if self.Items[index] then 887 | Item = self.Items[index] 888 | Item:Position(ItemOffset) 889 | Item:Draw() 890 | ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item) 891 | end 892 | end 893 | 894 | self.Extra.Up:Draw() 895 | self.Extra.Down:Draw() 896 | self.ArrowSprite:Draw() 897 | 898 | if self.PageCounter.Text ~= nil then 899 | local Caption = self.PageCounter.PreText .. CurrentSelection .. " / " .. #self.Items 900 | self.PageCounter.Text:Text(Caption) 901 | self.PageCounter.Text:Draw() 902 | end 903 | end 904 | 905 | if self.Settings.ScaleWithSafezone then 906 | ScreenDrawPositionEnd() 907 | end 908 | end 909 | 910 | function UIMenu:ProcessMouse() 911 | if not self._Visible or self.JustOpened or #self.Items == 0 or tobool(Controller()) or not self.Settings.MouseControlsEnabled then 912 | EnableControlAction(0, 2, true) 913 | EnableControlAction(0, 1, true) 914 | EnableControlAction(0, 25, true) 915 | EnableControlAction(0, 24, true) 916 | if self.Dirty then 917 | for _, Item in pairs(self.Items) do 918 | if Item:Hovered() then 919 | Item:Hovered(false) 920 | end 921 | end 922 | end 923 | return 924 | end 925 | 926 | local SafeZone = {X = 0, Y = 0} 927 | local WindowHeight = self:CalculateWindowHeight() 928 | if self.Settings.ScaleWithSafezone then 929 | SafeZone = GetSafeZoneBounds() 930 | end 931 | 932 | local Limit = #self.Items 933 | local ItemOffset = 0 934 | 935 | ShowCursorThisFrame() 936 | 937 | if #self.Items > self.Pagination.Total + 1 then 938 | Limit = self.Pagination.Max 939 | end 940 | 941 | if IsMouseInBounds(0, 0, 30, 1080) and self.Settings.MouseEdgeEnabled then 942 | SetGameplayCamRelativeHeading(GetGameplayCamRelativeHeading() + 5) 943 | SetCursorSprite(6) 944 | elseif IsMouseInBounds(1920 - 30, 0, 30, 1080) and self.Settings.MouseEdgeEnabled then 945 | SetGameplayCamRelativeHeading(GetGameplayCamRelativeHeading() - 5) 946 | SetCursorSprite(7) 947 | elseif self.Settings.MouseEdgeEnabled then 948 | SetCursorSprite(1) 949 | end 950 | 951 | for i = self.Pagination.Min + 1, Limit, 1 do 952 | local X, Y = self.Position.X + SafeZone.X, self.Position.Y + 144 - 37 + self.Subtitle.ExtraY + ItemOffset + SafeZone.Y + WindowHeight 953 | local Item = self.Items[i] 954 | local Type, SubType = Item() 955 | local Width, Height = 431 + self.WidthOffset, self:CalculateItemHeightOffset(Item) 956 | 957 | if IsMouseInBounds(X, Y, Width, Height) then 958 | Item:Hovered(true) 959 | if not self.Controls.MousePressed then 960 | if IsDisabledControlJustPressed(0, 24) then 961 | Citizen.CreateThread(function() 962 | local _X, _Y, _Width, _Height = X, Y, Width, Height 963 | self.Controls.MousePressed = true 964 | if Item:Selected() and Item:Enabled() then 965 | if SubType == "UIMenuListItem" then 966 | if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then 967 | self:GoLeft() 968 | elseif not IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then 969 | self:SelectItem() 970 | end 971 | if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then 972 | self:GoRight() 973 | elseif not IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then 974 | self:SelectItem() 975 | end 976 | elseif SubType == "UIMenuSliderItem" then 977 | if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then 978 | self:GoLeft() 979 | elseif not IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then 980 | self:SelectItem() 981 | end 982 | if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then 983 | self:GoRight() 984 | elseif not IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then 985 | self:SelectItem() 986 | end 987 | elseif SubType == "UIMenuProgressItem" then 988 | if IsMouseInBounds(Item.Bar.X + SafeZone.X, Item.Bar.Y + SafeZone.Y - 12, Item.Data.Max, Item.Bar.Height + 24) then 989 | Item:CalculateProgress(math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) 990 | self.OnProgressChange(self, Item, Item.Data.Index) 991 | Item.OnProgressChanged(self, Item, Item.Data.Index) 992 | else 993 | self:SelectItem() 994 | end 995 | else 996 | self:SelectItem() 997 | end 998 | elseif not Item:Selected() then 999 | self:CurrentSelection(i-1) 1000 | PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) 1001 | self.OnIndexChange(self, self:CurrentSelection()) 1002 | self.ReDraw = true 1003 | self:UpdateScaleform() 1004 | elseif not Item:Enabled() and Item:Selected() then 1005 | PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) 1006 | end 1007 | Citizen.Wait(175) 1008 | while IsDisabledControlPressed(0, 24) and IsMouseInBounds(_X, _Y, _Width, _Height) do 1009 | if Item:Selected() and Item:Enabled() then 1010 | if SubType == "UIMenuListItem" then 1011 | if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then 1012 | self:GoLeft() 1013 | end 1014 | if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then 1015 | self:GoRight() 1016 | end 1017 | elseif SubType == "UIMenuSliderItem" then 1018 | if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then 1019 | self:GoLeft() 1020 | end 1021 | if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then 1022 | self:GoRight() 1023 | end 1024 | elseif SubType == "UIMenuProgressItem" then 1025 | if IsMouseInBounds(Item.Bar.X + SafeZone.X, Item.Bar.Y + SafeZone.Y - 12, Item.Data.Max, Item.Bar.Height + 24) then 1026 | Item:CalculateProgress(math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) 1027 | self.OnProgressChange(self, Item, Item.Data.Index) 1028 | Item.OnProgressChanged(self, Item, Item.Data.Index) 1029 | else 1030 | self:SelectItem() 1031 | end 1032 | end 1033 | elseif not Item:Selected() then 1034 | self:CurrentSelection(i-1) 1035 | PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) 1036 | self.OnIndexChange(self, self:CurrentSelection()) 1037 | self.ReDraw = true 1038 | self:UpdateScaleform() 1039 | elseif not Item:Enabled() and Item:Selected() then 1040 | PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) 1041 | end 1042 | Citizen.Wait(125) 1043 | end 1044 | self.Controls.MousePressed = false 1045 | end) 1046 | end 1047 | end 1048 | else 1049 | Item:Hovered(false) 1050 | end 1051 | ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item) 1052 | end 1053 | 1054 | local ExtraX, ExtraY = self.Position.X + SafeZone.X, 144 + self:CalculateItemHeight() + self.Position.Y + SafeZone.Y + WindowHeight 1055 | 1056 | if #self.Items <= self.Pagination.Total + 1 then return end 1057 | 1058 | if IsMouseInBounds(ExtraX, ExtraY, 431 + self.WidthOffset, 18) then 1059 | self.Extra.Up:Colour(30, 30, 30, 255) 1060 | if not self.Controls.MousePressed then 1061 | if IsDisabledControlJustPressed(0, 24) then 1062 | Citizen.CreateThread(function() 1063 | local _ExtraX, _ExtraY = ExtraX, ExtraY 1064 | self.Controls.MousePressed = true 1065 | if #self.Items > self.Pagination.Total + 1 then 1066 | self:GoUpOverflow() 1067 | else 1068 | self:GoUp() 1069 | end 1070 | Citizen.Wait(175) 1071 | while IsDisabledControlPressed(0, 24) and IsMouseInBounds(_ExtraX, _ExtraY, 431 + self.WidthOffset, 18) do 1072 | if #self.Items > self.Pagination.Total + 1 then 1073 | self:GoUpOverflow() 1074 | else 1075 | self:GoUp() 1076 | end 1077 | Citizen.Wait(125) 1078 | end 1079 | self.Controls.MousePressed = false 1080 | end) 1081 | end 1082 | end 1083 | else 1084 | self.Extra.Up:Colour(0, 0, 0, 200) 1085 | end 1086 | 1087 | if IsMouseInBounds(ExtraX, ExtraY + 18, 431 + self.WidthOffset, 18) then 1088 | self.Extra.Down:Colour(30, 30, 30, 255) 1089 | if not self.Controls.MousePressed then 1090 | if IsDisabledControlJustPressed(0, 24) then 1091 | Citizen.CreateThread(function() 1092 | local _ExtraX, _ExtraY = ExtraX, ExtraY 1093 | self.Controls.MousePressed = true 1094 | if #self.Items > self.Pagination.Total + 1 then 1095 | self:GoDownOverflow() 1096 | else 1097 | self:GoDown() 1098 | end 1099 | Citizen.Wait(175) 1100 | while IsDisabledControlPressed(0, 24) and IsMouseInBounds(_ExtraX, _ExtraY + 18, 431 + self.WidthOffset, 18) do 1101 | if #self.Items > self.Pagination.Total + 1 then 1102 | self:GoDownOverflow() 1103 | else 1104 | self:GoDown() 1105 | end 1106 | Citizen.Wait(125) 1107 | end 1108 | self.Controls.MousePressed = false 1109 | end) 1110 | end 1111 | end 1112 | else 1113 | self.Extra.Down:Colour(0, 0, 0, 200) 1114 | end 1115 | end 1116 | 1117 | function UIMenu:AddInstructionButton(button) 1118 | if type(button) == "table" and #button == 2 then 1119 | table.insert(self.InstructionalButtons, button) 1120 | end 1121 | end 1122 | 1123 | function UIMenu:RemoveInstructionButton(button) 1124 | if type(button) == "table" then 1125 | for i = 1, #self.InstructionalButtons do 1126 | if button == self.InstructionalButtons[i] then 1127 | table.remove(self.InstructionalButtons, i) 1128 | break 1129 | end 1130 | end 1131 | else 1132 | if tonumber(button) then 1133 | if self.InstructionalButtons[tonumber(button)] then 1134 | table.remove(self.InstructionalButtons, tonumber(button)) 1135 | end 1136 | end 1137 | end 1138 | end 1139 | 1140 | function UIMenu:AddEnabledControl(Inputgroup, Control, Controller) 1141 | if tonumber(Inputgroup) and tonumber(Control) then 1142 | table.insert(self.Settings.EnabledControls[(Controller and "Controller" or "Keyboard")], {Inputgroup, Control}) 1143 | end 1144 | end 1145 | 1146 | function UIMenu:RemoveEnabledControl(Inputgroup, Control, Controller) 1147 | local Type = (Controller and "Controller" or "Keyboard") 1148 | for Index = 1, #self.Settings.EnabledControls[Type] do 1149 | if Inputgroup == self.Settings.EnabledControls[Type][Index][1] and Control == self.Settings.EnabledControls[Type][Index][2] then 1150 | table.remove(self.Settings.EnabledControls[Type], Index) 1151 | break 1152 | end 1153 | end 1154 | end 1155 | 1156 | function UIMenu:UpdateScaleform() 1157 | if not self._Visible or not self.Settings.InstructionalButtons then 1158 | return 1159 | end 1160 | 1161 | PushScaleformMovieFunction(self.InstructionalScaleform, "CLEAR_ALL") 1162 | PopScaleformMovieFunction() 1163 | 1164 | PushScaleformMovieFunction(self.InstructionalScaleform, "TOGGLE_MOUSE_BUTTONS") 1165 | PushScaleformMovieFunctionParameterInt(0) 1166 | PopScaleformMovieFunction() 1167 | 1168 | PushScaleformMovieFunction(self.InstructionalScaleform, "CREATE_CONTAINER") 1169 | PopScaleformMovieFunction() 1170 | 1171 | PushScaleformMovieFunction(self.InstructionalScaleform, "SET_DATA_SLOT") 1172 | PushScaleformMovieFunctionParameterInt(0) 1173 | PushScaleformMovieFunctionParameterString(GetControlInstructionalButton(2, 176, 0)) 1174 | PushScaleformMovieFunctionParameterString("Select") 1175 | PopScaleformMovieFunction() 1176 | 1177 | if self.Controls.Back.Enabled then 1178 | PushScaleformMovieFunction(self.InstructionalScaleform, "SET_DATA_SLOT") 1179 | PushScaleformMovieFunctionParameterInt(1) 1180 | PushScaleformMovieFunctionParameterString(GetControlInstructionalButton(2, 177, 0)) 1181 | PushScaleformMovieFunctionParameterString("Back") 1182 | PopScaleformMovieFunction() 1183 | end 1184 | 1185 | local count = 2 1186 | 1187 | for i = 1, #self.InstructionalButtons do 1188 | if self.InstructionalButtons[i] then 1189 | if #self.InstructionalButtons[i] == 2 then 1190 | PushScaleformMovieFunction(self.InstructionalScaleform, "SET_DATA_SLOT") 1191 | PushScaleformMovieFunctionParameterInt(count) 1192 | PushScaleformMovieFunctionParameterString(self.InstructionalButtons[i][1]) 1193 | PushScaleformMovieFunctionParameterString(self.InstructionalButtons[i][2]) 1194 | PopScaleformMovieFunction() 1195 | count = count + 1 1196 | end 1197 | end 1198 | end 1199 | 1200 | PushScaleformMovieFunction(self.InstructionalScaleform, "DRAW_INSTRUCTIONAL_BUTTONS") 1201 | PushScaleformMovieFunctionParameterInt(-1) 1202 | PopScaleformMovieFunction() 1203 | end 1204 | -------------------------------------------------------------------------------- /NativeUI from Frazzle/Utils.lua: -------------------------------------------------------------------------------- 1 | function GetResolution() 2 | local W, H = GetActiveScreenResolution() 3 | if (W/H) > 3.5 then 4 | return GetScreenResolution() 5 | else 6 | return W, H 7 | end 8 | end 9 | 10 | function FormatXWYH(Value, Value2) 11 | return Value/1920, Value2/1080 12 | end 13 | 14 | function math.round(num, numDecimalPlaces) 15 | return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num)) 16 | end 17 | 18 | function tobool(input) 19 | if input == "true" or tonumber(input) == 1 or input == true then 20 | return true 21 | else 22 | return false 23 | end 24 | end 25 | 26 | function string.split(inputstr, sep) 27 | if sep == nil then 28 | sep = "%s" 29 | end 30 | local t={} ; i=1 31 | for str in string.gmatch(inputstr, "([^"..sep.."]+)") do 32 | t[i] = str 33 | i = i + 1 34 | end 35 | 36 | return t 37 | end 38 | 39 | function string.starts(String, Start) 40 | return string.sub(String, 1, string.len(Start)) == Start 41 | end 42 | 43 | function IsMouseInBounds(X, Y, Width, Height) 44 | local MX, MY = math.round(GetControlNormal(0, 239) * 1920), math.round(GetControlNormal(0, 240) * 1080) 45 | MX, MY = FormatXWYH(MX, MY) 46 | X, Y = FormatXWYH(X, Y) 47 | Width, Height = FormatXWYH(Width, Height) 48 | return (MX >= X and MX <= X + Width) and (MY > Y and MY < Y + Height) 49 | end 50 | 51 | function GetSafeZoneBounds() 52 | local SafeSize = GetSafeZoneSize() 53 | SafeSize = math.round(SafeSize, 2) 54 | SafeSize = (SafeSize * 100) - 90 55 | SafeSize = 10 - SafeSize 56 | 57 | local W, H = 1920, 1080 58 | 59 | return {X = math.round(SafeSize * ((W/H) * 5.4)), Y = math.round(SafeSize * 5.4)} 60 | end 61 | 62 | function Controller() 63 | return not IsInputDisabled(2) 64 | end 65 | 66 | --[[ 67 | 68 | function UIMenu:ProcessMouse() 69 | if not self._Visible or self.JustOpened or #self.Items == 0 or tobool(Controller()) or not self.Settings.MouseControlsEnabled then 70 | EnableControlAction(0, 2, true) 71 | EnableControlAction(0, 1, true) 72 | EnableControlAction(0, 25, true) 73 | EnableControlAction(0, 24, true) 74 | if self.Dirty then 75 | for _, Item in pairs(self.Items) do 76 | if Item:Hovered() then 77 | Item:Hovered(false) 78 | end 79 | end 80 | end 81 | return 82 | end 83 | 84 | local SafeZone = GetSafeZoneBounds() 85 | 86 | local Limit = #self.Items - 1 87 | local Counter = 0 88 | 89 | ShowCursorThisFrame() 90 | 91 | if #self.Items > self.Pagination.Total + 1 then 92 | Limit = self.Pagination.Max 93 | end 94 | 95 | if IsMouseInBounds(0, 0, 30, 1080) and self.Settings.MouseEdgeEnabled then 96 | SetGameplayCamRelativeHeading(GetGameplayCamRelativeHeading() + 5) 97 | SetCursorSprite(6) 98 | elseif IsMouseInBounds(GetScreenResolutionMaintainRatio().Width - 30, 0, 30, 1080) and self.Settings.MouseEdgeEnabled then 99 | SetGameplayCamRelativeHeading(GetGameplayCamRelativeHeading() - 5) 100 | SetCursorSprite(7) 101 | elseif self.Settings.MouseEdgeEnabled then 102 | SetCursorSprite(1) 103 | end 104 | 105 | for i = self.Pagination.Min + 1, Limit, 1 do 106 | local X, Y = self.Position.X, self.Position.Y + 144 - 37 + self.Subtitle.ExtraY + (Counter * 38) 107 | local Width, Height = 431 + self.WidthOffset, 38 108 | local Item = self.Items[i] 109 | local Type, SubType = Item() 110 | 111 | DrawRectangle(X, Y, Width, Height, 255, 0, 0, 150) 112 | if SubType == "UIMenuListItem" or SubType == "UIMenuSliderItem" then 113 | DrawRectangle(Item.LeftArrow.X, Item.LeftArrow.Y, Item.LeftArrow.Width, Item.LeftArrow.Height, 0, 255, 0, 150) 114 | DrawRectangle(Item.RightArrow.X, Item.RightArrow.Y, Item.RightArrow.Width, Item.RightArrow.Height, 0, 255, 0, 150) 115 | end 116 | 117 | if IsMouseInBounds(X, Y, Width, Height) then 118 | Item:Hovered(true) 119 | if IsDisabledControlJustPressed(0, 24) then 120 | if Item:Selected() and Item:Enabled() then 121 | if SubType == "UIMenuListItem" then 122 | if IsMouseInBounds(Item.LeftArrow.X, Item.LeftArrow.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then 123 | self:GoLeft() 124 | elseif not IsMouseInBounds(Item.RightArrow.X, Item.RightArrow.Y, Item.RightArrow.Width, Item.RightArrow.Height) then 125 | self:SelectItem() 126 | end 127 | if IsMouseInBounds(Item.RightArrow.X, Item.RightArrow.Y, Item.RightArrow.Width, Item.RightArrow.Height) then 128 | self:GoRight() 129 | elseif not IsMouseInBounds(Item.LeftArrow.X, Item.LeftArrow.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then 130 | self:SelectItem() 131 | end 132 | elseif SubType == "UIMenuSliderItem" then 133 | if IsMouseInBounds(Item.LeftArrow.X, Item.LeftArrow.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then 134 | self:GoLeft() 135 | elseif not IsMouseInBounds(Item.RightArrow.X, Item.RightArrow.Y, Item.RightArrow.Width, Item.RightArrow.Height) then 136 | self:SelectItem() 137 | end 138 | if IsMouseInBounds(Item.RightArrow.X, Item.RightArrow.Y, Item.RightArrow.Width, Item.RightArrow.Height) then 139 | self:GoRight() 140 | elseif not IsMouseInBounds(Item.LeftArrow.X, Item.LeftArrow.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then 141 | self:SelectItem() 142 | end 143 | else 144 | self:SelectItem() 145 | end 146 | elseif not Item:Selected() then 147 | self:CurrentSelection(i-1) 148 | PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) 149 | self.OnIndexChange(self, self:CurrentSelection()) 150 | self.ReDraw = true 151 | elseif not Item:Enabled() and Item:Selected() then 152 | PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true) 153 | end 154 | end 155 | else 156 | Item:Hovered(false) 157 | end 158 | Counter = Counter + 1 159 | end 160 | 161 | local ExtraX, ExtraY = self.Position.X, 144 + 38 * (self.Pagination.Total + 1) + self.Position.Y - 37 + self.Subtitle.ExtraY 162 | 163 | if #self.Items <= self.Pagination.Total + 1 then return end 164 | 165 | if IsMouseInBounds(ExtraX, ExtraY, 431 + self.WidthOffset, 18) then 166 | self.Extra.Up:Colour(30, 30, 30, 255) 167 | if IsDisabledControlJustPressed(0, 24) then 168 | if #self.Items > self.Pagination.Total + 1 then 169 | self:GoUpOverflow() 170 | else 171 | self:GoUp() 172 | end 173 | end 174 | else 175 | self.Extra.Up:Colour(0, 0, 0, 200) 176 | end 177 | 178 | if IsMouseInBounds(ExtraX, ExtraY + 18, 431 + self.WidthOffset, 18) then 179 | self.Extra.Down:Colour(30, 30, 30, 255) 180 | if IsDisabledControlJustReleased(0, 24) then 181 | if #self.Items > self.Pagination.Total + 1 then 182 | self:GoDownOverflow() 183 | else 184 | self:GoDown() 185 | end 186 | end 187 | else 188 | self.Extra.Down:Colour(0, 0, 0, 200) 189 | end 190 | end 191 | --]] -------------------------------------------------------------------------------- /NativeUI from Frazzle/__resource.lua: -------------------------------------------------------------------------------- 1 | resource_manifest_version '05cfa83c-a124-4cfa-a768-c24a5811d8f9' 2 | 3 | --[[ 4 | --All items unpacked 5 | 6 | client_scripts { 7 | "Utils.lua", 8 | "elements/UIResRectangle.lua", 9 | "elements/UIResText.lua", 10 | "elements/Sprite.lua", 11 | "elements/StringMeasurer.lua", 12 | "elements/Badge.lua", 13 | "elements/Colours.lua", 14 | "items/UIMenuItem.lua", 15 | "items/UIMenuCheckboxItem.lua", 16 | "items/UIMenuListItem.lua", 17 | "items/UIMenuSliderItem.lua", 18 | "items/UIMenuColouredItem.lua", 19 | "items/UIMenuprogressItem.lua", 20 | "windows/UIMenuHeritageWindow.lua", 21 | "panels/UIMenuGridPanel.lua", 22 | "panels/UIMenuColourPanel.lua", 23 | "panels/UIMenuPercentagePanel.lua", 24 | "UIMenu.lua", 25 | "MenuPool.lua", 26 | "MenuExample.lua", 27 | } 28 | 29 | --All items packed 30 | --]] 31 | 32 | client_script "NativeUI.lua" -------------------------------------------------------------------------------- /NativeUI from Frazzle/elements/Badge.lua: -------------------------------------------------------------------------------- 1 | BadgeStyle = { 2 | None = 0, 3 | BronzeMedal = 1, 4 | GoldMedal = 2, 5 | SilverMedal = 3, 6 | Alert = 4, 7 | Crown = 5, 8 | Ammo = 6, 9 | Armour = 7, 10 | Barber = 8, 11 | Clothes = 9, 12 | Franklin = 10, 13 | Bike = 11, 14 | Car = 12, 15 | Gun = 13, 16 | Heart = 14, 17 | Makeup = 15, 18 | Mask = 16, 19 | Michael = 17, 20 | Star = 18, 21 | Tattoo = 19, 22 | Trevor = 20, 23 | Lock = 21, 24 | Tick = 22 25 | } 26 | 27 | BadgeTexture = { 28 | [0] = function() 29 | return "" 30 | end, 31 | [1] = function() 32 | return "mp_medal_bronze" 33 | end, 34 | [2] = function() 35 | return "mp_medal_gold" 36 | end, 37 | [3] = function() 38 | return "medal_silver" 39 | end, 40 | [4] = function() 41 | return "mp_alerttriangle" 42 | end, 43 | [5] = function() 44 | return "mp_hostcrown" 45 | end, 46 | [6] = function(Selected) 47 | if Selected then 48 | return "shop_ammo_icon_b" 49 | else 50 | return "shop_ammo_icon_a" 51 | end 52 | end, 53 | [7] = function(Selected) 54 | if Selected then 55 | return "shop_armour_icon_b" 56 | else 57 | return "shop_armour_icon_a" 58 | end 59 | end, 60 | [8] = function(Selected) 61 | if Selected then 62 | return "shop_barber_icon_b" 63 | else 64 | return "shop_barber_icon_a" 65 | end 66 | end, 67 | [9] = function(Selected) 68 | if Selected then 69 | return "shop_clothing_icon_b" 70 | else 71 | return "shop_clothing_icon_a" 72 | end 73 | end, 74 | [10] = function(Selected) 75 | if Selected then 76 | return "shop_franklin_icon_b" 77 | else 78 | return "shop_franklin_icon_a" 79 | end 80 | end, 81 | [11] = function(Selected) 82 | if Selected then 83 | return "shop_garage_bike_icon_b" 84 | else 85 | return "shop_garage_bike_icon_a" 86 | end 87 | end, 88 | [12] = function(Selected) 89 | if Selected then 90 | return "shop_garage_icon_b" 91 | else 92 | return "shop_garage_icon_a" 93 | end 94 | end, 95 | [13] = function(Selected) 96 | if Selected then 97 | return "shop_gunclub_icon_b" 98 | else 99 | return "shop_gunclub_icon_a" 100 | end 101 | end, 102 | [14] = function(Selected) 103 | if Selected then 104 | return "shop_health_icon_b" 105 | else 106 | return "shop_health_icon_a" 107 | end 108 | end, 109 | [15] = function(Selected) 110 | if Selected then 111 | return "shop_makeup_icon_b" 112 | else 113 | return "shop_makeup_icon_a" 114 | end 115 | end, 116 | [16] = function(Selected) 117 | if Selected then 118 | return "shop_mask_icon_b" 119 | else 120 | return "shop_mask_icon_a" 121 | end 122 | end, 123 | [17] = function(Selected) 124 | if Selected then 125 | return "shop_michael_icon_b" 126 | else 127 | return "shop_michael_icon_a" 128 | end 129 | end, 130 | [18] = function() 131 | return "shop_new_star" 132 | end, 133 | [19] = function(Selected) 134 | if Selected then 135 | return "shop_tattoos_icon_b" 136 | else 137 | return "shop_tattoos_icon_a" 138 | end 139 | end, 140 | [20] = function(Selected) 141 | if Selected then 142 | return "shop_trevor_icon_b" 143 | else 144 | return "shop_trevor_icon_a" 145 | end 146 | end, 147 | [21] = function() 148 | return "shop_lock" 149 | end, 150 | [22] = function() 151 | return "shop_tick_icon" 152 | end, 153 | } 154 | 155 | BadgeDictionary = { 156 | [0] = function(Selected) 157 | if Selected then 158 | return "commonmenu" 159 | else 160 | return "commonmenu" 161 | end 162 | end, 163 | } 164 | 165 | BadgeColour = { 166 | [5] = function(Selected) 167 | if Selected then 168 | return 0, 0, 0, 255 169 | else 170 | return 255, 255, 255, 255 171 | end 172 | end, 173 | [21] = function(Selected) 174 | if Selected then 175 | return 0, 0, 0, 255 176 | else 177 | return 255, 255, 255, 255 178 | end 179 | end, 180 | [22] = function(Selected) 181 | if Selected then 182 | return 0, 0, 0, 255 183 | else 184 | return 255, 255, 255, 255 185 | end 186 | end, 187 | } 188 | 189 | function GetBadgeTexture(Badge, Selected) 190 | if BadgeTexture[Badge] then 191 | return BadgeTexture[Badge](Selected) 192 | else 193 | return "" 194 | end 195 | end 196 | 197 | function GetBadgeDictionary(Badge, Selected) 198 | if BadgeDictionary[Badge] then 199 | return BadgeDictionary[Badge](Selected) 200 | else 201 | return "commonmenu" 202 | end 203 | end 204 | 205 | function GetBadgeColour(Badge, Selected) 206 | if BadgeColour[Badge] then 207 | return BadgeColour[Badge](Selected) 208 | else 209 | return 255, 255, 255, 255 210 | end 211 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/elements/Colours.lua: -------------------------------------------------------------------------------- 1 | Colours = { 2 | PureWhite = {255, 255, 255, 255}, 3 | White = {240, 240, 240, 255}, 4 | Black = {0, 0, 0, 255}, 5 | Grey = {155, 155, 155, 255}, 6 | GreyLight = {205, 205, 205, 255}, 7 | GreyDark = {77, 77, 77, 255}, 8 | Red = {224, 50, 50, 255}, 9 | RedLight = {240, 153, 153, 255}, 10 | RedDark = {112, 25, 25, 255}, 11 | Blue = {93, 182, 229, 255}, 12 | BlueLight = {174, 219, 242, 255}, 13 | BlueDark = {47, 92, 115, 255}, 14 | Yellow = {240, 200, 80, 255}, 15 | YellowLight = {254, 235, 169, 255}, 16 | YellowDark = {126, 107, 41, 255}, 17 | Orange = {255, 133, 85, 255}, 18 | OrangeLight = {255, 194, 170, 255}, 19 | OrangeDark = {127, 66, 42, 255}, 20 | Green = {114, 204, 114, 255}, 21 | GreenLight = {185, 230, 185, 255}, 22 | GreenDark = {57, 102, 57, 255}, 23 | Purple = {132, 102, 226, 255}, 24 | PurpleLight = {192, 179, 239, 255}, 25 | PurpleDark = {67, 57, 111, 255}, 26 | Pink = {203, 54, 148, 255}, 27 | RadarHealth = {53, 154, 71, 255}, 28 | RadarArmour = {93, 182, 229, 255}, 29 | RadarDamage = {235, 36, 39, 255}, 30 | NetPlayer1 = {194, 80, 80, 255}, 31 | NetPlayer2 = {156, 110, 175, 255}, 32 | NetPlayer3 = {255, 123, 196, 255}, 33 | NetPlayer4 = {247, 159, 123, 255}, 34 | NetPlayer5 = {178, 144, 132, 255}, 35 | NetPlayer6 = {141, 206, 167, 255}, 36 | NetPlayer7 = {113, 169, 175, 255}, 37 | NetPlayer8 = {211, 209, 231, 255}, 38 | NetPlayer9 = {144, 127, 153, 255}, 39 | NetPlayer10 = {106, 196, 191, 255}, 40 | NetPlayer11 = {214, 196, 153, 255}, 41 | NetPlayer12 = {234, 142, 80, 255}, 42 | NetPlayer13 = {152, 203, 234, 255}, 43 | NetPlayer14 = {178, 98, 135, 255}, 44 | NetPlayer15 = {144, 142, 122, 255}, 45 | NetPlayer16 = {166, 117, 94, 255}, 46 | NetPlayer17 = {175, 168, 168, 255}, 47 | NetPlayer18 = {232, 142, 155, 255}, 48 | NetPlayer19 = {187, 214, 91, 255}, 49 | NetPlayer20 = {12, 123, 86, 255}, 50 | NetPlayer21 = {123, 196, 255, 255}, 51 | NetPlayer22 = {171, 60, 230, 255}, 52 | NetPlayer23 = {206, 169, 13, 255}, 53 | NetPlayer24 = {71, 99, 173, 255}, 54 | NetPlayer25 = {42, 166, 185, 255}, 55 | NetPlayer26 = {186, 157, 125, 255}, 56 | NetPlayer27 = {201, 225, 255, 255}, 57 | NetPlayer28 = {240, 240, 150, 255}, 58 | NetPlayer29 = {237, 140, 161, 255}, 59 | NetPlayer30 = {249, 138, 138, 255}, 60 | NetPlayer31 = {252, 239, 166, 255}, 61 | NetPlayer32 = {240, 240, 240, 255}, 62 | SimpleBlipDefault = {159, 201, 166, 255}, 63 | MenuBlue = {140, 140, 140, 255}, 64 | MenuGreyLight = {140, 140, 140, 255}, 65 | MenuBlueExtraDark = {40, 40, 40, 255}, 66 | MenuYellow = {240, 160, 0, 255}, 67 | MenuYellowDark = {240, 160, 0, 255}, 68 | MenuGreen = {240, 160, 0, 255}, 69 | MenuGrey = {140, 140, 140, 255}, 70 | MenuGreyDark = {60, 60, 60, 255}, 71 | MenuHighlight = {30, 30, 30, 255}, 72 | MenuStandard = {140, 140, 140, 255}, 73 | MenuDimmed = {75, 75, 75, 255}, 74 | MenuExtraDimmed = {50, 50, 50, 255}, 75 | BriefTitle = {95, 95, 95, 255}, 76 | MidGreyMp = {100, 100, 100, 255}, 77 | NetPlayer1Dark = {93, 39, 39, 255}, 78 | NetPlayer2Dark = {77, 55, 89, 255}, 79 | NetPlayer3Dark = {124, 62, 99, 255}, 80 | NetPlayer4Dark = {120, 80, 80, 255}, 81 | NetPlayer5Dark = {87, 72, 66, 255}, 82 | NetPlayer6Dark = {74, 103, 83, 255}, 83 | NetPlayer7Dark = {60, 85, 88, 255}, 84 | NetPlayer8Dark = {105, 105, 64, 255}, 85 | NetPlayer9Dark = {72, 63, 76, 255}, 86 | NetPlayer10Dark = {53, 98, 95, 255}, 87 | NetPlayer11Dark = {107, 98, 76, 255}, 88 | NetPlayer12Dark = {117, 71, 40, 255}, 89 | NetPlayer13Dark = {76, 101, 117, 255}, 90 | NetPlayer14Dark = {65, 35, 47, 255}, 91 | NetPlayer15Dark = {72, 71, 61, 255}, 92 | NetPlayer16Dark = {85, 58, 47, 255}, 93 | NetPlayer17Dark = {87, 84, 84, 255}, 94 | NetPlayer18Dark = {116, 71, 77, 255}, 95 | NetPlayer19Dark = {93, 107, 45, 255}, 96 | NetPlayer20Dark = {6, 61, 43, 255}, 97 | NetPlayer21Dark = {61, 98, 127, 255}, 98 | NetPlayer22Dark = {85, 30, 115, 255}, 99 | NetPlayer23Dark = {103, 84, 6, 255}, 100 | NetPlayer24Dark = {35, 49, 86, 255}, 101 | NetPlayer25Dark = {21, 83, 92, 255}, 102 | NetPlayer26Dark = {93, 98, 62, 255}, 103 | NetPlayer27Dark = {100, 112, 127, 255}, 104 | NetPlayer28Dark = {120, 120, 75, 255}, 105 | NetPlayer29Dark = {152, 76, 93, 255}, 106 | NetPlayer30Dark = {124, 69, 69, 255}, 107 | NetPlayer31Dark = {10, 43, 50, 255}, 108 | NetPlayer32Dark = {95, 95, 10, 255}, 109 | Bronze = {180, 130, 97, 255}, 110 | Silver = {150, 153, 161, 255}, 111 | Gold = {214, 181, 99, 255}, 112 | Platinum = {166, 221, 190, 255}, 113 | Gang1 = {29, 100, 153, 255}, 114 | Gang2 = {214, 116, 15, 255}, 115 | Gang3 = {135, 125, 142, 255}, 116 | Gang4 = {229, 119, 185, 255}, 117 | SameCrew = {252, 239, 166, 255}, 118 | Freemode = {45, 110, 185, 255}, 119 | PauseBg = {0, 0, 0, 255}, 120 | Friendly = {93, 182, 229, 255}, 121 | Enemy = {194, 80, 80, 255}, 122 | Location = {240, 200, 80, 255}, 123 | Pickup = {114, 204, 114, 255}, 124 | PauseSingleplayer = {114, 204, 114, 255}, 125 | FreemodeDark = {22, 55, 92, 255}, 126 | InactiveMission = {154, 154, 154, 255}, 127 | Damage = {194, 80, 80, 255}, 128 | PinkLight = {252, 115, 201, 255}, 129 | PmMitemHighlight = {252, 177, 49, 255}, 130 | ScriptVariable = {0, 0, 0, 255}, 131 | Yoga = {109, 247, 204, 255}, 132 | Tennis = {241, 101, 34, 255}, 133 | Golf = {214, 189, 97, 255}, 134 | ShootingRange = {112, 25, 25, 255}, 135 | FlightSchool = {47, 92, 115, 255}, 136 | NorthBlue = {93, 182, 229, 255}, 137 | SocialClub = {234, 153, 28, 255}, 138 | PlatformBlue = {11, 55, 123, 255}, 139 | PlatformGreen = {146, 200, 62, 255}, 140 | PlatformGrey = {234, 153, 28, 255}, 141 | FacebookBlue = {66, 89, 148, 255}, 142 | IngameBg = {0, 0, 0, 255}, 143 | Darts = {114, 204, 114, 255}, 144 | Waypoint = {164, 76, 242, 255}, 145 | Michael = {101, 180, 212, 255}, 146 | Franklin = {171, 237, 171, 255}, 147 | Trevor = {255, 163, 87, 255}, 148 | GolfP1 = {240, 240, 240, 255}, 149 | GolfP2 = {235, 239, 30, 255}, 150 | GolfP3 = {255, 149, 14, 255}, 151 | GolfP4 = {246, 60, 161, 255}, 152 | WaypointLight = {210, 166, 249, 255}, 153 | WaypointDark = {82, 38, 121, 255}, 154 | PanelLight = {0, 0, 0, 255}, 155 | MichaelDark = {72, 103, 116, 255}, 156 | FranklinDark = {85, 118, 85, 255}, 157 | TrevorDark = {127, 81, 43, 255}, 158 | ObjectiveRoute = {240, 200, 80, 255}, 159 | PausemapTint = {0, 0, 0, 255}, 160 | PauseDeselect = {100, 100, 100, 255}, 161 | PmWeaponsPurchasable = {45, 110, 185, 255}, 162 | PmWeaponsLocked = {240, 240, 240, 255}, 163 | ScreenBg = {0, 0, 0, 255}, 164 | Chop = {224, 50, 50, 255}, 165 | PausemapTintHalf = {0, 0, 0, 255}, 166 | NorthBlueOfficial = {0, 71, 133, 255}, 167 | ScriptVariable2 = {0, 0, 0, 255}, 168 | H = {33, 118, 37, 255}, 169 | HDark = {37, 102, 40, 255}, 170 | T = {234, 153, 28, 255}, 171 | TDark = {225, 140, 8, 255}, 172 | HShard = {20, 40, 0, 255}, 173 | ControllerMichael = {48, 255, 255, 255}, 174 | ControllerFranklin = {48, 255, 0, 255}, 175 | ControllerTrevor = {176, 80, 0, 255}, 176 | ControllerChop = {127, 0, 0, 255}, 177 | VideoEditorVideo = {53, 166, 224, 255}, 178 | VideoEditorAudio = {162, 79, 157, 255}, 179 | VideoEditorText = {104, 192, 141, 255}, 180 | HbBlue = {29, 100, 153, 255}, 181 | HbYellow = {234, 153, 28, 255}, 182 | VideoEditorScore = {240, 160, 1, 255}, 183 | VideoEditorAudioFadeout = {59, 34, 57, 255}, 184 | VideoEditorTextFadeout = {41, 68, 53, 255}, 185 | VideoEditorScoreFadeout = {82, 58, 10, 255}, 186 | HeistBackground = {37, 102, 40, 255}, 187 | VideoEditorAmbient = {240, 200, 80, 255}, 188 | VideoEditorAmbientFadeout = {80, 70, 34, 255}, 189 | Gb = {255, 133, 85, 255}, 190 | G = {255, 194, 170, 255}, 191 | B = {255, 133, 85, 255}, 192 | LowFlow = {240, 200, 80, 255}, 193 | LowFlowDark = {126, 107, 41, 255}, 194 | G1 = {247, 159, 123, 255}, 195 | G2 = {226, 134, 187, 255}, 196 | G3 = {239, 238, 151, 255}, 197 | G4 = {113, 169, 175, 255}, 198 | G5 = {160, 140, 193, 255}, 199 | G6 = {141, 206, 167, 255}, 200 | G7 = {181, 214, 234, 255}, 201 | G8 = {178, 144, 132, 255}, 202 | G9 = {0, 132, 114, 255}, 203 | G10 = {216, 85, 117, 255}, 204 | G11 = {30, 100, 152, 255}, 205 | G12 = {43, 181, 117, 255}, 206 | G13 = {233, 141, 79, 255}, 207 | G14 = {137, 210, 215, 255}, 208 | G15 = {134, 125, 141, 255}, 209 | Adversary = {109, 34, 33, 255}, 210 | DegenRed = {255, 0, 0, 255}, 211 | DegenYellow = {255, 255, 0, 255}, 212 | DegenGreen = {0, 255, 0, 255}, 213 | DegenCyan = {0, 255, 255, 255}, 214 | DegenBlue = {0, 0, 255, 255}, 215 | DegenMagenta = {255, 0, 255, 255}, 216 | Stunt1 = {38, 136, 234, 255}, 217 | Stunt2 = {224, 50, 50, 255}, 218 | } -------------------------------------------------------------------------------- /NativeUI from Frazzle/elements/Sprite.lua: -------------------------------------------------------------------------------- 1 | Sprite = setmetatable({}, Sprite) 2 | Sprite.__index = Sprite 3 | Sprite.__call = function() return "Sprite" end 4 | 5 | function Sprite.New(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A) 6 | local _Sprite = { 7 | TxtDictionary = tostring(TxtDictionary), 8 | TxtName = tostring(TxtName), 9 | X = tonumber(X) or 0, 10 | Y = tonumber(Y) or 0, 11 | Width = tonumber(Width) or 0, 12 | Height = tonumber(Height) or 0, 13 | Heading = tonumber(Heading) or 0, 14 | _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255}, 15 | } 16 | return setmetatable(_Sprite, Sprite) 17 | end 18 | 19 | function Sprite:Position(X, Y) 20 | if tonumber(X) and tonumber(Y) then 21 | self.X = tonumber(X) 22 | self.Y = tonumber(Y) 23 | else 24 | return {X = self.X, Y = self.Y} 25 | end 26 | end 27 | 28 | function Sprite:Size(Width, Height) 29 | if tonumber(Width) and tonumber(Width) then 30 | self.Width = tonumber(Width) 31 | self.Height = tonumber(Height) 32 | else 33 | return {Width = self.Width, Height = self.Height} 34 | end 35 | end 36 | 37 | function Sprite:Colour(R, G, B, A) 38 | if tonumber(R) or tonumber(G) or tonumber(B) or tonumber(A) then 39 | self._Colour.R = tonumber(R) or 255 40 | self._Colour.B = tonumber(B) or 255 41 | self._Colour.G = tonumber(G) or 255 42 | self._Colour.A = tonumber(A) or 255 43 | else 44 | return self._Colour 45 | end 46 | end 47 | 48 | function Sprite:Draw() 49 | if not HasStreamedTextureDictLoaded(self.TxtDictionary) then 50 | RequestStreamedTextureDict(self.TxtDictionary, true) 51 | end 52 | local Position = self:Position() 53 | local Size = self:Size() 54 | Size.Width, Size.Height = FormatXWYH(Size.Width, Size.Height) 55 | Position.X, Position.Y = FormatXWYH(Position.X, Position.Y) 56 | DrawSprite(self.TxtDictionary, self.TxtName, Position.X + Size.Width * 0.5, Position.Y + Size.Height * 0.5, Size.Width, Size.Height, self.Heading, self._Colour.R, self._Colour.G, self._Colour.B, self._Colour.A) 57 | end 58 | 59 | function DrawTexture(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A) 60 | if not HasStreamedTextureDictLoaded(tostring(TxtDictionary) or "") then 61 | RequestStreamedTextureDict(tostring(TxtDictionary) or "", true) 62 | end 63 | X, Y, Width, Height = X or 0, Y or 0, Width or 0, Height or 0 64 | X, Y = FormatXWYH(X, Y) 65 | Width, Height = FormatXWYH(Width, Height) 66 | DrawSprite(tostring(TxtDictionary) or "", tostring(TxtName) or "", X + Width * 0.5, Y + Height * 0.5, Width, Height, tonumber(Heading) or 0, tonumber(R) or 255, tonumber(G) or 255, tonumber(B) or 255, tonumber(A) or 255) 67 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/elements/StringMeasurer.lua: -------------------------------------------------------------------------------- 1 | CharacterMap = { 2 | [' '] = 6, 3 | ['!'] = 6, 4 | ['"'] = 6, 5 | ['#'] = 11, 6 | ['$'] = 10, 7 | ['%'] = 17, 8 | ['&'] = 13, 9 | ['\\'] = 4, 10 | ['('] = 6, 11 | [')'] = 6, 12 | ['*'] = 7, 13 | ['+'] = 10, 14 | [','] = 4, 15 | ['-'] = 6, 16 | ['.'] = 4, 17 | ['/'] = 7, 18 | ['0'] = 12, 19 | ['1'] = 7, 20 | ['2'] = 11, 21 | ['3'] = 11, 22 | ['4'] = 11, 23 | ['5'] = 11, 24 | ['6'] = 12, 25 | ['7'] = 10, 26 | ['8'] = 11, 27 | ['9'] = 11, 28 | [':'] = 5, 29 | [';'] = 4, 30 | ['<'] = 9, 31 | ['='] = 9, 32 | ['>'] = 9, 33 | ['?'] = 10, 34 | ['@'] = 15, 35 | ['A'] = 12, 36 | ['B'] = 13, 37 | ['C'] = 14, 38 | ['D'] = 14, 39 | ['E'] = 12, 40 | ['F'] = 12, 41 | ['G'] = 15, 42 | ['H'] = 14, 43 | ['I'] = 5, 44 | ['J'] = 11, 45 | ['K'] = 13, 46 | ['L'] = 11, 47 | ['M'] = 16, 48 | ['N'] = 14, 49 | ['O'] = 16, 50 | ['P'] = 12, 51 | ['Q'] = 15, 52 | ['R'] = 13, 53 | ['S'] = 12, 54 | ['T'] = 11, 55 | ['U'] = 13, 56 | ['V'] = 12, 57 | ['W'] = 18, 58 | ['X'] = 11, 59 | ['Y'] = 11, 60 | ['Z'] = 12, 61 | ['['] = 6, 62 | [']'] = 6, 63 | ['^'] = 9, 64 | ['_'] = 18, 65 | ['`'] = 8, 66 | ['a'] = 11, 67 | ['b'] = 12, 68 | ['c'] = 11, 69 | ['d'] = 12, 70 | ['e'] = 12, 71 | ['f'] = 5, 72 | ['g'] = 13, 73 | ['h'] = 11, 74 | ['i'] = 4, 75 | ['j'] = 4, 76 | ['k'] = 10, 77 | ['l'] = 4, 78 | ['m'] = 18, 79 | ['n'] = 11, 80 | ['o'] = 12, 81 | ['p'] = 12, 82 | ['q'] = 12, 83 | ['r'] = 7, 84 | ['s'] = 9, 85 | ['t'] = 5, 86 | ['u'] = 11, 87 | ['v'] = 10, 88 | ['w'] = 14, 89 | ['x'] = 9, 90 | ['y'] = 10, 91 | ['z'] = 9, 92 | ['{'] = 6, 93 | ['|'] = 3, 94 | ['}'] = 6, 95 | } 96 | 97 | function MeasureString(str) 98 | local output = 0 99 | for i = 1, GetCharacterCount(str), 1 do 100 | if CharacterMap[string.sub(str, i, i)] then 101 | output = output + CharacterMap[string.sub(str, i, i)] + 1 102 | end 103 | end 104 | return output 105 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/elements/UIResRectangle.lua: -------------------------------------------------------------------------------- 1 | UIResRectangle = setmetatable({}, UIResRectangle) 2 | UIResRectangle.__index = UIResRectangle 3 | UIResRectangle.__call = function() return "Rectangle" end 4 | 5 | function UIResRectangle.New(X, Y, Width, Height, R, G, B, A) 6 | local _UIResRectangle = { 7 | X = tonumber(X) or 0, 8 | Y = tonumber(Y) or 0, 9 | Width = tonumber(Width) or 0, 10 | Height = tonumber(Height) or 0, 11 | _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255}, 12 | } 13 | return setmetatable(_UIResRectangle, UIResRectangle) 14 | end 15 | 16 | function UIResRectangle:Position(X, Y) 17 | if tonumber(X) and tonumber(Y) then 18 | self.X = tonumber(X) 19 | self.Y = tonumber(Y) 20 | else 21 | return {X = self.X, Y = self.Y} 22 | end 23 | end 24 | 25 | function UIResRectangle:Size(Width, Height) 26 | if tonumber(Width) and tonumber(Height) then 27 | self.Width = tonumber(Width) 28 | self.Height = tonumber(Height) 29 | else 30 | return {Width = self.Width, Height = self.Height} 31 | end 32 | end 33 | 34 | function UIResRectangle:Colour(R, G, B, A) 35 | if tonumber(R) or tonumber(G) or tonumber(B) or tonumber(A) then 36 | self._Colour.R = tonumber(R) or 255 37 | self._Colour.B = tonumber(B) or 255 38 | self._Colour.G = tonumber(G) or 255 39 | self._Colour.A = tonumber(A) or 255 40 | else 41 | return self._Colour 42 | end 43 | end 44 | 45 | function UIResRectangle:Draw() 46 | local Position = self:Position() 47 | local Size = self:Size() 48 | Size.Width, Size.Height = FormatXWYH(Size.Width, Size.Height) 49 | Position.X, Position.Y = FormatXWYH(Position.X, Position.Y) 50 | DrawRect(Position.X + Size.Width * 0.5, Position.Y + Size.Height * 0.5, Size.Width, Size.Height, self._Colour.R, self._Colour.G, self._Colour.B, self._Colour.A) 51 | end 52 | 53 | function DrawRectangle(X, Y, Width, Height, R, G, B, A) 54 | X, Y, Width, Height = X or 0, Y or 0, Width or 0, Height or 0 55 | X, Y = FormatXWYH(X, Y) 56 | Width, Height = FormatXWYH(Width, Height) 57 | DrawRect(X + Width * 0.5, Y + Height * 0.5, Width, Height, tonumber(R) or 255, tonumber(G) or 255, tonumber(B) or 255, tonumber(A) or 255) 58 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/elements/UIResText.lua: -------------------------------------------------------------------------------- 1 | UIResText = setmetatable({}, UIResText) 2 | UIResText.__index = UIResText 3 | UIResText.__call = function() return "Text" end 4 | 5 | function GetCharacterCount(str) 6 | local characters = 0 7 | for c in str:gmatch("[%z\1-\127\194-\244][\128-\191]*") do 8 | local a = c:byte(1, -1) 9 | if a ~= nil then 10 | characters = characters + 1 11 | end 12 | end 13 | return characters 14 | end 15 | 16 | function GetByteCount(str) 17 | local bytes = 0 18 | 19 | for c in str:gmatch("[%z\1-\127\194-\244][\128-\191]*") do 20 | local a,b,c,d = c:byte(1, -1) 21 | if a ~= nil then 22 | bytes = bytes + 1 23 | end 24 | if b ~= nil then 25 | bytes = bytes + 1 26 | end 27 | if c ~= nil then 28 | bytes = bytes + 1 29 | end 30 | if d ~= nil then 31 | bytes = bytes + 1 32 | end 33 | end 34 | return bytes 35 | end 36 | 37 | function AddLongStringForAscii(str) 38 | local maxbytelength = 99 39 | for i = 0, GetCharacterCount(str), 99 do 40 | AddTextComponentSubstringPlayerName(string.sub(str, i, math.min(maxbytelength, GetCharacterCount(str) - i))) --needs changed 41 | end 42 | end 43 | 44 | function AddLongStringForUtf8(str) 45 | local maxbytelength = 99 46 | local bytecount = GetByteCount(str) 47 | 48 | if bytecount < maxbytelength then 49 | AddTextComponentSubstringPlayerName(str) 50 | return 51 | end 52 | 53 | local startIndex = 0 54 | 55 | for i = 0, GetCharacterCount(str), 1 do 56 | local length = i - startIndex 57 | if GetByteCount(string.sub(str, startIndex, length)) > maxbytelength then 58 | AddTextComponentSubstringPlayerName(string.sub(str, startIndex, length - 1)) 59 | i = i - 1 60 | startIndex = startIndex + (length - 1) 61 | end 62 | end 63 | AddTextComponentSubstringPlayerName(string.sub(str, startIndex, GetCharacterCount(str) - startIndex)) 64 | end 65 | 66 | function AddLongString(str) 67 | local bytecount = GetByteCount(str) 68 | if bytecount == GetCharacterCount(str) then 69 | AddLongStringForAscii(str) 70 | else 71 | AddLongStringForUtf8(str) 72 | end 73 | end 74 | 75 | function MeasureStringWidthNoConvert(str, font, scale) 76 | BeginTextCommandWidth("STRING") 77 | AddLongString(str) 78 | SetTextFont(font or 0) 79 | SetTextScale(1.0, scale or 0) 80 | return EndTextCommandGetWidth(true) 81 | end 82 | 83 | function MeasureStringWidth(str, font, scale) 84 | return MeasureStringWidthNoConvert(str, font, scale) * 1920 85 | end 86 | 87 | function UIResText.New(Text, X, Y, Scale, R, G, B, A, Font, Alignment, DropShadow, Outline, WordWrap) 88 | local _UIResText = { 89 | _Text = tostring(Text) or "", 90 | X = tonumber(X) or 0, 91 | Y = tonumber(Y) or 0, 92 | Scale = tonumber(Scale) or 0, 93 | _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255}, 94 | Font = tonumber(Font) or 0, 95 | Alignment = Alignment or nil, 96 | DropShadow = Dropshadow or nil, 97 | Outline = Outline or nil, 98 | WordWrap = tonumber(WordWrap) or 0, 99 | } 100 | return setmetatable(_UIResText, UIResText) 101 | end 102 | 103 | function UIResText:Position(X, Y) 104 | if tonumber(X) and tonumber(Y) then 105 | self.X = tonumber(X) 106 | self.Y = tonumber(Y) 107 | else 108 | return {X = self.X, Y = self.Y} 109 | end 110 | end 111 | 112 | function UIResText:Colour(R, G, B, A) 113 | if tonumber(R) and tonumber(G) and tonumber(B) and tonumber(A) then 114 | self._Colour.R = tonumber(R) 115 | self._Colour.B = tonumber(B) 116 | self._Colour.G = tonumber(G) 117 | self._Colour.A = tonumber(A) 118 | else 119 | return self._Colour 120 | end 121 | end 122 | 123 | function UIResText:Text(Text) 124 | if tostring(Text) and Text ~= nil then 125 | self._Text = tostring(Text) 126 | else 127 | return self._Text 128 | end 129 | end 130 | 131 | function UIResText:Draw() 132 | local Position = self:Position() 133 | Position.X, Position.Y = FormatXWYH(Position.X, Position.Y) 134 | 135 | SetTextFont(self.Font) 136 | SetTextScale(1.0, self.Scale) 137 | SetTextColour(self._Colour.R, self._Colour.G, self._Colour.B, self._Colour.A) 138 | 139 | if self.DropShadow then 140 | SetTextDropShadow() 141 | end 142 | if self.Outline then 143 | SetTextOutline() 144 | end 145 | 146 | if self.Alignment ~= nil then 147 | if self.Alignment == 1 or self.Alignment == "Center" or self.Alignment == "Centre" then 148 | SetTextCentre(true) 149 | elseif self.Alignment == 2 or self.Alignment == "Right" then 150 | SetTextRightJustify(true) 151 | SetTextWrap(0, Position.X) 152 | end 153 | end 154 | 155 | if tonumber(self.WordWrap) then 156 | if tonumber(self.WordWrap) ~= 0 then 157 | SetTextWrap(Position.X, Position.X + (tonumber(self.WordWrap) / Resolution.Width)) 158 | end 159 | end 160 | 161 | BeginTextCommandDisplayText("STRING") 162 | AddLongString(self._Text) 163 | EndTextCommandDisplayText(Position.X, Position.Y) 164 | end 165 | 166 | function RenderText(Text, X, Y, Font, Scale, R, G, B, A, Alignment, DropShadow, Outline, WordWrap) 167 | Text = tostring(Text) 168 | X, Y = FormatXWYH(X, Y) 169 | SetTextFont(Font or 0) 170 | SetTextScale(1.0, Scale or 0) 171 | SetTextColour(R or 255, G or 255, B or 255, A or 255) 172 | 173 | if DropShadow then 174 | SetTextDropShadow() 175 | end 176 | if Outline then 177 | SetTextOutline() 178 | end 179 | 180 | if Alignment ~= nil then 181 | if Alignment == 1 or Alignment == "Center" or Alignment == "Centre" then 182 | SetTextCentre(true) 183 | elseif Alignment == 2 or Alignment == "Right" then 184 | SetTextRightJustify(true) 185 | SetTextWrap(0, X) 186 | end 187 | end 188 | 189 | if tonumber(WordWrap) then 190 | if tonumber(WordWrap) ~= 0 then 191 | WordWrap, _ = FormatXWYH(WordWrap, 0) 192 | SetTextWrap(WordWrap, X - WordWrap) 193 | end 194 | end 195 | 196 | BeginTextCommandDisplayText("STRING") 197 | AddLongString(Text) 198 | EndTextCommandDisplayText(X, Y) 199 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/items/UIMenuCheckboxItem.lua: -------------------------------------------------------------------------------- 1 | UIMenuCheckboxItem = setmetatable({}, UIMenuCheckboxItem) 2 | UIMenuCheckboxItem.__index = UIMenuCheckboxItem 3 | UIMenuCheckboxItem.__call = function() return "UIMenuItem", "UIMenuCheckboxItem" end 4 | 5 | function UIMenuCheckboxItem.New(Text, Check, Description) 6 | local _UIMenuCheckboxItem = { 7 | Base = UIMenuItem.New(Text or "", Description or ""), 8 | CheckedSprite = Sprite.New("commonmenu", "shop_box_blank", 410, 95, 50, 50), 9 | Checked = tobool(Check), 10 | CheckboxEvent = function(menu, item, checked) end, 11 | } 12 | return setmetatable(_UIMenuCheckboxItem, UIMenuCheckboxItem) 13 | end 14 | 15 | function UIMenuCheckboxItem:SetParentMenu(Menu) 16 | if Menu() == "UIMenu" then 17 | self.Base.ParentMenu = Menu 18 | else 19 | return self.Base.ParentMenu 20 | end 21 | end 22 | 23 | function UIMenuCheckboxItem:Position(Y) 24 | if tonumber(Y) then 25 | self.Base:Position(Y) 26 | self.CheckedSprite:Position(380 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 138 + self.Base._Offset.Y) 27 | end 28 | end 29 | 30 | function UIMenuCheckboxItem:Selected(bool) 31 | if bool ~= nil then 32 | self.Base._Selected = tobool(bool) 33 | else 34 | return self.Base._Selected 35 | end 36 | end 37 | 38 | function UIMenuCheckboxItem:Hovered(bool) 39 | if bool ~= nil then 40 | self.Base._Hovered = tobool(bool) 41 | else 42 | return self.Base._Hovered 43 | end 44 | end 45 | 46 | function UIMenuCheckboxItem:Enabled(bool) 47 | if bool ~= nil then 48 | self.Base._Enabled = tobool(bool) 49 | else 50 | return self.Base._Enabled 51 | end 52 | end 53 | 54 | function UIMenuCheckboxItem:Description(str) 55 | if tostring(str) and str ~= nil then 56 | self.Base._Description = tostring(str) 57 | else 58 | return self.Base._Description 59 | end 60 | end 61 | 62 | function UIMenuCheckboxItem:Offset(X, Y) 63 | if tonumber(X) or tonumber(Y) then 64 | if tonumber(X) then 65 | self.Base._Offset.X = tonumber(X) 66 | end 67 | if tonumber(Y) then 68 | self.Base._Offset.Y = tonumber(Y) 69 | end 70 | else 71 | return self.Base._Offset 72 | end 73 | end 74 | 75 | function UIMenuCheckboxItem:Text(Text) 76 | if tostring(Text) and Text ~= nil then 77 | self.Base.Text:Text(tostring(Text)) 78 | else 79 | return self.Base.Text:Text() 80 | end 81 | end 82 | 83 | function UIMenuCheckboxItem:SetLeftBadge() 84 | error("This item does not support badges") 85 | end 86 | 87 | function UIMenuCheckboxItem:SetRightBadge() 88 | error("This item does not support badges") 89 | end 90 | 91 | function UIMenuCheckboxItem:RightLabel() 92 | error("This item does not support a right label") 93 | end 94 | 95 | function UIMenuCheckboxItem:Draw() 96 | self.Base:Draw() 97 | self.CheckedSprite:Position(380 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.CheckedSprite.Y) 98 | if self.Base:Selected() then 99 | if self.Checked then 100 | self.CheckedSprite.TxtName = "shop_box_tickb" 101 | else 102 | self.CheckedSprite.TxtName = "shop_box_blankb" 103 | end 104 | else 105 | if self.Checked then 106 | self.CheckedSprite.TxtName = "shop_box_tick" 107 | else 108 | self.CheckedSprite.TxtName = "shop_box_blank" 109 | end 110 | end 111 | self.CheckedSprite:Draw() 112 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/items/UIMenuColouredItem.lua: -------------------------------------------------------------------------------- 1 | UIMenuColouredItem = setmetatable({}, UIMenuColouredItem) 2 | UIMenuColouredItem.__index = UIMenuColouredItem 3 | UIMenuColouredItem.__call = function() return "UIMenuItem", "UIMenuColouredItem" end 4 | 5 | function UIMenuColouredItem.New(Text, Description, MainColour, HighlightColour) 6 | if type(Colour) ~= "table" then Colour = {R = 0, G = 0, B = 0, A = 255} end 7 | if type(HighlightColour) ~= "table" then Colour = {R = 255, G = 255, B = 255, A = 255} end 8 | local _UIMenuColouredItem = { 9 | Base = UIMenuItem.New(Text or "", Description or ""), 10 | Rectangle = UIResRectangle.New(0, 0, 431, 38, MainColour.R, MainColour.G, MainColour.B, MainColour.A), 11 | MainColour = MainColour, 12 | HighlightColour = HighlightColour, 13 | Activated = function(menu, item) end, 14 | } 15 | _UIMenuColouredItem.Base.SelectedSprite:Colour(HighlightColour.R, HighlightColour.G, HighlightColour.B, HighlightColour.A) 16 | return setmetatable(_UIMenuColouredItem, UIMenuColouredItem) 17 | end 18 | 19 | function UIMenuColouredItem:SetParentMenu(Menu) 20 | if Menu() == "UIMenu" then 21 | self.Base.ParentMenu = Menu 22 | else 23 | return self.Base.ParentMenu 24 | end 25 | end 26 | 27 | function UIMenuColouredItem:Position(Y) 28 | if tonumber(Y) then 29 | self.Base:Position(Y) 30 | self.Rectangle:Position(self.Base._Offset.X, Y + 144 + self.Base._Offset.Y) 31 | end 32 | end 33 | 34 | function UIMenuColouredItem:Selected(bool) 35 | if bool ~= nil then 36 | self.Base._Selected = tobool(bool) 37 | else 38 | return self.Base._Selected 39 | end 40 | end 41 | 42 | function UIMenuColouredItem:Hovered(bool) 43 | if bool ~= nil then 44 | self.Base._Hovered = tobool(bool) 45 | else 46 | return self.Base._Hovered 47 | end 48 | end 49 | 50 | function UIMenuColouredItem:Enabled(bool) 51 | if bool ~= nil then 52 | self.Base._Enabled = tobool(bool) 53 | else 54 | return self.Base._Enabled 55 | end 56 | end 57 | 58 | function UIMenuColouredItem:Description(str) 59 | if tostring(str) and str ~= nil then 60 | self.Base._Description = tostring(str) 61 | else 62 | return self.Base._Description 63 | end 64 | end 65 | 66 | function UIMenuColouredItem:Offset(X, Y) 67 | if tonumber(X) or tonumber(Y) then 68 | if tonumber(X) then 69 | self.Base._Offset.X = tonumber(X) 70 | end 71 | if tonumber(Y) then 72 | self.Base._Offset.Y = tonumber(Y) 73 | end 74 | else 75 | return self.Base._Offset 76 | end 77 | end 78 | 79 | function UIMenuColouredItem:Text(Text) 80 | if tostring(Text) and Text ~= nil then 81 | self.Base.Text:Text(tostring(Text)) 82 | else 83 | return self.Base.Text:Text() 84 | end 85 | end 86 | 87 | function UIMenuColouredItem:RightLabel(Text, MainColour, HighlightColour) 88 | if tostring(Text) and Text ~= nil then 89 | if type(MainColour) == "table" then 90 | self.Base.Label.MainColour = MainColour 91 | end 92 | if type(HighlightColour) == "table" then 93 | self.Base.Label.HighlightColour = HighlightColour 94 | end 95 | self.Base.Label.Text:Text(tostring(Text)) 96 | else 97 | return self.Base.Label.Text:Text() 98 | end 99 | end 100 | 101 | function UIMenuColouredItem:SetLeftBadge(Badge) 102 | if tonumber(Badge) then 103 | self.Base.LeftBadge.Badge = tonumber(Badge) 104 | end 105 | end 106 | 107 | function UIMenuColouredItem:SetRightBadge(Badge) 108 | if tonumber(Badge) then 109 | self.Base.RightBadge.Badge = tonumber(Badge) 110 | end 111 | end 112 | 113 | function UIMenuColouredItem:Draw() 114 | self.Rectangle:Size(431 + self.ParentMenu.WidthOffset, self.Rectangle.Height) 115 | self.Rectangle:Draw() 116 | self.Base:Draw() 117 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/items/UIMenuItem.lua: -------------------------------------------------------------------------------- 1 | UIMenuItem = setmetatable({}, UIMenuItem) 2 | UIMenuItem.__index = UIMenuItem 3 | UIMenuItem.__call = function() return "UIMenuItem", "UIMenuItem" end 4 | 5 | function UIMenuItem.New(Text, Description) 6 | _UIMenuItem = { 7 | Rectangle = UIResRectangle.New(0, 0, 431, 38, 255, 255, 255, 20), 8 | Text = UIResText.New(tostring(Text) or "", 8, 0, 0.33, 245, 245, 245, 255, 0), 9 | _Description = tostring(Description) or ""; 10 | SelectedSprite = Sprite.New("commonmenu", "gradient_nav", 0, 0, 431, 38), 11 | LeftBadge = { Sprite = Sprite.New("commonmenu", "", 0, 0, 40, 40), Badge = 0}, 12 | RightBadge = { Sprite = Sprite.New("commonmenu", "", 0, 0, 40, 40), Badge = 0}, 13 | Label = { 14 | Text = UIResText.New("", 0, 0, 0.35, 245, 245, 245, 255, 0, "Right"), 15 | MainColour = {R = 255, G = 255, B = 255, A = 255}, 16 | HighlightColour = {R = 0, G = 0, B = 0, A = 255}, 17 | }, 18 | _Selected = false, 19 | _Hovered = false, 20 | _Enabled = true, 21 | _Offset = {X = 0, Y = 0}, 22 | ParentMenu = nil, 23 | Panels = {}, 24 | Activated = function(menu, item) end, 25 | ActivatedPanel = function(menu, item, panel, panelvalue) end, 26 | } 27 | return setmetatable(_UIMenuItem, UIMenuItem) 28 | end 29 | 30 | function UIMenuItem:SetParentMenu(Menu) 31 | if Menu ~= nil and Menu() == "UIMenu" then 32 | self.ParentMenu = Menu 33 | else 34 | return self.ParentMenu 35 | end 36 | end 37 | 38 | function UIMenuItem:Selected(bool) 39 | if bool ~= nil then 40 | self._Selected = tobool(bool) 41 | else 42 | return self._Selected 43 | end 44 | end 45 | 46 | function UIMenuItem:Hovered(bool) 47 | if bool ~= nil then 48 | self._Hovered = tobool(bool) 49 | else 50 | return self._Hovered 51 | end 52 | end 53 | 54 | function UIMenuItem:Enabled(bool) 55 | if bool ~= nil then 56 | self._Enabled = tobool(bool) 57 | else 58 | return self._Enabled 59 | end 60 | end 61 | 62 | function UIMenuItem:Description(str) 63 | if tostring(str) and str ~= nil then 64 | self._Description = tostring(str) 65 | else 66 | return self._Description 67 | end 68 | end 69 | 70 | function UIMenuItem:Offset(X, Y) 71 | if tonumber(X) or tonumber(Y) then 72 | if tonumber(X) then 73 | self._Offset.X = tonumber(X) 74 | end 75 | if tonumber(Y) then 76 | self._Offset.Y = tonumber(Y) 77 | end 78 | else 79 | return self._Offset 80 | end 81 | end 82 | 83 | function UIMenuItem:Position(Y) 84 | if tonumber(Y) then 85 | self.Rectangle:Position(self._Offset.X, Y + 144 + self._Offset.Y) 86 | self.SelectedSprite:Position(0 + self._Offset.X, Y + 144 + self._Offset.Y) 87 | self.Text:Position(8 + self._Offset.X, Y + 147 + self._Offset.Y) 88 | self.LeftBadge.Sprite:Position(0 + self._Offset.X, Y + 142 + self._Offset.Y) 89 | self.RightBadge.Sprite:Position(385 + self._Offset.X, Y + 142 + self._Offset.Y) 90 | self.Label.Text:Position(420 + self._Offset.X, Y + 148 + self._Offset.Y) 91 | end 92 | end 93 | 94 | function UIMenuItem:RightLabel(Text, MainColour, HighlightColour) 95 | if tostring(Text) and Text ~= nil then 96 | if type(MainColour) == "table" then 97 | self.Label.MainColour = MainColour 98 | end 99 | if type(HighlightColour) == "table" then 100 | self.Label.HighlightColour = HighlightColour 101 | end 102 | self.Label.Text:Text(tostring(Text)) 103 | else 104 | return self.Label.Text:Text() 105 | end 106 | end 107 | 108 | function UIMenuItem:SetLeftBadge(Badge) 109 | if tonumber(Badge) then 110 | self.LeftBadge.Badge = tonumber(Badge) 111 | end 112 | end 113 | 114 | function UIMenuItem:SetRightBadge(Badge) 115 | if tonumber(Badge) then 116 | self.RightBadge.Badge = tonumber(Badge) 117 | end 118 | end 119 | 120 | function UIMenuItem:Text(Text) 121 | if tostring(Text) and Text ~= nil then 122 | self.Text:Text(tostring(Text)) 123 | else 124 | return self.Text:Text() 125 | end 126 | end 127 | 128 | function UIMenuItem:AddPanel(Panel) 129 | if Panel() == "UIMenuPanel" then 130 | table.insert(self.Panels, Panel) 131 | Panel:SetParentItem(self) 132 | end 133 | end 134 | 135 | function UIMenuItem:RemovePanelAt(Index) 136 | if tonumber(Index) then 137 | if self.Panels[Index] then 138 | table.remove(self.Panels, tonumber(Index)) 139 | end 140 | end 141 | end 142 | 143 | function UIMenuItem:FindPanelIndex(Panel) 144 | if Panel() == "UIMenuPanel" then 145 | for Index = 1, #self.Panels do 146 | if self.Panels[Index] == Panel then 147 | return Index 148 | end 149 | end 150 | end 151 | return nil 152 | end 153 | 154 | function UIMenuItem:FindPanelItem() 155 | for Index = #self.Items, 1, -1 do 156 | if self.Items[Index].Panel then 157 | return Index 158 | end 159 | end 160 | return nil 161 | end 162 | 163 | function UIMenuItem:Draw() 164 | self.Rectangle:Size(431 + self.ParentMenu.WidthOffset, self.Rectangle.Height) 165 | self.SelectedSprite:Size(431 + self.ParentMenu.WidthOffset, self.SelectedSprite.Height) 166 | 167 | if self._Hovered and not self._Selected then 168 | self.Rectangle:Draw() 169 | end 170 | 171 | if self._Selected then 172 | self.SelectedSprite:Draw() 173 | end 174 | 175 | if self._Enabled then 176 | if self._Selected then 177 | self.Text:Colour(0, 0, 0, 255) 178 | self.Label.Text:Colour(self.Label.HighlightColour.R, self.Label.HighlightColour.G, self.Label.HighlightColour.B, self.Label.HighlightColour.A) 179 | else 180 | self.Text:Colour(245, 245, 245, 255) 181 | self.Label.Text:Colour(self.Label.MainColour.R, self.Label.MainColour.G, self.Label.MainColour.B, self.Label.MainColour.A) 182 | end 183 | else 184 | self.Text:Colour(163, 159, 148, 255) 185 | self.Label.Text:Colour(163, 159, 148, 255) 186 | end 187 | 188 | if self.LeftBadge.Badge == BadgeStyle.None then 189 | self.Text:Position(8 + self._Offset.X, self.Text.Y) 190 | else 191 | self.Text:Position(35 + self._Offset.X, self.Text.Y) 192 | self.LeftBadge.Sprite.TxtDictionary = GetBadgeDictionary(self.LeftBadge.Badge, self._Selected) 193 | self.LeftBadge.Sprite.TxtName = GetBadgeTexture(self.LeftBadge.Badge, self._Selected) 194 | self.LeftBadge.Sprite:Colour(GetBadgeColour(self.LeftBadge.Badge, self._Selected)) 195 | self.LeftBadge.Sprite:Draw() 196 | end 197 | 198 | if self.RightBadge.Badge ~= BadgeStyle.None then 199 | self.RightBadge.Sprite:Position(385 + self._Offset.X + self.ParentMenu.WidthOffset, self.RightBadge.Sprite.Y) 200 | self.RightBadge.Sprite.TxtDictionary = GetBadgeDictionary(self.RightBadge.Badge, self._Selected) 201 | self.RightBadge.Sprite.TxtName = GetBadgeTexture(self.RightBadge.Badge, self._Selected) 202 | self.RightBadge.Sprite:Colour(GetBadgeColour(self.RightBadge.Badge, self._Selected)) 203 | self.RightBadge.Sprite:Draw() 204 | end 205 | 206 | if self.Label.Text:Text() ~= "" and string.len(self.Label.Text:Text()) > 0 then 207 | self.Label.Text:Position(420 + self._Offset.X + self.ParentMenu.WidthOffset, self.Label.Text.Y) 208 | self.Label.Text:Draw() 209 | end 210 | 211 | self.Text:Draw() 212 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/items/UIMenuListItem.lua: -------------------------------------------------------------------------------- 1 | UIMenuListItem = setmetatable({}, UIMenuListItem) 2 | UIMenuListItem.__index = UIMenuListItem 3 | UIMenuListItem.__call = function() return "UIMenuItem", "UIMenuListItem" end 4 | 5 | function UIMenuListItem.New(Text, Items, Index, Description) 6 | if type(Items) ~= "table" then Items = {} end 7 | if Index == 0 then Index = 1 end 8 | local _UIMenuListItem = { 9 | Base = UIMenuItem.New(Text or "", Description or ""), 10 | Items = Items, 11 | LeftArrow = Sprite.New("commonmenu", "arrowleft", 110, 105, 30, 30), 12 | RightArrow = Sprite.New("commonmenu", "arrowright", 280, 105, 30, 30), 13 | ItemText = UIResText.New("", 290, 104, 0.35, 255, 255, 255, 255, 0, "Right"), 14 | _Index = tonumber(Index) or 1, 15 | Panels = {}, 16 | OnListChanged = function(menu, item, newindex) end, 17 | OnListSelected = function(menu, item, newindex) end, 18 | } 19 | return setmetatable(_UIMenuListItem, UIMenuListItem) 20 | end 21 | 22 | function UIMenuListItem:SetParentMenu(Menu) 23 | if Menu ~= nil and Menu() == "UIMenu" then 24 | self.Base.ParentMenu = Menu 25 | else 26 | return self.Base.ParentMenu 27 | end 28 | end 29 | 30 | function UIMenuListItem:Position(Y) 31 | if tonumber(Y) then 32 | self.LeftArrow:Position(300 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y) 33 | self.RightArrow:Position(400 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y) 34 | self.ItemText:Position(300 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y) 35 | self.Base:Position(Y) 36 | end 37 | end 38 | 39 | function UIMenuListItem:Selected(bool) 40 | if bool ~= nil then 41 | self.Base._Selected = tobool(bool) 42 | else 43 | return self.Base._Selected 44 | end 45 | end 46 | 47 | function UIMenuListItem:Hovered(bool) 48 | if bool ~= nil then 49 | self.Base._Hovered = tobool(bool) 50 | else 51 | return self.Base._Hovered 52 | end 53 | end 54 | 55 | function UIMenuListItem:Enabled(bool) 56 | if bool ~= nil then 57 | self.Base._Enabled = tobool(bool) 58 | else 59 | return self.Base._Enabled 60 | end 61 | end 62 | 63 | function UIMenuListItem:Description(str) 64 | if tostring(str) and str ~= nil then 65 | self.Base._Description = tostring(str) 66 | else 67 | return self.Base._Description 68 | end 69 | end 70 | 71 | function UIMenuListItem:Offset(X, Y) 72 | if tonumber(X) or tonumber(Y) then 73 | if tonumber(X) then 74 | self.Base._Offset.X = tonumber(X) 75 | end 76 | if tonumber(Y) then 77 | self.Base._Offset.Y = tonumber(Y) 78 | end 79 | else 80 | return self.Base._Offset 81 | end 82 | end 83 | 84 | function UIMenuListItem:Text(Text) 85 | if tostring(Text) and Text ~= nil then 86 | self.Base.Text:Text(tostring(Text)) 87 | else 88 | return self.Base.Text:Text() 89 | end 90 | end 91 | 92 | function UIMenuListItem:Index(Index) 93 | if tonumber(Index) then 94 | if tonumber(Index) > #self.Items then 95 | self._Index = 1 96 | elseif tonumber(Index) < 1 then 97 | self._Index = #self.Items 98 | else 99 | self._Index = tonumber(Index) 100 | end 101 | else 102 | return self._Index 103 | end 104 | end 105 | 106 | function UIMenuListItem:ItemToIndex(Item) 107 | for i = 1, #self.Items do 108 | if type(Item) == type(self.Items[i]) and Item == self.Items[i] then 109 | return i 110 | elseif type(self.Items[i]) == "table" and (type(Item) == type(self.Items[i].Name) or type(Item) == type(self.Items[i].Value)) and (Item == self.Items[i].Name or Item == self.Items[i].Value) then 111 | return i 112 | end 113 | end 114 | end 115 | 116 | function UIMenuListItem:IndexToItem(Index) 117 | if tonumber(Index) then 118 | if tonumber(Index) == 0 then Index = 1 end 119 | if self.Items[tonumber(Index)] then 120 | return self.Items[tonumber(Index)] 121 | end 122 | end 123 | end 124 | 125 | function UIMenuListItem:SetLeftBadge() 126 | error("This item does not support badges") 127 | end 128 | 129 | function UIMenuListItem:SetRightBadge() 130 | error("This item does not support badges") 131 | end 132 | 133 | function UIMenuListItem:RightLabel() 134 | error("This item does not support a right label") 135 | end 136 | 137 | function UIMenuListItem:AddPanel(Panel) 138 | if Panel() == "UIMenuPanel" then 139 | table.insert(self.Panels, Panel) 140 | Panel:SetParentItem(self) 141 | end 142 | end 143 | 144 | function UIMenuListItem:RemovePanelAt(Index) 145 | if tonumber(Index) then 146 | if self.Panels[Index] then 147 | table.remove(self.Panels, tonumber(Index)) 148 | end 149 | end 150 | end 151 | 152 | function UIMenuListItem:FindPanelIndex(Panel) 153 | if Panel() == "UIMenuPanel" then 154 | for Index = 1, #self.Panels do 155 | if self.Panels[Index] == Panel then 156 | return Index 157 | end 158 | end 159 | end 160 | return nil 161 | end 162 | 163 | function UIMenuListItem:FindPanelItem() 164 | for Index = #self.Items, 1, -1 do 165 | if self.Items[Index].Panel then 166 | return Index 167 | end 168 | end 169 | return nil 170 | end 171 | 172 | function UIMenuListItem:Draw() 173 | self.Base:Draw() 174 | 175 | if self:Enabled() then 176 | if self:Selected() then 177 | self.ItemText:Colour(0, 0, 0, 255) 178 | self.LeftArrow:Colour(0, 0, 0, 255) 179 | self.RightArrow:Colour(0, 0, 0, 255) 180 | else 181 | self.ItemText:Colour(245, 245, 245, 255) 182 | self.LeftArrow:Colour(245, 245, 245, 255) 183 | self.RightArrow:Colour(245, 245, 245, 255) 184 | end 185 | else 186 | self.ItemText:Colour(163, 159, 148, 255) 187 | self.LeftArrow:Colour(163, 159, 148, 255) 188 | self.RightArrow:Colour(163, 159, 148, 255) 189 | end 190 | 191 | local Text = (type(self.Items[self._Index]) == "table") and tostring(self.Items[self._Index].Name) or tostring(self.Items[self._Index]) 192 | local Offset = MeasureStringWidth(Text, 0, 0.35) 193 | 194 | self.ItemText:Text(Text) 195 | self.LeftArrow:Position(378 - Offset + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.LeftArrow.Y) 196 | 197 | if self:Selected() then 198 | self.LeftArrow:Draw() 199 | self.RightArrow:Draw() 200 | self.ItemText:Position(403 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.ItemText.Y) 201 | else 202 | self.ItemText:Position(418 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.ItemText.Y) 203 | end 204 | 205 | self.ItemText:Draw() 206 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/items/UIMenuProgressItem.lua: -------------------------------------------------------------------------------- 1 | UIMenuProgressItem = setmetatable({}, UIMenuProgressItem) 2 | UIMenuProgressItem.__index = UIMenuProgressItem 3 | UIMenuProgressItem.__call = function() return "UIMenuItem", "UIMenuProgressItem" end 4 | 5 | function UIMenuProgressItem.New(Text, Items, Index, Description, Counter) 6 | if type(Items) ~= "table" then Items = {} end 7 | if Index == 0 then Index = 1 end 8 | local _UIMenuProgressItem = { 9 | Base = UIMenuItem.New(Text or "", Description or ""), 10 | Data = { 11 | Items = Items, 12 | Counter = tobool(Counter), 13 | Max = 407.5, 14 | Index = tonumber(Index) or 1, 15 | }, 16 | Background = UIResRectangle.New(0, 0, 415, 20), 17 | Bar = UIResRectangle.New(0, 0, 407.5, 12.5), 18 | OnProgressChanged = function(menu, item, newindex) end, 19 | OnProgressSelected = function(menu, item, newindex) end, 20 | } 21 | 22 | _UIMenuProgressItem.Base.Rectangle.Height = 60 23 | _UIMenuProgressItem.Base.SelectedSprite.Height = 60 24 | 25 | if _UIMenuProgressItem.Data.Counter then 26 | _UIMenuProgressItem.Base:RightLabel(_UIMenuProgressItem.Data.Index.."/"..#_UIMenuProgressItem.Data.Items) 27 | else 28 | _UIMenuProgressItem.Base:RightLabel((type(_UIMenuProgressItem.Data.Items[_UIMenuProgressItem.Data.Index]) == "table") and tostring(_UIMenuProgressItem.Data.Items[_UIMenuProgressItem.Data.Index].Name) or tostring(_UIMenuProgressItem.Data.Items[_UIMenuProgressItem.Data.Index])) 29 | end 30 | 31 | _UIMenuProgressItem.Bar.Width = _UIMenuProgressItem.Data.Index/#_UIMenuProgressItem.Data.Items * _UIMenuProgressItem.Data.Max 32 | 33 | return setmetatable(_UIMenuProgressItem, UIMenuProgressItem) 34 | end 35 | 36 | function UIMenuProgressItem:SetParentMenu(Menu) 37 | if Menu() == "UIMenu" then 38 | self.Base.ParentMenu = Menu 39 | else 40 | return self.Base.ParentMenu 41 | end 42 | end 43 | 44 | function UIMenuProgressItem:Position(Y) 45 | if tonumber(Y) then 46 | self.Base:Position(Y) 47 | self.Background:Position(8 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 177 + Y + self.Base._Offset.Y) 48 | self.Bar:Position(11.75 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 180.75 + Y + self.Base._Offset.Y) 49 | end 50 | end 51 | 52 | function UIMenuProgressItem:Selected(bool) 53 | if bool ~= nil then 54 | self.Base._Selected = tobool(bool) 55 | else 56 | return self.Base._Selected 57 | end 58 | end 59 | 60 | function UIMenuProgressItem:Hovered(bool) 61 | if bool ~= nil then 62 | self.Base._Hovered = tobool(bool) 63 | else 64 | return self.Base._Hovered 65 | end 66 | end 67 | 68 | function UIMenuProgressItem:Enabled(bool) 69 | if bool ~= nil then 70 | self.Base._Enabled = tobool(bool) 71 | else 72 | return self.Base._Enabled 73 | end 74 | end 75 | 76 | function UIMenuProgressItem:Description(str) 77 | if tostring(str) and str ~= nil then 78 | self.Base._Description = tostring(str) 79 | else 80 | return self.Base._Description 81 | end 82 | end 83 | 84 | function UIMenuProgressItem:Offset(X, Y) 85 | if tonumber(X) or tonumber(Y) then 86 | if tonumber(X) then 87 | self.Base._Offset.X = tonumber(X) 88 | end 89 | if tonumber(Y) then 90 | self.Base._Offset.Y = tonumber(Y) 91 | end 92 | else 93 | return self.Base._Offset 94 | end 95 | end 96 | 97 | function UIMenuProgressItem:Text(Text) 98 | if tostring(Text) and Text ~= nil then 99 | self.Base.Text:Text(tostring(Text)) 100 | else 101 | return self.Base.Text:Text() 102 | end 103 | end 104 | 105 | function UIMenuProgressItem:Index(Index) 106 | if tonumber(Index) then 107 | if tonumber(Index) > #self.Data.Items then 108 | self.Data.Index = 1 109 | elseif tonumber(Index) < 1 then 110 | self.Data.Index = #self.Data.Items 111 | else 112 | self.Data.Index = tonumber(Index) 113 | end 114 | 115 | if self.Data.Counter then 116 | self.Base:RightLabel(self.Data.Index.."/"..#self.Data.Items) 117 | else 118 | self.Base:RightLabel((type(self.Data.Items[self.Data.Index]) == "table") and tostring(self.Data.Items[self.Data.Index].Name) or tostring(self.Data.Items[self.Data.Index])) 119 | end 120 | 121 | self.Bar.Width = self.Data.Index/#self.Data.Items * self.Data.Max 122 | else 123 | return self.Data.Index 124 | end 125 | end 126 | 127 | function UIMenuProgressItem:ItemToIndex(Item) 128 | for i = 1, #self.Data.Items do 129 | if type(Item) == type(self.Data.Items[i]) and Item == self.Data.Items[i] then 130 | return i 131 | elseif type(self.Data.Items[i]) == "table" and (type(Item) == type(self.Data.Items[i].Name) or type(Item) == type(self.Data.Items[i].Value)) and (Item == self.Data.Items[i].Name or Item == self.Data.Items[i].Value) then 132 | return i 133 | end 134 | end 135 | end 136 | 137 | function UIMenuProgressItem:IndexToItem(Index) 138 | if tonumber(Index) then 139 | if tonumber(Index) == 0 then Index = 1 end 140 | if self.Data.Items[tonumber(Index)] then 141 | return self.Data.Items[tonumber(Index)] 142 | end 143 | end 144 | end 145 | 146 | function UIMenuProgressItem:SetLeftBadge() 147 | error("This item does not support badges") 148 | end 149 | 150 | function UIMenuProgressItem:SetRightBadge() 151 | error("This item does not support badges") 152 | end 153 | 154 | function UIMenuProgressItem:RightLabel() 155 | error("This item does not support a right label") 156 | end 157 | 158 | function UIMenuProgressItem:CalculateProgress(CursorX) 159 | local Progress = CursorX - self.Bar.X 160 | self:Index(math.round(#self.Data.Items * (((Progress >= 0 and Progress <= self.Data.Max) and Progress or ((Progress < 0) and 0 or self.Data.Max))/self.Data.Max))) 161 | end 162 | 163 | function UIMenuProgressItem:Draw() 164 | self.Base:Draw() 165 | 166 | if self.Base._Selected then 167 | self.Background:Colour(table.unpack(Colours.Black)) 168 | self.Bar:Colour(table.unpack(Colours.White)) 169 | else 170 | self.Background:Colour(table.unpack(Colours.White)) 171 | self.Bar:Colour(table.unpack(Colours.Black)) 172 | end 173 | 174 | self.Background:Draw() 175 | self.Bar:Draw() 176 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/items/UIMenuSliderItem.lua: -------------------------------------------------------------------------------- 1 | UIMenuSliderItem = setmetatable({}, UIMenuSliderItem) 2 | UIMenuSliderItem.__index = UIMenuSliderItem 3 | UIMenuSliderItem.__call = function() return "UIMenuItem", "UIMenuSliderItem" end 4 | 5 | function UIMenuSliderItem.New(Text, Items, Index, Description, Divider) 6 | if type(Items) ~= "table" then Items = {} end 7 | if Index == 0 then Index = 1 end 8 | local _UIMenuSliderItem = { 9 | Base = UIMenuItem.New(Text or "", Description or ""), 10 | Items = Items, 11 | ShowDivider = tobool(Divider), 12 | LeftArrow = Sprite.New("commonmenutu", "arrowleft", 0, 105, 15, 15), 13 | RightArrow = Sprite.New("commonmenutu", "arrowright", 0, 105, 15, 15), 14 | Background = UIResRectangle.New(0, 0, 150, 9, 4, 32, 57, 255), 15 | Slider = UIResRectangle.New(0, 0, 75, 9, 57, 116, 200, 255), 16 | Divider = UIResRectangle.New(0, 0, 2.5, 20, 245, 245, 245, 255), 17 | _Index = tonumber(Index) or 1, 18 | OnSliderChanged = function(menu, item, newindex) end, 19 | OnSliderSelected = function(menu, item, newindex) end, 20 | } 21 | return setmetatable(_UIMenuSliderItem, UIMenuSliderItem) 22 | end 23 | 24 | function UIMenuSliderItem:SetParentMenu(Menu) 25 | if Menu() == "UIMenu" then 26 | self.Base.ParentMenu = Menu 27 | else 28 | return self.Base.ParentMenu 29 | end 30 | end 31 | 32 | function UIMenuSliderItem:Position(Y) 33 | if tonumber(Y) then 34 | self.Background:Position(250 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 158.5 + self.Base._Offset.Y) 35 | self.Slider:Position(250 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 158.5 + self.Base._Offset.Y) 36 | self.Divider:Position(323.5 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 153 + self.Base._Offset.Y) 37 | self.LeftArrow:Position(235 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 155.5 + Y + self.Base._Offset.Y) 38 | self.RightArrow:Position(400 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 155.5 + Y + self.Base._Offset.Y) 39 | self.Base:Position(Y) 40 | end 41 | end 42 | 43 | function UIMenuSliderItem:Selected(bool) 44 | if bool ~= nil then 45 | self.Base._Selected = tobool(bool) 46 | else 47 | return self.Base._Selected 48 | end 49 | end 50 | 51 | function UIMenuSliderItem:Hovered(bool) 52 | if bool ~= nil then 53 | self.Base._Hovered = tobool(bool) 54 | else 55 | return self.Base._Hovered 56 | end 57 | end 58 | 59 | function UIMenuSliderItem:Enabled(bool) 60 | if bool ~= nil then 61 | self.Base._Enabled = tobool(bool) 62 | else 63 | return self.Base._Enabled 64 | end 65 | end 66 | 67 | function UIMenuSliderItem:Description(str) 68 | if tostring(str) and str ~= nil then 69 | self.Base._Description = tostring(str) 70 | else 71 | return self.Base._Description 72 | end 73 | end 74 | 75 | function UIMenuSliderItem:Offset(X, Y) 76 | if tonumber(X) or tonumber(Y) then 77 | if tonumber(X) then 78 | self.Base._Offset.X = tonumber(X) 79 | end 80 | if tonumber(Y) then 81 | self.Base._Offset.Y = tonumber(Y) 82 | end 83 | else 84 | return self.Base._Offset 85 | end 86 | end 87 | 88 | function UIMenuSliderItem:Text(Text) 89 | if tostring(Text) and Text ~= nil then 90 | self.Base.Text:Text(tostring(Text)) 91 | else 92 | return self.Base.Text:Text() 93 | end 94 | end 95 | 96 | function UIMenuSliderItem:Index(Index) 97 | if tonumber(Index) then 98 | if tonumber(Index) > #self.Items then 99 | self._Index = 1 100 | elseif tonumber(Index) < 1 then 101 | self._Index = #self.Items 102 | else 103 | self._Index = tonumber(Index) 104 | end 105 | else 106 | return self._Index 107 | end 108 | end 109 | 110 | function UIMenuSliderItem:ItemToIndex(Item) 111 | for i = 1, #self.Items do 112 | if type(Item) == type(self.Items[i]) and Item == self.Items[i] then 113 | return i 114 | end 115 | end 116 | end 117 | 118 | function UIMenuSliderItem:IndexToItem(Index) 119 | if tonumber(Index) then 120 | if tonumber(Index) == 0 then Index = 1 end 121 | if self.Items[tonumber(Index)] then 122 | return self.Items[tonumber(Index)] 123 | end 124 | end 125 | end 126 | 127 | function UIMenuSliderItem:SetLeftBadge() 128 | error("This item does not support badges") 129 | end 130 | 131 | function UIMenuSliderItem:SetRightBadge() 132 | error("This item does not support badges") 133 | end 134 | 135 | function UIMenuSliderItem:RightLabel() 136 | error("This item does not support a right label") 137 | end 138 | 139 | function UIMenuSliderItem:Draw() 140 | self.Base:Draw() 141 | 142 | if self:Enabled() then 143 | if self:Selected() then 144 | self.LeftArrow:Colour(0, 0, 0, 255) 145 | self.RightArrow:Colour(0, 0, 0, 255) 146 | else 147 | self.LeftArrow:Colour(245, 245, 245, 255) 148 | self.RightArrow:Colour(245, 245, 245, 255) 149 | end 150 | else 151 | self.LeftArrow:Colour(163, 159, 148, 255) 152 | self.RightArrow:Colour(163, 159, 148, 255) 153 | end 154 | 155 | local Offset = ((self.Background.Width - self.Slider.Width)/(#self.Items - 1)) * (self._Index-1) 156 | 157 | self.Slider:Position(250 + self.Base._Offset.X + Offset + self.Base.ParentMenu.WidthOffset, self.Slider.Y) 158 | 159 | if self:Selected() then 160 | self.LeftArrow:Draw() 161 | self.RightArrow:Draw() 162 | end 163 | 164 | self.Background:Draw() 165 | self.Slider:Draw() 166 | if self.ShowDivider then 167 | self.Divider:Draw() 168 | end 169 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/panels/UIMenuColourPanel.lua: -------------------------------------------------------------------------------- 1 | UIMenuColourPanel = setmetatable({}, UIMenuColourPanel) 2 | UIMenuColourPanel.__index = UIMenuColourPanel 3 | UIMenuColourPanel.__call = function() return "UIMenuPanel", "UIMenuColourPanel" end 4 | 5 | function UIMenuColourPanel.New(Title, Colours) 6 | _UIMenuColourPanel = { 7 | Data = { 8 | Pagination = { 9 | Min = 1, 10 | Max = 8, 11 | Total = 8, 12 | }, 13 | Index = 1000, 14 | Items = Colours, 15 | Title = Title or "Title", 16 | Enabled = true, 17 | Value = 1, 18 | }, 19 | Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 112), 20 | Bar = {}, 21 | LeftArrow = Sprite.New("commonmenu", "arrowleft", 0, 0, 30, 30), 22 | RightArrow = Sprite.New("commonmenu", "arrowright", 0, 0, 30, 30), 23 | SelectedRectangle = UIResRectangle.New(0, 0, 44.5, 8), 24 | Text = UIResText.New(Title.." (1 of "..#Colours..")" or "Title".." (1 of "..#Colours..")", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), 25 | ParentItem = nil, 26 | } 27 | 28 | for Index = 1, #Colours do 29 | if Index < 10 then 30 | table.insert(_UIMenuColourPanel.Bar, UIResRectangle.New(0, 0, 44.5, 44.5, table.unpack(Colours[Index]))) 31 | else 32 | break 33 | end 34 | end 35 | 36 | if #_UIMenuColourPanel.Data.Items ~= 0 then 37 | _UIMenuColourPanel.Data.Index = 1000 - (1000 % #_UIMenuColourPanel.Data.Items) 38 | _UIMenuColourPanel.Data.Pagination.Max = _UIMenuColourPanel.Data.Pagination.Total + 1 39 | _UIMenuColourPanel.Data.Pagination.Min = 0 40 | end 41 | return setmetatable(_UIMenuColourPanel, UIMenuColourPanel) 42 | end 43 | 44 | function UIMenuColourPanel:SetParentItem(Item) -- required 45 | if Item() == "UIMenuItem" then 46 | self.ParentItem = Item 47 | else 48 | return self.ParentItem 49 | end 50 | end 51 | 52 | function UIMenuColourPanel:Enabled(Enabled) 53 | if type(Enabled) == "boolean" then 54 | self.Data.Enabled = Enabled 55 | else 56 | return self.Data.Enabled 57 | end 58 | end 59 | 60 | function UIMenuColourPanel:Position(Y) -- required 61 | if tonumber(Y) then 62 | local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset 63 | 64 | self.Background:Position(ParentOffsetX, Y) 65 | for Index = 1, #self.Bar do 66 | self.Bar[Index]:Position(15 + (44.5 * (Index - 1)) + ParentOffsetX + (ParentOffsetWidth/2), 55 + Y) 67 | end 68 | self.SelectedRectangle:Position(15 + (44.5 * ((self:CurrentSelection() - self.Data.Pagination.Min) - 1)) + ParentOffsetX + (ParentOffsetWidth/2), 47 + Y) 69 | self.LeftArrow:Position(7.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y) 70 | self.RightArrow:Position(393.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y) 71 | self.Text:Position(215.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y) 72 | end 73 | end 74 | 75 | function UIMenuColourPanel:CurrentSelection(value, PreventUpdate) 76 | if tonumber(value) then 77 | if #self.Data.Items == 0 then 78 | self.Data.Index = 0 79 | end 80 | 81 | self.Data.Index = 1000000 - (1000000 % #self.Data.Items) + tonumber(value) 82 | 83 | if self:CurrentSelection() > self.Data.Pagination.Max then 84 | self.Data.Pagination.Min = self:CurrentSelection() - (self.Data.Pagination.Total + 1) 85 | self.Data.Pagination.Max = self:CurrentSelection() 86 | elseif self:CurrentSelection() < self.Data.Pagination.Min then 87 | self.Data.Pagination.Min = self:CurrentSelection() - 1 88 | self.Data.Pagination.Max = self:CurrentSelection() + (self.Data.Pagination.Total + 1) 89 | end 90 | 91 | self:UpdateSelection(PreventUpdate) 92 | else 93 | if #self.Data.Items == 0 then 94 | return 1 95 | else 96 | if self.Data.Index % #self.Data.Items == 0 then 97 | return 1 98 | else 99 | return self.Data.Index % #self.Data.Items + 1 100 | end 101 | end 102 | end 103 | end 104 | 105 | function UIMenuColourPanel:UpdateParent(Colour) 106 | local _, ParentType = self.ParentItem() 107 | if ParentType == "UIMenuListItem" then 108 | local PanelItemIndex = self.ParentItem:FindPanelItem() 109 | local PanelIndex = self.ParentItem:FindPanelIndex(self) 110 | if PanelItemIndex then 111 | self.ParentItem.Items[PanelItemIndex].Value[PanelIndex] = Colour 112 | self.ParentItem:Index(PanelItemIndex) 113 | self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 114 | self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 115 | else 116 | for Index = 1, #self.ParentItem.Items do 117 | if type(self.ParentItem.Items[Index]) == "table" then 118 | if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end 119 | self.ParentItem.Items[Index].Panels[PanelIndex] = Colour 120 | else 121 | self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = Colour}} 122 | end 123 | end 124 | self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 125 | self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 126 | end 127 | elseif ParentType == "UIMenuItem" then 128 | self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, Colour) 129 | end 130 | end 131 | 132 | function UIMenuColourPanel:UpdateSelection(PreventUpdate) 133 | local CurrentSelection = self:CurrentSelection() 134 | if not PreventUpdate then 135 | self:UpdateParent(CurrentSelection) 136 | end 137 | self.SelectedRectangle:Position(15 + (44.5 * ((CurrentSelection - self.Data.Pagination.Min) - 1)) + self.ParentItem:Offset().X, self.SelectedRectangle.Y) 138 | for Index = 1, 9 do 139 | self.Bar[Index]:Colour(table.unpack(self.Data.Items[self.Data.Pagination.Min + Index])) 140 | end 141 | self.Text:Text(self.Data.Title.." ("..CurrentSelection.." of "..#self.Data.Items..")") 142 | end 143 | 144 | function UIMenuColourPanel:Functions() 145 | 146 | local SafeZone = {X = 0, Y = 0} 147 | if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then 148 | SafeZone = GetSafeZoneBounds() 149 | end 150 | 151 | 152 | if IsMouseInBounds(self.LeftArrow.X + SafeZone.X, self.LeftArrow.Y + SafeZone.Y, self.LeftArrow.Width, self.LeftArrow.Height) then 153 | if IsDisabledControlJustPressed(0, 24) then 154 | if #self.Data.Items > self.Data.Pagination.Total + 1 then 155 | if self:CurrentSelection() <= self.Data.Pagination.Min + 1 then 156 | if self:CurrentSelection() == 1 then 157 | self.Data.Pagination.Min = #self.Data.Items - (self.Data.Pagination.Total + 1) 158 | self.Data.Pagination.Max = #self.Data.Items 159 | self.Data.Index = 1000 - (1000 % #self.Data.Items) 160 | self.Data.Index = self.Data.Index + (#self.Data.Items - 1) 161 | self:UpdateSelection() 162 | else 163 | self.Data.Pagination.Min = self.Data.Pagination.Min - 1 164 | self.Data.Pagination.Max = self.Data.Pagination.Max - 1 165 | self.Data.Index = self.Data.Index - 1 166 | self:UpdateSelection() 167 | end 168 | else 169 | self.Data.Index = self.Data.Index - 1 170 | self:UpdateSelection() 171 | end 172 | else 173 | self.Data.Index = self.Data.Index - 1 174 | self:UpdateSelection() 175 | end 176 | end 177 | end 178 | 179 | if IsMouseInBounds(self.RightArrow.X + SafeZone.X, self.RightArrow.Y + SafeZone.Y, self.RightArrow.Width, self.RightArrow.Height) then 180 | if IsDisabledControlJustPressed(0, 24) then 181 | if #self.Data.Items > self.Data.Pagination.Total + 1 then 182 | if self:CurrentSelection() >= self.Data.Pagination.Max then 183 | if self:CurrentSelection() == #self.Data.Items then 184 | self.Data.Pagination.Min = 0 185 | self.Data.Pagination.Max = self.Data.Pagination.Total + 1 186 | self.Data.Index = 1000 - (1000 % #self.Data.Items) 187 | self:UpdateSelection() 188 | else 189 | self.Data.Pagination.Max = self.Data.Pagination.Max + 1 190 | self.Data.Pagination.Min = self.Data.Pagination.Max - (self.Data.Pagination.Total + 1) 191 | self.Data.Index = self.Data.Index + 1 192 | self:UpdateSelection() 193 | end 194 | else 195 | self.Data.Index = self.Data.Index + 1 196 | self:UpdateSelection() 197 | end 198 | else 199 | self.Data.Index = self.Data.Index + 1 200 | self:UpdateSelection() 201 | end 202 | end 203 | end 204 | 205 | for Index = 1, #self.Bar do 206 | if IsMouseInBounds(self.Bar[Index].X + SafeZone.X, self.Bar[Index].Y + SafeZone.Y, self.Bar[Index].Width, self.Bar[Index].Height) then 207 | if IsDisabledControlJustPressed(0, 24) then 208 | self:CurrentSelection(self.Data.Pagination.Min + Index - 1) 209 | end 210 | end 211 | end 212 | end 213 | 214 | function UIMenuColourPanel:Draw() -- required 215 | if self.Data.Enabled then 216 | self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 112) 217 | 218 | self.Background:Draw() 219 | self.LeftArrow:Draw() 220 | self.RightArrow:Draw() 221 | self.Text:Draw() 222 | self.SelectedRectangle:Draw() 223 | for Index = 1, #self.Bar do 224 | self.Bar[Index]:Draw() 225 | end 226 | self:Functions() 227 | end 228 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/panels/UIMenuGridPanel.lua: -------------------------------------------------------------------------------- 1 | UIMenuGridPanel = setmetatable({}, UIMenuGridPanel) 2 | UIMenuGridPanel.__index = UIMenuGridPanel 3 | UIMenuGridPanel.__call = function() return "UIMenuPanel", "UIMenuGridPanel" end 4 | 5 | function UIMenuGridPanel.New(TopText, LeftText, RightText, BottomText) 6 | _UIMenuGridPanel = { 7 | Data = { 8 | Enabled = true, 9 | }, 10 | Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 275), 11 | Grid = Sprite.New("pause_menu_pages_char_mom_dad", "nose_grid", 0, 0, 200, 200, 0), 12 | Circle = Sprite.New("mpinventory","in_world_circle", 0, 0, 20, 20, 0), 13 | Audio = {Slider = "CONTINUOUS_SLIDER", Library = "HUD_FRONTEND_DEFAULT_SOUNDSET", Id = nil}, 14 | ParentItem = nil, 15 | Text = { 16 | Top = UIResText.New(TopText or "Top", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), 17 | Left = UIResText.New(LeftText or "Left", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), 18 | Right = UIResText.New(RightText or "Right", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), 19 | Bottom = UIResText.New(BottomText or "Bottom", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), 20 | }, 21 | } 22 | return setmetatable(_UIMenuGridPanel, UIMenuGridPanel) 23 | end 24 | 25 | function UIMenuGridPanel:SetParentItem(Item) -- required 26 | if Item() == "UIMenuItem" then 27 | self.ParentItem = Item 28 | else 29 | return self.ParentItem 30 | end 31 | end 32 | 33 | function UIMenuGridPanel:Enabled(Enabled) 34 | if type(Enabled) == "boolean" then 35 | self.Data.Enabled = Enabled 36 | else 37 | return self.Data.Enabled 38 | end 39 | end 40 | 41 | function UIMenuGridPanel:CirclePosition(X, Y) 42 | if tonumber(X) and tonumber(Y) then 43 | self.Circle.X = (self.Grid.X + 20) + ((self.Grid.Width - 40) * ((X >= 0.0 and X <= 1.0) and X or 0.0)) - (self.Circle.Width/2) 44 | self.Circle.Y = (self.Grid.Y + 20) + ((self.Grid.Height - 40) * ((Y >= 0.0 and Y <= 1.0) and Y or 0.0)) - (self.Circle.Height/2) 45 | else 46 | return math.round((self.Circle.X - (self.Grid.X + 20) + (self.Circle.Width/2))/(self.Grid.Width - 40), 2), math.round((self.Circle.Y - (self.Grid.Y + 20) + (self.Circle.Height/2))/(self.Grid.Height - 40), 2) 47 | end 48 | end 49 | 50 | function UIMenuGridPanel:Position(Y) -- required 51 | if tonumber(Y) then 52 | local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset 53 | 54 | self.Background:Position(ParentOffsetX, Y) 55 | self.Grid:Position(ParentOffsetX + 115.5 + (ParentOffsetWidth/2), 37.5 + Y) 56 | self.Text.Top:Position(ParentOffsetX + 215.5 + (ParentOffsetWidth/2), 5 + Y) 57 | self.Text.Left:Position(ParentOffsetX + 57.75 + (ParentOffsetWidth/2), 120 + Y) 58 | self.Text.Right:Position(ParentOffsetX + 373.25 + (ParentOffsetWidth/2), 120 + Y) 59 | self.Text.Bottom:Position(ParentOffsetX + 215.5 + (ParentOffsetWidth/2), 240 + Y) 60 | 61 | if not self.CircleLocked then 62 | self.CircleLocked = true 63 | self:CirclePosition(0.5, 0.5) 64 | end 65 | end 66 | end 67 | 68 | function UIMenuGridPanel:UpdateParent(X, Y) 69 | local _, ParentType = self.ParentItem() 70 | self.Data.Value = {X = X, Y = Y} 71 | if ParentType == "UIMenuListItem" then 72 | local PanelItemIndex = self.ParentItem:FindPanelItem() 73 | if PanelItemIndex then 74 | self.ParentItem.Items[PanelItemIndex].Value[self.ParentItem:FindPanelIndex(self)] = {X = X, Y = Y} 75 | self.ParentItem:Index(PanelItemIndex) 76 | self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 77 | self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 78 | else 79 | local PanelIndex = self.ParentItem:FindPanelIndex(self) 80 | for Index = 1, #self.ParentItem.Items do 81 | if type(self.ParentItem.Items[Index]) == "table" then 82 | if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end 83 | self.ParentItem.Items[Index].Panels[PanelIndex] = {X = X, Y = Y} 84 | else 85 | self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = {X = X, Y = Y}}} 86 | end 87 | end 88 | self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 89 | self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 90 | end 91 | elseif ParentType == "UIMenuItem" then 92 | self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, {X = X, Y = Y}) 93 | end 94 | end 95 | 96 | function UIMenuGridPanel:Functions() 97 | local SafeZone = {X = 0, Y = 0} 98 | if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then 99 | SafeZone = GetSafeZoneBounds() 100 | end 101 | 102 | if IsMouseInBounds(self.Grid.X + 20 + SafeZone.X, self.Grid.Y + 20 + SafeZone.Y, self.Grid.Width - 40, self.Grid.Height - 40) then 103 | if IsDisabledControlJustPressed(0, 24) then 104 | if not self.Pressed then 105 | self.Pressed = true 106 | Citizen.CreateThread(function() 107 | self.Audio.Id = GetSoundId() 108 | PlaySoundFrontend(self.Audio.Id, self.Audio.Slider, self.Audio.Library, 1) 109 | while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.Grid.X + 20 + SafeZone.X, self.Grid.Y + 20 + SafeZone.Y, self.Grid.Width - 40, self.Grid.Height - 40) do 110 | Citizen.Wait(0) 111 | local CursorX, CursorY = math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X - (self.Circle.Width/2), math.round(GetControlNormal(0, 240) * 1080) - SafeZone.Y - (self.Circle.Height/2) 112 | 113 | self.Circle:Position(((CursorX > (self.Grid.X + 10 + self.Grid.Width - 40)) and (self.Grid.X + 10 + self.Grid.Width - 40) or ((CursorX < (self.Grid.X + 20 - (self.Circle.Width/2))) and (self.Grid.X + 20 - (self.Circle.Width/2)) or CursorX)), ((CursorY > (self.Grid.Y + 10 + self.Grid.Height - 40)) and (self.Grid.Y + 10 + self.Grid.Height - 40) or ((CursorY < (self.Grid.Y + 20 - (self.Circle.Height/2))) and (self.Grid.Y + 20 - (self.Circle.Height/2)) or CursorY))) 114 | end 115 | StopSound(self.Audio.Id) 116 | ReleaseSoundId(self.Audio.Id) 117 | self.Pressed = false 118 | end) 119 | Citizen.CreateThread(function() 120 | while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.Grid.X + 20 + SafeZone.X, self.Grid.Y + 20 + SafeZone.Y, self.Grid.Width - 40, self.Grid.Height - 40) do 121 | Citizen.Wait(75) 122 | local ResultX, ResultY = math.round((self.Circle.X - (self.Grid.X + 20) + (self.Circle.Width/2))/(self.Grid.Width - 40), 2), math.round((self.Circle.Y - (self.Grid.Y + 20) + (self.Circle.Height/2))/(self.Grid.Height - 40), 2) 123 | 124 | self:UpdateParent((((ResultX >= 0.0 and ResultX <= 1.0) and ResultX or ((ResultX <= 0) and 0.0) or 1.0) * 2) - 1, (((ResultY >= 0.0 and ResultY <= 1.0) and ResultY or ((ResultY <= 0) and 0.0) or 1.0) * 2) - 1) 125 | end 126 | end) 127 | end 128 | end 129 | end 130 | end 131 | 132 | function UIMenuGridPanel:Draw() -- required 133 | if self.Data.Enabled then 134 | self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 275) 135 | 136 | self.Background:Draw() 137 | self.Grid:Draw() 138 | self.Circle:Draw() 139 | self.Text.Top:Draw() 140 | self.Text.Left:Draw() 141 | self.Text.Right:Draw() 142 | self.Text.Bottom:Draw() 143 | self:Functions() 144 | end 145 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/panels/UIMenuPercentagePanel.lua: -------------------------------------------------------------------------------- 1 | UIMenuPercentagePanel = setmetatable({}, UIMenuPercentagePanel) 2 | UIMenuPercentagePanel.__index = UIMenuPercentagePanel 3 | UIMenuPercentagePanel.__call = function() return "UIMenuPanel", "UIMenuPercentagePanel" end 4 | 5 | function UIMenuPercentagePanel.New(MinText, MaxText) 6 | _UIMenuPercentagePanel = { 7 | Data = { 8 | Enabled = true, 9 | }, 10 | Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 76), 11 | ActiveBar = UIResRectangle.New(0, 0, 413, 10, 245, 245, 245, 255), 12 | BackgroundBar = UIResRectangle.New(0, 0, 413, 10, 87, 87, 87, 255), 13 | Text = { 14 | Min = UIResText.New(MinText or "0%", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), 15 | Max = UIResText.New("100%", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), 16 | Title = UIResText.New(MaxText or "Opacity", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"), 17 | }, 18 | Audio = {Slider = "CONTINUOUS_SLIDER", Library = "HUD_FRONTEND_DEFAULT_SOUNDSET", Id = nil}, 19 | ParentItem = nil, 20 | } 21 | 22 | return setmetatable(_UIMenuPercentagePanel, UIMenuPercentagePanel) 23 | end 24 | 25 | function UIMenuPercentagePanel:SetParentItem(Item) -- required 26 | if Item() == "UIMenuItem" then 27 | self.ParentItem = Item 28 | else 29 | return self.ParentItem 30 | end 31 | end 32 | 33 | function UIMenuPercentagePanel:Enabled(Enabled) 34 | if type(Enabled) == "boolean" then 35 | self.Data.Enabled = Enabled 36 | else 37 | return self.Data.Enabled 38 | end 39 | end 40 | 41 | function UIMenuPercentagePanel:Position(Y) -- required 42 | if tonumber(Y) then 43 | local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset 44 | self.Background:Position(ParentOffsetX, Y) 45 | self.ActiveBar:Position(ParentOffsetX + (ParentOffsetWidth/2) + 9, 50 + Y) 46 | self.BackgroundBar:Position(ParentOffsetX + (ParentOffsetWidth/2) + 9, 50 + Y) 47 | self.Text.Min:Position(ParentOffsetX + (ParentOffsetWidth/2) + 25, 15 + Y) 48 | self.Text.Max:Position(ParentOffsetX + (ParentOffsetWidth/2) + 398, 15 + Y) 49 | self.Text.Title:Position(ParentOffsetX + (ParentOffsetWidth/2) + 215.5, 15 + Y) 50 | end 51 | end 52 | 53 | function UIMenuPercentagePanel:Percentage(Value) 54 | if tonumber(Value) then 55 | local Percent = ((Value < 0.0) and 0.0) or ((Value > 1.0) and 1.0 or Value) 56 | self.ActiveBar:Size(self.BackgroundBar.Width * Percent, self.ActiveBar.Height) 57 | else 58 | local SafeZone = {X = 0, Y = 0} 59 | if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then 60 | SafeZone = GetSafeZoneBounds() 61 | end 62 | 63 | local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X 64 | return math.round(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413))/self.BackgroundBar.Width, 2) 65 | end 66 | end 67 | 68 | function UIMenuPercentagePanel:UpdateParent(Percentage) 69 | local _, ParentType = self.ParentItem() 70 | if ParentType == "UIMenuListItem" then 71 | local PanelItemIndex = self.ParentItem:FindPanelItem() 72 | if PanelItemIndex then 73 | self.ParentItem.Items[PanelItemIndex].Value[self.ParentItem:FindPanelIndex(self)] = Percentage 74 | self.ParentItem:Index(PanelItemIndex) 75 | self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 76 | self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 77 | else 78 | local PanelIndex = self.ParentItem:FindPanelIndex(self) 79 | for Index = 1, #self.ParentItem.Items do 80 | if type(self.ParentItem.Items[Index]) == "table" then 81 | if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end 82 | self.ParentItem.Items[Index].Panels[PanelIndex] = Percentage 83 | else 84 | self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = Percentage}} 85 | end 86 | end 87 | self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 88 | self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index) 89 | end 90 | elseif ParentType == "UIMenuItem" then 91 | self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, Percentage) 92 | end 93 | end 94 | 95 | function UIMenuPercentagePanel:Functions() 96 | 97 | local SafeZone = {X = 0, Y = 0} 98 | if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then 99 | SafeZone = GetSafeZoneBounds() 100 | end 101 | 102 | if IsMouseInBounds(self.BackgroundBar.X + SafeZone.X, self.BackgroundBar.Y - 4 + SafeZone.Y, self.BackgroundBar.Width, self.BackgroundBar.Height + 8) then 103 | if IsDisabledControlJustPressed(0, 24) then 104 | if not self.Pressed then 105 | self.Pressed = true 106 | Citizen.CreateThread(function() 107 | self.Audio.Id = GetSoundId() 108 | PlaySoundFrontend(self.Audio.Id, self.Audio.Slider, self.Audio.Library, 1) 109 | while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.BackgroundBar.X + SafeZone.X, self.BackgroundBar.Y - 4 + SafeZone.Y, self.BackgroundBar.Width, self.BackgroundBar.Height + 8) do 110 | Citizen.Wait(0) 111 | local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X 112 | self.ActiveBar:Size(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413)), self.ActiveBar.Height) 113 | end 114 | StopSound(self.Audio.Id) 115 | ReleaseSoundId(self.Audio.Id) 116 | self.Pressed = false 117 | end) 118 | Citizen.CreateThread(function() 119 | while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.BackgroundBar.X + SafeZone.X, self.BackgroundBar.Y - 4 + SafeZone.Y, self.BackgroundBar.Width, self.BackgroundBar.Height + 8) do 120 | Citizen.Wait(75) 121 | local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X 122 | self:UpdateParent(math.round(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413))/self.BackgroundBar.Width, 2)) 123 | end 124 | end) 125 | end 126 | end 127 | end 128 | end 129 | 130 | function UIMenuPercentagePanel:Draw() -- required 131 | if self.Data.Enabled then 132 | self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 76) 133 | self.Background:Draw() 134 | self.BackgroundBar:Draw() 135 | self.ActiveBar:Draw() 136 | self.Text.Min:Draw() 137 | self.Text.Max:Draw() 138 | self.Text.Title:Draw() 139 | self:Functions() 140 | end 141 | end -------------------------------------------------------------------------------- /NativeUI from Frazzle/windows/UIMenuHeritageWindow.lua: -------------------------------------------------------------------------------- 1 | UIMenuHeritageWindow = setmetatable({}, UIMenuHeritageWindow) 2 | UIMenuHeritageWindow.__index = UIMenuHeritageWindow 3 | UIMenuHeritageWindow.__call = function() return "UIMenuWindow", "UIMenuHeritageWindow" end 4 | 5 | function UIMenuHeritageWindow.New(Mum, Dad) 6 | if not tonumber(Mum) then Mum = 0 end 7 | if not (Mum >= 0 and Mum <= 21) then Mum = 0 end 8 | if not tonumber(Dad) then Dad = 0 end 9 | if not (Dad >= 0 and Dad <= 23) then Dad = 0 end 10 | _UIMenuHeritageWindow = { 11 | Background = Sprite.New("pause_menu_pages_char_mom_dad", "mumdadbg", 0, 0, 431, 228), -- Background is required, must be a sprite or a rectangle. 12 | MumSprite = Sprite.New("char_creator_portraits", ((Mum < 21) and "female_"..Mum or "special_female_"..(tonumber(string.sub(Mum, 2, 2)) - 1)), 0, 0, 228, 228), 13 | DadSprite = Sprite.New("char_creator_portraits", ((Dad < 21) and "male_"..Dad or "special_male_"..(tonumber(string.sub(Dad, 2, 2)) - 1)), 0, 0, 228, 228), 14 | Mum = Mum, 15 | Dad = Dad, 16 | _Offset = {X = 0, Y = 0}, -- required 17 | ParentMenu = nil, -- required 18 | } 19 | return setmetatable(_UIMenuHeritageWindow, UIMenuHeritageWindow) 20 | end 21 | 22 | function UIMenuHeritageWindow:SetParentMenu(Menu) -- required 23 | if Menu() == "UIMenu" then 24 | self.ParentMenu = Menu 25 | else 26 | return self.ParentMenu 27 | end 28 | end 29 | 30 | function UIMenuHeritageWindow:Offset(X, Y) -- required 31 | if tonumber(X) or tonumber(Y) then 32 | if tonumber(X) then 33 | self._Offset.X = tonumber(X) 34 | end 35 | if tonumber(Y) then 36 | self._Offset.Y = tonumber(Y) 37 | end 38 | else 39 | return self._Offset 40 | end 41 | end 42 | 43 | function UIMenuHeritageWindow:Position(Y) -- required 44 | if tonumber(Y) then 45 | self.Background:Position(self._Offset.X, 144 + Y + self._Offset.Y) 46 | self.MumSprite:Position(self._Offset.X + (self.ParentMenu.WidthOffset/2) + 25, 144 + Y + self._Offset.Y) 47 | self.DadSprite:Position(self._Offset.X + (self.ParentMenu.WidthOffset/2) + 195, 144 + Y + self._Offset.Y) 48 | end 49 | end 50 | 51 | function UIMenuHeritageWindow:Index(Mum, Dad) 52 | if not tonumber(Mum) then Mum = self.Mum end 53 | if not (Mum >= 0 and Mum <= 21) then Mum = self.Mum end 54 | if not tonumber(Dad) then Dad = self.Dad end 55 | if not (Dad >= 0 and Dad <= 23) then Dad = self.Dad end 56 | 57 | self.Mum = Mum 58 | self.Dad = Dad 59 | 60 | self.MumSprite.TxtName = ((self.Mum < 21) and "female_"..self.Mum or "special_female_"..(tonumber(string.sub(Mum, 2, 2)) - 1)) 61 | self.DadSprite.TxtName = ((self.Dad < 21) and "male_"..self.Dad or "special_male_"..(tonumber(string.sub(Dad, 2, 2)) - 1)) 62 | end 63 | 64 | function UIMenuHeritageWindow:Draw() -- required 65 | self.Background:Size(431 + self.ParentMenu.WidthOffset, 228) 66 | self.Background:Draw() 67 | self.DadSprite:Draw() 68 | self.MumSprite:Draw() 69 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimpleMenu 2 | 3 | [Visit the Wiki for MORE!](https://github.com/Thymester/SimpleMenu/wiki) 4 | 5 | # NOTE 6 | 7 | The code is a absolute mess. This was my first ever project and was extremely bad at coding. 8 | -------------------------------------------------------------------------------- /Tutorial.html: -------------------------------------------------------------------------------- 1 | 2 | SimpleMenu 3 | 4 |

SimpleMenu Tutorial

5 |
6 | 7 | 8 |

SimpleMenu

9 |

10 | 11 |

How to get Emergency Services Vehicle List

12 |
13 |

1: Uncomment Lines 453 --> 458

14 |
15 | 16 |

INSTALL INSTRUCTIONS: 17 |

18 | 1: Download the Menu from FiveM Forums: SimpleMenu 19 |
20 | 2: Drag & Drop the two folders into resources 21 |
22 | 3: In order do the following 23 |


24 |
start NativeUI 25 |
26 | start SimpleMenu 27 |


28 | 4: Do not change the name of any of the folders to make it easier. server.cfg is case sensitive 29 |
30 |

31 | * - If you wish you may use this in any private or public project!

32 |
33 |

Changelog

34 |
35 |

Visit Releases at GitHub for Releases!

36 |
37 | 38 |

To add Permissions to any given person do the following.

39 |
40 |

# SimpleMenu Group 41 |
42 |


43 | add_ace identifier.steam:[Steam HEX Here] simplemenu.admin allow --Name of Person Here 44 |

45 | add_ace identifier.steam:[Steam HEX Here] simplemenu.state allow --Name of Person Here 46 |

47 | add_ace identifier.steam:[Steam HEX Here] simplemenu.highway allow --Name of Person Here 48 |

49 | add_ace identifier.steam:[Steam HEX Here] simplemenu.sheriff allow --Name of Person Here 50 |

51 | add_ace identifier.steam:[Steam HEX Here] simplemenu.emt allow --Name of Person Here 52 |

53 | add_ace identifier.steam:[Steam HEX Here] simplemenu.emergency allow --Name of Person Here

54 |

55 | 56 |

How to ONLY allow Admins to Open the Menu

57 |
58 | 59 |

1: Go to line 1871 60 |
61 | 2: Uncomment lines 1871 –> 1881 62 |
63 | NOTE: To uncomment take out “–[[” and “]]”

64 |
65 | 66 |

How to add Emergency Services Cars

67 |
68 | 69 |

1: Go to lines 386 –> 406 70 |
71 | 2: When you go there add the Emergency Services spawn codes (On your server) to be able to spawn them in-game 72 |
73 | 3: Must reload script after changes

74 |
75 | 76 |

How to get Emergency Loadouts

77 |
78 | 79 |

1: Go to 452 –> 457 80 |
81 | 2: Uncomment those lines by removing the two “–” before each ‘submenu:AddItem()

82 |
83 | 84 |

How to get Addon Peds

85 |
86 | 87 |

1: Go to line 1681 and uncomment it 88 |
89 | 2: Go to line 1683 and uncomment it 90 |
91 | 3: Go to line 1689 and uncomment it which is commented from 1689 –> 1693 (Remove “–[[” and “]]”)

92 |
93 | 94 |

Ace Permissions are added to the following.

95 |
96 | 97 |

1: Healing 98 |
99 | 2: Armour Giving 100 |
101 | 3: Godmode 102 |
103 | 4: Invisibility 104 |
105 | NOTE: There may or may not be more added from updates.

106 |
107 | 108 |

How to enable Custom Car & Ped Spawning

109 |
110 | 111 |

For Custom Car Spawns 112 |
113 | 1: Uncomment lines 385 & 387 (To uncomment remove “–”) 114 |
115 | 2: Uncomment lines 393 -> 397 (To uncomment remove “–[[” and “]]”) 116 |
117 | For Custom Ped Spawns 118 |
119 | 1: Uncomment lines 1286 & 1288 (To uncomment remove “–”) 120 |
121 | 2: Uncomment lines 1294 -> 1298 (To uncomment remove “–[[” and “]]”) 122 |
123 | To add the Custom Peds and Custom Cars follow the templates located on lines 310 & 1234

124 |
125 | 126 |

NOTE:

127 |
128 | 129 |

NativeUI is from Frazzle not myself, if you wish to download the files located on GitHub (SimpleMenu & NativeUI) it is NOT in a drag & drop format!

130 |

NativeUI Download Link
-------------------------------------------------------------------------------- /__resource.lua: -------------------------------------------------------------------------------- 1 | resource_manifest_version '05cfa83c-a124-4cfa-a768-c24a5811d8f9' 2 | 3 | dependency 'NativeUI' 4 | 5 | client_scripts { 6 | "@NativeUI/NativeUI.lua", 7 | "SimpleMenu.lua", 8 | } 9 | 10 | server_scripts { 11 | "perms/perms.lua", 12 | } 13 | 14 | client_scripts "SimpleMenu.lua" -------------------------------------------------------------------------------- /perms/perms.lua: -------------------------------------------------------------------------------- 1 | RegisterServerEvent("admin:getIsAllowed") 2 | AddEventHandler("admin:getIsAllowed", function() 3 | if IsPlayerAceAllowed(source, "simplemenu.admin") then 4 | TriggerClientEvent("admin:returnIsAllowed", source, true) 5 | else 6 | TriggerClientEvent("admin:returnIsAllowed", source, false) 7 | end 8 | end) 9 | 10 | RegisterServerEvent("fire:getIsFire") 11 | AddEventHandler("fire:getIsFire", function() 12 | if IsPlayerAceAllowed(source, "simplemenu.fire") then 13 | TriggerClientEvent("fire:returnIsFire", source, true) 14 | else 15 | TriggerClientEvent("fire:returnIsFire", source, false) 16 | end 17 | end) 18 | 19 | RegisterServerEvent("emt:getIsEmt") 20 | AddEventHandler("emt:getIsEmt", function() 21 | if IsPlayerAceAllowed(source, "simplemenu.emt") then 22 | TriggerClientEvent("emt:returnIsEmt", source, true) 23 | else 24 | TriggerClientEvent("emt:returnIsEmt", source, false) 25 | end 26 | end) 27 | 28 | RegisterServerEvent("police:getIsPolice") 29 | AddEventHandler("police:getIsPolice", function() 30 | if IsPlayerAceAllowed(source, "simplemenu.police") then 31 | TriggerClientEvent("police:returnIsPolice", source, true) 32 | else 33 | TriggerClientEvent("police:returnIsPolice", source, false) 34 | end 35 | end) 36 | 37 | RegisterServerEvent("sheriff:getIsSheriff") 38 | AddEventHandler("sheriff:getIsSheriff", function() 39 | if IsPlayerAceAllowed(source, "simplemenu.sheriff") then 40 | TriggerClientEvent("sheriff:returnIsSheriff", source, true) 41 | else 42 | TriggerClientEvent("sheriff:returnIsSheriff", source, false) 43 | end 44 | end) 45 | 46 | RegisterServerEvent("state:getIsState") 47 | AddEventHandler("state:getIsState", function() 48 | if IsPlayerAceAllowed(source, "simplemenu.state") then 49 | TriggerClientEvent("state:returnIsState", source, true) 50 | else 51 | TriggerClientEvent("state:returnIsState", source, false) 52 | end 53 | end) 54 | 55 | RegisterServerEvent("highway:getIsHighway") 56 | AddEventHandler("highway:getIsHighway", function() 57 | if IsPlayerAceAllowed(source, "simplemenu.highway") then 58 | TriggerClientEvent("highway:returnIsHighway", source, true) 59 | else 60 | TriggerClientEvent("highway:returnIsHighway", source, false) 61 | end 62 | end) 63 | 64 | function SendWebhookMessage(webhook,message) 65 | if webhook ~= "false" then 66 | PerformHttpRequest(webhook, function(err, text, headers) end, 'POST', json.encode({content = message}), { ['Content-Type'] = 'application/json' }) 67 | end 68 | end 69 | 70 | function mysplit(inputstr, sep) 71 | if sep == nil then 72 | sep = "%s" 73 | end 74 | local t={} ; i=1 75 | for str in string.gmatch(inputstr, "([^"..sep.."]+)") do 76 | t[i] = str 77 | i = i + 1 78 | end 79 | return t 80 | end -------------------------------------------------------------------------------- /tutorial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SimpleMenu 5 | 63 | 64 | 65 |
66 |

SimpleMenu Tutorial

67 |
68 | 69 |
70 |

SimpleMenu

71 |
72 |
73 | 74 |
75 |

How to Get Emergency Services Vehicle List

76 |
77 |

1: Uncomment Lines 453 - 458

78 |
79 | 80 |
81 |

Install Instructions:

82 |
83 |

1: Download the Menu from FiveM Forums: SimpleMenu

84 |

2: Drag & Drop the two folders into resources

85 |

3: In order do the following:

86 |

start NativeUI
start SimpleMenu

87 |

4: Do not change the name of any folders to maintain case sensitivity in server.cfg

88 |

- You may use this in any private or public project!

89 |
90 | 91 |
92 |

Changelog

93 |
94 |

Visit Releases at GitHub for Releases!

95 |
96 | 97 |
98 |

To add Permissions to any given person do the following.

99 |
100 |

# SimpleMenu Group

101 |

add_ace identifier.steam:[Steam HEX Here] simplemenu.admin allow --Name of Person Here

102 |

add_ace identifier.steam:[Steam HEX Here] simplemenu.state allow --Name of Person Here

103 |

add_ace identifier.steam:[Steam HEX Here] simplemenu.highway allow --Name of Person Here

104 |

add_ace identifier.steam:[Steam HEX Here] simplemenu.sheriff allow --Name of Person Here

105 |

add_ace identifier.steam:[Steam HEX Here] simplemenu.emt allow --Name of Person Here

106 |

add_ace identifier.steam:[Steam HEX Here] simplemenu.emergency allow --Name of Person Here

107 |
108 | 109 |
110 |

How to ONLY allow Admins to Open the Menu

111 |
112 |

1: Go to line 1871

113 |

2: Uncomment lines 1871 - 1881

114 |

NOTE: To uncomment, remove ""

115 |
116 | 117 |
118 |

How to add Emergency Services Cars

119 |
120 |

1: Go to lines 386 - 406

121 |

2: Add Emergency Services spawn codes (On your server) to be able to spawn them in-game

122 |

3: Must reload script after changes

123 |
124 | 125 |
126 |

How to get Emergency Loadouts

127 |
128 |

1: Go to 452 - 457

129 |

2: Uncomment those lines by removing the two "--" before each submenu:AddItem()

130 |
131 | 132 |
133 |

How to get Addon Peds

134 |
135 |

1: Go to line 1681 and uncomment it

136 |

2: Go to line 1683 and uncomment it

137 |

3: Go to line 1689 and uncomment it which is commented from 1689 - 1693 (Remove "")

138 |

To add the Custom Peds and Custom Cars, follow the templates located on lines 310 & 1234

139 |
140 | 141 |
142 |

Ace Permissions are added to the following.

143 |
144 |

1: Healing

145 |

2: Armour Giving

146 |

3: Godmode

147 |

4: Invisibility

148 |

NOTE: There may or may not be more added from updates.

149 |
150 | 151 |
152 |

How to enable Custom Car & Ped Spawning

153 |
154 |

For Custom Car Spawns

155 |

1: Uncomment lines 385 & 387 (To uncomment, remove "--")

156 |

2: Uncomment lines 393 - 397 (To uncomment, remove "")

157 |

For Custom Ped Spawns

158 |

1: Uncomment lines 1286 & 1288 (To uncomment, remove "--")

159 |

2: Uncomment lines 1294 - 1298 (To uncomment, remove "")

160 |

To add the Custom Peds and Custom Cars, follow the templates located on lines 310 & 1234

161 |
162 | 163 |
164 |

NOTE:

165 |
166 |

NativeUI Download Link

167 |

NativeUI is from Frazzle, not myself. If you wish to download the files located on GitHub (SimpleMenu & NativeUI), they are NOT in a drag & drop format!

168 |
169 |
170 | 171 | 172 | -------------------------------------------------------------------------------- /version.lua: -------------------------------------------------------------------------------- 1 | v1.4 2 | --------------------------------------------------------------------------------