├── .gitignore
├── LICENSE
├── NativeUI.lua
├── README.md
├── __resource.lua
├── base
├── MenuPool.lua
└── UIMenu.lua
├── elements
├── Badge.lua
├── Colours.lua
├── ColoursPanel.lua
├── Sprite.lua
├── StringMeasurer.lua
├── UIResRectangle.lua
└── UIResText.lua
├── example
└── DefaultShowcase.lua
├── items
├── UIMenuCheckboxItem.lua
├── UIMenuColouredItem.lua
├── UIMenuItem.lua
├── UIMenuListItem.lua
├── UIMenuProgressItem.lua
├── UIMenuSliderHeritageItem.lua
└── UIMenuSliderItem.lua
├── panels
├── UIMenuColourPanel.lua
├── UIMenuGridPanel.lua
└── UIMenuPercentagePanel.lua
├── share
└── Utils.lua
└── windows
└── UIMenuHeritageWindow.lua
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Lua sources
2 | luac.out
3 |
4 | # luarocks build files
5 | *.src.rock
6 | *.zip
7 | *.tar.gz
8 |
9 | # Object files
10 | *.o
11 | *.os
12 | *.ko
13 | *.obj
14 | *.elf
15 |
16 | # Precompiled Headers
17 | *.gch
18 | *.pch
19 |
20 | # Libraries
21 | *.lib
22 | *.a
23 | *.la
24 | *.lo
25 | *.def
26 | *.exp
27 |
28 | # Shared objects (inc. Windows DLLs)
29 | *.dll
30 | *.so
31 | *.so.*
32 | *.dylib
33 |
34 | # Executables
35 | *.exe
36 | *.out
37 | *.app
38 | *.i*86
39 | *.x86_64
40 | *.hex
41 |
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/NativeUI.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | _ _ _ _ _ _ ___ _
3 | | \ | | __ _| |_(_)_ _____| | | |_ _| | _ _ __ _
4 | | \| |/ _` | __| \ \ / / _ \ | | || || | | | | |/ _` |
5 | | |\ | (_| | |_| |\ V / __/ |_| || || |__| |_| | (_| |
6 | |_| \_|\__,_|\__|_| \_/ \___|\___/|___|_____\__,_|\__,_|~GTA:O UI Menu
7 |
8 | Owner : Frazzle
9 |
10 | Git : iTexZoz/NativeUILua
11 |
12 | =Releases history 2018 - 2019
13 |
14 | [1.0]
15 | -Initial comit
16 |
17 | [1.0.1]
18 | -Fixed __resource.lua
19 |
20 | [1.0.2]
21 | -Fixed the NativeUI.* functions not working as intended
22 |
23 | [1.0.3]
24 | -Fixed a typo that prevented safezone scaling
25 |
26 | [1.0.4]
27 | -Fixed mouse tracking that broke after fixing my safezone type..
28 |
29 | [1.0.5 ]
30 | -Added support for all resolutions!
31 |
32 | [1.0.6]
33 | -Fixed item events
34 | -Added a Colours table filled with the HUD colours
35 | -Fixed mouse on resolutions below 1280x720
36 | -Added text colour and highlight colour options to the :RightLabel() on UIMenuItem
37 |
38 | [1.0.7]
39 | -Conflicting function name
40 |
41 | [1.0.8]
42 | -Fixed resolution scaling on resolutions > 1920x1080
43 |
44 | [1.0.9]
45 | -Removed all mentions of a function that is no longer used and breaks the script
46 |
47 | [1.1.0]
48 | -Fixed scaling on 3840x1080
49 |
50 | [2.0.0]
51 | -Lots of bug fixes
52 | -Panels
53 | -Windows
54 |
55 | [2.1.0]
56 | -More bug fixes related to resolution and positioning.
57 | -Added UIMenuProgressItem item
58 |
59 | [2.1.1]
60 | -Diverses résolutions de bugs (comme les UIMenuColouredItem)
61 | -Divers ajouts tel que le UIMenuSliderHeritageItem et bien d'autres...
62 | -Quelques résolutions de problèmes mineurs au niveau de l'interface tel que les "arrowleft" / "arrowright" de UIMenuListItem.
63 | -Quelques ajouts de configurations supplémentaires pour certains éléments.
64 | -Un exemple complet de toutes les features disponibles dans cette version.
65 | -Modifications de certains bruits sonores du menu lors de l'utilisation des sliders.
66 | -Modification possible de la couleur/opacité de la banière du menu et des sliders.
67 | -Possibilité d'ajouter des badges et des labels sur les submenus.
68 | -Possibilité de modifier la couleur/opacité du background et de la barre de progression.
69 |
70 | [2.1.2]
71 | ...
72 |
73 | --TODO Ajout d'un systeme d'actualisation de badge dynamique, (comme warmenu)
74 | --TODO Ajout de badge custome possible.
75 | --TODO Resoudre des problémes mineurs sur l'interface.
76 | --TODO ...
77 | ]]--
78 |
79 |
80 |
81 | NativeUI = {}
82 |
83 | ---CreatePool
84 | function NativeUI.CreatePool()
85 | return MenuPool.New()
86 | end
87 |
88 | ---CreateMenu
89 | ---@param Title string
90 | ---@param Subtitle string
91 | ---@param X number
92 | ---@param Y number
93 | ---@param TxtDictionary string
94 | ---@param TxtName string
95 | ---@param Heading number
96 | ---@param R number
97 | ---@param G number
98 | ---@param B number
99 | ---@param A number
100 | function NativeUI.CreateMenu(Title, Subtitle, X, Y, TxtDictionary, TxtName, Heading, R, G, B, A)
101 | return UIMenu.New(Title, Subtitle, X, Y, TxtDictionary, TxtName, Heading, R, G, B, A)
102 | end
103 |
104 | ---CreateItem
105 | ---@param Text string
106 | ---@param Description string
107 | function NativeUI.CreateItem(Text, Description)
108 | return UIMenuItem.New(Text, Description)
109 | end
110 |
111 | ---CreateColouredItem
112 | ---@param Text string
113 | ---@param Description string
114 | ---@param MainColour table
115 | ---@param HighlightColour table
116 | function NativeUI.CreateColouredItem(Text, Description, MainColour, HighlightColour)
117 | return UIMenuColouredItem.New(Text, Description, MainColour, HighlightColour)
118 | end
119 |
120 | ---CreateCheckboxItem
121 | ---@param Text string
122 | ---@param Check boolean
123 | ---@param Description string
124 | function NativeUI.CreateCheckboxItem(Text, Check, Description)
125 | return UIMenuCheckboxItem.New(Text, Check, Description)
126 | end
127 |
128 | ---CreateListItem
129 | ---@param Text string
130 | ---@param Items number
131 | ---@param Index table
132 | ---@param Description string
133 | function NativeUI.CreateListItem(Text, Items, Index, Description)
134 | return UIMenuListItem.New(Text, Items, Index, Description)
135 | end
136 |
137 | ---CreateSliderItem
138 | ---@param Text string
139 | ---@param Items number
140 | ---@param Index table
141 | ---@param Description string
142 | ---@param Divider boolean
143 | ---@param SliderColors table
144 | ---@param BackgroundSliderColors table
145 | function NativeUI.CreateSliderItem(Text, Items, Index, Description, Divider, SliderColors, BackgroundSliderColors)
146 | return UIMenuSliderItem.New(Text, Items, Index, Description, Divider, SliderColors, BackgroundSliderColors)
147 | end
148 | ---CreateSliderHeritageItem
149 | ---@param Text string
150 | ---@param Items number
151 | ---@param Index table
152 | ---@param Description string
153 | ---@param SliderColors table
154 | ---@param BackgroundSliderColors table
155 | function NativeUI.CreateSliderHeritageItem(Text, Items, Index, Description, SliderColors, BackgroundSliderColors)
156 | return UIMenuSliderHeritageItem.New(Text, Items, Index, Description, SliderColors, BackgroundSliderColors)
157 | end
158 |
159 | ---CreateProgressItem
160 | ---@param Text string
161 | ---@param Items number
162 | ---@param Index table
163 | ---@param Description number
164 | ---@param Counter boolean
165 | function NativeUI.CreateProgressItem(Text, Items, Index, Description, Counter)
166 | return UIMenuProgressItem.New(Text, Items, Index, Description, Counter)
167 | end
168 |
169 | ---CreateHeritageWindow
170 | ---@param Mum number
171 | ---@param Dad number
172 | function NativeUI.CreateHeritageWindow(Mum, Dad)
173 | return UIMenuHeritageWindow.New(Mum, Dad)
174 | end
175 |
176 | ---CreateGridPanel
177 | ---@param TopText string
178 | ---@param LeftText string
179 | ---@param RightText string
180 | ---@param BottomText string
181 | function NativeUI.CreateGridPanel(TopText, LeftText, RightText, BottomText)
182 | return UIMenuGridPanel.New(TopText, LeftText, RightText, BottomText)
183 | end
184 |
185 | ---CreateColourPanel
186 | ---@param Title string
187 | ---@param Colours table
188 | function NativeUI.CreateColourPanel(Title, Colours)
189 | return UIMenuColourPanel.New(Title, Colours)
190 | end
191 |
192 | ---CreatePercentagePanel
193 | ---@param MinText string
194 | ---@param MaxText string
195 | function NativeUI.CreatePercentagePanel(MinText, MaxText)
196 | return UIMenuPercentagePanel.New(MinText, MaxText)
197 | end
198 |
199 | ---CreateSprite
200 | ---@param TxtDictionary string
201 | ---@param TxtName string
202 | ---@param X number
203 | ---@param Y number
204 | ---@param Width number
205 | ---@param Height number
206 | ---@param Heading number
207 | ---@param R number
208 | ---@param G number
209 | ---@param B number
210 | ---@param A number
211 | function NativeUI.CreateSprite(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A)
212 | return Sprite.New(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A)
213 | end
214 |
215 | ---CreateRectangle
216 | ---@param X number
217 | ---@param Y number
218 | ---@param Width number
219 | ---@param Height number
220 | ---@param R number
221 | ---@param G number
222 | ---@param B number
223 | ---@param A number
224 | function NativeUI.CreateRectangle(X, Y, Width, Height, R, G, B, A)
225 | return UIResRectangle.New(X, Y, Width, Height, R, G, B, A)
226 | end
227 |
228 | ---CreateText
229 | ---@param Text string
230 | ---@param X number
231 | ---@param Y number
232 | ---@param Scale number
233 | ---@param R number
234 | ---@param G number
235 | ---@param B number
236 | ---@param A number
237 | ---@param Font number
238 | ---@param Alignment number
239 | ---@param DropShadow number
240 | ---@param Outline number
241 | ---@param WordWrap number
242 | function NativeUI.CreateText(Text, X, Y, Scale, R, G, B, A, Font, Alignment, DropShadow, Outline, WordWrap)
243 | return UIResText.New(Text, X, Y, Scale, R, G, B, A, Font, Alignment, DropShadow, Outline, WordWrap)
244 | end
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # NativeUI en LUA
3 | ##### ⚠️Following a change and for more understanding I decided to remove the fork and to dedicate a repository to this magnificent project that will be named NativeUI Reloaded , previously based on [FrazzIe](https://github.com/FrazzIe) work . ⚠️
4 |
5 | Original code : [NativeUILua](https://github.com/FrazzIe/NativeUILua)
6 |
7 | > ### EmmyLUA
8 |
9 | JetBrain : https://github.com/EmmyLua/IntelliJ-EmmyLua
10 | Visual Studio code : https://github.com/EmmyLua/VSCode-EmmyLua
11 | 
12 |
13 | ># About this project
14 |
15 | This version cotains in addition :
16 | - Several bugs resolutions (As the UIMenuColouredItem).
17 | - Various add like UIMenuSliderHeritageItem and many others ... .
18 | - Some resolutions of minor problems concerning interface like "arrowleft" / "arroright" of UIMenuListItem.
19 | - A few add of additional configuration for certains elements.
20 | - An complete example of all available features in this version
21 | - Un exemple complet de toutes les features disponibles dans cette version.
22 | - Changes of sliding sound in the sliders menu.
23 | - Modifications of certain noise from the menu when using sliders.
24 | - Modifications of possibility to change color/opacity of the banners of menu and sliders.
25 | - Adding possibility of badges and labels in sub-menu.
26 | - Possibility to change the color/opacity of the background and the progress bar.
27 | - Compatibility with the EmmyLUA plugin
28 |
29 | ✌ And other features to come ... ✌
30 |
31 | NB: Anyone discovering a bug on this version is asked to report the error via an issue so that it can be corrected as quickly as possible.
32 |
33 | ➟ Please use this template for any bug postponement:
34 |
35 | ```
36 | - Describe the bug: A clear and precise description of the bug.
37 |
38 | ➡️ How to reproduces the bug:
39 |
40 | - Go to '...'
41 | - Click on '....'
42 | - Scroll until '....'
43 | - Show the error
44 |
45 | - Clearly describe what should happen instead.
46 |
47 | ➡️ Sreenshot : Add some images or screenshot for help us for the resolutions of the problems.
48 |
49 | ```
50 | For any suggest for adding features , do not hesitate to use this template:
51 |
52 | - In the title of the issue specify : [Adding features request]
53 | - Describe the utility of the features.
54 | - Why you want you would add this features
55 | - Why do you wants to add this features.
56 |
57 | THANK YOU TO ALL WHO FOLLOW THE CHANGES OF THIS FORK!
58 |
59 |
--------------------------------------------------------------------------------
/__resource.lua:
--------------------------------------------------------------------------------
1 | resource_manifest_version '05cfa83c-a124-4cfa-a768-c24a5811d8f9'
2 |
3 | name 'NativeUI'
4 | description 'NativeUI in LUA for FiveM'
5 | author 'FrazzIe (https://github.com/FrazzIe)'
6 | version '2.1.0'
7 |
8 | client_scripts {
9 | "share/Utils.lua",
10 |
11 | "elements/UIResRectangle.lua",
12 | "elements/UIResText.lua",
13 | "elements/Sprite.lua",
14 | "elements/StringMeasurer.lua",
15 | "elements/Badge.lua",
16 | "elements/Colours.lua",
17 | "elements/ColoursPanel.lua",
18 |
19 | "items/UIMenuItem.lua",
20 | "items/UIMenuCheckboxItem.lua",
21 | "items/UIMenuListItem.lua",
22 | "items/UIMenuSliderItem.lua",
23 | "items/UIMenuSliderHeritageItem.lua",
24 | "items/UIMenuColouredItem.lua",
25 | "items/UIMenuprogressItem.lua",
26 |
27 | "windows/UIMenuHeritageWindow.lua",
28 |
29 | "panels/UIMenuGridPanel.lua",
30 | "panels/UIMenuColourPanel.lua",
31 | "panels/UIMenuPercentagePanel.lua",
32 |
33 | "base/UIMenu.lua",
34 | "base/MenuPool.lua",
35 |
36 | "NativeUI.lua",
37 |
38 | "example/DefaultShowcase.lua",
39 | }
40 |
--------------------------------------------------------------------------------
/base/MenuPool.lua:
--------------------------------------------------------------------------------
1 | MenuPool = setmetatable({}, MenuPool)
2 | MenuPool.__index = MenuPool
3 |
4 | ---New
5 | function MenuPool.New()
6 | local _MenuPool = {
7 | Menus = {}
8 | }
9 | return setmetatable(_MenuPool, MenuPool)
10 | end
11 |
12 | ---AddSubMenu
13 | ---@param Menu table
14 | ---@param Text string
15 | ---@param Description string
16 | ---@param KeepPosition boolean
17 | ---@param KeepBanner boolean
18 | function MenuPool:AddSubMenu(Menu, Text, Description, KeepPosition, KeepBanner)
19 | if Menu() == "UIMenu" then
20 | local Item = UIMenuItem.New(tostring(Text), Description or "")
21 | Menu:AddItem(Item)
22 | local SubMenu
23 | if KeepPosition then
24 | SubMenu = UIMenu.New(Menu.Title:Text(), Text, Menu.Position.X, Menu.Position.Y)
25 | else
26 | SubMenu = UIMenu.New(Menu.Title:Text(), Text)
27 | end
28 | if KeepBanner then
29 | if Menu.Logo ~= nil then
30 | SubMenu.Logo = Menu.Logo
31 | else
32 | SubMenu.Logo = nil
33 | SubMenu.Banner = Menu.Banner
34 | end
35 | end
36 |
37 |
38 | self:Add(SubMenu)
39 | Menu:BindMenuToItem(SubMenu, Item)
40 | return {
41 | SubMenu = SubMenu,
42 | Item = Item
43 | }
44 | end
45 | end
46 |
47 | ---Add
48 | ---@param Menu table
49 | function MenuPool:Add(Menu)
50 | if Menu() == "UIMenu" then
51 | table.insert(self.Menus, Menu)
52 | end
53 | end
54 |
55 | ---MouseEdgeEnabled
56 | ---@param bool boolean
57 | function MenuPool:MouseEdgeEnabled(bool)
58 | if bool ~= nil then
59 | for _, Menu in pairs(self.Menus) do
60 | Menu.Settings.MouseEdgeEnabled = tobool(bool)
61 | end
62 | end
63 | end
64 |
65 | ---ControlDisablingEnabled
66 | ---@param bool boolean
67 | function MenuPool:ControlDisablingEnabled(bool)
68 | if bool ~= nil then
69 | for _, Menu in pairs(self.Menus) do
70 | Menu.Settings.ControlDisablingEnabled = tobool(bool)
71 | end
72 | end
73 | end
74 |
75 | ---ResetCursorOnOpen
76 | ---@param bool boolean
77 | function MenuPool:ResetCursorOnOpen(bool)
78 | if bool ~= nil then
79 | for _, Menu in pairs(self.Menus) do
80 | Menu.Settings.ResetCursorOnOpen = tobool(bool)
81 | end
82 | end
83 | end
84 |
85 | ---MultilineFormats
86 | ---@param bool boolean
87 | function MenuPool:MultilineFormats(bool)
88 | if bool ~= nil then
89 | for _, Menu in pairs(self.Menus) do
90 | Menu.Settings.MultilineFormats = tobool(bool)
91 | end
92 | end
93 | end
94 |
95 | ---Audio
96 | ---@param Attribute number
97 | ---@param Setting table
98 | function MenuPool:Audio(Attribute, Setting)
99 | if Attribute ~= nil and Setting ~= nil then
100 | for _, Menu in pairs(self.Menus) do
101 | if Menu.Settings.Audio[Attribute] then
102 | Menu.Settings.Audio[Attribute] = Setting
103 | end
104 | end
105 | end
106 | end
107 |
108 | ---WidthOffset
109 | ---@param offset number
110 | function MenuPool:WidthOffset(offset)
111 | if tonumber(offset) then
112 | for _, Menu in pairs(self.Menus) do
113 | Menu:SetMenuWidthOffset(tonumber(offset))
114 | end
115 | end
116 | end
117 |
118 | ---CounterPreText
119 | ---@param str string
120 | function MenuPool:CounterPreText(str)
121 | if str ~= nil then
122 | for _, Menu in pairs(self.Menus) do
123 | Menu.PageCounter.PreText = tostring(str)
124 | end
125 | end
126 | end
127 |
128 | ---DisableInstructionalButtons
129 | ---@param bool boolean
130 | function MenuPool:DisableInstructionalButtons(bool)
131 | if bool ~= nil then
132 | for _, Menu in pairs(self.Menus) do
133 | Menu.Settings.InstructionalButtons = tobool(bool)
134 | end
135 | end
136 | end
137 |
138 | ---MouseControlsEnabled
139 | ---@param bool boolean
140 | function MenuPool:MouseControlsEnabled(bool)
141 | if bool ~= nil then
142 | for _, Menu in pairs(self.Menus) do
143 | Menu.Settings.MouseControlsEnabled = tobool(bool)
144 | end
145 | end
146 | end
147 |
148 | ---RefreshIndex
149 | function MenuPool:RefreshIndex()
150 | for _, Menu in pairs(self.Menus) do
151 | Menu:RefreshIndex()
152 | end
153 | end
154 |
155 | ---ProcessMenus
156 | function MenuPool:ProcessMenus()
157 | self:ProcessControl()
158 | self:ProcessMouse()
159 | self:Draw()
160 | end
161 |
162 | ---ProcessControl
163 | function MenuPool:ProcessControl()
164 | for _, Menu in pairs(self.Menus) do
165 | if Menu:Visible() then
166 | Menu:ProcessControl()
167 | end
168 | end
169 | end
170 |
171 | ---ProcessMouse
172 | function MenuPool:ProcessMouse()
173 | for _, Menu in pairs(self.Menus) do
174 | if Menu:Visible() then
175 | Menu:ProcessMouse()
176 | end
177 | end
178 | end
179 |
180 | ---Draw
181 | function MenuPool:Draw()
182 | for _, Menu in pairs(self.Menus) do
183 | if Menu:Visible() then
184 | Menu:Draw()
185 | end
186 | end
187 | end
188 |
189 | ---IsAnyMenuOpen
190 | function MenuPool:IsAnyMenuOpen()
191 | local open = false
192 | for _, Menu in pairs(self.Menus) do
193 | if Menu:Visible() then
194 | open = true
195 | break
196 | end
197 | end
198 | return open
199 | end
200 |
201 | ---CloseAllMenus
202 | function MenuPool:CloseAllMenus()
203 | for _, Menu in pairs(self.Menus) do
204 | if Menu:Visible() then
205 | Menu:Visible(false)
206 | Menu.OnMenuClosed(Menu)
207 | end
208 | end
209 | end
210 |
211 | ---SetBannerSprite
212 | ---@param Sprite table
213 | function MenuPool:SetBannerSprite(Sprite)
214 | if Sprite() == "Sprite" then
215 | for _, Menu in pairs(self.Menus) do
216 | Menu:SetBannerSprite(Sprite)
217 | end
218 | end
219 | end
220 |
221 | ---SetBannerRectangle
222 | ---@param Rectangle table
223 | function MenuPool:SetBannerRectangle(Rectangle)
224 | if Rectangle() == "Rectangle" then
225 | for _, Menu in pairs(self.Menus) do
226 | Menu:SetBannerRectangle(Rectangle)
227 | end
228 | end
229 | end
230 |
231 | ---TotalItemsPerPage
232 | ---@param Value table
233 | function MenuPool:TotalItemsPerPage(Value)
234 | if tonumber(Value) then
235 | for _, Menu in pairs(self.Menus) do
236 | Menu.Pagination.Total = Value - 1
237 | end
238 | end
239 | end
--------------------------------------------------------------------------------
/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 "mp_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 | [23] = function(Selected)
154 | if Selected then
155 | return "mp_specitem_coke_black"
156 | else
157 | return "mp_specitem_coke"
158 | end
159 | end,
160 | }
161 |
162 | BadgeDictionary = {
163 | [0] = function(Selected)
164 | if Selected then
165 | return "commonmenu"
166 | else
167 | return "commonmenu"
168 | end
169 | end,
170 | [1] = function(Selected)
171 | if Selected then
172 | return "mpinventory"
173 | else
174 | return "mpinventory"
175 | end
176 | end,
177 | }
178 |
179 | BadgeColour = {
180 | [5] = 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 | [21] = function(Selected)
188 | if Selected then
189 | return 0, 0, 0, 255
190 | else
191 | return 255, 255, 255, 255
192 | end
193 | end,
194 | [22] = function(Selected)
195 | if Selected then
196 | return 0, 0, 0, 255
197 | else
198 | return 255, 255, 255, 255
199 | end
200 | end,
201 | }
202 |
203 | ---GetBadgeTexture
204 | ---@param Badge number
205 | ---@param Selected table
206 | function GetBadgeTexture(Badge, Selected)
207 | if BadgeTexture[Badge] then
208 | return BadgeTexture[Badge](Selected)
209 | else
210 | return ""
211 | end
212 | end
213 |
214 | ---GetBadgeDictionary
215 | ---@param Badge number
216 | ---@param Selected table
217 | function GetBadgeDictionary(Badge, Selected)
218 | if BadgeDictionary[Badge] then
219 | return BadgeDictionary[Badge](Selected)
220 | else
221 | return "commonmenu"
222 | end
223 | end
224 |
225 | ---GetBadgeColour
226 | ---@param Badge number
227 | ---@param Selected table
228 | function GetBadgeColour(Badge, Selected)
229 | if BadgeColour[Badge] then
230 | return BadgeColour[Badge](Selected)
231 | else
232 | return 255, 255, 255, 255
233 | end
234 | end
--------------------------------------------------------------------------------
/elements/Colours.lua:
--------------------------------------------------------------------------------
1 | Colours = {
2 | DefaultColors = {R = 0, G = 0, B = 0, A = 0},
3 | PureWhite = {R = 255, G = 255, B = 255, A = 255},
4 | White = {R = 240, G = 240, B = 240, A = 255},
5 | Black = {R = 0, G = 0, B = 0, A = 255},
6 | Grey = {R = 155, G = 155, B = 155, A = 255},
7 | GreyLight = {R = 205, G = 205, B = 205, A = 255},
8 | GreyDark = {R = 77, G = 77, B = 77, A = 255},
9 | Red = {R = 224, G = 50, B = 50, A = 255},
10 | RedLight = {R = 240, G = 153, B = 153, A = 255},
11 | RedDark = {R = 112, G = 25, B = 25, A = 255},
12 | Blue = {R = 93, G = 182, B = 229, A = 255},
13 | BlueLight = {R = 174, G = 219, B = 242, A = 255},
14 | BlueDark = {R = 47, G = 92, B = 115, A = 255},
15 | Yellow = {R = 240, G = 200, B = 80, A = 255},
16 | YellowLight = {R = 254, G = 235, B = 169, A = 255},
17 | YellowDark = {R = 126, G = 107, B = 41, A = 255},
18 | Orange = {R = 255, G = 133, B = 85, A = 255},
19 | OrangeLight = {R = 255, G = 194, B = 170, A = 255},
20 | OrangeDark = {R = 127, G = 66, B = 42, A = 255},
21 | Green = {R = 114, G = 204, B = 114, A = 255},
22 | GreenLight = {R = 185, G = 230, B = 185, A = 255},
23 | GreenDark = {R = 57, G = 102, B = 57, A = 255},
24 | Purple = {R = 132, G = 102, B = 226, A = 255},
25 | PurpleLight = {R = 192, G = 179, B = 239, A = 255},
26 | PurpleDark = {R = 67, G = 57, B = 111, A = 255},
27 | Pink = {R = 203, G = 54, B = 148, A = 255},
28 | RadarHealth = {R = 53, G = 154, B = 71, A = 255},
29 | RadarArmour = {R = 93, G = 182, B = 229, A = 255},
30 | RadarDamage = {R = 235, G = 36, B = 39, A = 255},
31 | NetPlayer1 = {R = 194, G = 80, B = 80, A = 255},
32 | NetPlayer2 = {R = 156, G = 110, B = 175, A = 255},
33 | NetPlayer3 = {R = 255, G = 123, B = 196, A = 255},
34 | NetPlayer4 = {R = 247, G = 159, B = 123, A = 255},
35 | NetPlayer5 = {R = 178, G = 144, B = 132, A = 255},
36 | NetPlayer6 = {R = 141, G = 206, B = 167, A = 255},
37 | NetPlayer7 = {R = 113, G = 169, B = 175, A = 255},
38 | NetPlayer8 = {R = 211, G = 209, B = 231, A = 255},
39 | NetPlayer9 = {R = 144, G = 127, B = 153, A = 255},
40 | NetPlayer10 = {R = 106, G = 196, B = 191, A = 255},
41 | NetPlayer11 = {R = 214, G = 196, B = 153, A = 255},
42 | NetPlayer12 = {R = 234, G = 142, B = 80, A = 255},
43 | NetPlayer13 = {R = 152, G = 203, B = 234, A = 255},
44 | NetPlayer14 = {R = 178, G = 98, B = 135, A = 255},
45 | NetPlayer15 = {R = 144, G = 142, B = 122, A = 255},
46 | NetPlayer16 = {R = 166, G = 117, B = 94, A = 255},
47 | NetPlayer17 = {R = 175, G = 168, B = 168, A = 255},
48 | NetPlayer18 = {R = 232, G = 142, B = 155, A = 255},
49 | NetPlayer19 = {R = 187, G = 214, B = 91, A = 255},
50 | NetPlayer20 = {R = 12, G = 123, B = 86, A = 255},
51 | NetPlayer21 = {R = 123, G = 196, B = 255, A = 255},
52 | NetPlayer22 = {R = 171, G = 60, B = 230, A = 255},
53 | NetPlayer23 = {R = 206, G = 169, B = 13, A = 255},
54 | NetPlayer24 = {R = 71, G = 99, B = 173, A = 255},
55 | NetPlayer25 = {R = 42, G = 166, B = 185, A = 255},
56 | NetPlayer26 = {R = 186, G = 157, B = 125, A = 255},
57 | NetPlayer27 = {R = 201, G = 225, B = 255, A = 255},
58 | NetPlayer28 = {R = 240, G = 240, B = 150, A = 255},
59 | NetPlayer29 = {R = 237, G = 140, B = 161, A = 255},
60 | NetPlayer30 = {R = 249, G = 138, B = 138, A = 255},
61 | NetPlayer31 = {R = 252, G = 239, B = 166, A = 255},
62 | NetPlayer32 = {R = 240, G = 240, B = 240, A = 255},
63 | SimpleBlipDefault = {R = 159, G = 201, B = 166, A = 255},
64 | MenuBlue = {R = 140, G = 140, B = 140, A = 255},
65 | MenuGreyLight = {R = 140, G = 140, B = 140, A = 255},
66 | MenuBlueExtraDark = {R = 40, G = 40, B = 40, A = 255},
67 | MenuYellow = {R = 240, G = 160, B = 0, A = 255},
68 | MenuYellowDark = {R = 240, G = 160, B = 0, A = 255},
69 | MenuGreen = {R = 240, G = 160, B = 0, A = 255},
70 | MenuGrey = {R = 140, G = 140, B = 140, A = 255},
71 | MenuGreyDark = {R = 60, G = 60, B = 60, A = 255},
72 | MenuHighlight = {R = 30, G = 30, B = 30, A = 255},
73 | MenuStandard = {R = 140, G = 140, B = 140, A = 255},
74 | MenuDimmed = {R = 75, G = 75, B = 75, A = 255},
75 | MenuExtraDimmed = {R = 50, G = 50, B = 50, A = 255},
76 | BriefTitle = {R = 95, G = 95, B = 95, A = 255},
77 | MidGreyMp = {R = 100, G = 100, B = 100, A = 255},
78 | NetPlayer1Dark = {R = 93, G = 39, B = 39, A = 255},
79 | NetPlayer2Dark = {R = 77, G = 55, B = 89, A = 255},
80 | NetPlayer3Dark = {R = 124, G = 62, B = 99, A = 255},
81 | NetPlayer4Dark = {R = 120, G = 80, B = 80, A = 255},
82 | NetPlayer5Dark = {R = 87, G = 72, B = 66, A = 255},
83 | NetPlayer6Dark = {R = 74, G = 103, B = 83, A = 255},
84 | NetPlayer7Dark = {R = 60, G = 85, B = 88, A = 255},
85 | NetPlayer8Dark = {R = 105, G = 105, B = 64, A = 255},
86 | NetPlayer9Dark = {R = 72, G = 63, B = 76, A = 255},
87 | NetPlayer10Dark = {R = 53, G = 98, B = 95, A = 255},
88 | NetPlayer11Dark = {R = 107, G = 98, B = 76, A = 255},
89 | NetPlayer12Dark = {R = 117, G = 71, B = 40, A = 255},
90 | NetPlayer13Dark = {R = 76, G = 101, B = 117, A = 255},
91 | NetPlayer14Dark = {R = 65, G = 35, B = 47, A = 255},
92 | NetPlayer15Dark = {R = 72, G = 71, B = 61, A = 255},
93 | NetPlayer16Dark = {R = 85, G = 58, B = 47, A = 255},
94 | NetPlayer17Dark = {R = 87, G = 84, B = 84, A = 255},
95 | NetPlayer18Dark = {R = 116, G = 71, B = 77, A = 255},
96 | NetPlayer19Dark = {R = 93, G = 107, B = 45, A = 255},
97 | NetPlayer20Dark = {R = 6, G = 61, B = 43, A = 255},
98 | NetPlayer21Dark = {R = 61, G = 98, B = 127, A = 255},
99 | NetPlayer22Dark = {R = 85, G = 30, B = 115, A = 255},
100 | NetPlayer23Dark = {R = 103, G = 84, B = 6, A = 255},
101 | NetPlayer24Dark = {R = 35, G = 49, B = 86, A = 255},
102 | NetPlayer25Dark = {R = 21, G = 83, B = 92, A = 255},
103 | NetPlayer26Dark = {R = 93, G = 98, B = 62, A = 255},
104 | NetPlayer27Dark = {R = 100, G = 112, B = 127, A = 255},
105 | NetPlayer28Dark = {R = 120, G = 120, B = 75, A = 255},
106 | NetPlayer29Dark = {R = 152, G = 76, B = 93, A = 255},
107 | NetPlayer30Dark = {R = 124, G = 69, B = 69, A = 255},
108 | NetPlayer31Dark = {R = 10, G = 43, B = 50, A = 255},
109 | NetPlayer32Dark = {R = 95, G = 95, B = 10, A = 255},
110 | Bronze = {R = 180, G = 130, B = 97, A = 255},
111 | Silver = {R = 150, G = 153, B = 161, A = 255},
112 | Gold = {R = 214, G = 181, B = 99, A = 255},
113 | Platinum = {R = 166, G = 221, B = 190, A = 255},
114 | Gang1 = {R = 29, G = 100, B = 153, A = 255},
115 | Gang2 = {R = 214, G = 116, B = 15, A = 255},
116 | Gang3 = {R = 135, G = 125, B = 142, A = 255},
117 | Gang4 = {R = 229, G = 119, B = 185, A = 255},
118 | SameCrew = {R = 252, G = 239, B = 166, A = 255},
119 | Freemode = {R = 45, G = 110, B = 185, A = 255},
120 | PauseBg = {R = 0, G = 0, B = 0, A = 255},
121 | Friendly = {R = 93, G = 182, B = 229, A = 255},
122 | Enemy = {R = 194, G = 80, B = 80, A = 255},
123 | Location = {R = 240, G = 200, B = 80, A = 255},
124 | Pickup = {R = 114, G = 204, B = 114, A = 255},
125 | PauseSingleplayer = {R = 114, G = 204, B = 114, A = 255},
126 | FreemodeDark = {R = 22, G = 55, B = 92, A = 255},
127 | InactiveMission = {R = 154, G = 154, B = 154, A = 255},
128 | Damage = {R = 194, G = 80, B = 80, A = 255},
129 | PinkLight = {R = 252, G = 115, B = 201, A = 255},
130 | PmMitemHighlight = {R = 252, G = 177, B = 49, A = 255},
131 | ScriptVariable = {R = 0, G = 0, B = 0, A = 255},
132 | Yoga = {R = 109, G = 247, B = 204, A = 255},
133 | Tennis = {R = 241, G = 101, B = 34, A = 255},
134 | Golf = {R = 214, G = 189, B = 97, A = 255},
135 | ShootingRange = {R = 112, G = 25, B = 25, A = 255},
136 | FlightSchool = {R = 47, G = 92, B = 115, A = 255},
137 | NorthBlue = {R = 93, G = 182, B = 229, A = 255},
138 | SocialClub = {R = 234, G = 153, B = 28, A = 255},
139 | PlatformBlue = {R = 11, G = 55, B = 123, A = 255},
140 | PlatformGreen = {R = 146, G = 200, B = 62, A = 255},
141 | PlatformGrey = {R = 234, G = 153, B = 28, A = 255},
142 | FacebookBlue = {R = 66, G = 89, B = 148, A = 255},
143 | IngameBg = {R = 0, G = 0, B = 0, A = 255},
144 | Darts = {R = 114, G = 204, B = 114, A = 255},
145 | Waypoint = {R = 164, G = 76, B = 242, A = 255},
146 | Michael = {R = 101, G = 180, B = 212, A = 255},
147 | Franklin = {R = 171, G = 237, B = 171, A = 255},
148 | Trevor = {R = 255, G = 163, B = 87, A = 255},
149 | GolfP1 = {R = 240, G = 240, B = 240, A = 255},
150 | GolfP2 = {R = 235, G = 239, B = 30, A = 255},
151 | GolfP3 = {R = 255, G = 149, B = 14, A = 255},
152 | GolfP4 = {R = 246, G = 60, B = 161, A = 255},
153 | WaypointLight = {R = 210, G = 166, B = 249, A = 255},
154 | WaypointDark = {R = 82, G = 38, B = 121, A = 255},
155 | PanelLight = {R = 0, G = 0, B = 0, A = 255},
156 | MichaelDark = {R = 72, G = 103, B = 116, A = 255},
157 | FranklinDark = {R = 85, G = 118, B = 85, A = 255},
158 | TrevorDark = {R = 127, G = 81, B = 43, A = 255},
159 | ObjectiveRoute = {R = 240, G = 200, B = 80, A = 255},
160 | PausemapTint = {R = 0, G = 0, B = 0, A = 255},
161 | PauseDeselect = {R = 100, G = 100, B = 100, A = 255},
162 | PmWeaponsPurchasable = {R = 45, G = 110, B = 185, A = 255},
163 | PmWeaponsLocked = {R = 240, G = 240, B = 240, A = 255},
164 | EndScreenBg = {R = 0, G = 0, B = 0, A = 255},
165 | Chop = {R = 224, G = 50, B = 50, A = 255},
166 | PausemapTintHalf = {R = 0, G = 0, B = 0, A = 255},
167 | NorthBlueOfficial = {R = 0, G = 71, B = 133, A = 255},
168 | ScriptVariable2 = {R = 0, G = 0, B = 0, A = 255},
169 | H = {R = 33, G = 118, B = 37, A = 255},
170 | HDark = {R = 37, G = 102, B = 40, A = 255},
171 | T = {R = 234, G = 153, B = 28, A = 255},
172 | TDark = {R = 225, G = 140, B = 8, A = 255},
173 | HShard = {R = 20, G = 40, B = 0, A = 255},
174 | ControllerMichael = {R = 48, G = 255, B = 255, A = 255},
175 | ControllerFranklin = {R = 48, G = 255, B = 0, A = 255},
176 | ControllerTrevor = {R = 176, G = 80, B = 0, A = 255},
177 | ControllerChop = {R = 127, G = 0, B = 0, A = 255},
178 | VideoEditorVideo = {R = 53, G = 166, B = 224, A = 255},
179 | VideoEditorAudio = {R = 162, G = 79, B = 157, A = 255},
180 | VideoEditorText = {R = 104, G = 192, B = 141, A = 255},
181 | HbBlue = {R = 29, G = 100, B = 153, A = 255},
182 | HbYellow = {R = 234, G = 153, B = 28, A = 255},
183 | VideoEditorScore = {R = 240, G = 160, B = 1, A = 255},
184 | VideoEditorAudioFadeout = {R = 59, G = 34, B = 57, A = 255},
185 | VideoEditorTextFadeout = {R = 41, G = 68, B = 53, A = 255},
186 | VideoEditorScoreFadeout = {R = 82, G = 58, B = 10, A = 255},
187 | HeistBackground = {R = 37, G = 102, B = 40, A = 255},
188 | VideoEditorAmbient = {R = 240, G = 200, B = 80, A = 255},
189 | VideoEditorAmbientFadeout = {R = 80, G = 70, B = 34, A = 255},
190 | Gb = {R = 255, G = 133, B = 85, A = 255},
191 | G = {R = 255, G = 194, B = 170, A = 255},
192 | B = {R = 255, G = 133, B = 85, A = 255},
193 | LowFlow = {R = 240, G = 200, B = 80, A = 255},
194 | LowFlowDark = {R = 126, G = 107, B = 41, A = 255},
195 | G1 = {R = 247, G = 159, B = 123, A = 255},
196 | G2 = {R = 226, G = 134, B = 187, A = 255},
197 | G3 = {R = 239, G = 238, B = 151, A = 255},
198 | G4 = {R = 113, G = 169, B = 175, A = 255},
199 | G5 = {R = 160, G = 140, B = 193, A = 255},
200 | G6 = {R = 141, G = 206, B = 167, A = 255},
201 | G7 = {R = 181, G = 214, B = 234, A = 255},
202 | G8 = {R = 178, G = 144, B = 132, A = 255},
203 | G9 = {R = 0, G = 132, B = 114, A = 255},
204 | G10 = {R = 216, G = 85, B = 117, A = 255},
205 | G11 = {R = 30, G = 100, B = 152, A = 255},
206 | G12 = {R = 43, G = 181, B = 117, A = 255},
207 | G13 = {R = 233, G = 141, B = 79, A = 255},
208 | G14 = {R = 137, G = 210, B = 215, A = 255},
209 | G15 = {R = 134, G = 125, B = 141, A = 255},
210 | Adversary = {R = 109, G = 34, B = 33, A = 255},
211 | DegenRed = {R = 255, G = 0, B = 0, A = 255},
212 | DegenYellow = {R = 255, G = 255, B = 0, A = 255},
213 | DegenGreen = {R = 0, G = 255, B = 0, A = 255},
214 | DegenCyan = {R = 0, G = 255, B = 255, A = 255},
215 | DegenBlue = {R = 0, G = 0, B = 255, A = 255},
216 | DegenMagenta = {R = 255, G = 0, B = 255, A = 255},
217 | Stunt1 = {R = 38, G = 136, B = 234, A = 255},
218 | Stunt2 = {R = 224, G = 50, B = 50, A = 255},
219 | }
--------------------------------------------------------------------------------
/elements/ColoursPanel.lua:
--------------------------------------------------------------------------------
1 | ColoursPanel = {}
2 |
3 |
4 | ColoursPanel.HairCut = {
5 | { 22, 19, 19 }, -- 0
6 | { 30, 28, 25 }, -- 1
7 | { 76, 56, 45 }, -- 2
8 | { 69, 34, 24 }, -- 3
9 | { 123, 59, 31 }, -- 4
10 | { 149, 68, 35 }, -- 5
11 | { 165, 87, 50 }, -- 6
12 | { 175, 111, 72 }, -- 7
13 | { 159, 105, 68 }, -- 8
14 | { 198, 152, 108 }, -- 9
15 | { 213, 170, 115 }, -- 10
16 | { 223, 187, 132 }, -- 11
17 | { 202, 164, 110 }, -- 12
18 | { 238, 204, 130 }, -- 13
19 | { 229, 190, 126 }, -- 14
20 | { 250, 225, 167 }, -- 15
21 | { 187, 140, 96 }, -- 16
22 | { 163, 92, 60 }, -- 17
23 | { 144, 52, 37 }, -- 18
24 | { 134, 21, 17 }, -- 19
25 | { 164, 24, 18 }, -- 20
26 | { 195, 33, 24 }, -- 21
27 | { 221, 69, 34 }, -- 22
28 | { 229, 71, 30 }, -- 23
29 | { 208, 97, 56 }, -- 24
30 | { 113, 79, 38 }, -- 25
31 | { 132, 107, 95 }, -- 26
32 | { 185, 164, 150 }, -- 27
33 | { 218, 196, 180 }, -- 28
34 | { 247, 230, 217 }, -- 29
35 | { 102, 72, 93 }, -- 30
36 | { 162, 105, 138 }, -- 31
37 | { 171, 174, 11 }, -- 32
38 | { 239, 61, 200 }, -- 33
39 | { 255, 69, 152 }, -- 34
40 | { 255, 178, 191 }, -- 35
41 | { 12, 168, 146 }, -- 36
42 | { 8, 146, 165 }, -- 37
43 | { 11, 82, 134 }, -- 38
44 | { 118, 190, 117 }, -- 39
45 | { 52, 156, 104 }, -- 40
46 | { 22, 86, 85 }, -- 41
47 | { 152, 177, 40 }, -- 42
48 | { 127, 162, 23 }, -- 43
49 | { 241, 200, 98 }, -- 44
50 | { 238, 178, 16 }, -- 45
51 | { 224, 134, 14 }, -- 46
52 | { 247, 157, 15 }, -- 47
53 | { 243, 143, 16 }, -- 48
54 | { 231, 70, 15 }, -- 49
55 | { 255, 101, 21 }, -- 50
56 | { 254, 91, 34 }, -- 51
57 | { 252, 67, 21 }, -- 52
58 | { 196, 12, 15 }, -- 53
59 | { 143, 10, 14 }, -- 54
60 | { 44, 27, 22 }, -- 55
61 | { 80, 51, 37 }, -- 56
62 | { 98, 54, 37 }, -- 57
63 | { 60, 31, 24 }, -- 58
64 | { 69, 43, 32 }, -- 59
65 | { 8, 10, 14 }, -- 60
66 | { 212, 185, 158 }, -- 61
67 | { 212, 185, 158 }, -- 62
68 | { 213, 170, 115 }, -- 63
69 | }
--------------------------------------------------------------------------------
/elements/Sprite.lua:
--------------------------------------------------------------------------------
1 | Sprite = setmetatable({}, Sprite)
2 | Sprite.__index = Sprite
3 | Sprite.__call = function() return "Sprite" end
4 |
5 | ---New
6 | ---@param TxtDictionary string
7 | ---@param TxtName string
8 | ---@param X number
9 | ---@param Y number
10 | ---@param Width number
11 | ---@param Height number
12 | ---@param Heading number
13 | ---@param R number
14 | ---@param G number
15 | ---@param B number
16 | ---@param A number
17 | function Sprite.New(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A)
18 | local _Sprite = {
19 | TxtDictionary = tostring(TxtDictionary),
20 | TxtName = tostring(TxtName),
21 | X = tonumber(X) or 0,
22 | Y = tonumber(Y) or 0,
23 | Width = tonumber(Width) or 0,
24 | Height = tonumber(Height) or 0,
25 | Heading = tonumber(Heading) or 0,
26 | _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255},
27 | }
28 | return setmetatable(_Sprite, Sprite)
29 | end
30 |
31 | ---Position
32 | ---@param X number
33 | ---@param Y number
34 | function Sprite:Position(X, Y)
35 | if tonumber(X) and tonumber(Y) then
36 | self.X = tonumber(X)
37 | self.Y = tonumber(Y)
38 | else
39 | return {X = self.X, Y = self.Y}
40 | end
41 | end
42 |
43 | ---Size
44 | ---@param Width number
45 | ---@param Height number
46 | function Sprite:Size(Width, Height)
47 | if tonumber(Width) and tonumber(Width) then
48 | self.Width = tonumber(Width)
49 | self.Height = tonumber(Height)
50 | else
51 | return {Width = self.Width, Height = self.Height}
52 | end
53 | end
54 |
55 | ---Colour
56 | ---@param R number
57 | ---@param G number
58 | ---@param B number
59 | ---@param A number
60 | function Sprite:Colour(R, G, B, A)
61 | if tonumber(R) or tonumber(G) or tonumber(B) or tonumber(A) then
62 | self._Colour.R = tonumber(R) or 255
63 | self._Colour.B = tonumber(B) or 255
64 | self._Colour.G = tonumber(G) or 255
65 | self._Colour.A = tonumber(A) or 255
66 | else
67 | return self._Colour
68 | end
69 | end
70 |
71 | ---Draw
72 | function Sprite:Draw()
73 | if not HasStreamedTextureDictLoaded(self.TxtDictionary) then
74 | RequestStreamedTextureDict(self.TxtDictionary, true)
75 | end
76 | local Position = self:Position()
77 | local Size = self:Size()
78 | Size.Width, Size.Height = FormatXWYH(Size.Width, Size.Height)
79 | Position.X, Position.Y = FormatXWYH(Position.X, Position.Y)
80 | 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)
81 | end
--------------------------------------------------------------------------------
/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 | ---MeasureString
98 | ---@param str string
99 | function MeasureString(str)
100 | local output = 0
101 | for i = 1, GetCharacterCount(str), 1 do
102 | if CharacterMap[string.sub(str, i, i)] then
103 | output = output + CharacterMap[string.sub(str, i, i)] + 1
104 | end
105 | end
106 | return output
107 | end
--------------------------------------------------------------------------------
/elements/UIResRectangle.lua:
--------------------------------------------------------------------------------
1 | UIResRectangle = setmetatable({}, UIResRectangle)
2 | UIResRectangle.__index = UIResRectangle
3 | UIResRectangle.__call = function() return "Rectangle" end
4 |
5 | ---New
6 | ---@param X number
7 | ---@param Y number
8 | ---@param Width number
9 | ---@param Height number
10 | ---@param R number
11 | ---@param G number
12 | ---@param B number
13 | ---@param A number
14 | function UIResRectangle.New(X, Y, Width, Height, R, G, B, A)
15 | local _UIResRectangle = {
16 | X = tonumber(X) or 0,
17 | Y = tonumber(Y) or 0,
18 | Width = tonumber(Width) or 0,
19 | Height = tonumber(Height) or 0,
20 | _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255},
21 | }
22 | return setmetatable(_UIResRectangle, UIResRectangle)
23 | end
24 |
25 | ---Position
26 | ---@param X number
27 | ---@param Y number
28 | function UIResRectangle:Position(X, Y)
29 | if tonumber(X) and tonumber(Y) then
30 | self.X = tonumber(X)
31 | self.Y = tonumber(Y)
32 | else
33 | return {X = self.X, Y = self.Y}
34 | end
35 | end
36 |
37 | ---Size
38 | ---@param Width number
39 | ---@param Height number
40 | function UIResRectangle:Size(Width, Height)
41 | if tonumber(Width) and tonumber(Height) then
42 | self.Width = tonumber(Width)
43 | self.Height = tonumber(Height)
44 | else
45 | return {Width = self.Width, Height = self.Height}
46 | end
47 | end
48 |
49 | ---Colour
50 | ---@param R number
51 | ---@param G number
52 | ---@param B number
53 | ---@param A number
54 | function UIResRectangle:Colour(R, G, B, A)
55 | if tonumber(R) or tonumber(G) or tonumber(B) or tonumber(A) then
56 | self._Colour.R = tonumber(R) or 255
57 | self._Colour.B = tonumber(B) or 255
58 | self._Colour.G = tonumber(G) or 255
59 | self._Colour.A = tonumber(A) or 255
60 | else
61 | return self._Colour
62 | end
63 | end
64 |
65 | ---Draw
66 | function UIResRectangle:Draw()
67 | local Position = self:Position()
68 | local Size = self:Size()
69 | Size.Width, Size.Height = FormatXWYH(Size.Width, Size.Height)
70 | Position.X, Position.Y = FormatXWYH(Position.X, Position.Y)
71 | 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)
72 | end
73 |
--------------------------------------------------------------------------------
/elements/UIResText.lua:
--------------------------------------------------------------------------------
1 | UIResText = setmetatable({}, UIResText)
2 | UIResText.__index = UIResText
3 | UIResText.__call = function() return "Text" end
4 |
5 | ---GetCharacterCount
6 | ---@param str string
7 | function GetCharacterCount(str)
8 | local characters = 0
9 | for c in str:gmatch("[%z\1-\127\194-\244][\128-\191]*") do
10 | local a = c:byte(1, -1)
11 | if a ~= nil then
12 | characters = characters + 1
13 | end
14 | end
15 | return characters
16 | end
17 |
18 | ---GetByteCount
19 | ---@param str string
20 | function GetByteCount(str)
21 | local bytes = 0
22 |
23 | for c in str:gmatch("[%z\1-\127\194-\244][\128-\191]*") do
24 | local a,b,c,d = c:byte(1, -1)
25 | if a ~= nil then
26 | bytes = bytes + 1
27 | end
28 | if b ~= nil then
29 | bytes = bytes + 1
30 | end
31 | if c ~= nil then
32 | bytes = bytes + 1
33 | end
34 | if d ~= nil then
35 | bytes = bytes + 1
36 | end
37 | end
38 | return bytes
39 | end
40 |
41 | ---AddLongStringForAscii
42 | ---@param str string
43 | function AddLongStringForAscii(str)
44 | local maxbytelength = 99
45 | for i = 0, GetCharacterCount(str), 99 do
46 | AddTextComponentSubstringPlayerName(string.sub(str, i, math.min(maxbytelength, GetCharacterCount(str) - i))) --needs changed
47 | end
48 | end
49 |
50 | ---AddLongStringForUtf8
51 | ---@param str string
52 | function AddLongStringForUtf8(str)
53 | local maxbytelength = 99
54 | local bytecount = GetByteCount(str)
55 |
56 | if bytecount < maxbytelength then
57 | AddTextComponentSubstringPlayerName(str)
58 | return
59 | end
60 | local startIndex = 0
61 | for i = 0, GetCharacterCount(str), 1 do
62 | local length = i - startIndex
63 | if GetByteCount(string.sub(str, startIndex, length)) > maxbytelength then
64 | AddTextComponentSubstringPlayerName(string.sub(str, startIndex, length - 1))
65 | i = i - 1
66 | startIndex = startIndex + (length - 1)
67 | end
68 | end
69 | AddTextComponentSubstringPlayerName(string.sub(str, startIndex, GetCharacterCount(str) - startIndex))
70 | end
71 |
72 | ---AddLongString
73 | ---@param str string
74 | function AddLongString(str)
75 | local bytecount = GetByteCount(str)
76 | if bytecount == GetCharacterCount(str) then
77 | AddLongStringForAscii(str)
78 | else
79 | AddLongStringForUtf8(str)
80 | end
81 | end
82 |
83 | ---MeasureStringWidthNoConvert
84 | ---@param str string
85 | ---@param font number
86 | ---@param scale number
87 | function MeasureStringWidthNoConvert(str, font, scale)
88 | BeginTextCommandWidth("STRING")
89 | AddLongString(str)
90 | SetTextFont(font or 0)
91 | SetTextScale(1.0, scale or 0)
92 | return EndTextCommandGetWidth(true)
93 | end
94 |
95 | ---MeasureStringWidth
96 | ---@param str string
97 | ---@param font number
98 | ---@param scale number
99 | function MeasureStringWidth(str, font, scale)
100 | return MeasureStringWidthNoConvert(str, font, scale) * 1920
101 | end
102 |
103 | ---New
104 | ---@param Text string
105 | ---@param X number
106 | ---@param Y number
107 | ---@param Scale number
108 | ---@param R number
109 | ---@param G number
110 | ---@param B number
111 | ---@param A number
112 | ---@param Font number
113 | ---@param Alignment number
114 | ---@param DropShadow number
115 | ---@param Outline number
116 | ---@param WordWrap number
117 | function UIResText.New(Text, X, Y, Scale, R, G, B, A, Font, Alignment, DropShadow, Outline, WordWrap)
118 | local _UIResText = {
119 | _Text = tostring(Text) or "",
120 | X = tonumber(X) or 0,
121 | Y = tonumber(Y) or 0,
122 | Scale = tonumber(Scale) or 0,
123 | _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255},
124 | Font = tonumber(Font) or 0,
125 | Alignment = Alignment or nil,
126 | DropShadow = DropShadow or nil,
127 | Outline = Outline or nil,
128 | WordWrap = tonumber(WordWrap) or 0,
129 | }
130 | return setmetatable(_UIResText, UIResText)
131 | end
132 |
133 | ---Position
134 | ---@param X number
135 | ---@param Y number
136 | function UIResText:Position(X, Y)
137 | if tonumber(X) and tonumber(Y) then
138 | self.X = tonumber(X)
139 | self.Y = tonumber(Y)
140 | else
141 | return {X = self.X, Y = self.Y}
142 | end
143 | end
144 |
145 | ---Colour
146 | ---@param R number
147 | ---@param G number
148 | ---@param B number
149 | ---@param A number
150 | function UIResText:Colour(R, G, B, A)
151 | if tonumber(R) and tonumber(G) and tonumber(B) and tonumber(A) then
152 | self._Colour.R = tonumber(R)
153 | self._Colour.B = tonumber(B)
154 | self._Colour.G = tonumber(G)
155 | self._Colour.A = tonumber(A)
156 | else
157 | return self._Colour
158 | end
159 | end
160 |
161 | ---Text
162 | ---@param Text string
163 | function UIResText:Text(Text)
164 | if tostring(Text) and Text ~= nil then
165 | self._Text = tostring(Text)
166 | else
167 | return self._Text
168 | end
169 | end
170 |
171 | ---Draw
172 | function UIResText:Draw()
173 | local Position = self:Position()
174 | Position.X, Position.Y = FormatXWYH(Position.X, Position.Y)
175 |
176 | SetTextFont(self.Font)
177 | SetTextScale(1.0, self.Scale)
178 | SetTextColour(self._Colour.R, self._Colour.G, self._Colour.B, self._Colour.A)
179 |
180 | if self.DropShadow then
181 | SetTextDropShadow()
182 | end
183 | if self.Outline then
184 | SetTextOutline()
185 | end
186 |
187 | if self.Alignment ~= nil then
188 | if self.Alignment == 1 or self.Alignment == "Center" or self.Alignment == "Centre" then
189 | SetTextCentre(true)
190 | elseif self.Alignment == 2 or self.Alignment == "Right" then
191 | SetTextRightJustify(true)
192 | SetTextWrap(0, Position.X)
193 | end
194 | end
195 |
196 |
197 | if tonumber(self.WordWrap) then
198 | if tonumber(self.WordWrap) ~= 0 then
199 | SetTextWrap(Position.X, Position.X + (tonumber(self.WordWrap) / Resolution.Width))
200 | end
201 | end
202 |
203 | BeginTextCommandDisplayText("STRING")
204 | AddLongString(self._Text)
205 | EndTextCommandDisplayText(Position.X, Position.Y)
206 | end
207 |
--------------------------------------------------------------------------------
/example/DefaultShowcase.lua:
--------------------------------------------------------------------------------
1 | ketchup = false
2 | dish = "Banana"
3 | quantity = 1
4 | _menuPool = NativeUI.CreatePool()
5 |
6 | mainMenu = NativeUI.CreateMenu("Native UI", "~b~NATIVEUI SHOWCASE", nil, nil, nil, nil, nil, 255, 255, 255, 210)
7 | _menuPool:Add(mainMenu)
8 |
9 |
10 | mainMenu:AddInstructionButton({
11 | [1] = GetControlInstructionalButton(2, 54, 0),
12 | [2] = "Wsh les ami",
13 | })
14 |
15 | function AddMenuKetchup(menu)
16 | local newitem = NativeUI.CreateCheckboxItem("Add ketchup?", ketchup, "Do you wish to add ketchup?")
17 | menu:AddItem(newitem)
18 | menu.OnCheckboxChange = function(sender, item, checked_)
19 | if item == newitem then
20 | ketchup = checked_
21 | ShowNotification("~r~Ketchup status: ~b~" .. tostring(ketchup))
22 | end
23 | end
24 | end
25 |
26 | function AddMenuFoods(menu)
27 | local foods = {
28 | "Banana",
29 | "Apple",
30 | "Pizza",
31 | "Quartilicious",
32 | "Steak",
33 | 0xF00D,
34 | }
35 | local newitem = NativeUI.CreateListItem("Food", foods, 1)
36 | menu:AddItem(newitem)
37 | menu.OnListChange = function(sender, item, index)
38 | if item == newitem then
39 | dish = item:IndexToItem(index)
40 | ShowNotification("Preparing ~b~" .. dish .. "~w~...")
41 | end
42 | end
43 | end
44 |
45 | function AddMenuFoodCount(menu)
46 | local amount = {}
47 | for i = 1, 100 do
48 | amount[i] = i
49 | end
50 | local newitem = NativeUI.CreateSliderItem("Quantity", amount, 1, false)
51 | menu:AddItem(newitem)
52 | menu.OnSliderChange = function(sender, item, index)
53 | if item == newitem then
54 | quantity = item:IndexToItem(index)
55 | ShowNotification("Preparing ~r~" .. quantity .. " ~b~" .. dish .. "(s)~w~...")
56 | end
57 | end
58 | end
59 |
60 | function AddMenuCook(menu)
61 | local badge = 1
62 | local newitem = NativeUI.CreateItem("Cook!", "Cook the dish with the appropriate ingredients and ketchup.")
63 | newitem:SetLeftBadge(BadgeStyle.Star)
64 | newitem:SetRightBadge(BadgeStyle.Tick)
65 | menu:AddItem(newitem)
66 | menu.OnItemSelect = function(sender, item, index)
67 | if item == newitem then
68 | local string = "You have ordered ~r~" .. quantity .. " ~b~" .. dish .. "(s)~w~ ~r~with~w~ ketchup."
69 | if not ketchup then
70 | string = "You have ordered ~r~" .. quantity .. " ~b~" .. dish .. "(s)~w~ ~r~without~w~ ketchup."
71 | end
72 | ShowNotification(string)
73 | badge = badge + 1
74 | if (badge == 23) then
75 | badge = 0
76 | end
77 | if (badge == 22) then
78 | newitem:RightLabel('Reset badge to ~r~0')
79 | else
80 | newitem:RightLabel(nil)
81 | end
82 | newitem:SetRightBadge(badge)
83 | end
84 | end
85 | menu.OnIndexChange = function(sender, index)
86 | if sender.Items[index] == newitem then
87 | newitem:SetLeftBadge(BadgeStyle.None)
88 | end
89 | end
90 | end
91 |
92 | function AddMenuAnotherMenu(menu)
93 | local submenu = _menuPool:AddSubMenu(menu, "Another Menu")
94 |
95 | --submenu.SubMenu:SetMenuWidthOffset(60)
96 | submenu.Item:RightLabel('>>>')
97 | for i = 1, 69, 1 do
98 | submenu.SubMenu:AddItem(NativeUI.CreateItem("PageFiller - " .. i, "Sample description that takes more than one line. Moreso, it takes way more t"))
99 | end
100 | end
101 |
102 | AddMenuKetchup(mainMenu)
103 | AddMenuFoods(mainMenu)
104 | AddMenuFoodCount(mainMenu)
105 | AddMenuCook(mainMenu)
106 | AddMenuAnotherMenu(mainMenu)
107 | _menuPool:RefreshIndex()
108 |
109 | Citizen.CreateThread(function()
110 | while true do
111 | Citizen.Wait(1)
112 | _menuPool:ProcessMenus()
113 | if IsControlJustPressed(1, 51) then
114 | mainMenu:Visible(not mainMenu:Visible())
115 | end
116 | end
117 | end)
118 |
--------------------------------------------------------------------------------
/items/UIMenuCheckboxItem.lua:
--------------------------------------------------------------------------------
1 | UIMenuCheckboxItem = setmetatable({}, UIMenuCheckboxItem)
2 | UIMenuCheckboxItem.__index = UIMenuCheckboxItem
3 | UIMenuCheckboxItem.__call = function() return "UIMenuItem", "UIMenuCheckboxItem" end
4 |
5 | ---New
6 | ---@param Text string
7 | ---@param Check boolean
8 | ---@param Description string
9 | function UIMenuCheckboxItem.New(Text, Check, Description)
10 | local _UIMenuCheckboxItem = {
11 | Base = UIMenuItem.New(Text or "", Description or ""),
12 | CheckedSprite = Sprite.New("commonmenu", "shop_box_blank", 410, 95, 50, 50),
13 | Checked = tobool(Check),
14 | CheckboxEvent = function(menu, item, checked) end,
15 | }
16 | return setmetatable(_UIMenuCheckboxItem, UIMenuCheckboxItem)
17 | end
18 |
19 | ---SetParentMenu
20 | ---@param Menu table
21 | function UIMenuCheckboxItem:SetParentMenu(Menu)
22 | if Menu() == "UIMenu" then
23 | self.Base.ParentMenu = Menu
24 | else
25 | return self.Base.ParentMenu
26 | end
27 | end
28 |
29 | ---Position
30 | ---@param Y number
31 | function UIMenuCheckboxItem:Position(Y)
32 | if tonumber(Y) then
33 | self.Base:Position(Y)
34 | self.CheckedSprite:Position(380 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 138 + self.Base._Offset.Y)
35 | end
36 | end
37 |
38 | ---Selected
39 | ---@param bool boolean
40 | function UIMenuCheckboxItem:Selected(bool)
41 | if bool ~= nil then
42 | self.Base._Selected = tobool(bool)
43 | else
44 | return self.Base._Selected
45 | end
46 | end
47 |
48 | ---Hovered
49 | ---@param bool boolean
50 | function UIMenuCheckboxItem:Hovered(bool)
51 | if bool ~= nil then
52 | self.Base._Hovered = tobool(bool)
53 | else
54 | return self.Base._Hovered
55 | end
56 | end
57 |
58 | ---Enabled
59 | ---@param bool boolean
60 | function UIMenuCheckboxItem:Enabled(bool)
61 | if bool ~= nil then
62 | self.Base._Enabled = tobool(bool)
63 | else
64 | return self.Base._Enabled
65 | end
66 | end
67 |
68 | ---Description
69 | ---@param str string
70 | function UIMenuCheckboxItem:Description(str)
71 | if tostring(str) and str ~= nil then
72 | self.Base._Description = tostring(str)
73 | else
74 | return self.Base._Description
75 | end
76 | end
77 |
78 | ---Offset
79 | ---@param X number
80 | ---@param Y number
81 | function UIMenuCheckboxItem:Offset(X, Y)
82 | if tonumber(X) or tonumber(Y) then
83 | if tonumber(X) then
84 | self.Base._Offset.X = tonumber(X)
85 | end
86 | if tonumber(Y) then
87 | self.Base._Offset.Y = tonumber(Y)
88 | end
89 | else
90 | return self.Base._Offset
91 | end
92 | end
93 |
94 | ---Text
95 | ---@param Text string
96 | function UIMenuCheckboxItem:Text(Text)
97 | if tostring(Text) and Text ~= nil then
98 | self.Base.Text:Text(tostring(Text))
99 | else
100 | return self.Base.Text:Text()
101 | end
102 | end
103 |
104 | ---SetLeftBadge
105 | function UIMenuCheckboxItem:SetLeftBadge()
106 | error("This item does not support badges")
107 | end
108 |
109 | ---SetRightBadge
110 | function UIMenuCheckboxItem:SetRightBadge()
111 | error("This item does not support badges")
112 | end
113 |
114 | ---RightLabel
115 | function UIMenuCheckboxItem:RightLabel()
116 | error("This item does not support a right label")
117 | end
118 |
119 | ---Draw
120 | function UIMenuCheckboxItem:Draw()
121 | self.Base:Draw()
122 | self.CheckedSprite:Position(380 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.CheckedSprite.Y)
123 | if self.Base:Selected() then
124 | if self.Checked then
125 | self.CheckedSprite.TxtName = "shop_box_tickb"
126 | else
127 | self.CheckedSprite.TxtName = "shop_box_blankb"
128 | end
129 | else
130 | if self.Checked then
131 | self.CheckedSprite.TxtName = "shop_box_tick"
132 | else
133 | self.CheckedSprite.TxtName = "shop_box_blank"
134 | end
135 | end
136 | self.CheckedSprite:Draw()
137 | end
--------------------------------------------------------------------------------
/items/UIMenuColouredItem.lua:
--------------------------------------------------------------------------------
1 | UIMenuColouredItem = setmetatable({}, UIMenuColouredItem)
2 | UIMenuColouredItem.__index = UIMenuColouredItem
3 | UIMenuColouredItem.__call = function() return "UIMenuItem", "UIMenuColouredItem" end
4 |
5 | ---New
6 | ---@param Text string
7 | ---@param Description string
8 | ---@param MainColour table
9 | ---@param HighlightColour table
10 | function UIMenuColouredItem.New(Text, Description, MainColour, HighlightColour)
11 | if type(Colour) ~= "table" then Colour = { R = 0, G = 0, B = 0, A = 255 } end
12 | if type(HighlightColour) ~= "table" then Colour = { R = 255, G = 255, B = 255, A = 255 } end
13 | local _UIMenuColouredItem = {
14 | Base = UIMenuItem.New(Text or "", Description or ""),
15 | Rectangle = UIResRectangle.New(0, 0, 431, 38, MainColour.R, MainColour.G, MainColour.B, MainColour.A),
16 | MainColour = MainColour,
17 | HighlightColour = HighlightColour,
18 | ParentMenu = nil,
19 | Activated = function(menu, item) end,
20 | }
21 | _UIMenuColouredItem.Base.SelectedSprite:Colour(HighlightColour.R, HighlightColour.G, HighlightColour.B, HighlightColour.A)
22 | return setmetatable(_UIMenuColouredItem, UIMenuColouredItem)
23 | end
24 |
25 | ---SetParentMenu
26 | ---@param Menu table
27 | function UIMenuColouredItem:SetParentMenu(Menu)
28 | if Menu() == "UIMenu" then
29 | self.Base.ParentMenu = Menu
30 | else
31 | return self.Base.ParentMenu
32 | end
33 | end
34 |
35 | ---Position
36 | ---@param Y number
37 | function UIMenuColouredItem:Position(Y)
38 | if tonumber(Y) then
39 | self.Base:Position(Y)
40 | self.Rectangle:Position(self.Base._Offset.X, Y + 144 + self.Base._Offset.Y)
41 | end
42 | end
43 |
44 | ---Selected
45 | ---@param bool boolean
46 | function UIMenuColouredItem:Selected(bool)
47 | if bool ~= nil then
48 | self.Base._Selected = tobool(bool)
49 | else
50 | return self.Base._Selected
51 | end
52 | end
53 |
54 | ---Hovered
55 | ---@param bool boolean
56 | function UIMenuColouredItem:Hovered(bool)
57 | if bool ~= nil then
58 | self.Base._Hovered = tobool(bool)
59 | else
60 | return self.Base._Hovered
61 | end
62 | end
63 |
64 | ---Enabled
65 | ---@param bool boolean
66 | function UIMenuColouredItem:Enabled(bool)
67 | if bool ~= nil then
68 | self.Base._Enabled = tobool(bool)
69 | else
70 | return self.Base._Enabled
71 | end
72 | end
73 |
74 | ---Description
75 | ---@param str string
76 | function UIMenuColouredItem: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 | ---Offset
85 | ---@param X number
86 | ---@param Y number
87 | function UIMenuColouredItem:Offset(X, Y)
88 | if tonumber(X) or tonumber(Y) then
89 | if tonumber(X) then
90 | self.Base._Offset.X = tonumber(X)
91 | end
92 | if tonumber(Y) then
93 | self.Base._Offset.Y = tonumber(Y)
94 | end
95 | else
96 | return self.Base._Offset
97 | end
98 | end
99 |
100 | ---Text
101 | ---@param Text string
102 | function UIMenuColouredItem:Text(Text)
103 | if tostring(Text) and Text ~= nil then
104 | self.Base.Text:Text(tostring(Text))
105 | else
106 | return self.Base.Text:Text()
107 | end
108 | end
109 |
110 | ---RightLabel
111 | ---@param Text string
112 | ---@param MainColour table
113 | ---@param HighlightColour table
114 | function UIMenuColouredItem:RightLabel(Text, MainColour, HighlightColour)
115 | if tostring(Text) and Text ~= nil then
116 | if type(MainColour) == "table" then
117 | self.Base.Label.MainColour = MainColour
118 | end
119 | if type(HighlightColour) == "table" then
120 | self.Base.Label.HighlightColour = HighlightColour
121 | end
122 | self.Base.Label.Text:Text(tostring(Text))
123 | else
124 | self.Label.MainColour = { R = 0, G = 0, B = 0, A = 0 }
125 | self.Label.HighlightColour = { R = 0, G = 0, B = 0, A = 0 }
126 | return self.Base.Label.Text:Text()
127 | end
128 | end
129 |
130 | ---SetLeftBadge
131 | ---@param Badge number
132 | function UIMenuColouredItem:SetLeftBadge(Badge)
133 | if tonumber(Badge) then
134 | self.Base.LeftBadge.Badge = tonumber(Badge)
135 | end
136 | end
137 |
138 | ---SetRightBadge
139 | ---@param Badge number
140 | function UIMenuColouredItem:SetRightBadge(Badge)
141 | if tonumber(Badge) then
142 | self.Base.RightBadge.Badge = tonumber(Badge)
143 | end
144 | end
145 |
146 | ---Draw
147 | function UIMenuColouredItem:Draw()
148 | self.Rectangle:Draw()
149 | self.Base:Draw()
150 | end
--------------------------------------------------------------------------------
/items/UIMenuItem.lua:
--------------------------------------------------------------------------------
1 | UIMenuItem = setmetatable({}, UIMenuItem)
2 | UIMenuItem.__index = UIMenuItem
3 | UIMenuItem.__call = function()
4 | return "UIMenuItem", "UIMenuItem"
5 | end
6 |
7 | ---New
8 | ---@param Text string
9 | ---@param Description string
10 | function UIMenuItem.New(Text, Description)
11 | _UIMenuItem = {
12 | Rectangle = UIResRectangle.New(0, 0, 431, 38, 255, 255, 255, 20),
13 | Text = UIResText.New(tostring(Text) or "", 8, 0, 0.33, 245, 245, 245, 255, 0),
14 | _Description = tostring(Description) or "";
15 | SelectedSprite = Sprite.New("commonmenu", "gradient_nav", 0, 0, 431, 38),
16 | LeftBadge = { Sprite = Sprite.New("commonmenu", "", 0, 0, 40, 40), Badge = 0 },
17 | RightBadge = { Sprite = Sprite.New("commonmenu", "", 0, 0, 40, 40), Badge = 0 },
18 | Label = {
19 | Text = UIResText.New("", 0, 0, 0.35, 245, 245, 245, 255, 0, "Right"),
20 | MainColour = { R = 255, G = 255, B = 255, A = 255 },
21 | HighlightColour = { R = 0, G = 0, B = 0, A = 255 },
22 | },
23 | _Selected = false,
24 | _Hovered = false,
25 | _Enabled = true,
26 | _Offset = { X = 0, Y = 0 },
27 | ParentMenu = nil,
28 | Panels = {},
29 | Activated = function(menu, item)
30 | end,
31 | ActivatedPanel = function(menu, item, panel, panelvalue)
32 | end,
33 | }
34 | return setmetatable(_UIMenuItem, UIMenuItem)
35 | end
36 |
37 | ---SetParentMenu
38 | ---@param Menu table
39 | function UIMenuItem:SetParentMenu(Menu)
40 | if Menu ~= nil and Menu() == "UIMenu" then
41 | self.ParentMenu = Menu
42 | else
43 | return self.ParentMenu
44 | end
45 | end
46 |
47 | ---Selected
48 | ---@param bool boolean
49 | function UIMenuItem:Selected(bool)
50 | if bool ~= nil then
51 | self._Selected = tobool(bool)
52 | else
53 | return self._Selected
54 | end
55 | end
56 |
57 | ---Hovered
58 | ---@param bool boolean
59 | function UIMenuItem:Hovered(bool)
60 | if bool ~= nil then
61 | self._Hovered = tobool(bool)
62 | else
63 | return self._Hovered
64 | end
65 | end
66 |
67 | ---Enabled
68 | ---@param bool boolean
69 | function UIMenuItem:Enabled(bool)
70 | if bool ~= nil then
71 | self._Enabled = tobool(bool)
72 | else
73 | return self._Enabled
74 | end
75 | end
76 |
77 | ---Description
78 | ---@param str string
79 | function UIMenuItem:Description(str)
80 | if tostring(str) and str ~= nil then
81 | self._Description = tostring(str)
82 | else
83 | return self._Description
84 | end
85 | end
86 |
87 | ---Offset
88 | ---@param X number
89 | ---@param Y number
90 | function UIMenuItem:Offset(X, Y)
91 | if tonumber(X) or tonumber(Y) then
92 | if tonumber(X) then
93 | self._Offset.X = tonumber(X)
94 | end
95 | if tonumber(Y) then
96 | self._Offset.Y = tonumber(Y)
97 | end
98 | else
99 | return self._Offset
100 | end
101 | end
102 |
103 |
104 | ---Position
105 | ---@param Y number
106 | function UIMenuItem:Position(Y)
107 | if tonumber(Y) then
108 | self.Rectangle:Position(self._Offset.X, Y + 144 + self._Offset.Y)
109 | self.SelectedSprite:Position(0 + self._Offset.X, Y + 144 + self._Offset.Y)
110 | self.Text:Position(8 + self._Offset.X, Y + 147 + self._Offset.Y)
111 | self.LeftBadge.Sprite:Position(0 + self._Offset.X, Y + 142 + self._Offset.Y)
112 | self.RightBadge.Sprite:Position(385 + self._Offset.X, Y + 142 + self._Offset.Y)
113 | self.Label.Text:Position(420 + self._Offset.X, Y + 148 + self._Offset.Y)
114 | end
115 | end
116 |
117 | ---RightLabel
118 | ---@param Text string
119 | ---@param MainColour table
120 | ---@param HighlightColour table
121 | function UIMenuItem:RightLabel(Text, MainColour, HighlightColour)
122 | if MainColour ~= nil then labelMainColour = MainColour else labelMainColour = { R = 255, G = 255, B = 255, A = 255 } end
123 | if HighlightColour ~= nil then labelHighlightColour = HighlightColour else labelHighlightColour = { R = 0, G = 0, B = 0, A = 255 } end
124 | if tostring(Text) and Text ~= nil then
125 | if type(labelMainColour) == "table" then
126 | self.Label.MainColour = labelMainColour
127 | end
128 | if type(labelHighlightColour) == "table" then
129 | self.Label.HighlightColour = labelHighlightColour
130 | end
131 | self.Label.Text:Text(tostring(Text))
132 | else
133 | self.Label.MainColour = { R = 0, G = 0, B = 0, A = 0 }
134 | self.Label.HighlightColour = { R = 0, G = 0, B = 0, A = 0 }
135 | return self.Label.Text:Text()
136 | end
137 | end
138 |
139 | ---SetLeftBadge
140 | ---@param Badge number
141 | function UIMenuItem:SetLeftBadge(Badge)
142 | if tonumber(Badge) then
143 | self.LeftBadge.Badge = tonumber(Badge)
144 | end
145 | end
146 |
147 | ---SetRightBadge
148 | ---@param Badge number
149 | function UIMenuItem:SetRightBadge(Badge)
150 | if tonumber(Badge) then
151 | self.RightBadge.Badge = tonumber(Badge)
152 | end
153 | end
154 |
155 | ---Text
156 | ---@param Text string
157 | function UIMenuItem:Text(Text)
158 | if tostring(Text) and Text ~= nil then
159 | self.Text:Text(tostring(Text))
160 | else
161 | return self.Text:Text()
162 | end
163 | end
164 |
165 | ---AddPanel
166 | ---@param Panel table
167 | function UIMenuItem:AddPanel(Panel)
168 | if Panel() == "UIMenuPanel" then
169 | table.insert(self.Panels, Panel)
170 | Panel:SetParentItem(self)
171 | end
172 | end
173 |
174 | ---RemovePanelAt
175 | ---@param Index table
176 | function UIMenuItem:RemovePanelAt(Index)
177 | if tonumber(Index) then
178 | if self.Panels[Index] then
179 | table.remove(self.Panels, tonumber(Index))
180 | end
181 | end
182 | end
183 |
184 | ---FindPanelIndex
185 | ---@param Panel table
186 | function UIMenuItem:FindPanelIndex(Panel)
187 | if Panel() == "UIMenuPanel" then
188 | for Index = 1, #self.Panels do
189 | if self.Panels[Index] == Panel then
190 | return Index
191 | end
192 | end
193 | end
194 | return nil
195 | end
196 |
197 | function UIMenuItem:FindPanelItem()
198 | for Index = #self.Items, 1, -1 do
199 | if self.Items[Index].Panel then
200 | return Index
201 | end
202 | end
203 | return nil
204 | end
205 |
206 | function UIMenuItem:Draw()
207 | self.Rectangle:Size(431 + self.ParentMenu.WidthOffset, self.Rectangle.Height)
208 | self.SelectedSprite:Size(431 + self.ParentMenu.WidthOffset, self.SelectedSprite.Height)
209 |
210 | if self._Hovered and not self._Selected then
211 | self.Rectangle:Draw()
212 | end
213 |
214 | if self._Selected then
215 | self.SelectedSprite:Draw()
216 | end
217 |
218 | if self._Enabled then
219 | if self._Selected then
220 | self.Text:Colour(0, 0, 0, 255)
221 | self.Label.Text:Colour(self.Label.HighlightColour.R, self.Label.HighlightColour.G, self.Label.HighlightColour.B, self.Label.HighlightColour.A)
222 | else
223 | self.Text:Colour(245, 245, 245, 255)
224 | self.Label.Text:Colour(self.Label.MainColour.R, self.Label.MainColour.G, self.Label.MainColour.B, self.Label.MainColour.A)
225 | end
226 | else
227 | self.Text:Colour(163, 159, 148, 255)
228 | self.Label.Text:Colour(163, 159, 148, 255)
229 | end
230 |
231 | if self.LeftBadge.Badge == BadgeStyle.None then
232 | self.Text:Position(8 + self._Offset.X, self.Text.Y)
233 | else
234 | self.Text:Position(35 + self._Offset.X, self.Text.Y)
235 | self.LeftBadge.Sprite.TxtDictionary = GetBadgeDictionary(self.LeftBadge.Badge, self._Selected)
236 | self.LeftBadge.Sprite.TxtName = GetBadgeTexture(self.LeftBadge.Badge, self._Selected)
237 | self.LeftBadge.Sprite:Colour(GetBadgeColour(self.LeftBadge.Badge, self._Selected))
238 | self.LeftBadge.Sprite:Draw()
239 | end
240 |
241 | if self.RightBadge.Badge ~= BadgeStyle.None then
242 | self.RightBadge.Sprite:Position(385 + self._Offset.X + self.ParentMenu.WidthOffset, self.RightBadge.Sprite.Y)
243 | self.RightBadge.Sprite.TxtDictionary = GetBadgeDictionary(self.RightBadge.Badge, self._Selected)
244 | self.RightBadge.Sprite.TxtName = GetBadgeTexture(self.RightBadge.Badge, self._Selected)
245 | self.RightBadge.Sprite:Colour(GetBadgeColour(self.RightBadge.Badge, self._Selected))
246 | self.RightBadge.Sprite:Draw()
247 | end
248 |
249 | if self.Label.Text:Text() ~= "" and string.len(self.Label.Text:Text()) > 0 then
250 | if self.RightBadge.Badge ~= BadgeStyle.None then
251 | self.Label.Text:Position(385 + self._Offset.X + self.ParentMenu.WidthOffset, self.Label.Text.Y)
252 | self.Label.Text:Draw()
253 | else
254 | self.Label.Text:Position(420 + self._Offset.X + self.ParentMenu.WidthOffset, self.Label.Text.Y)
255 | self.Label.Text:Draw()
256 | end
257 | end
258 |
259 | self.Text:Draw()
260 | end
261 |
--------------------------------------------------------------------------------
/items/UIMenuListItem.lua:
--------------------------------------------------------------------------------
1 | UIMenuListItem = setmetatable({}, UIMenuListItem)
2 | UIMenuListItem.__index = UIMenuListItem
3 | UIMenuListItem.__call = function() return "UIMenuItem", "UIMenuListItem" end
4 |
5 | ---New
6 | ---@param Text string
7 | ---@param Items table
8 | ---@param Index number
9 | ---@param Description string
10 | function UIMenuListItem.New(Text, Items, Index, Description)
11 | if type(Items) ~= "table" then Items = {} end
12 | if Index == 0 then Index = 1 end
13 | local _UIMenuListItem = {
14 | Base = UIMenuItem.New(Text or "", Description or ""),
15 | Items = Items,
16 | LeftArrow = Sprite.New("commonmenu", "arrowleft", 110, 105, 30, 30),
17 | RightArrow = Sprite.New("commonmenu", "arrowright", 280, 105, 30, 30),
18 | ItemText = UIResText.New("", 290, 104, 0.35, 255, 255, 255, 255, 0, "Right"),
19 | _Index = tonumber(Index) or 1,
20 | Panels = {},
21 | OnListChanged = function(menu, item, newindex) end,
22 | OnListSelected = function(menu, item, newindex) end,
23 | }
24 | return setmetatable(_UIMenuListItem, UIMenuListItem)
25 | end
26 |
27 | ---SetParentMenu
28 | ---@param Menu table
29 | function UIMenuListItem:SetParentMenu(Menu)
30 | if Menu ~= nil and Menu() == "UIMenu" then
31 | self.Base.ParentMenu = Menu
32 | else
33 | return self.Base.ParentMenu
34 | end
35 | end
36 |
37 | ---Position
38 | ---@param Y number
39 | function UIMenuListItem:Position(Y)
40 | if tonumber(Y) then
41 | self.LeftArrow:Position(300 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y)
42 | self.RightArrow:Position(400 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y)
43 | self.ItemText:Position(300 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y)
44 | self.Base:Position(Y)
45 | end
46 | end
47 |
48 | ---Selected
49 | ---@param bool boolean
50 | function UIMenuListItem:Selected(bool)
51 | if bool ~= nil then
52 | self.Base._Selected = tobool(bool)
53 | else
54 | return self.Base._Selected
55 | end
56 | end
57 |
58 | ---Hovered
59 | ---@param bool boolean
60 | function UIMenuListItem: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 | ---Enabled
69 | ---@param bool boolean
70 | function UIMenuListItem:Enabled(bool)
71 | if bool ~= nil then
72 | self.Base._Enabled = tobool(bool)
73 | else
74 | return self.Base._Enabled
75 | end
76 | end
77 |
78 | ---Description
79 | ---@param str string
80 | function UIMenuListItem:Description(str)
81 | if tostring(str) and str ~= nil then
82 | self.Base._Description = tostring(str)
83 | else
84 | return self.Base._Description
85 | end
86 | end
87 |
88 | ---Offset
89 | ---@param X number
90 | ---@param Y number
91 | function UIMenuListItem:Offset(X, Y)
92 | if tonumber(X) or tonumber(Y) then
93 | if tonumber(X) then
94 | self.Base._Offset.X = tonumber(X)
95 | end
96 | if tonumber(Y) then
97 | self.Base._Offset.Y = tonumber(Y)
98 | end
99 | else
100 | return self.Base._Offset
101 | end
102 | end
103 |
104 | ---Text
105 | ---@param Text string
106 | function UIMenuListItem:Text(Text)
107 | if tostring(Text) and Text ~= nil then
108 | self.Base.Text:Text(tostring(Text))
109 | else
110 | return self.Base.Text:Text()
111 | end
112 | end
113 |
114 | ---Index
115 | ---@param Index table
116 | function UIMenuListItem:Index(Index)
117 | if tonumber(Index) then
118 | if tonumber(Index) > #self.Items then
119 | self._Index = 1
120 | elseif tonumber(Index) < 1 then
121 | self._Index = #self.Items
122 | else
123 | self._Index = tonumber(Index)
124 | end
125 | else
126 | return self._Index
127 | end
128 | end
129 |
130 | ---ItemToIndex
131 | ---@param Item table
132 | function UIMenuListItem:ItemToIndex(Item)
133 | for i = 1, #self.Items do
134 | if type(Item) == type(self.Items[i]) and Item == self.Items[i] then
135 | return i
136 | 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
137 | return i
138 | end
139 | end
140 | end
141 |
142 | ---IndexToItem
143 | ---@param Index table
144 | function UIMenuListItem:IndexToItem(Index)
145 | if tonumber(Index) then
146 | if tonumber(Index) == 0 then Index = 1 end
147 | if self.Items[tonumber(Index)] then
148 | return self.Items[tonumber(Index)]
149 | end
150 | end
151 | end
152 |
153 | ---SetLeftBadge
154 | function UIMenuListItem:SetLeftBadge()
155 | error("This item does not support badges")
156 | end
157 |
158 | ---SetRightBadge
159 | function UIMenuListItem:SetRightBadge()
160 | error("This item does not support badges")
161 | end
162 |
163 | ---RightLabel
164 | function UIMenuListItem:RightLabel()
165 | error("This item does not support a right label")
166 | end
167 |
168 | ---AddPanel
169 | ---@param Panel table
170 | function UIMenuListItem:AddPanel(Panel)
171 | if Panel() == "UIMenuPanel" then
172 | table.insert(self.Panels, Panel)
173 | Panel:SetParentItem(self)
174 | end
175 | end
176 |
177 | ---RemovePanelAt
178 | ---@param Index table
179 | function UIMenuListItem:RemovePanelAt(Index)
180 | if tonumber(Index) then
181 | if self.Panels[Index] then
182 | table.remove(self.Panels, tonumber(Index))
183 | end
184 | end
185 | end
186 |
187 | ---FindPanelIndex
188 | ---@param Panel table
189 | function UIMenuListItem:FindPanelIndex(Panel)
190 | if Panel() == "UIMenuPanel" then
191 | for Index = 1, #self.Panels do
192 | if self.Panels[Index] == Panel then
193 | return Index
194 | end
195 | end
196 | end
197 | return nil
198 | end
199 |
200 | ---FindPanelItem
201 | function UIMenuListItem:FindPanelItem()
202 | for Index = #self.Items, 1, -1 do
203 | if self.Items[Index].Panel then
204 | return Index
205 | end
206 | end
207 | return nil
208 | end
209 |
210 | ---Draw
211 | function UIMenuListItem:Draw()
212 | self.Base:Draw()
213 |
214 | if self:Enabled() then
215 | if self:Selected() then
216 | self.ItemText:Colour(0, 0, 0, 255)
217 | self.LeftArrow:Colour(0, 0, 0, 255)
218 | self.RightArrow:Colour(0, 0, 0, 255)
219 | else
220 | self.ItemText:Colour(245, 245, 245, 255)
221 | self.LeftArrow:Colour(245, 245, 245, 255)
222 | self.RightArrow:Colour(245, 245, 245, 255)
223 | end
224 | else
225 | self.ItemText:Colour(163, 159, 148, 255)
226 | self.LeftArrow:Colour(163, 159, 148, 255)
227 | self.RightArrow:Colour(163, 159, 148, 255)
228 | end
229 |
230 | local Text = (type(self.Items[self._Index]) == "table") and tostring(self.Items[self._Index].Name) or tostring(self.Items[self._Index])
231 | local Offset = MeasureStringWidth(Text, 0, 0.35)
232 |
233 | self.ItemText:Text(Text)
234 | self.LeftArrow:Position(378 - Offset + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.LeftArrow.Y)
235 |
236 |
237 | self.LeftArrow:Draw()
238 | self.RightArrow:Draw()
239 | self.ItemText:Position(403 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.ItemText.Y)
240 |
241 |
242 | self.ItemText:Draw()
243 | end
--------------------------------------------------------------------------------
/items/UIMenuProgressItem.lua:
--------------------------------------------------------------------------------
1 | UIMenuProgressItem = setmetatable({}, UIMenuProgressItem)
2 | UIMenuProgressItem.__index = UIMenuProgressItem
3 | UIMenuProgressItem.__call = function() return "UIMenuItem", "UIMenuProgressItem" end
4 |
5 | ---New
6 | ---@param Text string
7 | ---@param Items table
8 | ---@param Index number
9 | ---@param Description string
10 | ---@param Counter boolean
11 | function UIMenuProgressItem.New(Text, Items, Index, Description, Counter)
12 | if type(Items) ~= "table" then Items = {} end
13 | if Index == 0 then Index = 1 end
14 | local _UIMenuProgressItem = {
15 | Base = UIMenuItem.New(Text or "", Description or ""),
16 | Data = {
17 | Items = Items,
18 | Counter = tobool(Counter),
19 | Max = 407.5,
20 | Index = tonumber(Index) or 1,
21 | },
22 | Background = UIResRectangle.New(0, 0, 415, 20, 0, 0, 0, 255),
23 | Bar = UIResRectangle.New(0, 0, 407.5, 12.5),
24 | OnProgressChanged = function(menu, item, newindex) end,
25 | OnProgressSelected = function(menu, item, newindex) end,
26 | }
27 |
28 | _UIMenuProgressItem.Base.Rectangle.Height = 60
29 | _UIMenuProgressItem.Base.SelectedSprite.Height = 60
30 |
31 | if _UIMenuProgressItem.Data.Counter then
32 | _UIMenuProgressItem.Base:RightLabel(_UIMenuProgressItem.Data.Index.."/"..#_UIMenuProgressItem.Data.Items)
33 | else
34 | _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]))
35 | end
36 |
37 | _UIMenuProgressItem.Bar.Width = _UIMenuProgressItem.Data.Index/#_UIMenuProgressItem.Data.Items * _UIMenuProgressItem.Data.Max
38 |
39 | return setmetatable(_UIMenuProgressItem, UIMenuProgressItem)
40 | end
41 |
42 | ---SetParentMenu
43 | ---@param Menu table
44 | function UIMenuProgressItem:SetParentMenu(Menu)
45 | if Menu() == "UIMenu" then
46 | self.Base.ParentMenu = Menu
47 | else
48 | return self.Base.ParentMenu
49 | end
50 | end
51 |
52 | ---Position
53 | ---@param Y number
54 | function UIMenuProgressItem:Position(Y)
55 | if tonumber(Y) then
56 | self.Base:Position(Y)
57 | self.Background:Position(8 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 177 + Y + self.Base._Offset.Y)
58 | self.Bar:Position(11.75 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 180.75 + Y + self.Base._Offset.Y)
59 | end
60 | end
61 |
62 | ---Selected
63 | ---@param bool number
64 | function UIMenuProgressItem:Selected(bool)
65 | if bool ~= nil then
66 | self.Base._Selected = tobool(bool)
67 | else
68 | return self.Base._Selected
69 | end
70 | end
71 |
72 | ---Hovered
73 | ---@param bool boolean
74 | function UIMenuProgressItem:Hovered(bool)
75 | if bool ~= nil then
76 | self.Base._Hovered = tobool(bool)
77 | else
78 | return self.Base._Hovered
79 | end
80 | end
81 |
82 | ---Enabled
83 | ---@param bool boolean
84 | function UIMenuProgressItem:Enabled(bool)
85 | if bool ~= nil then
86 | self.Base._Enabled = tobool(bool)
87 | else
88 | return self.Base._Enabled
89 | end
90 | end
91 |
92 | ---Description
93 | ---@param str string
94 | function UIMenuProgressItem:Description(str)
95 | if tostring(str) and str ~= nil then
96 | self.Base._Description = tostring(str)
97 | else
98 | return self.Base._Description
99 | end
100 | end
101 |
102 | ---Offset
103 | ---@param X number
104 | ---@param Y number
105 | function UIMenuProgressItem:Offset(X, Y)
106 | if tonumber(X) or tonumber(Y) then
107 | if tonumber(X) then
108 | self.Base._Offset.X = tonumber(X)
109 | end
110 | if tonumber(Y) then
111 | self.Base._Offset.Y = tonumber(Y)
112 | end
113 | else
114 | return self.Base._Offset
115 | end
116 | end
117 |
118 | ---Text
119 | ---@param Text string
120 | function UIMenuProgressItem:Text(Text)
121 | if tostring(Text) and Text ~= nil then
122 | self.Base.Text:Text(tostring(Text))
123 | else
124 | return self.Base.Text:Text()
125 | end
126 | end
127 |
128 | ---Index
129 | ---@param Index table
130 | function UIMenuProgressItem:Index(Index)
131 | if tonumber(Index) then
132 | if tonumber(Index) > #self.Data.Items then
133 | self.Data.Index = 1
134 | elseif tonumber(Index) < 1 then
135 | self.Data.Index = #self.Data.Items
136 | else
137 | self.Data.Index = tonumber(Index)
138 | end
139 |
140 | if self.Data.Counter then
141 | self.Base:RightLabel(self.Data.Index.."/"..#self.Data.Items)
142 | else
143 | 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]))
144 | end
145 |
146 | self.Bar.Width = self.Data.Index/#self.Data.Items * self.Data.Max
147 | else
148 | return self.Data.Index
149 | end
150 | end
151 |
152 | ---ItemToIndex
153 | ---@param Item table
154 | function UIMenuProgressItem:ItemToIndex(Item)
155 | for i = 1, #self.Data.Items do
156 | if type(Item) == type(self.Data.Items[i]) and Item == self.Data.Items[i] then
157 | return i
158 | 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
159 | return i
160 | end
161 | end
162 | end
163 |
164 | ---IndexToItem
165 | ---@param Index table
166 | function UIMenuProgressItem:IndexToItem(Index)
167 | if tonumber(Index) then
168 | if tonumber(Index) == 0 then Index = 1 end
169 | if self.Data.Items[tonumber(Index)] then
170 | return self.Data.Items[tonumber(Index)]
171 | end
172 | end
173 | end
174 |
175 | ---SetLeftBadge
176 | function UIMenuProgressItem:SetLeftBadge()
177 | error("This item does not support badges")
178 | end
179 |
180 | ---SetRightBadge
181 | function UIMenuProgressItem:SetRightBadge()
182 | error("This item does not support badges")
183 | end
184 |
185 | ---RightLabel
186 | function UIMenuProgressItem:RightLabel()
187 | error("This item does not support a right label")
188 | end
189 |
190 | ---CalculateProgress
191 | ---@param CursorX number
192 | function UIMenuProgressItem:CalculateProgress(CursorX)
193 | local Progress = CursorX - self.Bar.X
194 | 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)))
195 | end
196 |
197 | ---Draw
198 | function UIMenuProgressItem:Draw()
199 | self.Base:Draw()
200 |
201 | if self.Base._Selected then
202 | self.Background:Colour(table.unpack(Colours.Black))
203 | self.Bar:Colour(table.unpack(Colours.White))
204 | else
205 | self.Background:Colour(table.unpack(Colours.White))
206 | self.Bar:Colour(table.unpack(Colours.Black))
207 | end
208 |
209 | self.Background:Draw()
210 | self.Bar:Draw()
211 | end
--------------------------------------------------------------------------------
/items/UIMenuSliderHeritageItem.lua:
--------------------------------------------------------------------------------
1 | UIMenuSliderHeritageItem = setmetatable({}, UIMenuSliderHeritageItem)
2 | UIMenuSliderHeritageItem.__index = UIMenuSliderHeritageItem
3 | UIMenuSliderHeritageItem.__call = function() return "UIMenuItem", "UIMenuSliderHeritageItem" end
4 |
5 | ---New
6 | ---@param Text string
7 | ---@param Items table
8 | ---@param Index boolean
9 | ---@param Description string
10 | ---@param SliderColors table
11 | ---@param BackgroundSliderColors table
12 | function UIMenuSliderHeritageItem.New(Text, Items, Index, Description, SliderColors, BackgroundSliderColors)
13 | if type(Items) ~= "table" then Items = {} end
14 | if Index == 0 then Index = 1 end
15 |
16 | if type(SliderColors) ~= "table" or SliderColors == nil then
17 | _SliderColors = { R = 57, G = 119, B = 200, A = 255 }
18 | else
19 | _SliderColors = SliderColors
20 | end
21 |
22 | if type(BackgroundSliderColors) ~= "table" or BackgroundSliderColors == nil then
23 | _BackgroundSliderColors = { R = 4, G = 32, B = 57, A = 255 }
24 | else
25 | _BackgroundSliderColors = BackgroundSliderColors
26 | end
27 |
28 | local _UIMenuSliderHeritageItem = {
29 | Base = UIMenuItem.New(Text or "", Description or ""),
30 | Items = Items,
31 | ShowDivider = 1,
32 | LeftArrow = Sprite.New("mpleaderboard", "leaderboard_male_icon", 0, 0, 30, 30, 0, 255, 255, 255, 255),
33 | RightArrow = Sprite.New("mpleaderboard", "leaderboard_female_icon", 0, 0, 30, 30, 0, 255, 255, 255, 255),
34 | Background = UIResRectangle.New(0, 0, 150, 10, _BackgroundSliderColors.R, _BackgroundSliderColors.G, _BackgroundSliderColors.B, _BackgroundSliderColors.A),
35 | Slider = UIResRectangle.New(0, 0, 75, 10, _SliderColors.R, _SliderColors.G, _SliderColors.B, _SliderColors.A),
36 | Divider = UIResRectangle.New(0, 0, 4, 20, 255, 255, 255, 255),
37 | _Index = tonumber(Index) or 1,
38 | Audio = { Slider = "CONTINUOUS_SLIDER", Library = "HUD_FRONTEND_DEFAULT_SOUNDSET", Id = nil },
39 | OnSliderChanged = function(menu, item, newindex) end,
40 | OnSliderSelected = function(menu, item, newindex) end,
41 | }
42 | return setmetatable(_UIMenuSliderHeritageItem, UIMenuSliderHeritageItem)
43 | end
44 |
45 | ---SetParentMenu
46 | ---@param Menu table
47 | function UIMenuSliderHeritageItem:SetParentMenu(Menu)
48 | if Menu() == "UIMenu" then
49 | self.Base.ParentMenu = Menu
50 | else
51 | return self.Base.ParentMenu
52 | end
53 | end
54 |
55 | ---Position
56 | ---@param Y number
57 | function UIMenuSliderHeritageItem:Position(Y)
58 | if tonumber(Y) then
59 | self.Background:Position(250 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 158.5 + self.Base._Offset.Y)
60 | self.Slider:Position(250 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 158.5 + self.Base._Offset.Y)
61 | self.Divider:Position(323.5 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 153 + self.Base._Offset.Y)
62 | self.LeftArrow:Position(220 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 148.5 + Y + self.Base._Offset.Y)
63 | self.RightArrow:Position(400 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 148.5 + Y + self.Base._Offset.Y)
64 | self.Base:Position(Y)
65 | end
66 | end
67 |
68 | ---Selected
69 | ---@param bool boolean
70 | function UIMenuSliderHeritageItem:Selected(bool)
71 | if bool ~= nil then
72 | self.Base._Selected = tobool(bool)
73 | else
74 | return self.Base._Selected
75 | end
76 | end
77 |
78 | ---Hovered
79 | ---@param bool boolean
80 | function UIMenuSliderHeritageItem:Hovered(bool)
81 | if bool ~= nil then
82 | self.Base._Hovered = tobool(bool)
83 | else
84 | return self.Base._Hovered
85 | end
86 | end
87 |
88 | ---Enabled
89 | ---@param bool boolean
90 | function UIMenuSliderHeritageItem:Enabled(bool)
91 | if bool ~= nil then
92 | self.Base._Enabled = tobool(bool)
93 | else
94 | return self.Base._Enabled
95 | end
96 | end
97 |
98 | ---Description
99 | ---@param str string
100 | function UIMenuSliderHeritageItem:Description(str)
101 | if tostring(str) and str ~= nil then
102 | self.Base._Description = tostring(str)
103 | else
104 | return self.Base._Description
105 | end
106 | end
107 |
108 | ---Offset
109 | ---@param X number
110 | ---@param Y number
111 | function UIMenuSliderHeritageItem:Offset(X, Y)
112 | if tonumber(X) or tonumber(Y) then
113 | if tonumber(X) then
114 | self.Base._Offset.X = tonumber(X)
115 | end
116 | if tonumber(Y) then
117 | self.Base._Offset.Y = tonumber(Y)
118 | end
119 | else
120 | return self.Base._Offset
121 | end
122 | end
123 |
124 | ---Text
125 | ---@param Text string
126 | function UIMenuSliderHeritageItem:Text(Text)
127 | if tostring(Text) and Text ~= nil then
128 | self.Base.Text:Text(tostring(Text))
129 | else
130 | return self.Base.Text:Text()
131 | end
132 | end
133 |
134 | ---Index
135 | ---@param Index number
136 | function UIMenuSliderHeritageItem:Index(Index)
137 | if tonumber(Index) then
138 | if tonumber(Index) > #self.Items then
139 | self._Index = 1
140 | elseif tonumber(Index) < 1 then
141 | self._Index = #self.Items
142 | else
143 | self._Index = tonumber(Index)
144 | end
145 | else
146 | return self._Index
147 | end
148 | end
149 |
150 | ---ItemToIndex
151 | ---@param Item table
152 | function UIMenuSliderHeritageItem:ItemToIndex(Item)
153 | for i = 1, #self.Items do
154 | if type(Item) == type(self.Items[i]) and Item == self.Items[i] then
155 | return i
156 | end
157 | end
158 | end
159 |
160 | ---IndexToItem
161 | ---@param Index number
162 | function UIMenuSliderHeritageItem:IndexToItem(Index)
163 | if tonumber(Index) then
164 | if tonumber(Index) == 0 then Index = 1 end
165 | if self.Items[tonumber(Index)] then
166 | return self.Items[tonumber(Index)]
167 | end
168 | end
169 | end
170 |
171 | ---SetLeftBadge
172 | function UIMenuSliderHeritageItem:SetLeftBadge()
173 | error("This item does not support badges")
174 | end
175 |
176 | ---SetRightBadge
177 | function UIMenuSliderHeritageItem:SetRightBadge()
178 | error("This item does not support badges")
179 | end
180 |
181 | ---RightLabel
182 | function UIMenuSliderHeritageItem:RightLabel()
183 | error("This item does not support a right label")
184 | end
185 |
186 | ---Draw
187 | function UIMenuSliderHeritageItem:Draw()
188 | self.Base:Draw()
189 |
190 | if self:Enabled() then
191 | if self:Selected() then
192 | self.LeftArrow:Colour(0, 0, 0, 255)
193 | self.RightArrow:Colour(0, 0, 0, 255)
194 | else
195 | self.LeftArrow:Colour(255, 255, 255, 255)
196 | self.RightArrow:Colour(255, 255, 255, 255)
197 | end
198 | else
199 | self.LeftArrow:Colour(255, 255, 255, 255)
200 | self.RightArrow:Colour(255, 255, 255, 255)
201 | end
202 |
203 | local Offset = ((self.Background.Width - self.Slider.Width) / (#self.Items - 1)) * (self._Index - 1)
204 |
205 | self.Slider:Position(250 + self.Base._Offset.X + Offset + self.Base.ParentMenu.WidthOffset, self.Slider.Y)
206 |
207 | self.LeftArrow:Draw()
208 | self.RightArrow:Draw()
209 |
210 | self.Background:Draw()
211 | self.Slider:Draw()
212 |
213 | if self.ShowDivider then
214 | self.Divider:Draw()
215 | if self:Selected() then
216 | self.Divider:Colour(0, 0, 0, 255)
217 | else
218 | self.Divider:Colour(255, 255, 255, 255)
219 | end
220 | end
221 |
222 | end
--------------------------------------------------------------------------------
/items/UIMenuSliderItem.lua:
--------------------------------------------------------------------------------
1 | UIMenuSliderItem = setmetatable({}, UIMenuSliderItem)
2 | UIMenuSliderItem.__index = UIMenuSliderItem
3 | UIMenuSliderItem.__call = function() return "UIMenuItem", "UIMenuSliderItem" end
4 |
5 | ---New
6 | ---@param Text string
7 | ---@param Items table
8 | ---@param Index number
9 | ---@param Description string
10 | ---@param Divider boolean
11 | ---@param SliderColors table
12 | ---@param BackgroundSliderColors table
13 | function UIMenuSliderItem.New(Text, Items, Index, Description, Divider, SliderColors, BackgroundSliderColors)
14 | if type(Items) ~= "table" then Items = {} end
15 | if Index == 0 then Index = 1 end
16 | if type(SliderColors) ~= "table" or SliderColors == nil then
17 | _SliderColors = { R = 57, G = 119, B = 200, A = 255 }
18 | else
19 | _SliderColors = SliderColors
20 | end
21 | if type(BackgroundSliderColors) ~= "table" or BackgroundSliderColors == nil then
22 | _BackgroundSliderColors = { R = 4, G = 32, B = 57, A = 255 }
23 | else
24 | _BackgroundSliderColors = BackgroundSliderColors
25 | end
26 | local _UIMenuSliderItem = {
27 | Base = UIMenuItem.New(Text or "", Description or ""),
28 | Items = Items,
29 | ShowDivider = tobool(Divider),
30 | LeftArrow = Sprite.New("commonmenu", "arrowleft", 0, 105, 25, 25),
31 | RightArrow = Sprite.New("commonmenu", "arrowright", 0, 105, 25, 25),
32 | Background = UIResRectangle.New(0, 0, 150, 10,_BackgroundSliderColors.R, _BackgroundSliderColors.G, _BackgroundSliderColors.B, _BackgroundSliderColors.A),
33 | Slider = UIResRectangle.New(0, 0, 75, 10, _SliderColors.R, _SliderColors.G, _SliderColors.B, _SliderColors.A),
34 | Divider = UIResRectangle.New(0, 0, 4, 20, 255, 255, 255, 255),
35 | _Index = tonumber(Index) or 1,
36 | OnSliderChanged = function(menu, item, newindex) end,
37 | OnSliderSelected = function(menu, item, newindex) end,
38 | }
39 | return setmetatable(_UIMenuSliderItem, UIMenuSliderItem)
40 | end
41 |
42 | ---SetParentMenu
43 | ---@param Menu table
44 | function UIMenuSliderItem:SetParentMenu(Menu)
45 | if Menu() == "UIMenu" then
46 | self.Base.ParentMenu = Menu
47 | else
48 | return self.Base.ParentMenu
49 | end
50 | end
51 |
52 | ---Position
53 | ---@param Y number
54 | function UIMenuSliderItem:Position(Y)
55 | if tonumber(Y) then
56 | self.Background:Position(250 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 158.5 + self.Base._Offset.Y)
57 | self.Slider:Position(250 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 158.5 + self.Base._Offset.Y)
58 | self.Divider:Position(323.5 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 153 + self.Base._Offset.Y)
59 | self.LeftArrow:Position(225 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 150.5 + Y + self.Base._Offset.Y)
60 | self.RightArrow:Position(400 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 150.5 + Y + self.Base._Offset.Y)
61 | self.Base:Position(Y)
62 | end
63 | end
64 |
65 | ---Selected
66 | ---@param bool table
67 | function UIMenuSliderItem:Selected(bool)
68 | if bool ~= nil then
69 |
70 | self.Base._Selected = tobool(bool)
71 | else
72 | return self.Base._Selected
73 | end
74 | end
75 |
76 | function UIMenuSliderItem:Hovered(bool)
77 | if bool ~= nil then
78 | self.Base._Hovered = tobool(bool)
79 | else
80 | return self.Base._Hovered
81 | end
82 | end
83 |
84 | function UIMenuSliderItem:Enabled(bool)
85 | if bool ~= nil then
86 | self.Base._Enabled = tobool(bool)
87 | else
88 | return self.Base._Enabled
89 | end
90 | end
91 |
92 | function UIMenuSliderItem:Description(str)
93 | if tostring(str) and str ~= nil then
94 | self.Base._Description = tostring(str)
95 | else
96 | return self.Base._Description
97 | end
98 | end
99 |
100 | function UIMenuSliderItem:Offset(X, Y)
101 | if tonumber(X) or tonumber(Y) then
102 | if tonumber(X) then
103 | self.Base._Offset.X = tonumber(X)
104 | end
105 | if tonumber(Y) then
106 | self.Base._Offset.Y = tonumber(Y)
107 | end
108 | else
109 | return self.Base._Offset
110 | end
111 | end
112 |
113 | function UIMenuSliderItem:Text(Text)
114 | if tostring(Text) and Text ~= nil then
115 | self.Base.Text:Text(tostring(Text))
116 | else
117 | return self.Base.Text:Text()
118 | end
119 | end
120 |
121 | function UIMenuSliderItem:Index(Index)
122 | if tonumber(Index) then
123 | if tonumber(Index) > #self.Items then
124 | self._Index = 1
125 | elseif tonumber(Index) < 1 then
126 | self._Index = #self.Items
127 | else
128 | self._Index = tonumber(Index)
129 | end
130 | else
131 | return self._Index
132 | end
133 | end
134 |
135 | function UIMenuSliderItem:ItemToIndex(Item)
136 | for i = 1, #self.Items do
137 | if type(Item) == type(self.Items[i]) and Item == self.Items[i] then
138 | return i
139 | end
140 | end
141 | end
142 |
143 | function UIMenuSliderItem:IndexToItem(Index)
144 | if tonumber(Index) then
145 | if tonumber(Index) == 0 then Index = 1 end
146 | if self.Items[tonumber(Index)] then
147 | return self.Items[tonumber(Index)]
148 | end
149 | end
150 | end
151 |
152 | function UIMenuSliderItem:SetLeftBadge()
153 | error("This item does not support badges")
154 | end
155 |
156 | function UIMenuSliderItem:SetRightBadge()
157 | error("This item does not support badges")
158 | end
159 |
160 | function UIMenuSliderItem:RightLabel()
161 | error("This item does not support a right label")
162 | end
163 |
164 | function UIMenuSliderItem:Draw()
165 | self.Base:Draw()
166 |
167 | if self:Enabled() then
168 | if self:Selected() then
169 | self.LeftArrow:Colour(0, 0, 0, 255)
170 | self.RightArrow:Colour(0, 0, 0, 255)
171 | else
172 | self.LeftArrow:Colour(245, 245, 245, 255)
173 | self.RightArrow:Colour(245, 245, 245, 255)
174 | end
175 | else
176 | self.LeftArrow:Colour(163, 159, 148, 255)
177 | self.RightArrow:Colour(163, 159, 148, 255)
178 | end
179 |
180 | local Offset = ((self.Background.Width - self.Slider.Width)/(#self.Items - 1)) * (self._Index-1)
181 |
182 | self.Slider:Position(250 + self.Base._Offset.X + Offset + self.Base.ParentMenu.WidthOffset, self.Slider.Y)
183 |
184 | if self:Selected() then
185 | self.LeftArrow:Draw()
186 | self.RightArrow:Draw()
187 | end
188 |
189 | self.Background:Draw()
190 | self.Slider:Draw()
191 | if self.ShowDivider then
192 | self.Divider:Draw()
193 | end
194 | end
--------------------------------------------------------------------------------
/panels/UIMenuColourPanel.lua:
--------------------------------------------------------------------------------
1 | UIMenuColourPanel = setmetatable({}, UIMenuColourPanel)
2 | UIMenuColourPanel.__index = UIMenuColourPanel
3 | UIMenuColourPanel.__call = function() return "UIMenuPanel", "UIMenuColourPanel" end
4 |
5 | ---New
6 | ---@param Title string
7 | ---@param Colours number
8 | function UIMenuColourPanel.New(Title, Colours)
9 | _UIMenuColourPanel = {
10 | Data = {
11 | Pagination = {
12 | Min = 1,
13 | Max = 8,
14 | Total = 8,
15 | },
16 | Index = 1000,
17 | Items = Colours,
18 | Title = Title or "Title",
19 | Enabled = true,
20 | Value = 1,
21 | },
22 | Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 112),
23 | Bar = {},
24 | LeftArrow = Sprite.New("commonmenu", "arrowleft", 0, 0, 30, 30),
25 | RightArrow = Sprite.New("commonmenu", "arrowright", 0, 0, 30, 30),
26 | SelectedRectangle = UIResRectangle.New(0, 0, 44.5, 8),
27 | Text = UIResText.New(Title.." (1 of "..#Colours..")" or "Title".." (1 of "..#Colours..")", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
28 | ParentItem = nil,
29 | }
30 |
31 | for Index = 1, #Colours do
32 | if Index < 10 then
33 | table.insert(_UIMenuColourPanel.Bar, UIResRectangle.New(0, 0, 44.5, 44.5, table.unpack(Colours[Index])))
34 | else
35 | break
36 | end
37 | end
38 |
39 | if #_UIMenuColourPanel.Data.Items ~= 0 then
40 | _UIMenuColourPanel.Data.Index = 1000 - (1000 % #_UIMenuColourPanel.Data.Items)
41 | _UIMenuColourPanel.Data.Pagination.Max = _UIMenuColourPanel.Data.Pagination.Total + 1
42 | _UIMenuColourPanel.Data.Pagination.Min = 0
43 | end
44 | return setmetatable(_UIMenuColourPanel, UIMenuColourPanel)
45 | end
46 |
47 | ---SetParentItem
48 | ---@param Item table
49 | function UIMenuColourPanel:SetParentItem(Item) -- required
50 | if Item() == "UIMenuItem" then
51 | self.ParentItem = Item
52 | else
53 | return self.ParentItem
54 | end
55 | end
56 |
57 | ---Enabled
58 | ---@param Enabled boolean
59 | function UIMenuColourPanel:Enabled(Enabled)
60 | if type(Enabled) == "boolean" then
61 | self.Data.Enabled = Enabled
62 | else
63 | return self.Data.Enabled
64 | end
65 | end
66 |
67 | ---Position
68 | ---@param Y number
69 | function UIMenuColourPanel:Position(Y) -- required
70 | if tonumber(Y) then
71 | local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset
72 |
73 | self.Background:Position(ParentOffsetX, Y)
74 | for Index = 1, #self.Bar do
75 | self.Bar[Index]:Position(15 + (44.5 * (Index - 1)) + ParentOffsetX + (ParentOffsetWidth/2), 55 + Y)
76 | end
77 | self.SelectedRectangle:Position(15 + (44.5 * ((self:CurrentSelection() - self.Data.Pagination.Min) - 1)) + ParentOffsetX + (ParentOffsetWidth/2), 47 + Y)
78 | self.LeftArrow:Position(7.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y)
79 | self.RightArrow:Position(393.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y)
80 | self.Text:Position(215.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y)
81 | end
82 | end
83 |
84 | ---CurrentSelection
85 | ---@param value number
86 | ---@param PreventUpdate table
87 | function UIMenuColourPanel:CurrentSelection(value, PreventUpdate)
88 | if tonumber(value) then
89 | if #self.Data.Items == 0 then
90 | self.Data.Index = 0
91 | end
92 |
93 | self.Data.Index = 1000000 - (1000000 % #self.Data.Items) + tonumber(value)
94 |
95 | if self:CurrentSelection() > self.Data.Pagination.Max then
96 | self.Data.Pagination.Min = self:CurrentSelection() - (self.Data.Pagination.Total + 1)
97 | self.Data.Pagination.Max = self:CurrentSelection()
98 | elseif self:CurrentSelection() < self.Data.Pagination.Min then
99 | self.Data.Pagination.Min = self:CurrentSelection() - 1
100 | self.Data.Pagination.Max = self:CurrentSelection() + (self.Data.Pagination.Total + 1)
101 | end
102 |
103 | self:UpdateSelection(PreventUpdate)
104 | else
105 | if #self.Data.Items == 0 then
106 | return 1
107 | else
108 | if self.Data.Index % #self.Data.Items == 0 then
109 | return 1
110 | else
111 | return self.Data.Index % #self.Data.Items + 1
112 | end
113 | end
114 | end
115 | end
116 |
117 | ---UpdateParent
118 | ---@param Colour table
119 | function UIMenuColourPanel:UpdateParent(Colour)
120 | local _, ParentType = self.ParentItem()
121 | if ParentType == "UIMenuListItem" then
122 | local PanelItemIndex = self.ParentItem:FindPanelItem()
123 | local PanelIndex = self.ParentItem:FindPanelIndex(self)
124 | if PanelItemIndex then
125 | self.ParentItem.Items[PanelItemIndex].Value[PanelIndex] = Colour
126 | self.ParentItem:Index(PanelItemIndex)
127 | self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
128 | self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
129 | else
130 | for Index = 1, #self.ParentItem.Items do
131 | if type(self.ParentItem.Items[Index]) == "table" then
132 | if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end
133 | self.ParentItem.Items[Index].Panels[PanelIndex] = Colour
134 | else
135 | self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = Colour}}
136 | end
137 | end
138 | self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
139 | self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
140 | end
141 | elseif ParentType == "UIMenuItem" then
142 | self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, Colour)
143 | end
144 | end
145 |
146 | ---UpdateSelection
147 | ---@param PreventUpdate table
148 | function UIMenuColourPanel:UpdateSelection(PreventUpdate)
149 | local CurrentSelection = self:CurrentSelection()
150 | if not PreventUpdate then
151 | self:UpdateParent(CurrentSelection)
152 | end
153 | self.SelectedRectangle:Position(15 + (44.5 * ((CurrentSelection - self.Data.Pagination.Min) - 1)) + self.ParentItem:Offset().X, self.SelectedRectangle.Y)
154 | for Index = 1, 9 do
155 | self.Bar[Index]:Colour(table.unpack(self.Data.Items[self.Data.Pagination.Min + Index]))
156 | end
157 | self.Text:Text(self.Data.Title.." ("..CurrentSelection.." of "..#self.Data.Items..")")
158 | end
159 |
160 | ---Functions
161 | function UIMenuColourPanel:Functions()
162 | local SafeZone = {X = 0, Y = 0}
163 | if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then
164 | SafeZone = GetSafeZoneBounds()
165 | end
166 | if IsMouseInBounds(self.LeftArrow.X + SafeZone.X, self.LeftArrow.Y + SafeZone.Y, self.LeftArrow.Width, self.LeftArrow.Height) then
167 | if IsDisabledControlJustPressed(0, 24) then
168 | if #self.Data.Items > self.Data.Pagination.Total + 1 then
169 | if self:CurrentSelection() <= self.Data.Pagination.Min + 1 then
170 | if self:CurrentSelection() == 1 then
171 | self.Data.Pagination.Min = #self.Data.Items - (self.Data.Pagination.Total + 1)
172 | self.Data.Pagination.Max = #self.Data.Items
173 | self.Data.Index = 1000 - (1000 % #self.Data.Items)
174 | self.Data.Index = self.Data.Index + (#self.Data.Items - 1)
175 | self:UpdateSelection()
176 | else
177 | self.Data.Pagination.Min = self.Data.Pagination.Min - 1
178 | self.Data.Pagination.Max = self.Data.Pagination.Max - 1
179 | self.Data.Index = self.Data.Index - 1
180 | self:UpdateSelection()
181 | end
182 | else
183 | self.Data.Index = self.Data.Index - 1
184 | self:UpdateSelection()
185 | end
186 | else
187 | self.Data.Index = self.Data.Index - 1
188 | self:UpdateSelection()
189 | end
190 | end
191 | end
192 |
193 | if IsMouseInBounds(self.RightArrow.X + SafeZone.X, self.RightArrow.Y + SafeZone.Y, self.RightArrow.Width, self.RightArrow.Height) then
194 | if IsDisabledControlJustPressed(0, 24) then
195 | if #self.Data.Items > self.Data.Pagination.Total + 1 then
196 | if self:CurrentSelection() >= self.Data.Pagination.Max then
197 | if self:CurrentSelection() == #self.Data.Items then
198 | self.Data.Pagination.Min = 0
199 | self.Data.Pagination.Max = self.Data.Pagination.Total + 1
200 | self.Data.Index = 1000 - (1000 % #self.Data.Items)
201 | self:UpdateSelection()
202 | else
203 | self.Data.Pagination.Max = self.Data.Pagination.Max + 1
204 | self.Data.Pagination.Min = self.Data.Pagination.Max - (self.Data.Pagination.Total + 1)
205 | self.Data.Index = self.Data.Index + 1
206 | self:UpdateSelection()
207 | end
208 | else
209 | self.Data.Index = self.Data.Index + 1
210 | self:UpdateSelection()
211 | end
212 | else
213 | self.Data.Index = self.Data.Index + 1
214 | self:UpdateSelection()
215 | end
216 | end
217 | end
218 |
219 | for Index = 1, #self.Bar do
220 | if IsMouseInBounds(self.Bar[Index].X + SafeZone.X, self.Bar[Index].Y + SafeZone.Y, self.Bar[Index].Width, self.Bar[Index].Height) then
221 | if IsDisabledControlJustPressed(0, 24) then
222 | self:CurrentSelection(self.Data.Pagination.Min + Index - 1)
223 | end
224 | end
225 | end
226 | end
227 |
228 | ---Draw
229 | function UIMenuColourPanel:Draw()
230 | if self.Data.Enabled then
231 | self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 112)
232 |
233 | self.Background:Draw()
234 | self.LeftArrow:Draw()
235 | self.RightArrow:Draw()
236 | self.Text:Draw()
237 | self.SelectedRectangle:Draw()
238 | for Index = 1, #self.Bar do
239 | self.Bar[Index]:Draw()
240 | end
241 | self:Functions()
242 | end
243 | end
--------------------------------------------------------------------------------
/panels/UIMenuGridPanel.lua:
--------------------------------------------------------------------------------
1 | UIMenuGridPanel = setmetatable({}, UIMenuGridPanel)
2 | UIMenuGridPanel.__index = UIMenuGridPanel
3 | UIMenuGridPanel.__call = function() return "UIMenuPanel", "UIMenuGridPanel" end
4 |
5 | ---New
6 | ---@param TopText string
7 | ---@param LeftText string
8 | ---@param RightText string
9 | ---@param BottomText string
10 | function UIMenuGridPanel.New(TopText, LeftText, RightText, BottomText)
11 | _UIMenuGridPanel = {
12 | Data = {
13 | Enabled = true,
14 | },
15 | Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 275),
16 | Grid = Sprite.New("pause_menu_pages_char_mom_dad", "nose_grid", 0, 0, 200, 200, 0),
17 | Circle = Sprite.New("mpinventory","in_world_circle", 0, 0, 20, 20, 0),
18 | Audio = {Slider = "CONTINUOUS_SLIDER", Library = "HUD_FRONTEND_DEFAULT_SOUNDSET", Id = nil},
19 | ParentItem = nil,
20 | Text = {
21 | Top = UIResText.New(TopText or "Top", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
22 | Left = UIResText.New(LeftText or "Left", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
23 | Right = UIResText.New(RightText or "Right", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
24 | Bottom = UIResText.New(BottomText or "Bottom", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
25 | },
26 | }
27 | return setmetatable(_UIMenuGridPanel, UIMenuGridPanel)
28 | end
29 |
30 | ---SetParentItem
31 | ---@param Item table
32 | function UIMenuGridPanel:SetParentItem(Item) -- required
33 | if Item() == "UIMenuItem" then
34 | self.ParentItem = Item
35 | else
36 | return self.ParentItem
37 | end
38 | end
39 |
40 | ---Enabled
41 | ---@param Enabled boolean
42 | function UIMenuGridPanel:Enabled(Enabled)
43 | if type(Enabled) == "boolean" then
44 | self.Data.Enabled = Enabled
45 | else
46 | return self.Data.Enabled
47 | end
48 | end
49 |
50 | ---CirclePosition
51 | ---@param X number
52 | ---@param Y number
53 | function UIMenuGridPanel:CirclePosition(X, Y)
54 | if tonumber(X) and tonumber(Y) then
55 | 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)
56 | 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)
57 | else
58 | 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)
59 | end
60 | end
61 |
62 | ---Position
63 | ---@param Y number
64 | function UIMenuGridPanel:Position(Y)
65 | if tonumber(Y) then
66 | local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset
67 |
68 | self.Background:Position(ParentOffsetX, Y)
69 | self.Grid:Position(ParentOffsetX + 115.5 + (ParentOffsetWidth/2), 37.5 + Y)
70 | self.Text.Top:Position(ParentOffsetX + 215.5 + (ParentOffsetWidth/2), 5 + Y)
71 | self.Text.Left:Position(ParentOffsetX + 57.75 + (ParentOffsetWidth/2), 120 + Y)
72 | self.Text.Right:Position(ParentOffsetX + 373.25 + (ParentOffsetWidth/2), 120 + Y)
73 | self.Text.Bottom:Position(ParentOffsetX + 215.5 + (ParentOffsetWidth/2), 240 + Y)
74 |
75 | if not self.CircleLocked then
76 | self.CircleLocked = true
77 | self:CirclePosition(0.5, 0.5)
78 | end
79 | end
80 | end
81 |
82 | ---UpdateParent
83 | ---@param X number
84 | ---@param Y number
85 | function UIMenuGridPanel:UpdateParent(X, Y)
86 | local _, ParentType = self.ParentItem()
87 | self.Data.Value = {X = X, Y = Y}
88 | if ParentType == "UIMenuListItem" then
89 | local PanelItemIndex = self.ParentItem:FindPanelItem()
90 | if PanelItemIndex then
91 | self.ParentItem.Items[PanelItemIndex].Value[self.ParentItem:FindPanelIndex(self)] = {X = X, Y = Y}
92 | self.ParentItem:Index(PanelItemIndex)
93 | self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
94 | self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
95 | else
96 | local PanelIndex = self.ParentItem:FindPanelIndex(self)
97 | for Index = 1, #self.ParentItem.Items do
98 | if type(self.ParentItem.Items[Index]) == "table" then
99 | if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end
100 | self.ParentItem.Items[Index].Panels[PanelIndex] = {X = X, Y = Y}
101 | else
102 | self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = {X = X, Y = Y}}}
103 | end
104 | end
105 | self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
106 | self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
107 | end
108 | elseif ParentType == "UIMenuItem" then
109 | self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, {X = X, Y = Y})
110 | end
111 | end
112 |
113 | ---Functions
114 | function UIMenuGridPanel:Functions()
115 | local SafeZone = {X = 0, Y = 0}
116 | if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then
117 | SafeZone = GetSafeZoneBounds()
118 | end
119 |
120 | if IsMouseInBounds(self.Grid.X + 20 + SafeZone.X, self.Grid.Y + 20 + SafeZone.Y, self.Grid.Width - 40, self.Grid.Height - 40) then
121 | if IsDisabledControlJustPressed(0, 24) then
122 | if not self.Pressed then
123 | self.Pressed = true
124 | Citizen.CreateThread(function()
125 | self.Audio.Id = GetSoundId()
126 | PlaySoundFrontend(self.Audio.Id, self.Audio.Slider, self.Audio.Library, 1)
127 | 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
128 | Citizen.Wait(0)
129 | 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)
130 |
131 | 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)))
132 | end
133 | StopSound(self.Audio.Id)
134 | ReleaseSoundId(self.Audio.Id)
135 | self.Pressed = false
136 | end)
137 | Citizen.CreateThread(function()
138 | 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
139 | Citizen.Wait(75)
140 | 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)
141 |
142 | 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)
143 | end
144 | end)
145 | end
146 | end
147 | end
148 | end
149 |
150 | ---Draw
151 | function UIMenuGridPanel:Draw()
152 | if self.Data.Enabled then
153 | self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 275)
154 | self.Background:Draw()
155 | self.Grid:Draw()
156 | self.Circle:Draw()
157 | self.Text.Top:Draw()
158 | self.Text.Left:Draw()
159 | self.Text.Right:Draw()
160 | self.Text.Bottom:Draw()
161 | self:Functions()
162 | end
163 | end
164 |
--------------------------------------------------------------------------------
/panels/UIMenuPercentagePanel.lua:
--------------------------------------------------------------------------------
1 | UIMenuPercentagePanel = setmetatable({}, UIMenuPercentagePanel)
2 | UIMenuPercentagePanel.__index = UIMenuPercentagePanel
3 | UIMenuPercentagePanel.__call = function() return "UIMenuPanel", "UIMenuPercentagePanel" end
4 |
5 | ---New
6 | ---@param MinText number
7 | ---@param MaxText number
8 | function UIMenuPercentagePanel.New(MinText, MaxText)
9 | _UIMenuPercentagePanel = {
10 | Data = {
11 | Enabled = true,
12 | },
13 | Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 76),
14 | ActiveBar = UIResRectangle.New(0, 0, 413, 10, 245, 245, 245, 255),
15 | BackgroundBar = UIResRectangle.New(0, 0, 413, 10, 87, 87, 87, 255),
16 | Text = {
17 | Min = UIResText.New(MinText or "0%", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
18 | Max = UIResText.New("100%", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
19 | Title = UIResText.New(MaxText or "Opacity", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
20 | },
21 | Audio = {Slider = "CONTINUOUS_SLIDER", Library = "HUD_FRONTEND_DEFAULT_SOUNDSET", Id = nil},
22 | ParentItem = nil,
23 | }
24 |
25 | return setmetatable(_UIMenuPercentagePanel, UIMenuPercentagePanel)
26 | end
27 |
28 | ---SetParentItem
29 | ---@param Item table
30 | function UIMenuPercentagePanel:SetParentItem(Item)
31 | if Item() == "UIMenuItem" then
32 | self.ParentItem = Item
33 | else
34 | return self.ParentItem
35 | end
36 | end
37 |
38 | ---Enabled
39 | ---@param Enabled boolean
40 | function UIMenuPercentagePanel:Enabled(Enabled)
41 | if type(Enabled) == "boolean" then
42 | self.Data.Enabled = Enabled
43 | else
44 | return self.Data.Enabled
45 | end
46 | end
47 |
48 | ---Position
49 | ---@param Y number
50 | function UIMenuPercentagePanel:Position(Y) -- required
51 | if tonumber(Y) then
52 | local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset
53 | self.Background:Position(ParentOffsetX, Y)
54 | self.ActiveBar:Position(ParentOffsetX + (ParentOffsetWidth/2) + 9, 50 + Y)
55 | self.BackgroundBar:Position(ParentOffsetX + (ParentOffsetWidth/2) + 9, 50 + Y)
56 | self.Text.Min:Position(ParentOffsetX + (ParentOffsetWidth/2) + 25, 15 + Y)
57 | self.Text.Max:Position(ParentOffsetX + (ParentOffsetWidth/2) + 398, 15 + Y)
58 | self.Text.Title:Position(ParentOffsetX + (ParentOffsetWidth/2) + 215.5, 15 + Y)
59 | end
60 | end
61 |
62 | ---Percentage
63 | ---@param Value number
64 | function UIMenuPercentagePanel:Percentage(Value)
65 | if tonumber(Value) then
66 | local Percent = ((Value < 0.0) and 0.0) or ((Value > 1.0) and 1.0 or Value)
67 | self.ActiveBar:Size(self.BackgroundBar.Width * Percent, self.ActiveBar.Height)
68 | else
69 | local SafeZone = {X = 0, Y = 0}
70 | if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then
71 | SafeZone = GetSafeZoneBounds()
72 | end
73 |
74 | local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X
75 | return math.round(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413))/self.BackgroundBar.Width, 2)
76 | end
77 | end
78 |
79 | ---UpdateParent
80 | ---@param Percentage number
81 | function UIMenuPercentagePanel:UpdateParent(Percentage)
82 | local _, ParentType = self.ParentItem()
83 | if ParentType == "UIMenuListItem" then
84 | local PanelItemIndex = self.ParentItem:FindPanelItem()
85 | if PanelItemIndex then
86 | self.ParentItem.Items[PanelItemIndex].Value[self.ParentItem:FindPanelIndex(self)] = Percentage
87 | self.ParentItem:Index(PanelItemIndex)
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 | else
91 | local PanelIndex = self.ParentItem:FindPanelIndex(self)
92 | for Index = 1, #self.ParentItem.Items do
93 | if type(self.ParentItem.Items[Index]) == "table" then
94 | if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end
95 | self.ParentItem.Items[Index].Panels[PanelIndex] = Percentage
96 | else
97 | self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = Percentage}}
98 | end
99 | end
100 | self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
101 | self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
102 | end
103 | elseif ParentType == "UIMenuItem" then
104 | self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, Percentage)
105 | end
106 | end
107 |
108 | ---Functions
109 | function UIMenuPercentagePanel:Functions()
110 | local SafeZone = {X = 0, Y = 0}
111 | if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then
112 | SafeZone = GetSafeZoneBounds()
113 | end
114 | if IsMouseInBounds(self.BackgroundBar.X + SafeZone.X, self.BackgroundBar.Y - 4 + SafeZone.Y, self.BackgroundBar.Width, self.BackgroundBar.Height + 8) then
115 | if IsDisabledControlJustPressed(0, 24) then
116 | if not self.Pressed then
117 | self.Pressed = true
118 | Citizen.CreateThread(function()
119 | self.Audio.Id = GetSoundId()
120 | PlaySoundFrontend(self.Audio.Id, self.Audio.Slider, self.Audio.Library, 1)
121 | 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
122 | Citizen.Wait(0)
123 | local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X
124 | self.ActiveBar:Size(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413)), self.ActiveBar.Height)
125 | end
126 | StopSound(self.Audio.Id)
127 | ReleaseSoundId(self.Audio.Id)
128 | self.Pressed = false
129 | end)
130 | Citizen.CreateThread(function()
131 | 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
132 | Citizen.Wait(75)
133 | local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X
134 | self:UpdateParent(math.round(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413))/self.BackgroundBar.Width, 2))
135 | end
136 | end)
137 | end
138 | end
139 | end
140 | end
141 |
142 | ---Draw
143 | function UIMenuPercentagePanel:Draw()
144 | if self.Data.Enabled then
145 | self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 76)
146 | self.Background:Draw()
147 | self.BackgroundBar:Draw()
148 | self.ActiveBar:Draw()
149 | self.Text.Min:Draw()
150 | self.Text.Max:Draw()
151 | self.Text.Title:Draw()
152 | self:Functions()
153 | end
154 | end
--------------------------------------------------------------------------------
/share/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 TableDump(o)
52 | if type(o) == 'table' then
53 | local s = '{ '
54 | for k,v in pairs(o) do
55 | if type(k) ~= 'number' then k = '"'..k..'"' end
56 | s = s .. '['..k..'] = ' .. TableDump(v) .. ','
57 | end
58 | return s .. '} '
59 | else
60 | return print(tostring(o))
61 | end
62 | end
63 |
64 | function GetSafeZoneBounds()
65 | local SafeSize = GetSafeZoneSize()
66 | SafeSize = math.round(SafeSize, 2)
67 | SafeSize = (SafeSize * 100) - 90
68 | SafeSize = 10 - SafeSize
69 |
70 | local W, H = 1920, 1080
71 |
72 | return {X = math.round(SafeSize * ((W/H) * 5.4)), Y = math.round(SafeSize * 5.4)}
73 | end
74 |
75 | function Controller()
76 | return not IsInputDisabled(2)
77 | end
78 |
79 | function ShowPopup(text)
80 | SetNotificationTextEntry("STRING")
81 | AddTextComponentString(text)
82 | DrawNotification(false, false)
83 | end
84 |
85 | function ShowNotification(text)
86 | ClearPrints()
87 | SetTextEntry_2("STRING")
88 | AddTextComponentString(text)
89 | DrawSubtitleTimed(6000, 1)
90 | end
91 |
92 | function print_table(node)
93 | -- to make output beautiful
94 | local function tab(amt)
95 | local str = ""
96 | for i=1,amt do
97 | str = str .. "\t"
98 | end
99 | return str
100 | end
101 |
102 | local cache, stack, output = {},{},{}
103 | local depth = 1
104 | local output_str = "{\n"
105 |
106 | while true do
107 | local size = 0
108 | for k,v in pairs(node) do
109 | size = size + 1
110 | end
111 |
112 | local cur_index = 1
113 | for k,v in pairs(node) do
114 | if (cache[node] == nil) or (cur_index >= cache[node]) then
115 |
116 | if (string.find(output_str,"}",output_str:len())) then
117 | output_str = output_str .. ",\n"
118 | elseif not (string.find(output_str,"\n",output_str:len())) then
119 | output_str = output_str .. "\n"
120 | end
121 |
122 | -- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
123 | table.insert(output,output_str)
124 | output_str = ""
125 |
126 | local key
127 | if (type(k) == "number" or type(k) == "boolean") then
128 | key = "["..tostring(k).."]"
129 | else
130 | key = "['"..tostring(k).."']"
131 | end
132 |
133 | if (type(v) == "number" or type(v) == "boolean") then
134 | output_str = output_str .. tab(depth) .. key .. " = "..tostring(v)
135 | elseif (type(v) == "table") then
136 | output_str = output_str .. tab(depth) .. key .. " = {\n"
137 | table.insert(stack,node)
138 | table.insert(stack,v)
139 | cache[node] = cur_index+1
140 | break
141 | else
142 | output_str = output_str .. tab(depth) .. key .. " = '"..tostring(v).."'"
143 | end
144 |
145 | if (cur_index == size) then
146 | output_str = output_str .. "\n" .. tab(depth-1) .. "}"
147 | else
148 | output_str = output_str .. ","
149 | end
150 | else
151 | -- close the table
152 | if (cur_index == size) then
153 | output_str = output_str .. "\n" .. tab(depth-1) .. "}"
154 | end
155 | end
156 |
157 | cur_index = cur_index + 1
158 | end
159 |
160 | if (size == 0) then
161 | output_str = output_str .. "\n" .. tab(depth-1) .. "}"
162 | end
163 |
164 | if (#stack > 0) then
165 | node = stack[#stack]
166 | stack[#stack] = nil
167 | depth = cache[node] == nil and depth + 1 or depth - 1
168 | else
169 | break
170 | end
171 | end
172 |
173 | -- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
174 | table.insert(output,output_str)
175 | output_str = table.concat(output)
176 |
177 | print(output_str)
178 | end
179 |
180 |
181 | function RenderText(Text, X, Y, Font, Scale, R, G, B, A, Alignment, DropShadow, Outline, WordWrap)
182 | Text = tostring(Text)
183 | X, Y = FormatXWYH(X, Y)
184 | SetTextFont(Font or 0)
185 | SetTextScale(1.0, Scale or 0)
186 | SetTextColour(R or 255, G or 255, B or 255, A or 255)
187 |
188 | if DropShadow then
189 | SetTextDropShadow()
190 | end
191 | if Outline then
192 | SetTextOutline()
193 | end
194 |
195 | if Alignment ~= nil then
196 | if Alignment == 1 or Alignment == "Center" or Alignment == "Centre" then
197 | SetTextCentre(true)
198 | elseif Alignment == 2 or Alignment == "Right" then
199 | SetTextRightJustify(true)
200 | SetTextWrap(0, X)
201 | end
202 | end
203 |
204 | if tonumber(WordWrap) then
205 | if tonumber(WordWrap) ~= 0 then
206 | WordWrap, _ = FormatXWYH(WordWrap, 0)
207 | SetTextWrap(WordWrap, X - WordWrap)
208 | end
209 | end
210 |
211 | BeginTextCommandDisplayText("STRING")
212 | AddLongString(Text)
213 | EndTextCommandDisplayText(X, Y)
214 | end
215 |
216 |
217 | function DrawRectangle(X, Y, Width, Height, R, G, B, A)
218 | X, Y, Width, Height = X or 0, Y or 0, Width or 0, Height or 0
219 | X, Y = FormatXWYH(X, Y)
220 | Width, Height = FormatXWYH(Width, Height)
221 | 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)
222 | end
223 |
224 | function DrawTexture(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A)
225 | if not HasStreamedTextureDictLoaded(tostring(TxtDictionary) or "") then
226 | RequestStreamedTextureDict(tostring(TxtDictionary) or "", true)
227 | end
228 | X, Y, Width, Height = X or 0, Y or 0, Width or 0, Height or 0
229 | X, Y = FormatXWYH(X, Y)
230 | Width, Height = FormatXWYH(Width, Height)
231 | 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)
232 | end
--------------------------------------------------------------------------------