├── !build_release.py ├── .gitignore ├── Assets └── Readme │ └── TileGUI Logo.png ├── LICENSE ├── README.md └── TileGUI ├── Modules ├── Textures │ └── virtual_cursor.dds └── VirtualCursor.ini ├── Shaders ├── instance_writer.hlsl ├── tile_draw_service.hlsl ├── tile_features_service.hlsl ├── tile_group_writer.hlsl ├── tile_position_service.hlsl ├── tile_reader.hlsl └── tile_writer.hlsl ├── TileGUI.ini └── UserControls.ini /!build_release.py: -------------------------------------------------------------------------------- 1 | # Assembles source files into release build, just run it and grab freshly built .zip from \!RELEASE\X.X.X 2 | 3 | import shutil 4 | import re 5 | import time 6 | 7 | from pathlib import Path 8 | from dataclasses import dataclass, field 9 | from datetime import datetime 10 | 11 | 12 | class Version: 13 | def __init__(self, ini_path): 14 | self.ini_path = ini_path 15 | self.version = None 16 | self.parse_version() 17 | 18 | def parse_version(self): 19 | with open(self.ini_path, 'r', encoding='utf-8') as f: 20 | 21 | version_pattern = re.compile(r'^\$return_version = (\d+)\.*(\d)(\d*)') 22 | 23 | for line in f.readlines(): 24 | 25 | result = version_pattern.findall(line) 26 | 27 | if len(result) != 1: 28 | continue 29 | 30 | result = list(result[0]) 31 | 32 | if len(result) == 2: 33 | result.append(0) 34 | 35 | if len(result) != 3: 36 | raise ValueError(f'Malformed WWMI version!') 37 | 38 | self.version = result 39 | 40 | return 41 | 42 | raise ValueError(f'Failed to locate WWMI version!') 43 | 44 | def __str__(self) -> str: 45 | return f'{self.version[0]}.{self.version[1]}.{self.version[2]}' 46 | 47 | def as_float(self): 48 | return float(f'{self.version[0]}.{self.version[1]}{self.version[2]}') 49 | 50 | def as_ints(self): 51 | return [map(int, self.version)] 52 | 53 | 54 | class Project: 55 | def __init__(self): 56 | self.release_name = 'TileGUI' 57 | self.root_dir = Path(__file__).resolve().parent 58 | self.trash_path = self.root_dir / '!TRASH' 59 | self.source_dir = self.root_dir / 'TileGUI' 60 | self.release_dir = self.root_dir / '!RELEASES' 61 | self.version = Version(self.source_dir / 'TileGUI.ini') 62 | self.version_dir = self.release_dir / str(self.version) 63 | 64 | def trash(self, target_path: Path): 65 | trashed_path = self.trash_path / target_path.name 66 | if trashed_path.is_dir(): 67 | timestamp = datetime.now().strftime('%Y-%m-%d %H-%M-%S') 68 | trashed_path = trashed_path.with_name(f'{trashed_path.name} {timestamp}') 69 | shutil.move(target_path, trashed_path) 70 | 71 | def build(self): 72 | if self.version_dir.is_dir(): 73 | remove_ok = input(f'Directory {self.version_dir} already exists! Overwrite? (y/n)') 74 | if remove_ok != 'y': 75 | print('Version building aborted!') 76 | return 77 | else: 78 | self.trash(self.version_dir) 79 | print(f'Existing directory sent to {self.trash_path}!') 80 | 81 | release_path = self.version_dir / self.release_name 82 | shutil.copytree(self.source_dir, release_path, ignore=shutil.ignore_patterns('*.bin')) 83 | print(f'Copied loose release files to {release_path}') 84 | 85 | zip_release_path = self.version_dir / f'{self.release_name}-v{self.version}.zip' 86 | shutil.make_archive(str(zip_release_path.parent / f'{zip_release_path.stem}'), 'zip', self.version_dir, self.release_name) 87 | print(f'Created .zip release {zip_release_path.name} in {zip_release_path.parent}') 88 | 89 | 90 | 91 | if __name__ == '__main__': 92 | try: 93 | project = Project() 94 | project.build() 95 | except Exception as e: 96 | print(f'Error:', e) 97 | print(f'Press eny key to exit') 98 | input() 99 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /!RELEASES/ 2 | /!TRASH/ 3 | *.bin -------------------------------------------------------------------------------- /Assets/Readme/TileGUI Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpectrumQT/TileGUI/5d6beebcfdfa6925a2577a45dbb48f32ed6fd246/Assets/Readme/TileGUI Logo.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | TileGUI logo 3 |

4 | 5 |

Simple yet powerful GUI framework for XXMI

6 | 7 |

8 | Features • 9 | Installation • 10 | How To Use As Mod User • 11 | How To Use As Mod Author • 12 | Resources • 13 | License 14 |

15 | 16 |

17 | 18 | 19 | ## Features 20 | - **INI Native** — Designed as .ini with bunch of HLSL shaders, no .dll required 21 | - **Fully Dynamic** — All Tile properties can be changed on the fly 22 | - **Expandible** — Create your own CustomShaders to directly modify data arrays 23 | - **Highly Optimized** — Aims to minimize performance footprint 24 | - **Robust** — Stateless architecture isolates clients from each other 25 | 26 | 27 | ## Installation 28 | 29 | 1. Download the [latest release](https://github.com/SpectrumQT/TileGUI/releases/latest) of **TileGUI_vX.X.X.zip** 30 | 2. Extract **TileGUI_vX.X.X.zip** to `\Mods\` folder 31 | 32 | Correct path to extracted TileGUI folder should look like: 33 | 34 | ``` 35 | \Mods\TileGUI 36 | ``` 37 | 38 | ## How To Use As Mod User 39 | 40 | Just install it if you have any mods requiring TileGUI. Framework won't do anything on its own. 41 | 42 | 43 | ## How To Use As Mod Author 44 | 45 | Framework is currently in the early alpha-testing phase with no docs ready. Also, while current API is unlikely to change significantly, there's absolutely no guarantee that it'll be compatible with first modder-friendly release. I'd advice to wait for further announcements before jump into. 46 | 47 | 48 | ## Showcase Mods 49 | 50 | - [Camellya x Acheron (TileGUI 0.8.0)](https://gamebanana.com/mods/594216) 51 | - [Eula in Skirk's outfit (TileGUI 0.7.0)](https://gamebanana.com/mods/478260) 52 | - [Raiden in Acheron's outfit (TileGUI 0.7.0)](https://gamebanana.com/mods/495878) 53 | 54 | ## License 55 | TileGUI is licensed under the [GPLv3 License](https://github.com/SpectrumQT/TileGUI/blob/main/LICENSE). 56 | -------------------------------------------------------------------------------- /TileGUI/Modules/Textures/virtual_cursor.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpectrumQT/TileGUI/5d6beebcfdfa6925a2577a45dbb48f32ed6fd246/TileGUI/Modules/Textures/virtual_cursor.dds -------------------------------------------------------------------------------- /TileGUI/Modules/VirtualCursor.ini: -------------------------------------------------------------------------------- 1 | ; ---------------------------------------------------------------- 2 | ; !!! WARNING !!! Do NOT use this .ini as template for your GUI code! 3 | ; ---------------------------------------------------------------- 4 | ; This module is used to draw fake mouse cursor for universal keyboard and gamepad support 5 | ; Requires to be called the last to overlay other GUIs, so it uses a bit different render approach 6 | 7 | namespace=TileGUI_VirtualCursor 8 | 9 | 10 | [CommandListDrawVirtualCursor] 11 | if $\TileGUI\virtual_cursor_x != -1 || $\TileGUI\virtual_cursor_y != -1 12 | $gui_active = 1 13 | run = CommandListOnFrameDrawGUI 14 | endif 15 | 16 | 17 | [Constants] 18 | ; Variables: TileGUI Instance Core 19 | global $api_status = -1 20 | global $gui_initialized = 0 21 | global $gui_active = 0 22 | global $gui_scale = 1.0 23 | ; Constants: TileGUI Tile Ids 24 | global $TILE_VIRTUAL_CURSOR = 0 25 | 26 | 27 | ; TileGUI Resources ------------------------- 28 | 29 | [ResourceTextureVirtualCursor] 30 | filename = Textures\virtual_cursor.dds 31 | 32 | [ResourceTextureVirtualCursorOverride] 33 | 34 | 35 | ; TileGUI Tiles ------------------------- 36 | 37 | [CommandListRegisterTiles] 38 | $\TileGUI\target_tile_id = $TILE_VIRTUAL_CURSOR 39 | $\TileGUI\width = 32 * $gui_scale 40 | $\TileGUI\height = 32 * $gui_scale 41 | $\TileGUI\texture_id = 64 42 | run = CommandList\TileGUI\SetTile 43 | 44 | 45 | ; TileGUI Controller ------------------------- 46 | 47 | [CommandListOnGuiFrame] 48 | if ResourceTextureVirtualCursorOverride !== null 49 | ps-t64 = ResourceTextureVirtualCursorOverride 50 | else 51 | ps-t64 = ResourceTextureVirtualCursor 52 | endif 53 | 54 | local $offset_x 55 | local $offset_y 56 | 57 | local $new_offset_x = $\TileGUI\virtual_cursor_x + 16 58 | local $new_offset_y = $\TileGUI\virtual_cursor_y - 16 59 | 60 | if $new_offset_x != $offset_x || $new_offset_y != $offset_y 61 | $offset_x = $new_offset_x 62 | $offset_y = $new_offset_y 63 | 64 | $\TileGUI\target_tile_id = $TILE_VIRTUAL_CURSOR 65 | $\TileGUI\offset_x = $new_offset_x 66 | $\TileGUI\offset_y = $new_offset_y 67 | run = CommandList\TileGUI\SetTile 68 | endif 69 | 70 | 71 | ; TileGUI Instance Configuration ------------------------- 72 | 73 | ; === START: TILEGUI INSTANCE CONFIGURATION === === === === === === === === === === === === === === === === === 74 | ; Here you can adjust this instance to fit your needs 75 | ; Please don't set those values any higer than you actually need, don't load GPU with useless work 76 | ; ================================================================================================= 77 | [CommandListSetConfiguration] 78 | ; Configure minimal required TileGUI version 79 | ; User with older TileGUI version will get Error Message displayed and to ensure user safety GUI won't run 80 | $\TileGUI\required_version = 0.80 81 | ; Configure the number of tiles to process (allowed values: 128, 256, 512, 1024) 82 | ; Pick the lowest acceptable value from the allowed ones (i.e. for 17 tile GUI pick 128) 83 | ; WARNING! For this setting to have effect, you should also resize [ResourceTilesData]: 84 | ; For example, for $max_tiles_count = 256, find 'array = 128' in [ResourceTilesData] below and replace with 'array = 256' 85 | $\TileGUI\max_tiles_count = 128 86 | ; Configure the number of GUI layers to process (allowed values: 1 ... 32) 87 | ; For most cases 1 layer is enough because within one layer tiles with higher TileID are always rendered on top of ones with lower 88 | $\TileGUI\max_layers_count = 1 89 | ; Configure the max length of parent chain checked by per-frame tile positions updates (allowed values: 0 ... 8) 90 | ; Set it to 0 if you're not going to use draggable windows in your GUI, otherwise make sure to not go above 8 91 | $\TileGUI\max_parent_recursion = 0 92 | ; Configure how much screen scale should affect tile sizes 93 | ; Default factor of 0.25 makes tiles 25% bigger for each 100% of scale above base 100% 94 | ; For 4k displays Windows returns 300% scale, so factor of 0.25 will make tiles 50% bigger 95 | $\TileGUI\scaling_factor = 0.25 96 | ; === END: TILEGUI INSTANCE CONFIGURATION === === === === === === === === === === === === === === === === === === 97 | 98 | 99 | ; === START: TILEGUI INSTANCE RESOURCES === === === === === === === === === === === === === === === === === === === 100 | 101 | ; Stores tiles 102 | ; Allowed array length values: 128, 256, 512, 1024 (default: array = 128) 103 | [ResourceTilesData] 104 | type = RWStructuredBuffer 105 | array = 128 106 | data = R32_FLOAT 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 107 | 108 | ; Stores templates 109 | ; Allowed array length values: 64, 128, 256, 512, 1024 (default: array = 64) 110 | [ResourceTemplatesData] 111 | type = RWStructuredBuffer 112 | array = 64 113 | data = R32_FLOAT 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 114 | 115 | ; === END: TILEGUI INSTANCE RESOURCES === === === === === === === === === === === === === === === === === === === === 116 | 117 | 118 | ; TileGUI Instance Core ------------------------- 119 | 120 | ; WARNING! TILEGUI INSTANCE CORE CODE IS LISTED BELOW, DO NOT EDIT IF YOU'RE NOT SURE WHAT YOU'RE DOING!!! 121 | 122 | [ResourceInstance] 123 | type = RWStructuredBuffer 124 | array = 1 125 | data = R32_FLOAT 0 0 0 0 0 0 0 0 0 0 0 0 126 | 127 | ; Error message displayed to user when CommandListOnFrameDrawGUI code is FUBAR 128 | [ResourceErrorCoreIsFUBAR] 129 | type = Buffer 130 | data = "Error! Virtual Cursor Core is FUBAR" 131 | 132 | ; Error message displayed to user when TileGUI is not installed 133 | [ResourceErrorNotInstalledTileGUI] 134 | type = Buffer 135 | data = "Error! Virtual Cursor requires TileGUI to function! Please install TileGUI from https://gamebanana.com/mods/505941" 136 | 137 | ; Error message displayed to user when TileGUI version is below than minimally required 138 | [ResourceErrorWrongVersionTileGUI] 139 | type = Buffer 140 | data = "Error! Virtual Cursor requires newer TileGUI version to function! Please update TileGUI from https://gamebanana.com/mods/505941" 141 | 142 | ; Error mesage display parameters 143 | [ResourceErrorMessageFormat] 144 | type = StructuredBuffer 145 | array = 1 146 | data = R32_FLOAT -0.25 -0.85 +0.25 -0.90 1.00 1.00 0.00 1.00 0.00 0.00 0.00 0.95 0.02 0.05 2 3 1 1.0 147 | ; x1-^ y1-^ x2-^ y2-^ | R-^ G-^ B-^ A-^ | R-^ G-^ B-^ A-^ | ^-H V-^ | ^ ^ | ^- text alignment: 0=left 1=center 2=right | ^- font scale 148 | ; Rectangle (range -1:+1) | Text Color | Background Color | Border | ^- h/v-anchor: 0=none 1=left/top 2=center 3=right/bottom 149 | 150 | [CommandListOnFrameDrawGUI] 151 | post $gui_active = 0 152 | 153 | if $gui_active == 1 154 | 155 | if $gui_initialized == 0 156 | ; Pass our instance data to the library 157 | run = CommandListConnectLibrary 158 | ; Initialize API status as 'FUBAR' 159 | $api_status = -1 160 | ; Declare local variables so we can compare potentially non-existing $\TileGUI\ values 161 | local $api_version = -1 162 | local $api_required_version = -1 163 | ; If TileGUI is installed, this value is set by CommandListSetConfiguration via CommandListConnectLibrary 164 | ; If TileGUI is missing, it defaults to -1 165 | $api_required_version = $\TileGUI\required_version 166 | ; Detect actual API status 167 | if $api_required_version != -1 168 | ; Get version of currently installed TileGUI 169 | run = CommandList\TileGUI\GetVersion 170 | $api_version = $\TileGUI\return_version 171 | 172 | if $api_version >= $api_required_version 173 | ; Change API status to 'OK' 174 | $api_status = 200 175 | else 176 | ; Change API status to 'Upgrade Required' 177 | $api_status = 426 178 | endif 179 | else 180 | ; Change API status to 'Not Found' 181 | $api_status = 404 182 | endif 183 | ; Initialize GUI if API status is 'OK' 184 | if $api_status == 200 185 | ; Initialize instance data 186 | run = CommandListInitializeDataStorage 187 | endif 188 | ; Remember that we're initialized so we don't have to do it again 189 | $gui_initialized = 1 190 | endif 191 | 192 | if $api_status == 200 193 | ; Pass our instance data to the library 194 | run = CommandListConnectLibrary 195 | ; Execute user per-frame GUI logic 196 | run = CommandListOnGuiFrame 197 | ; Draw GUI to back buffer to show on next frame if there are layers to draw 198 | run = CommandListDrawGUI 199 | ; Detach our instance data from the library 200 | run = CommandListDisconnectLibrary 201 | else 202 | if $api_status == 404 203 | ; Display TileGUI Not Installed Error Message 204 | Resource\ShaderFixes\help.ini\Help = ref ResourceErrorNotInstalledTileGUI 205 | else if $api_status == 426 206 | ; Display TileGUI Wrong Version Error Message 207 | Resource\ShaderFixes\help.ini\Help = ref ResourceErrorWrongVersionTileGUI 208 | else 209 | ; Display Core Is FUBAR Error Message 210 | Resource\ShaderFixes\help.ini\Help = ref ResourceErrorCoreIsFUBAR 211 | endif 212 | Resource\ShaderFixes\help.ini\Params = ref ResourceErrorMessageFormat 213 | run = CustomShader\ShaderFixes\help.ini\FormatText 214 | endif 215 | else if $api_status != 200 216 | ; Clean Up Error Message 217 | if $gui_initialized == 1 218 | $gui_initialized = 0 219 | Resource\ShaderFixes\help.ini\Help = null 220 | Resource\ShaderFixes\help.ini\Params = null 221 | endif 222 | endif 223 | 224 | 225 | [CommandListConnectLibrary] 226 | ; Clear any leftover data 227 | run = CommandList\TileGUI\ResetTempVars 228 | ; Pass configuration variables 229 | run = CommandListSetConfiguration 230 | ; Pass our data storage to the library 231 | Resource\TileGUI\ClientInstanceData = reference ResourceInstance 232 | Resource\TileGUI\ClientTilesData = reference ResourceTilesData 233 | Resource\TileGUI\ClientTemplatesData = reference ResourceTemplatesData 234 | 235 | 236 | [CommandListInitializeDataStorage] 237 | ; Load our instance configuration to the data storage 238 | run = CommandList\TileGUI\SetInstance 239 | ; Load our tiles to the data storage 240 | run = CommandListRegisterTiles 241 | 242 | 243 | [CommandListDrawGUI] 244 | ; Run compute shader to process "shader-accelerated" features like hover-overlays, loops and dragging 245 | run = CustomShader\TileGUI\TileFeaturesService 246 | ; Run compute shader to update tile positions 247 | run = CustomShader\TileGUI\TilePositionService 248 | ; Run GUI shaders 249 | run = CustomShader\TileGUI\TileDrawService 250 | 251 | 252 | [CommandListDisconnectLibrary] 253 | Resource\TileGUI\ClientInstanceData = null 254 | Resource\TileGUI\ClientTilesData = null 255 | Resource\TileGUI\ClientTemplatesData = null 256 | ResourceTextureVirtualCursorOverride = null 257 | 258 | 259 | ; EOF ------------------------- 260 | -------------------------------------------------------------------------------- /TileGUI/Shaders/instance_writer.hlsl: -------------------------------------------------------------------------------- 1 | // Updates client's instance storage with given ini variables 2 | 3 | Texture1D IniParams : register(t120); 4 | 5 | // #define WindowWidth IniParams[0].x 6 | // #define WindowHeight IniParams[0].y 7 | #define CursorX IniParams[0].z 8 | #define CursorY IniParams[0].w 9 | 10 | #define MaxTilesCount IniParams[10].x 11 | #define MaxLayersCount IniParams[10].y 12 | 13 | #define DragTileId IniParams[15].x 14 | 15 | struct Instance { 16 | float max_tiles_count; 17 | float max_layers_count; 18 | float2 unused1; 19 | 20 | float drag_tile_id; 21 | float2 drag_pos; 22 | float1 unused2; 23 | 24 | float4 unused3; 25 | }; 26 | 27 | RWStructuredBuffer InstanceContainerRW : register(u0); 28 | #define CurrentInstance InstanceContainerRW[0] 29 | 30 | //RWBuffer DebugRW : register(u7); 31 | 32 | 33 | void UpdateInstanceFromIni(inout Instance instance_data) 34 | { 35 | if (MaxTilesCount != 100000) { 36 | instance_data.max_tiles_count = MaxTilesCount; 37 | } 38 | if (MaxLayersCount != 100000) { 39 | instance_data.max_layers_count = MaxLayersCount; 40 | } 41 | if (DragTileId != 100000) { 42 | instance_data.drag_tile_id = DragTileId; 43 | instance_data.drag_pos = float2(0, 0); 44 | } else { 45 | instance_data.drag_tile_id = -1; 46 | } 47 | } 48 | 49 | 50 | // #ifdef COMPUTE_SHADER 51 | 52 | [numthreads(1,1,1)] 53 | void main(uint3 ThreadId : SV_DispatchThreadID) 54 | { 55 | UpdateInstanceFromIni(CurrentInstance); 56 | 57 | InstanceContainerRW[0] = CurrentInstance; 58 | 59 | // DebugRW[0] = float4(0, 0, 0, 0); 60 | } 61 | 62 | // #endif 63 | 64 | -------------------------------------------------------------------------------- /TileGUI/Shaders/tile_draw_service.hlsl: -------------------------------------------------------------------------------- 1 | // Draws all tiles on screen 2 | 3 | struct vs2gs { 4 | uint vertex_id : TEXCOORD0; 5 | }; 6 | 7 | struct gs2ps { 8 | float4 pos : SV_Position0; 9 | float2 uv : TEXCOORD1; 10 | float texture_index : PSIZE0; 11 | float tex_arr_id : PSIZE1; 12 | }; 13 | 14 | 15 | #ifdef VERTEX_SHADER 16 | void main(uint vertex_id : SV_VertexID, out vs2gs output) 17 | { 18 | output.vertex_id = vertex_id; 19 | } 20 | #endif 21 | 22 | 23 | #ifdef GEOMETRY_SHADER 24 | 25 | struct Instance { 26 | float max_tiles_count; 27 | float max_layers_count; 28 | float2 unused1; 29 | 30 | float drag_tile_id; 31 | float2 drag_pos; 32 | float1 unused2; 33 | 34 | float4 unused3; 35 | }; 36 | 37 | StructuredBuffer InstanceContainer : register(t121); 38 | #define CurrentInstance InstanceContainer[0] 39 | 40 | struct Tile { 41 | // Base config 42 | float sys_state_id; 43 | float layer_id; 44 | float parent_tile_id; 45 | float template_id; 46 | // Features config 47 | float show; 48 | float select; 49 | float clamp; 50 | float track_mouse; 51 | // Advanced features config 52 | float loop_start; 53 | float loop_method; 54 | float hover_overlay_tile_id; 55 | float select_overlay_tile_id; 56 | // Display config 57 | float2 size; 58 | float texture_id; 59 | float tex_arr_id; 60 | // Texture config 61 | float4 tex_uv; 62 | // Texture config 2 63 | float opacity; 64 | float saturation; 65 | float2 reserved_1; 66 | // Layout config 67 | float2 offset; 68 | float2 anchor; 69 | // Current state 70 | float loop_stage; 71 | float is_hovered_over; 72 | float2 reserved_2; 73 | // Absolute coords of current position 74 | float4 abs_pos; 75 | // Relative coords of current position 76 | float4 rel_pos; 77 | }; 78 | 79 | StructuredBuffer Tiles : register(t122); 80 | 81 | // Here we devide MaxTilesCount (128, 256, 512 or 1024) by the number of geometry shader instances (32) 82 | #define OutputTilesPerInstance (CurrentInstance.max_tiles_count / 32) 83 | 84 | // Packs unsigned float with max integer part of 999 into another unsigned integer 85 | float Pack(uint integer_var, float float_var) 86 | { 87 | return integer_var * 1000 + abs(float_var) % 1000; 88 | } 89 | 90 | // Our aim is to draw the whole GUI layer of 1024 tiles per vertex on input 91 | // Each tile consists of 4 vertices (2 triangles) 92 | // Each geometry shader invocation will output up to 128 vertices (32 tiles) 93 | // So we'll use 32 instances, making total of 32 * 32 = 1024 tiles 94 | [instance(32)] 95 | // Our gs2ps has size of 8, and maxvertexcount * sizeof(gs2ps) cannot exceed 1024, thus 1024 / 8 = 128 96 | // Note: While UV and tex ids could be packed to unused pos floats, marginal performance gain doesn't worth the precision loss 97 | [maxvertexcount(128)] 98 | void main(uint instance_id : SV_GSInstanceID, point vs2gs input[1], inout TriangleStream triangle_stream) 99 | { 100 | int layer_id = input[0].vertex_id; 101 | 102 | gs2ps output; 103 | 104 | for (int i = 0; i < OutputTilesPerInstance; i++) { 105 | int tile_id = instance_id * OutputTilesPerInstance + i; 106 | 107 | Tile tile = Tiles[tile_id]; 108 | 109 | if (tile.sys_state_id == 0 || tile.show != 1 || tile.texture_id == -1) { 110 | continue; 111 | } 112 | 113 | if (tile.layer_id != layer_id) { 114 | continue; 115 | } 116 | 117 | output.texture_index = Pack(tile.texture_id - 64, tile.opacity); // Pack opacity as floating point value 118 | output.tex_arr_id = Pack(tile.tex_arr_id, tile.saturation); // Pack saturation as floating point value 119 | 120 | output.pos = float4(tile.rel_pos.x, tile.rel_pos.w, 1, 1); // X, Y, Z coord and View Space Depth 121 | output.uv = float2(tile.tex_uv.x, tile.tex_uv.y); // X, Y 122 | triangle_stream.Append(output); 123 | 124 | output.pos = float4(tile.rel_pos.x, tile.rel_pos.y, 1, 1); // X, Y, Z coord and View Space Depth 125 | output.uv = float2(tile.tex_uv.x, tile.tex_uv.w); // X, Y 126 | triangle_stream.Append(output); 127 | 128 | output.pos = float4(tile.rel_pos.z, tile.rel_pos.w, 1, 1); // X, Y, Z coord and View Space Depth 129 | output.uv = float2(tile.tex_uv.z, tile.tex_uv.y); // X, Y 130 | triangle_stream.Append(output); 131 | 132 | output.pos = float4(tile.rel_pos.z, tile.rel_pos.y, 1, 1); // X, Y, Z coord and View Space Depth 133 | output.uv = float2(tile.tex_uv.z, tile.tex_uv.w); // X, Y 134 | triangle_stream.Append(output); 135 | 136 | triangle_stream.RestartStrip(); 137 | } 138 | } 139 | 140 | #endif 141 | 142 | 143 | #ifdef PIXEL_SHADER 144 | 145 | Texture2DArray ImageTextures[64] : register(t64); 146 | 147 | SamplerState LinearSampler : register(s0); 148 | 149 | float4 Saturate(float4 color, float saturation) 150 | { 151 | float3 luminance_weights = float3(0.299, 0.587, 0.114); 152 | float luminance = dot(color.rgb, luminance_weights); 153 | return float4(lerp(luminance, color.rgb, saturation), color.a); 154 | } 155 | 156 | void main(gs2ps input, out float4 result : SV_Target0) 157 | { 158 | result.xyzw = 0; 159 | uint texture_index = uint(input.texture_index / 1000); 160 | 161 | [unroll] 162 | for (uint i = 0; i < 64; i++) { 163 | if (texture_index == i) { 164 | // Unpack opacity and saturation 165 | uint tex_arr_id = uint(input.tex_arr_id / 1000); 166 | float opacity = input.texture_index % 1000; 167 | float saturation = input.tex_arr_id % 1000; 168 | 169 | // Get pixel float4 RGBA color from texture 170 | result = ImageTextures[i].Sample(LinearSampler, float3(input.uv, tex_arr_id)); 171 | 172 | // Blend opacity setting 173 | if (opacity != 1) { 174 | result.a *= opacity; 175 | } 176 | // Blend saturation setting 177 | if (saturation != 1) { 178 | result = Saturate(result, saturation); 179 | } 180 | 181 | return; 182 | } 183 | } 184 | } 185 | 186 | #endif 187 | -------------------------------------------------------------------------------- /TileGUI/Shaders/tile_features_service.hlsl: -------------------------------------------------------------------------------- 1 | // Handles special (re)actions for all tiles, like hover over, overlays, dragging and so on 2 | // Simplifies and accelerates common GUI logic that would require tons of STORE calls otherwise 3 | 4 | Texture1D IniParams : register(t120); 5 | 6 | #define WindowWidth IniParams[0].x 7 | #define WindowHeight IniParams[0].y 8 | #define CursorX IniParams[0].z 9 | #define CursorY IniParams[0].w 10 | 11 | #define RootParentCoords float4(0, 0, IniParams[0].x, IniParams[0].y) 12 | 13 | struct Instance { 14 | float max_tiles_count; 15 | float max_layers_count; 16 | float2 unused1; 17 | 18 | float drag_tile_id; 19 | float2 drag_pos; 20 | float1 unused2; 21 | 22 | float4 unused3; 23 | }; 24 | 25 | RWStructuredBuffer InstanceContainerRW : register(u0); 26 | #define Instance InstanceContainerRW[0] 27 | 28 | struct Tile { 29 | // Base config 30 | float sys_state_id; 31 | float layer_id; 32 | float parent_tile_id; 33 | float template_id; 34 | // Features config 35 | float show; 36 | float select; 37 | float clamp; 38 | float track_mouse; 39 | // Advanced features config 40 | float loop_start; 41 | float loop_method; 42 | float hover_overlay_tile_id; 43 | float select_overlay_tile_id; 44 | // Display config 45 | float2 size; 46 | float texture_id; 47 | float tex_arr_id; 48 | // Texture config 49 | float4 tex_uv; 50 | // Texture config 2 51 | float opacity; 52 | float saturation; 53 | float2 reserved_1; 54 | // Layout config 55 | float2 offset; 56 | float2 anchor; 57 | // Current state 58 | float loop_stage; 59 | float is_hovered_over; 60 | float2 reserved_2; 61 | // Absolute coords of current position 62 | float4 abs_pos; 63 | // Relative coords of current position 64 | float4 rel_pos; 65 | }; 66 | 67 | RWStructuredBuffer TilesRW : register(u1); 68 | //RWBuffer DebugRW : register(u7); 69 | 70 | void HandleDrag(int tile_id, inout Tile tile) 71 | { 72 | if (Instance.drag_tile_id != tile_id) { 73 | return; 74 | } 75 | float cursor_abs_x = abs(CursorX + 1) / 2 * WindowWidth; 76 | float cursor_abs_y = abs(CursorY + 1) / 2 * WindowHeight; 77 | 78 | if (Instance.drag_pos.x == 0) { 79 | Instance.drag_pos.x = cursor_abs_x; 80 | } 81 | if (Instance.drag_pos.y == 0) { 82 | Instance.drag_pos.y = cursor_abs_y; 83 | } 84 | 85 | float drag_abs_x = cursor_abs_x - Instance.drag_pos.x; 86 | float drag_abs_y = cursor_abs_y - Instance.drag_pos.y; 87 | 88 | // Tile tile = TilesRW[Instance.drag_tile_id]; 89 | 90 | // Ignore cursor movement outside of parent's range (conventional slider behavior) 91 | // Requires more checks to be less wanky, so lets comment it for now 92 | // float4 parent_coords = (tile.parent_tile_id == -1 ? RootParentCoords : TilesRW[tile.parent_tile_id].abs_pos); 93 | // float parent_right_edge = parent_coords.z; 94 | // float parent_left_edge = parent_coords.x; 95 | // if (cursor_abs_x > parent_right_edge || cursor_abs_x < parent_left_edge) { 96 | // drag_abs_x = 0; 97 | // } 98 | // float parent_top_edge = parent_coords.w; 99 | // float parent_bot_edge = parent_coords.y; 100 | // if (cursor_abs_y > parent_top_edge || cursor_abs_y < parent_bot_edge) { 101 | // drag_abs_y = 0; 102 | // } 103 | 104 | if (drag_abs_x != 0 || drag_abs_y != 0) { 105 | Instance.drag_pos.x = cursor_abs_x; 106 | Instance.drag_pos.y = cursor_abs_y; 107 | 108 | tile.offset.x += drag_abs_x; 109 | tile.offset.y += drag_abs_y; 110 | } 111 | 112 | // DebugRW[Instance.drag_tile_id] = float4(drag_abs_x, CursorX, drag_abs_y, CursorY); 113 | } 114 | 115 | void AddOverlay(int target_tile_id, int overlay_tile_id) 116 | { 117 | Tile overlay_tile = TilesRW[overlay_tile_id]; 118 | overlay_tile.parent_tile_id = target_tile_id; 119 | overlay_tile.show = 1; 120 | TilesRW[overlay_tile_id] = overlay_tile; 121 | } 122 | 123 | void RemoveOverlay(int target_tile_id, int overlay_tile_id) 124 | { 125 | Tile overlay_tile = TilesRW[overlay_tile_id]; 126 | if (overlay_tile.parent_tile_id != target_tile_id) { 127 | return; 128 | } 129 | overlay_tile.parent_tile_id = -1; 130 | overlay_tile.show = 0; 131 | TilesRW[overlay_tile_id] = overlay_tile; 132 | } 133 | 134 | void HandleHoverOver(int tile_id, inout Tile tile) 135 | { 136 | if (tile.show == 0) { 137 | return; 138 | } 139 | if (CursorX > tile.rel_pos.x && CursorY > tile.rel_pos.y && CursorX < tile.rel_pos.z && CursorY < tile.rel_pos.w) { 140 | if (tile.is_hovered_over == 1) { 141 | return; 142 | } 143 | if (tile.hover_overlay_tile_id != -1) { 144 | AddOverlay(tile_id, tile.hover_overlay_tile_id); 145 | } 146 | tile.is_hovered_over = 1; 147 | } else { 148 | if (tile.is_hovered_over == 0) { 149 | return; 150 | } 151 | if (tile.hover_overlay_tile_id != -1) { 152 | RemoveOverlay(tile_id, tile.hover_overlay_tile_id); 153 | } 154 | tile.is_hovered_over = 0; 155 | }; 156 | } 157 | 158 | void HandleSelect(int tile_id, inout Tile tile) 159 | { 160 | if (tile.show == 0) { 161 | return; 162 | } 163 | if (tile.select_overlay_tile_id == -1) { 164 | return; 165 | } 166 | if (tile.select == 1) { 167 | AddOverlay(tile_id, tile.select_overlay_tile_id); 168 | } else { 169 | RemoveOverlay(tile_id, tile.select_overlay_tile_id); 170 | } 171 | } 172 | 173 | void HandleLoopStage(int tile_id, inout Tile tile) 174 | { 175 | if (tile.loop_method < 1) { 176 | return; 177 | } 178 | if (tile.loop_method == 1) { 179 | // Loop via tex_arr_id 180 | tile.tex_arr_id = tile.loop_start + tile.loop_stage; 181 | } else if (tile.loop_method == 2) { 182 | // Set current UV coords as loop start 183 | if (tile.loop_start == -1) { 184 | tile.loop_start = tile.tex_uv.x; 185 | } 186 | // Loop via UV 187 | float uv_width = tile.tex_uv.z - tile.tex_uv.x; 188 | tile.tex_uv.x = tile.loop_start + uv_width * tile.loop_stage; 189 | tile.tex_uv.z = tile.tex_uv.x + uv_width; 190 | } 191 | } 192 | 193 | // #ifdef COMPUTE_SHADER 194 | 195 | [numthreads(64,1,1)] 196 | void main(uint3 ThreadId : SV_DispatchThreadID) 197 | { 198 | int tile_id = ThreadId.x; 199 | Tile tile = TilesRW[tile_id]; 200 | 201 | if (tile.sys_state_id != 1) { 202 | return; 203 | } 204 | 205 | if (tile.track_mouse == 1) { 206 | HandleDrag(tile_id, tile); 207 | HandleHoverOver(tile_id, tile); 208 | }; 209 | 210 | HandleSelect(tile_id, tile); 211 | HandleLoopStage(tile_id, tile); 212 | 213 | TilesRW[tile_id] = tile; 214 | } 215 | 216 | // #endif 217 | 218 | -------------------------------------------------------------------------------- /TileGUI/Shaders/tile_group_writer.hlsl: -------------------------------------------------------------------------------- 1 | // Streamlines multiple tiles declaration and property updates both for initialization and runtime 2 | 3 | Texture1D IniParams : register(t120); 4 | 5 | #define RequestType (IniParams[0].x != 100000 ? IniParams[0].x : -1) 6 | #define TemplateId (IniParams[0].y != 100000 ? IniParams[0].y : -1) 7 | #define ParentTileId (IniParams[0].z != 100000 ? IniParams[0].z : -1000) 8 | 9 | #define FirstTileId (IniParams[1].x != 100000 ? IniParams[1].x : -1) 10 | #define LastTileId (IniParams[1].y != 100000 ? IniParams[1].y : FirstTileId) 11 | 12 | #define CreateTiles (IniParams[2].x != 100000 ? IniParams[2].x : 0) 13 | #define SkipExistingTiles (IniParams[2].y != 100000 ? IniParams[2].y : 0) 14 | 15 | #define ColsCount (IniParams[3].x != 100000 ? IniParams[3].x : -1) 16 | #define RowsCount (IniParams[3].y != 100000 ? IniParams[3].y : -1) 17 | #define ColsPadding (IniParams[3].z != 100000 ? IniParams[3].z : 0) 18 | #define RowsPadding (IniParams[3].w != 100000 ? IniParams[3].w : 0) 19 | 20 | #define AnchorX (IniParams[4].x != 100000 ? IniParams[4].x : 0) 21 | #define AnchorY (IniParams[4].y != 100000 ? IniParams[4].y : 0) 22 | 23 | struct Tile { 24 | // Base config 25 | float sys_state_id; 26 | float layer_id; 27 | float parent_tile_id; 28 | float template_id; 29 | // Features config 30 | float show; 31 | float select; 32 | float clamp; 33 | float track_mouse; 34 | // Advanced features config 35 | float loop_start; 36 | float loop_method; 37 | float hover_overlay_tile_id; 38 | float select_overlay_tile_id; 39 | // Display config 40 | float2 size; 41 | float texture_id; 42 | float tex_arr_id; 43 | // Texture config 44 | float4 tex_uv; 45 | // Texture config 2 46 | float opacity; 47 | float saturation; 48 | float2 reserved_1; 49 | // Layout config 50 | float2 offset; 51 | float2 anchor; 52 | // Current state 53 | float loop_stage; 54 | float is_hovered_over; 55 | float2 reserved_2; 56 | // Absolute coords of current position 57 | float4 abs_pos; 58 | // Relative coords of current position 59 | float4 rel_pos; 60 | }; 61 | 62 | RWStructuredBuffer TileTemplateDataRW : register(u0); 63 | RWStructuredBuffer TilesRW : register(u1); 64 | //RWBuffer DebugRW : register(u7); 65 | 66 | void InitializeTile(inout Tile tile) 67 | { 68 | // Base config 69 | tile.sys_state_id = 1; 70 | tile.layer_id = 0; 71 | tile.parent_tile_id = -1; 72 | tile.template_id = -1; 73 | // Features config 74 | tile.show = 1; 75 | tile.select = 0; 76 | tile.clamp = 1; 77 | tile.track_mouse = 1; 78 | // Advanced features config 79 | tile.loop_start = -1; 80 | tile.loop_method = -1; 81 | tile.hover_overlay_tile_id = -1; 82 | tile.select_overlay_tile_id = -1; 83 | // Display config 84 | tile.size = 0; 85 | tile.texture_id = -1; 86 | tile.tex_arr_id = 0; 87 | // Texture config 88 | tile.tex_uv = float4(0, 0, 1, 1); 89 | // Texture config 2 90 | tile.opacity = 1; 91 | tile.saturation = 1; 92 | tile.reserved_1 = 0; 93 | // Layout config 94 | tile.offset = 0; 95 | tile.anchor = 0; 96 | // Current state 97 | tile.loop_stage = 0; 98 | tile.is_hovered_over = 0; 99 | tile.reserved_2 = 0; 100 | // Absolute coords of current position 101 | tile.abs_pos = 0; 102 | // Relative coords of current position 103 | tile.rel_pos = 0; 104 | } 105 | 106 | void LoadDataUpdate(Tile tile_data, inout Tile tile) 107 | { 108 | // Base config 109 | if (tile_data.sys_state_id != 100000) { 110 | tile.sys_state_id = tile_data.sys_state_id; 111 | } 112 | if (tile_data.layer_id != 100000) { 113 | tile.layer_id = tile_data.layer_id; 114 | } 115 | if (tile_data.parent_tile_id != 100000) { 116 | tile.parent_tile_id = tile_data.parent_tile_id; 117 | } 118 | if (tile_data.template_id != 100000) { 119 | tile.template_id = tile_data.template_id; 120 | } 121 | // Features config 122 | if (tile_data.show != 100000) { 123 | tile.show = tile_data.show; 124 | } 125 | if (tile_data.select != 100000) { 126 | tile.select = tile_data.select; 127 | } 128 | if (tile_data.clamp != 100000) { 129 | tile.clamp = tile_data.clamp; 130 | } 131 | if (tile_data.track_mouse != 100000) { 132 | tile.track_mouse = tile_data.track_mouse; 133 | } 134 | // Advanced features config 135 | if (tile_data.loop_start != 100000) { 136 | tile.loop_start = tile_data.loop_start; 137 | } 138 | if (tile_data.loop_method != 100000) { 139 | tile.loop_method = tile_data.loop_method; 140 | } 141 | if (tile_data.hover_overlay_tile_id != 100000) { 142 | tile.hover_overlay_tile_id = tile_data.hover_overlay_tile_id; 143 | } 144 | if (tile_data.select_overlay_tile_id != 100000) { 145 | tile.select_overlay_tile_id = tile_data.select_overlay_tile_id; 146 | } 147 | // Display config 148 | if (tile_data.size.x != 100000) { 149 | tile.size.x = tile_data.size.x; 150 | } 151 | if (tile_data.size.y != 100000) { 152 | tile.size.y = tile_data.size.y; 153 | } 154 | if (tile_data.texture_id != 100000) { 155 | tile.texture_id = tile_data.texture_id; 156 | } 157 | if (tile_data.tex_arr_id != 100000) { 158 | tile.tex_arr_id = tile_data.tex_arr_id; 159 | } 160 | // Texture config 161 | if (tile_data.tex_uv.x != 100000) { 162 | tile.tex_uv.x = tile_data.tex_uv.x; 163 | } 164 | if (tile_data.tex_uv.y != 100000) { 165 | tile.tex_uv.y = tile_data.tex_uv.y; 166 | } 167 | if (tile_data.tex_uv.z != 100000) { 168 | tile.tex_uv.z = tile_data.tex_uv.z; 169 | } 170 | if (tile_data.tex_uv.w != 100000) { 171 | tile.tex_uv.w = tile_data.tex_uv.w; 172 | } 173 | // Texture config 2 174 | if (tile_data.opacity != 100000) { 175 | tile.opacity = tile_data.opacity; 176 | } 177 | if (tile_data.saturation != 100000) { 178 | tile.saturation = tile_data.saturation; 179 | } 180 | // Layout config 181 | if (tile_data.offset.x != 100000) { 182 | tile.offset.x = tile_data.offset.x; 183 | } 184 | if (tile_data.offset.y != 100000) { 185 | tile.offset.y = tile_data.offset.y; 186 | } 187 | if (tile_data.anchor.x != 100000) { 188 | tile.anchor.x = tile_data.anchor.x; 189 | } 190 | if (tile_data.anchor.y != 100000) { 191 | tile.anchor.y = tile_data.anchor.y; 192 | } 193 | // Current state 194 | if (tile_data.loop_stage != 100000) { 195 | tile.loop_stage = tile_data.loop_stage; 196 | } 197 | // if (tile_data.is_hovered_over != 100000) { 198 | // tile.is_hovered_over = tile_data.is_hovered_over; 199 | // } 200 | // tile_data.not_used_2 = 0; 201 | } 202 | 203 | void ApplyTemplate(int tile_id) 204 | { 205 | // Skip tile if template isn't specified 206 | if (TemplateId == -1) { 207 | return; 208 | } 209 | 210 | Tile tile = TilesRW[tile_id]; 211 | 212 | // Check if tile doesn't have requested template 213 | if (tile.template_id != TemplateId) { 214 | // Check if parent isn't specified or if tile doesn't have requested parent 215 | if ((ParentTileId == -1000) || (tile.parent_tile_id != ParentTileId)) { 216 | // Check if tile isn't in requested range 217 | if (FirstTileId > tile_id || tile_id > LastTileId) { 218 | // Skip tile if all checks passed 219 | return; 220 | } 221 | } 222 | } 223 | 224 | // Get requested template 225 | Tile tile_template = TileTemplateDataRW[TemplateId]; 226 | // Skip non-existing template 227 | if (tile_template.sys_state_id == 0) { 228 | return; 229 | } 230 | 231 | if (tile.sys_state_id != 1) { 232 | // Handle non-existing tile 233 | if (CreateTiles == 1) { 234 | // Create new tile if requested 235 | InitializeTile(tile); 236 | } else { 237 | // Skip non-existing tile 238 | return; 239 | } 240 | } else { 241 | // Skip existing tile if requested 242 | if (SkipExistingTiles == 1) { 243 | return; 244 | } 245 | } 246 | 247 | LoadDataUpdate(tile_template, tile); 248 | TilesRW[tile_id] = tile; 249 | } 250 | 251 | void ApplyLayout(int tile_id) 252 | { 253 | // Skip if layout is not specified 254 | if (ColsCount < 1 || RowsCount < 1) { 255 | return; 256 | } 257 | // Skip out-of-requested-range tile 258 | if (FirstTileId > tile_id || tile_id > LastTileId) { 259 | return; 260 | } 261 | 262 | Tile tile = TilesRW[tile_id]; 263 | 264 | // Skip non-existing tile 265 | if (tile.sys_state_id != 1) { 266 | return; 267 | } 268 | 269 | uint total_tiles = LastTileId - FirstTileId + 1; 270 | uint tile_number = tile_id - LastTileId + total_tiles - 1; 271 | uint tile_row = tile_number / uint(ColsCount); 272 | uint tile_col = tile_number % uint(ColsCount); 273 | 274 | tile.offset.x += (tile.size.x + ColsPadding) * tile_col; 275 | tile.offset.y += (tile.size.y + RowsPadding) * tile_row; 276 | 277 | tile.anchor.x = AnchorX; 278 | tile.anchor.y = AnchorY; 279 | 280 | // Quick, dirty but efficient approach to anchor entire layout 281 | // Relies heavily on current position_service implementation and trusts it blindly, leaving the rest of the work to it 282 | if (AnchorX == 0) { 283 | tile.offset.x -= ((tile.size.x + ColsPadding) * ColsCount - ColsPadding) / 2 - tile.size.x / 2; 284 | } else if (abs(AnchorX == 2)) { 285 | tile.offset.x -= ((tile.size.x + ColsPadding) * (ColsCount - 1)); 286 | } 287 | if (AnchorY == 0) { 288 | tile.offset.y -= ((tile.size.y + RowsPadding) * RowsCount - RowsPadding) / 2 - tile.size.y / 2; 289 | } else if (abs(AnchorY == 2)) { 290 | tile.offset.y -= ((tile.size.y + RowsPadding) * (RowsCount - 1)); 291 | } 292 | 293 | // DebugRW[tile_id] = float4(tile_col, tile_row, tile.offset.x, tile.offset.y); 294 | // DebugRW[tile_id] = float4(AnchorX, AnchorY, tile.offset.x, tile.offset.y); 295 | 296 | TilesRW[tile_id] = tile; 297 | } 298 | 299 | // #ifdef COMPUTE_SHADER 300 | 301 | [numthreads(64,1,1)] 302 | void main(uint3 ThreadId : SV_DispatchThreadID) 303 | { 304 | int tile_id = ThreadId.x; 305 | 306 | if (RequestType == 1) { 307 | ApplyTemplate(tile_id); 308 | } else if (RequestType == 2) { 309 | ApplyLayout(tile_id); 310 | } 311 | } 312 | 313 | // #endif 314 | -------------------------------------------------------------------------------- /TileGUI/Shaders/tile_position_service.hlsl: -------------------------------------------------------------------------------- 1 | // Updates positions of all tiles based on sizes, offsets, anchors and parents 2 | 3 | Texture1D IniParams : register(t120); 4 | 5 | #define WindowWidth IniParams[0].x 6 | #define WindowHeight IniParams[0].y 7 | 8 | #define MaxParentRecursion (IniParams[1].x <= 8 ? IniParams[1].x : 0) 9 | 10 | #define RootParentCoords float4(0, 0, IniParams[0].x, IniParams[0].y) 11 | 12 | struct Tile { 13 | // Base config 14 | float sys_state_id; 15 | float layer_id; 16 | float parent_tile_id; 17 | float template_id; 18 | // Features config 19 | float show; 20 | float select; 21 | float clamp; 22 | float track_mouse; 23 | // Advanced features config 24 | float loop_start; 25 | float loop_method; 26 | float hover_overlay_tile_id; 27 | float select_overlay_tile_id; 28 | // Display config 29 | float2 size; 30 | float texture_id; 31 | float tex_arr_id; 32 | // Texture config 33 | float4 tex_uv; 34 | // Texture config 2 35 | float opacity; 36 | float saturation; 37 | float2 reserved_1; 38 | // Layout config 39 | float2 offset; 40 | float2 anchor; 41 | // Current state 42 | float loop_stage; 43 | float is_hovered_over; 44 | float2 reserved_2; 45 | // Absolute coords of current position 46 | float4 abs_pos; 47 | // Relative coords of current position 48 | float4 rel_pos; 49 | }; 50 | 51 | RWStructuredBuffer TilesRW : register(u1); 52 | //RWBuffer DebugRW : register(u7); 53 | 54 | float2 GetAnchoredAxisCoords(float anchor, float child_size, float2 parent_coords) { 55 | float2 axis_coords; 56 | if (anchor == 1) { 57 | // Min Inside (align child's Min edge to Min edge of the parent) 58 | // [[ C ]P ] ----axis----> 59 | axis_coords.x = parent_coords.x; 60 | axis_coords.y = axis_coords.x + child_size; 61 | } else if (anchor == 2) { 62 | // Max Inside (align child's Max edge to Max edge of the parent) 63 | // [ P[ C ]] ----axis----> 64 | axis_coords.y = parent_coords.y; 65 | axis_coords.x = axis_coords.y - child_size; 66 | } else if (anchor == -1) { 67 | // Min Outside (align child's Max edge to Min edge of the parent) 68 | // [ C ][ P ] ----axis----> 69 | axis_coords.y = parent_coords.x; 70 | axis_coords.x = axis_coords.y - child_size; 71 | } else if (anchor == -2) { 72 | // Max Outside (align child's Min edge to Max edge of the parent) 73 | // [ P ][ C ] ----axis----> 74 | axis_coords.x = parent_coords.y; 75 | axis_coords.y = axis_coords.x + child_size; 76 | } else { 77 | // Center (align child's Center to Center of the parent) 78 | // [ P [ C ] P ] ----axis----> 79 | float parent_width = parent_coords.y - parent_coords.x; 80 | float parent_anchor_x = parent_coords.y - parent_width / 2; 81 | axis_coords.x = parent_anchor_x - child_size / 2; 82 | axis_coords.y = parent_anchor_x + child_size / 2; 83 | } 84 | return axis_coords; 85 | } 86 | 87 | float4 GetAnchoredAbsolutePosition(float2 anchor, float2 child_size, float4 parent_coords) { 88 | // Absolute screen space coords: 89 | // x1 (Left) = 0 90 | // y1 (Bottom) = 0 91 | // x2 (Right) = window_max_x - 1 92 | // y2 (Top) = window_max_y - 1 93 | 94 | // Image position is described by two points: 95 | // 1. Bottom-Left aka (x1, y1), where x1 is absolute_coords.x and y1 is absolute_coords.y 96 | // 1. Top-Right aka (x2, y2), where x2 is absolute_coords.z and y2 is absolute_coords.w 97 | // Calculate x1 and x2 coords based on anchor point 98 | float2 absolute_coords_x = GetAnchoredAxisCoords(anchor.x, child_size.x, parent_coords.xz); 99 | // Calculate y1 and y2 coords based on anchor point 100 | float2 absolute_coords_y = GetAnchoredAxisCoords(anchor.y, child_size.y, parent_coords.yw); 101 | 102 | return float4(absolute_coords_x.x, absolute_coords_y.x, absolute_coords_x.y, absolute_coords_y.y); 103 | } 104 | 105 | float GetClampedAxisOffset(float offset, float child_size, float2 parent_coords, float2 child_coords) { 106 | // Keeps tile a1 and a2 coords within the parent's axis range 107 | float parent_size = parent_coords.y - parent_coords.x; 108 | if (child_size <= parent_size) { 109 | float excess_min = child_coords.x + offset - parent_coords.x; 110 | if (excess_min < 0) { 111 | offset -= excess_min; 112 | } 113 | float excess_max = child_coords.y + offset - parent_coords.y; 114 | if (excess_max > 0) { 115 | offset -= excess_max; 116 | } 117 | } else if (parent_size != 0) { 118 | offset = 0; 119 | } 120 | return offset; 121 | } 122 | 123 | float2 GetClampedOffset(float2 offset, float2 anchor, float2 child_size, float4 parent_coords, float4 child_coords) { 124 | if (anchor.x >= 0 && anchor.y >= 0) { 125 | offset.x = GetClampedAxisOffset(offset.x, child_size.x, parent_coords.xz, child_coords.xz); 126 | offset.y = GetClampedAxisOffset(offset.y, child_size.y, parent_coords.yw, child_coords.yw); 127 | } 128 | return offset; 129 | } 130 | 131 | Tile UpdateAbsolutePosition(Tile tile, float4 parent_coords) 132 | { 133 | float4 absolute_coords = GetAnchoredAbsolutePosition(tile.anchor, tile.size, parent_coords); 134 | 135 | if (tile.clamp == 1) { 136 | tile.offset = GetClampedOffset(tile.offset, tile.anchor, tile.size, parent_coords, absolute_coords); 137 | } 138 | 139 | absolute_coords.xz += tile.offset.x; 140 | absolute_coords.yw += tile.offset.y; 141 | 142 | tile.abs_pos = absolute_coords; 143 | 144 | return tile; 145 | } 146 | 147 | // 148 | // Supports recursive 149 | float4 GetParentAbsolutePosition(Tile tile) 150 | { 151 | int parent_tile_id = tile.parent_tile_id; 152 | 153 | if (parent_tile_id == -1) { 154 | // Return app window absolute coords if parent chain is empty 155 | return RootParentCoords; 156 | } else if (MaxParentRecursion == 0) { 157 | // Return parent tile absolute coords without updating them 158 | return TilesRW[parent_tile_id].abs_pos; 159 | } else { 160 | // Recursively calculate up-to-date position of up to 8 parents in the chain 161 | // Makes child tiles to move after parent without lagging but puts a bit more stress on GPU 162 | Tile parent_tiles[8]; 163 | // Index chain of parents 164 | for (int i = 0; i < MaxParentRecursion; i++) { 165 | // Cache current parent 166 | parent_tiles[i] = TilesRW[parent_tile_id]; 167 | // Remember id of the next parent 168 | parent_tile_id = parent_tiles[i].parent_tile_id; 169 | // Stop if no more parents in the chain 170 | if (parent_tile_id == -1) { 171 | break; 172 | } 173 | } 174 | // Calculate absolute coords of last parent in the chain 175 | Tile updated_parent_tile = UpdateAbsolutePosition(parent_tiles[i], RootParentCoords); 176 | // Calculate absolute coords of previous parents in reversed order 177 | for (int r = i - 1; r >= 0; r--) { 178 | updated_parent_tile = UpdateAbsolutePosition(parent_tiles[r], updated_parent_tile.abs_pos); 179 | } 180 | // Return absolute coords of first parent in the chain 181 | return updated_parent_tile.abs_pos; 182 | } 183 | } 184 | 185 | void UpdateRelativePosition(inout Tile tile) 186 | { 187 | if (tile.abs_pos.x == 0 && tile.abs_pos.z == 0) { 188 | return; 189 | } 190 | 191 | // Relative screen space coords: 192 | // x1 (Left) = -1.0 193 | // y1 (Bottom) = -1.0 194 | // x2 (Right) = 1 195 | // y2 (Top) = 1 196 | // Screen center point coords (x, y) are (0.0, 0.0) 197 | 198 | // Relative position is relative to the center of the screen 199 | // For example we'll use common 1920x1080 screen: 200 | // window_max_x=1920 201 | // window_max_y=1080 202 | 203 | // 1. At first, we need to calculate absolute coords for central point of the screen 204 | // Current coordinate range: x = [1, 1920] and y = [1, 1080] 205 | float center_x = WindowWidth / 2; // 1920 / 2 = 960 206 | float center_y = WindowHeight / 2; // 1080 / 2 = 540 207 | 208 | // 2. Then we need to make said central point a new reference point of the absolute coordinate system 209 | // New coordinate range: x = [-960,960] and y = [-540,540] 210 | // 3. Finally, we need to transform coordinate range from absolute to relative 211 | // New coordinate range: x = [-1,1] and y = [-1,1] 212 | 213 | // Both 2. and 3. steps can be done by simply deducting central point coords and then dividing by the same value 214 | tile.rel_pos.xz = (tile.abs_pos.xz - center_x) / center_x; 215 | tile.rel_pos.yw = (tile.abs_pos.yw - center_y) / center_y; 216 | } 217 | 218 | 219 | // #ifdef COMPUTE_SHADER 220 | 221 | // Runs 1 thread per tile, 64 threads per group, and expects up to 16 thread groups 222 | // Processes up to 1 * 64 * 16 = 1024 tiles total per dispatch 223 | [numthreads(64,1,1)] 224 | void main(uint3 ThreadId : SV_DispatchThreadID) 225 | { 226 | int tile_id = ThreadId.x; 227 | Tile tile = TilesRW[tile_id]; 228 | 229 | if (tile.sys_state_id == 0 || tile.show != 1) { 230 | return; 231 | } 232 | 233 | tile = UpdateAbsolutePosition(tile, GetParentAbsolutePosition(tile)); 234 | 235 | UpdateRelativePosition(tile); 236 | 237 | TilesRW[tile_id] = tile; 238 | } 239 | 240 | // #endif 241 | 242 | -------------------------------------------------------------------------------- /TileGUI/Shaders/tile_reader.hlsl: -------------------------------------------------------------------------------- 1 | 2 | Texture1D IniParams : register(t120); 3 | 4 | #define RequestType IniParams[1].x 5 | #define TileId IniParams[1].y 6 | #define VarId IniParams[1].z 7 | 8 | struct Instance { 9 | float max_tiles_count; 10 | float max_layers_count; 11 | float2 unused1; 12 | 13 | float drag_tile_id; 14 | float2 drag_pos; 15 | float1 unused2; 16 | 17 | float4 unused3; 18 | }; 19 | 20 | StructuredBuffer InstanceContainer : register(t121); 21 | #define Instance InstanceContainer[0] 22 | 23 | struct Tile { 24 | // Base config 25 | float sys_state_id; 26 | float layer_id; 27 | float parent_tile_id; 28 | float template_id; 29 | // Features config 30 | float show; 31 | float select; 32 | float clamp; 33 | float track_mouse; 34 | // Advanced features config 35 | float loop_start; 36 | float loop_method; 37 | float hover_overlay_tile_id; 38 | float select_overlay_tile_id; 39 | // Display config 40 | float2 size; 41 | float texture_id; 42 | float tex_arr_id; 43 | // Texture config 44 | float4 tex_uv; 45 | // Texture config 2 46 | float opacity; 47 | float saturation; 48 | float2 reserved_1; 49 | // Layout config 50 | float2 offset; 51 | float2 anchor; 52 | // Current state 53 | float loop_stage; 54 | float is_hovered_over; 55 | float2 reserved_2; 56 | // Absolute coords of current position 57 | float4 abs_pos; 58 | // Relative coords of current position 59 | float4 rel_pos; 60 | }; 61 | 62 | StructuredBuffer Tiles : register(t122); 63 | RWBuffer OutputRW : register(u0); 64 | //RWBuffer DebugRW : register(u7); 65 | 66 | float GetTileVar() 67 | { 68 | if (TileId == 100000) { 69 | return 100000; 70 | } 71 | Tile tile = Tiles[TileId]; 72 | if (VarId == 0) { 73 | return tile.sys_state_id; 74 | } else if (VarId == 1) { 75 | return tile.layer_id; 76 | } else if (VarId == 2) { 77 | return tile.parent_tile_id; 78 | } else if (VarId == 3) { 79 | return tile.template_id; 80 | } else if (VarId == 4) { 81 | return tile.show; 82 | } else if (VarId == 5) { 83 | return tile.select; 84 | } else if (VarId == 6) { 85 | return tile.clamp; 86 | } else if (VarId == 7) { 87 | return tile.track_mouse; 88 | } else if (VarId == 8) { 89 | return tile.loop_start; 90 | } else if (VarId == 9) { 91 | return tile.loop_method; 92 | } else if (VarId == 10) { 93 | return tile.hover_overlay_tile_id; 94 | } else if (VarId == 11) { 95 | return tile.select_overlay_tile_id; 96 | } else if (VarId == 12) { 97 | return tile.size.x; 98 | } else if (VarId == 13) { 99 | return tile.size.y; 100 | } else if (VarId == 14) { 101 | return tile.texture_id; 102 | } else if (VarId == 15) { 103 | return tile.tex_arr_id; 104 | } else if (VarId == 16) { 105 | return tile.tex_uv.x; 106 | } else if (VarId == 17) { 107 | return tile.tex_uv.y; 108 | } else if (VarId == 18) { 109 | return tile.tex_uv.z; 110 | } else if (VarId == 19) { 111 | return tile.tex_uv.w; 112 | } else if (VarId == 20) { 113 | return tile.opacity; 114 | } else if (VarId == 21) { 115 | return tile.saturation; 116 | // } else if (VarId == 22) { 117 | // return tile.reserved_1.x; 118 | // } else if (VarId == 23) { 119 | // return tile.reserved_1.y; 120 | } else if (VarId == 24) { 121 | return tile.offset.x; 122 | } else if (VarId == 25) { 123 | return tile.offset.y; 124 | } else if (VarId == 26) { 125 | return tile.anchor.x; 126 | } else if (VarId == 27) { 127 | return tile.anchor.y; 128 | } else if (VarId == 28) { 129 | return tile.loop_stage; 130 | } else if (VarId == 29) { 131 | return tile.is_hovered_over; 132 | // } else if (VarId == 30) { 133 | // return tile.reserved_2; 134 | // } else if (VarId == 31) { 135 | // return tile.reserved_2; 136 | } else if (VarId == 32) { 137 | return tile.abs_pos.x; 138 | } else if (VarId == 33) { 139 | return tile.abs_pos.y; 140 | } else if (VarId == 34) { 141 | return tile.abs_pos.z; 142 | } else if (VarId == 35) { 143 | return tile.abs_pos.w; 144 | } else { 145 | return 100000; 146 | } 147 | } 148 | 149 | float GetHoveredOverTileId() 150 | { 151 | float hovered_tile_id = -1; 152 | float layer_id = -1; 153 | for (int tile_id = Instance.max_tiles_count; tile_id > -1; tile_id--) { 154 | Tile tile = Tiles[tile_id]; 155 | if (tile.is_hovered_over == 1) { 156 | if (tile.layer_id > layer_id) { 157 | layer_id = tile.layer_id; 158 | hovered_tile_id = tile_id; 159 | } 160 | }; 161 | } 162 | return hovered_tile_id; 163 | } 164 | 165 | float GetSliderValue() 166 | { 167 | if (TileId == 100000) { 168 | return 100000; 169 | } 170 | Tile tile = Tiles[TileId]; 171 | if (tile.parent_tile_id == -1) { 172 | return 100000; 173 | } 174 | Tile parent_tile = Tiles[tile.parent_tile_id]; 175 | if (parent_tile.size.x > parent_tile.size.y) { 176 | return (tile.abs_pos.x - parent_tile.abs_pos.x) / (parent_tile.size.x - tile.size.x); 177 | } else { 178 | return (tile.abs_pos.y - parent_tile.abs_pos.y) / (parent_tile.size.y - tile.size.y); 179 | } 180 | } 181 | 182 | // #ifdef COMPUTE_SHADER 183 | 184 | [numthreads(1,1,1)] 185 | void main(uint3 ThreadId : SV_DispatchThreadID) 186 | { 187 | switch(RequestType) { 188 | // GetTileVar 189 | case 1: 190 | OutputRW[33] = GetTileVar(); 191 | break; 192 | // GetHoveredOverTileId 193 | case 2: 194 | OutputRW[33] = GetHoveredOverTileId(); 195 | break; 196 | // GetSliderValue 197 | case 3: 198 | OutputRW[33] = GetSliderValue(); 199 | break; 200 | // Unknown 201 | default: 202 | OutputRW[33] = 100000; 203 | break; 204 | }; 205 | } 206 | 207 | // #endif 208 | -------------------------------------------------------------------------------- /TileGUI/Shaders/tile_writer.hlsl: -------------------------------------------------------------------------------- 1 | // Updates client's tile storage with given ini variables 2 | 3 | Texture1D IniParams : register(t120); 4 | 5 | #define TileType IniParams[1].x 6 | #define TemplateId IniParams[1].y 7 | #define TileId IniParams[1].z 8 | #define SetValue IniParams[1].w 9 | 10 | // Base config 11 | #define SysStateId IniParams[2].x 12 | #define LayerId IniParams[2].y 13 | #define ParentTileId IniParams[2].z 14 | #define DynamicTemplateId IniParams[2].w 15 | // Features config 16 | #define Show IniParams[3].x 17 | #define Select IniParams[3].y 18 | #define Clamp IniParams[3].z 19 | #define TrackMouse IniParams[3].w 20 | // Advanced features config 21 | #define LoopStartTexArrId IniParams[4].x 22 | #define LoopEndTexArrId IniParams[4].y 23 | #define HoverOverlayTileId IniParams[4].z 24 | #define SelectOverlayTileId IniParams[4].w 25 | // Display config 26 | #define Size IniParams[5].xy 27 | #define TextureId IniParams[5].z 28 | #define TexArrId IniParams[5].w 29 | // Texture config 30 | #define TexUV IniParams[6].xyzw 31 | // Texture config 2 32 | #define Opacity IniParams[7].x 33 | #define Saturation IniParams[7].y 34 | // Layout config 35 | #define Offset IniParams[8].xy 36 | #define Anchor IniParams[8].zw 37 | // Current state 38 | #define LoopStage IniParams[9].x 39 | 40 | struct Tile { 41 | // Base config 42 | float sys_state_id; 43 | float layer_id; 44 | float parent_tile_id; 45 | float template_id; 46 | // Features config 47 | float show; 48 | float select; 49 | float clamp; 50 | float track_mouse; 51 | // Advanced features config 52 | float loop_start; 53 | float loop_method; 54 | float hover_overlay_tile_id; 55 | float select_overlay_tile_id; 56 | // Display config 57 | float2 size; 58 | float texture_id; 59 | float tex_arr_id; 60 | // Texture config 61 | float4 tex_uv; 62 | // Texture config 2 63 | float opacity; 64 | float saturation; 65 | float2 reserved_1; 66 | // Layout config 67 | float2 offset; 68 | float2 anchor; 69 | // Current state 70 | float loop_stage; 71 | float is_hovered_over; 72 | float2 reserved_2; 73 | // Absolute coords of current position 74 | float4 abs_pos; 75 | // Relative coords of current position 76 | float4 rel_pos; 77 | }; 78 | 79 | RWStructuredBuffer TileTemplateDataRW : register(u0); 80 | RWStructuredBuffer TilesRW : register(u1); 81 | // RWBuffer DebugRW : register(u7); 82 | 83 | void InitializeTile(inout Tile tile) 84 | { 85 | // Base config 86 | tile.sys_state_id = 1; 87 | tile.layer_id = 0; 88 | tile.parent_tile_id = -1; 89 | tile.template_id = -1; 90 | // Features config 91 | tile.show = 1; 92 | tile.select = 0; 93 | tile.clamp = 1; 94 | tile.track_mouse = 1; 95 | // Advanced features config 96 | tile.loop_start = -1; 97 | tile.loop_method = -1; 98 | tile.hover_overlay_tile_id = -1; 99 | tile.select_overlay_tile_id = -1; 100 | // Display config 101 | tile.size = 0; 102 | tile.texture_id = -1; 103 | tile.tex_arr_id = 0; 104 | // Texture config 105 | tile.tex_uv = float4(0, 0, 1, 1); 106 | // Texture config 2 107 | tile.opacity = 1; 108 | tile.saturation = 1; 109 | tile.reserved_1 = 0; 110 | // Layout config 111 | tile.offset = 0; 112 | tile.anchor = 0; 113 | // Current state 114 | tile.loop_stage = 0; 115 | tile.is_hovered_over = 0; 116 | tile.reserved_2 = 0; 117 | // Absolute coords of current position 118 | tile.abs_pos = 0; 119 | // Relative coords of current position 120 | tile.rel_pos = 0; 121 | } 122 | 123 | void InitializeTemplate(inout Tile tile) 124 | { 125 | // Base config 126 | tile.sys_state_id = 100000; 127 | tile.layer_id = 100000; 128 | tile.parent_tile_id = 100000; 129 | tile.template_id = 100000; 130 | // Features config 131 | tile.show = 100000; 132 | tile.select = 100000; 133 | tile.clamp = 100000; 134 | tile.track_mouse = 100000; 135 | // Advanced features config 136 | tile.loop_start = 100000; 137 | tile.loop_method = 100000; 138 | tile.hover_overlay_tile_id = 100000; 139 | tile.select_overlay_tile_id = 100000; 140 | // Display config 141 | tile.size = 100000; 142 | tile.texture_id = 100000; 143 | tile.tex_arr_id = 100000; 144 | // Texture config 145 | tile.tex_uv = 100000; 146 | // Texture config 2 147 | tile.opacity = 100000; 148 | tile.saturation = 100000; 149 | tile.reserved_1 = 100000; 150 | // Layout config 151 | tile.offset = 100000; 152 | tile.anchor = 100000; 153 | // Current state 154 | tile.loop_stage = 100000; 155 | tile.is_hovered_over = 100000; 156 | tile.reserved_2 = 100000; 157 | } 158 | 159 | void LoadDataUpdate(Tile tile_data, inout Tile tile) 160 | { 161 | // Base config 162 | if (tile_data.sys_state_id != 100000) { 163 | tile.sys_state_id = tile_data.sys_state_id; 164 | } 165 | if (tile_data.layer_id != 100000) { 166 | tile.layer_id = tile_data.layer_id; 167 | } 168 | if (tile_data.parent_tile_id != 100000) { 169 | tile.parent_tile_id = tile_data.parent_tile_id; 170 | } 171 | if (tile_data.template_id != 100000) { 172 | tile.template_id = tile_data.template_id; 173 | } 174 | // Features config 175 | if (tile_data.show != 100000) { 176 | tile.show = tile_data.show; 177 | } 178 | if (tile_data.select != 100000) { 179 | tile.select = tile_data.select; 180 | } 181 | if (tile_data.clamp != 100000) { 182 | tile.clamp = tile_data.clamp; 183 | } 184 | if (tile_data.track_mouse != 100000) { 185 | tile.track_mouse = tile_data.track_mouse; 186 | } 187 | // Advanced features config 188 | if (tile_data.loop_start != 100000) { 189 | tile.loop_start = tile_data.loop_start; 190 | } 191 | if (tile_data.loop_method != 100000) { 192 | tile.loop_method = tile_data.loop_method; 193 | } 194 | if (tile_data.hover_overlay_tile_id != 100000) { 195 | tile.hover_overlay_tile_id = tile_data.hover_overlay_tile_id; 196 | } 197 | if (tile_data.select_overlay_tile_id != 100000) { 198 | tile.select_overlay_tile_id = tile_data.select_overlay_tile_id; 199 | } 200 | // Display config 201 | if (tile_data.size.x != 100000) { 202 | tile.size.x = tile_data.size.x; 203 | } 204 | if (tile_data.size.y != 100000) { 205 | tile.size.y = tile_data.size.y; 206 | } 207 | if (tile_data.texture_id != 100000) { 208 | tile.texture_id = tile_data.texture_id; 209 | } 210 | if (tile_data.tex_arr_id != 100000) { 211 | tile.tex_arr_id = tile_data.tex_arr_id; 212 | } 213 | // Texture config 214 | if (tile_data.tex_uv.x != 100000) { 215 | tile.tex_uv.x = tile_data.tex_uv.x; 216 | } 217 | if (tile_data.tex_uv.y != 100000) { 218 | tile.tex_uv.y = tile_data.tex_uv.y; 219 | } 220 | if (tile_data.tex_uv.z != 100000) { 221 | tile.tex_uv.z = tile_data.tex_uv.z; 222 | } 223 | if (tile_data.tex_uv.w != 100000) { 224 | tile.tex_uv.w = tile_data.tex_uv.w; 225 | } 226 | // Texture config 2 227 | if (tile_data.opacity != 100000) { 228 | tile.opacity = tile_data.opacity; 229 | } 230 | if (tile_data.saturation != 100000) { 231 | tile.saturation = tile_data.saturation; 232 | } 233 | // Layout config 234 | if (tile_data.offset.x != 100000) { 235 | tile.offset.x = tile_data.offset.x; 236 | } 237 | if (tile_data.offset.y != 100000) { 238 | tile.offset.y = tile_data.offset.y; 239 | } 240 | if (tile_data.anchor.x != 100000) { 241 | tile.anchor.x = tile_data.anchor.x; 242 | } 243 | if (tile_data.anchor.y != 100000) { 244 | tile.anchor.y = tile_data.anchor.y; 245 | } 246 | // Current state 247 | if (tile_data.loop_stage != 100000) { 248 | tile.loop_stage = tile_data.loop_stage; 249 | } 250 | // if (tile_data.is_hovered_over != 100000) { 251 | // tile.is_hovered_over = tile_data.is_hovered_over; 252 | // } 253 | // tile_data.not_used_2 = 0; 254 | } 255 | 256 | Tile GetDataFromIni() 257 | { 258 | Tile tile_data; 259 | // Base config 260 | tile_data.sys_state_id = SysStateId; 261 | tile_data.layer_id = LayerId; 262 | tile_data.parent_tile_id = ParentTileId; 263 | tile_data.template_id = DynamicTemplateId; 264 | // Features config 265 | tile_data.show = Show; 266 | tile_data.select = Select; 267 | tile_data.clamp = Clamp; 268 | tile_data.track_mouse = TrackMouse; 269 | // Advanced features config 270 | tile_data.loop_start = LoopStartTexArrId; 271 | tile_data.loop_method = LoopEndTexArrId; 272 | tile_data.hover_overlay_tile_id = HoverOverlayTileId; 273 | tile_data.select_overlay_tile_id = SelectOverlayTileId; 274 | // Display config 275 | tile_data.size = Size; 276 | tile_data.texture_id = TextureId; 277 | tile_data.tex_arr_id = TexArrId; 278 | // Texture config 279 | tile_data.tex_uv = TexUV; 280 | // Texture config 2 281 | tile_data.opacity = Opacity; 282 | tile_data.saturation = Saturation; 283 | // Layout config 284 | tile_data.offset = Offset; 285 | tile_data.anchor = Anchor; 286 | // Current state 287 | tile_data.loop_stage = LoopStage; 288 | // tile_data.is_hovered_over = IsHoveredOver; 289 | // tile_data.not_used_2 = 0; 290 | return tile_data; 291 | } 292 | 293 | 294 | void UpdateTileTemplate(int template_id) 295 | { 296 | // Get template from storage 297 | Tile tile_template = TileTemplateDataRW[TemplateId]; 298 | // Initialize template if empty 299 | if (tile_template.sys_state_id == 0) { 300 | InitializeTemplate(tile_template); 301 | } 302 | // Read update data from ini variables to cache 303 | Tile update_data = GetDataFromIni(); 304 | // Write cached update data to template 305 | LoadDataUpdate(update_data, tile_template); 306 | // Save updated template to storage 307 | TileTemplateDataRW[TemplateId] = tile_template; 308 | } 309 | 310 | void UpdateTile(int tile_id, int template_id) 311 | { 312 | // Get tile from storage 313 | Tile tile = TilesRW[tile_id]; 314 | // Initialize tile if empty 315 | if (tile.sys_state_id == 0) { 316 | InitializeTile(tile); 317 | } 318 | // Load data from provided template 319 | if (template_id != 100000) { 320 | LoadDataUpdate(TileTemplateDataRW[template_id], tile); 321 | } 322 | // Read update data from ini variables to cache 323 | Tile update_data = GetDataFromIni(); 324 | // Write cached update data to tile 325 | LoadDataUpdate(update_data, tile); 326 | // Save updated tile to storage 327 | TilesRW[tile_id] = tile; 328 | } 329 | 330 | void SetSliderValue() 331 | { 332 | if (TileId == 100000) { 333 | return; 334 | } 335 | Tile tile = TilesRW[TileId]; 336 | if (tile.parent_tile_id == -1) { 337 | return; 338 | } 339 | Tile parent_tile = TilesRW[tile.parent_tile_id]; 340 | if (parent_tile.size.x > parent_tile.size.y) { 341 | tile.offset.x = parent_tile.abs_pos.x + (parent_tile.size.x - tile.size.x) * SetValue - tile.abs_pos.x; 342 | } else { 343 | tile.offset.y = parent_tile.abs_pos.y + (parent_tile.size.y - tile.size.y) * SetValue - tile.abs_pos.y; 344 | } 345 | TilesRW[TileId] = tile; 346 | } 347 | 348 | 349 | // #ifdef COMPUTE_SHADER 350 | 351 | [numthreads(1,1,1)] 352 | void main(uint3 ThreadId : SV_DispatchThreadID) 353 | { 354 | if (TileType == 1) { 355 | UpdateTileTemplate(TemplateId); 356 | } else if (TileType == 2) { 357 | UpdateTile(TileId, TemplateId); 358 | // DebugRW[TileId] = float4(TilesRW[TileId].anchor, 0, 0); 359 | } else if (TileType == 3) { 360 | SetSliderValue(); 361 | } 362 | } 363 | 364 | // #endif 365 | -------------------------------------------------------------------------------- /TileGUI/TileGUI.ini: -------------------------------------------------------------------------------- 1 | ; TileGUI v0.8.2 BETA 2 | ; Simple yet powerful GUI framework for XXMI 3 | ; https://github.com/SpectrumQT/TileGUI 4 | 5 | namespace=TileGUI 6 | 7 | 8 | ; API ------------------------- 9 | 10 | [CommandListGetVersion] 11 | $return_version = 0.82 12 | 13 | 14 | [CommandListDrawGUI] 15 | ; Run compute shader to process "shader-accelerated" features like hover-overlays, loops and dragging 16 | run = CustomShaderTileFeaturesService 17 | ; Run compute shader to update tile positions 18 | run = CustomShaderTilePositionService 19 | ; Run GUI shaders 20 | run = CustomShaderTileDrawService 21 | ; Draw virtual cursor for gamepad & keyboard controls support 22 | run = CommandList\TileGUI_VirtualCursor\DrawVirtualCursor 23 | 24 | 25 | [CommandListSetInstance] 26 | if ResourceClientInstanceData !== null 27 | run = CustomShaderInstanceWriter 28 | run = CommandListSetScale 29 | endif 30 | 31 | 32 | [CommandListSetTemplate] 33 | if ResourceClientTemplatesData !== null 34 | $set_tile_type = 1 35 | run = CustomShaderTileWriter 36 | endif 37 | 38 | 39 | [CommandListApplyTemplate] 40 | if ResourceClientTemplatesData !== null 41 | $request_type = 1 42 | run = CustomShaderTileGroupWriter 43 | endif 44 | 45 | 46 | [CommandListApplyLayout] 47 | if ResourceClientTilesData !== null 48 | $request_type = 2 49 | run = CustomShaderTileGroupWriter 50 | endif 51 | 52 | 53 | [CommandListSetTile] 54 | if ResourceClientTilesData !== null 55 | $set_tile_type = 2 56 | run = CustomShaderTileWriter 57 | endif 58 | 59 | 60 | [CommandListSetSliderValue] 61 | if ResourceClientTilesData !== null 62 | $set_tile_type = 3 63 | run = CustomShaderTileWriter 64 | endif 65 | 66 | 67 | [CommandListGetHoveredOverTileId] 68 | if ResourceClientTilesData !== null 69 | $arg_request_type = 2 70 | run = CustomShaderTileReader 71 | endif 72 | 73 | 74 | [CommandListGetSliderValue] 75 | if ResourceClientTilesData !== null 76 | $arg_request_type = 3 77 | run = CustomShaderTileReader 78 | endif 79 | 80 | 81 | [CommandListGetTileVar] 82 | if ResourceClientTilesData !== null 83 | $arg_request_type = 1 84 | run = CustomShaderTileReader 85 | endif 86 | 87 | 88 | [CommandListGetSysStateId] 89 | $arg_tile_var_id = 0 90 | run = CommandListGetTileVar 91 | 92 | [CommandListGetLayerId] 93 | $arg_tile_var_id = 1 94 | run = CommandListGetTileVar 95 | 96 | [CommandListGetParentTileId] 97 | $arg_tile_var_id = 2 98 | run = CommandListGetTileVar 99 | 100 | [CommandListGetDynamicTemplateId] 101 | $arg_tile_var_id = 3 102 | run = CommandListGetTileVar 103 | 104 | [CommandListGetShow] 105 | $arg_tile_var_id = 4 106 | run = CommandListGetTileVar 107 | 108 | [CommandListGetSelect] 109 | $arg_tile_var_id = 5 110 | run = CommandListGetTileVar 111 | 112 | [CommandListGetClamp] 113 | $arg_tile_var_id = 6 114 | run = CommandListGetTileVar 115 | 116 | [CommandListGetTrackMouse] 117 | $arg_tile_var_id = 7 118 | run = CommandListGetTileVar 119 | 120 | [CommandListGetLoopStartTexArrId] 121 | $arg_tile_var_id = 8 122 | run = CommandListGetTileVar 123 | 124 | [CommandListGetLoopEndTexArrId] 125 | $arg_tile_var_id = 9 126 | run = CommandListGetTileVar 127 | 128 | [CommandListGetHoverOverlayTileId] 129 | $arg_tile_var_id = 10 130 | run = CommandListGetTileVar 131 | 132 | [CommandListGetSelectOverlayTileId] 133 | $arg_tile_var_id = 11 134 | run = CommandListGetTileVar 135 | 136 | [CommandListGetWidth] 137 | $arg_tile_var_id = 12 138 | run = CommandListGetTileVar 139 | 140 | [CommandListGetHeight] 141 | $arg_tile_var_id = 13 142 | run = CommandListGetTileVar 143 | 144 | [CommandListGetTextureId] 145 | $arg_tile_var_id = 14 146 | run = CommandListGetTileVar 147 | 148 | [CommandListGetTexArrId] 149 | $arg_tile_var_id = 15 150 | run = CommandListGetTileVar 151 | 152 | [CommandListGetTexUvX] 153 | $arg_tile_var_id = 16 154 | run = CommandListGetTileVar 155 | 156 | [CommandListGetTexUvY] 157 | $arg_tile_var_id = 17 158 | run = CommandListGetTileVar 159 | 160 | [CommandListGetTexUvZ] 161 | $arg_tile_var_id = 18 162 | run = CommandListGetTileVar 163 | 164 | [CommandListGetTexUvW] 165 | $arg_tile_var_id = 19 166 | run = CommandListGetTileVar 167 | 168 | [CommandListGetOpacity] 169 | $arg_tile_var_id = 20 170 | run = CommandListGetTileVar 171 | 172 | [CommandListGetSaturation] 173 | $arg_tile_var_id = 21 174 | run = CommandListGetTileVar 175 | 176 | ; [CommandListGetReserved1X] 177 | ; $arg_tile_var_id = 22 178 | ; run = CommandListGetTileVar 179 | 180 | ; [CommandListGetReserved1Y] 181 | ; $arg_tile_var_id = 23 182 | ; run = CommandListGetTileVar 183 | 184 | [CommandListGetOffsetX] 185 | $arg_tile_var_id = 24 186 | run = CommandListGetTileVar 187 | 188 | [CommandListGetOffsetY] 189 | $arg_tile_var_id = 25 190 | run = CommandListGetTileVar 191 | 192 | [CommandListGetAnchorX] 193 | $arg_tile_var_id = 26 194 | run = CommandListGetTileVar 195 | 196 | [CommandListGetAnchorY] 197 | $arg_tile_var_id = 27 198 | run = CommandListGetTileVar 199 | 200 | [CommandListGetLoopStage] 201 | $arg_tile_var_id = 28 202 | run = CommandListGetTileVar 203 | 204 | [CommandListGetIsHoveredOver] 205 | $arg_tile_var_id = 29 206 | run = CommandListGetTileVar 207 | 208 | ; [CommandListGetReserved2X] 209 | ; $arg_tile_var_id = 30 210 | ; run = CommandListGetTileVar 211 | 212 | ; [CommandListGetReserved2Y] 213 | ; $arg_tile_var_id = 31 214 | ; run = CommandListGetTileVar 215 | 216 | [CommandListGetAbsPosX] 217 | $arg_tile_var_id = 32 218 | run = CommandListGetTileVar 219 | 220 | [CommandListGetAbsPosY] 221 | $arg_tile_var_id = 33 222 | run = CommandListGetTileVar 223 | 224 | [CommandListGetAbsPosZ] 225 | $arg_tile_var_id = 34 226 | run = CommandListGetTileVar 227 | 228 | [CommandListGetAbsPosW] 229 | $arg_tile_var_id = 35 230 | run = CommandListGetTileVar 231 | 232 | 233 | ; VARIABLES ------------------------- 234 | 235 | [Constants] 236 | global $return_version = -1 237 | global $required_version = -1 238 | ; While TileGUI is a stateless library, we still need to pass variables and get results somehow 239 | ; So we'll use temp variables that are explicitly getting reset on connect or after a method call 240 | ; Also, as we can't exchange 'null' with shaders, we'll mask it with 100000 instead 241 | ; This arbitrary big number doesn't have any sense for any value used by this library 242 | ;================================================================================================= 243 | ; Temp vars of client configuration 244 | global $max_tiles_count = 128 245 | global $max_layers_count = 1 246 | global $max_parent_recursion = 0 247 | global $scaling_factor = 0.25 248 | ;================================================================================================= 249 | ; Temp vars of user controls 250 | global $toggle_gui = 0 251 | global $mouse_left = 0 252 | global $mouse_right = 0 253 | global $mouse_mid = 0 254 | global $mouse_forward = 0 255 | global $mouse_backward = 0 256 | global $virtual_cursor_x = -1 257 | global $virtual_cursor_y = -1 258 | ;================================================================================================= 259 | ; Temp vars of CustomShaderInstanceWriter 260 | global $drag_tile_id = 100000 261 | ;================================================================================================= 262 | ; Temp vars of CustomShaderTileWriter 263 | global $screen_scaling = 1.0 264 | global $set_tile_type = 100000 265 | global $target_template_id = 100000 266 | global $target_tile_id = 100000 267 | global $set_value = 100000 268 | ; System config 269 | global $sys_state_id = 100000 270 | global $layer_id = 100000 271 | global $parent_tile_id = 100000 272 | global $template_id = 100000 273 | ; Features config 274 | global $show = 100000 275 | global $select = 100000 276 | global $clamp = 100000 277 | global $track_mouse = 100000 278 | ; Advanced features config 279 | global $loop_start = 100000 280 | global $loop_method = 100000 281 | global $hover_overlay_tile_id = 100000 282 | global $select_overlay_tile_id = 100000 283 | ; Display config 284 | global $width = 100000 285 | global $height = 100000 286 | global $texture_id = 100000 287 | global $tex_arr_id = 100000 288 | ; Texture config 289 | global $tex_uv_x = 100000 290 | global $tex_uv_y = 100000 291 | global $tex_uv_z = 100000 292 | global $tex_uv_w = 100000 293 | ; Texture config 2 294 | global $opacity = 100000 295 | global $saturation = 100000 296 | ; Layout config 297 | global $offset_x = 100000 298 | global $offset_y = 100000 299 | global $anchor_x = 100000 300 | global $anchor_y = 100000 301 | ; Current state 302 | global $loop_stage = 100000 303 | ;================================================================================================= 304 | ; Temp vars of CustomShaderTileGroupWriter 305 | global $request_type = 100000 306 | global $first_tile_id = 100000 307 | global $last_tile_id = 100000 308 | global $create_tiles = 100000 309 | global $skip_existing_tiles = 100000 310 | global $cols_count = 100000 311 | global $rows_count = 100000 312 | global $cols_padding = 100000 313 | global $rows_padding = 100000 314 | ;================================================================================================= 315 | ; Temp vars of CustomShaderTileReader 316 | global $arg_request_type = 100000 317 | global $arg_tile_var_id = 100000 318 | global $return_var = 100000 319 | ;================================================================================================= 320 | 321 | 322 | 323 | ; HELPERS ------------------------- 324 | 325 | ; Make sure to make temp variables really 'temp' via calling this method on connect! 326 | [CommandListResetTempVars] 327 | ; Reset configuration to defaults 328 | $return_version = -1 329 | $required_version = -1 330 | $max_tiles_count = 128 331 | $max_layers_count = 1 332 | $max_parent_recursion = 0 333 | $scaling_factor = 0.25 334 | ; Reset all temp vars used by shaders 335 | run = CommandListResetVarsOfCustomShaderInstanceWriter 336 | run = CommandListResetVarsOfCustomShaderTileWriter 337 | run = CommandListResetVarsOfCustomShaderTileGroupWriter 338 | run = CommandListResetVarsOfCustomShaderTileReader 339 | 340 | 341 | [CommandListPassWindowInfo] 342 | ; Pass a game window size to the shader 343 | x0 = window_width 344 | y0 = window_height 345 | ; Pass cursor relative coords to the shader 346 | if $virtual_cursor_x == -1 && $virtual_cursor_y == -1 347 | ; Pass real mouse cursor 348 | z0 = cursor_x * 2 - 1 349 | w0 = -(cursor_y * 2 - 1) 350 | else 351 | ; Pass virtual mouse cursor 352 | z0 = $\TileGUI\virtual_cursor_x / (x0 / 2) 353 | w0 = $\TileGUI\virtual_cursor_y / (y0 / 2) 354 | endif 355 | 356 | 357 | ; Set UI scaling factor 358 | [CommandListSetScale] 359 | ; Windows returns 96 as effective_dpi for 100% scale 360 | $screen_scaling = effective_dpi / 96 361 | if $screen_scaling > 1.0 362 | $screen_scaling = 1.0 + ($screen_scaling - 1.0) * $scaling_factor 363 | endif 364 | 365 | 366 | ; INSTANCE WRITER SHADER ------------------------- 367 | 368 | ; Updates client's instance storage with given ini variables 369 | [CustomShaderInstanceWriter] 370 | ; Load shader and explicitly unbind other shaders for safety 371 | cs = Shaders/instance_writer.hlsl 372 | vs = null 373 | ps = null 374 | hs = null 375 | ds = null 376 | gs = null 377 | ; Pass RWBuffers to communicate with the shader 378 | cs-u0 = ResourceClientInstanceData 379 | ; cs-u7 = ResourceDebugRW 380 | ; Backup IniParams we are about to use 381 | local $bak_x0 = x0 382 | local $bak_y0 = y0 383 | local $bak_z0 = z0 384 | local $bak_w0 = w0 385 | local $bak_x10 = x10 386 | local $bak_y10 = y10 387 | local $bak_x15 = x15 388 | ; Pass a game window size and cursor relative coords to the shader 389 | run = CommandListPassWindowInfo 390 | ; Pass variables to the shader 391 | x10 = $max_tiles_count 392 | y10 = $max_layers_count 393 | x15 = $drag_tile_id 394 | ; Run calulations 395 | Dispatch = 1, 1, 1 396 | ; Reset variables 397 | run = CommandListResetVarsOfCustomShaderInstanceWriter 398 | ; Unbind RWBuffers 399 | post cs-u0 = null 400 | ; Restore IniParams: 401 | post x0 = $bak_x0 402 | post y0 = $bak_y0 403 | post z0 = $bak_z0 404 | post w0 = $bak_w0 405 | post x10 = $bak_x10 406 | post y10 = $bak_y10 407 | post x15 = $bak_x15 408 | 409 | [CommandListResetVarsOfCustomShaderInstanceWriter] 410 | $drag_tile_id = 100000 411 | 412 | 413 | ; TILE WRITER SHADER ------------------------- 414 | 415 | ; Updates client's tile storage with given ini variables 416 | [CustomShaderTileWriter] 417 | ; Load shader and explicitly unbind other shaders for safety 418 | cs = Shaders/tile_writer.hlsl 419 | vs = null 420 | ps = null 421 | hs = null 422 | ds = null 423 | gs = null 424 | ; Backup IniParams we are about to use 425 | local $bak_x1 = x1 426 | local $bak_y1 = y1 427 | local $bak_z1 = z1 428 | local $bak_w1 = w1 429 | local $bak_x2 = x2 430 | local $bak_y2 = y2 431 | local $bak_z2 = z2 432 | local $bak_w2 = w2 433 | local $bak_x3 = x3 434 | local $bak_y3 = y3 435 | local $bak_z3 = z3 436 | local $bak_w3 = w3 437 | local $bak_x4 = x4 438 | local $bak_y4 = y4 439 | local $bak_z4 = z4 440 | local $bak_w4 = w4 441 | local $bak_x5 = x5 442 | local $bak_y5 = y5 443 | local $bak_z5 = z5 444 | local $bak_w5 = w5 445 | local $bak_x6 = x6 446 | local $bak_y6 = y6 447 | local $bak_z6 = z6 448 | local $bak_w6 = w6 449 | local $bak_x7 = x7 450 | local $bak_y7 = y7 451 | local $bak_z7 = z7 452 | local $bak_w7 = w7 453 | local $bak_x8 = x8 454 | local $bak_y8 = y8 455 | local $bak_z8 = z8 456 | local $bak_w8 = w8 457 | local $bak_x9 = x9 458 | ; local $bak_y9 = y9 459 | ; local $bak_z9 = z9 460 | ; local $bak_w9 = w9 461 | ; Pass RWBuffers to communicate with the shader 462 | cs-u0 = ResourceClientTemplatesData 463 | cs-u1 = ResourceClientTilesData 464 | ; cs-u7 = ResourceDebugRW 465 | ; For template we should pass only TemplateId 466 | if $set_tile_type == 1 467 | x1 = 1 468 | y1 = $target_template_id 469 | ; For regular tile we should pass both TileID and TemplateId (TemplateId is optional though) 470 | else if $set_tile_type == 2 471 | x1 = 2 472 | y1 = $template_id 473 | z1 = $target_tile_id 474 | else if $set_tile_type == 3 475 | x1 = 3 476 | z1 = $target_tile_id 477 | w1 = $set_value 478 | endif 479 | ; Pass a tile update data to the shader 480 | ; System config 481 | x2 = $sys_state_id 482 | y2 = $layer_id 483 | z2 = $parent_tile_id 484 | w2 = $template_id 485 | ; Features config 486 | x3 = $show 487 | y3 = $select 488 | z3 = $clamp 489 | w3 = $track_mouse 490 | ; Advanced features config 491 | x4 = $loop_start 492 | y4 = $loop_method 493 | z4 = $hover_overlay_tile_id 494 | w4 = $select_overlay_tile_id 495 | ; Display config 496 | if $width == 100000 497 | x5 = $width 498 | else 499 | x5 = $width * $screen_scaling 500 | endif 501 | if $height == 100000 502 | y5 = $height 503 | else 504 | y5 = $height * $screen_scaling 505 | endif 506 | z5 = $texture_id 507 | w5 = $tex_arr_id 508 | ; Texture config 509 | x6 = $tex_uv_x 510 | y6 = $tex_uv_y 511 | z6 = $tex_uv_z 512 | w6 = $tex_uv_w 513 | ; Texture config 2 514 | x7 = $opacity 515 | y7 = $saturation 516 | ; z7 = $reserved_1 517 | ; w7 = $reserved_1 518 | ; Layout config 519 | x8 = $offset_x 520 | y8 = $offset_y 521 | z8 = $anchor_x 522 | w8 = $anchor_y 523 | ; Current state 524 | x9 = $loop_stage 525 | ; Run calulations 526 | Dispatch = 1, 1, 1 527 | ; Reset variables 528 | run = CommandListResetVarsOfCustomShaderTileWriter 529 | ; Unbind RWBuffers 530 | post cs-u0 = null 531 | post cs-u1 = null 532 | ; Restore IniParams: 533 | post x1 = $bak_x1 534 | post y1 = $bak_y1 535 | post z1 = $bak_z1 536 | post w1 = $bak_w1 537 | post x2 = $bak_x2 538 | post y2 = $bak_y2 539 | post z2 = $bak_z2 540 | post w2 = $bak_w2 541 | post x3 = $bak_x3 542 | post y3 = $bak_y3 543 | post z3 = $bak_z3 544 | post w3 = $bak_w3 545 | post x4 = $bak_x4 546 | post y4 = $bak_y4 547 | post z4 = $bak_z4 548 | post w4 = $bak_w4 549 | post x5 = $bak_x5 550 | post y5 = $bak_y5 551 | post z5 = $bak_z5 552 | post w5 = $bak_w5 553 | post x6 = $bak_x6 554 | post y6 = $bak_y6 555 | post z6 = $bak_z6 556 | post w6 = $bak_w6 557 | post x7 = $bak_x7 558 | post y7 = $bak_y7 559 | post z7 = $bak_z7 560 | post w7 = $bak_w7 561 | post x8 = $bak_x8 562 | post y8 = $bak_y8 563 | post z8 = $bak_z8 564 | post w8 = $bak_w8 565 | post x9 = $bak_x9 566 | ; post y9 = $bak_y9 567 | ; post z9 = $bak_z9 568 | ; post w9 = $bak_w9 569 | 570 | [CommandListResetVarsOfCustomShaderTileWriter] 571 | ; Request config 572 | $set_tile_type = 100000 573 | $target_template_id = 100000 574 | $target_tile_id = 100000 575 | $set_value = 100000 576 | ; System config 577 | $sys_state_id = 100000 578 | $layer_id = 100000 579 | $parent_tile_id = 100000 580 | $template_id = 100000 581 | ; Features config 582 | $show = 100000 583 | $select = 100000 584 | $clamp = 100000 585 | $track_mouse = 100000 586 | ; Advanced features config 587 | $loop_start = 100000 588 | $loop_method = 100000 589 | $hover_overlay_tile_id = 100000 590 | $select_overlay_tile_id = 100000 591 | ; Display config 592 | $width = 100000 593 | $height = 100000 594 | $texture_id = 100000 595 | $tex_arr_id = 100000 596 | ; Texture config 597 | $tex_uv_x = 100000 598 | $tex_uv_y = 100000 599 | $tex_uv_z = 100000 600 | $tex_uv_w = 100000 601 | ; Texture config 2 602 | $opacity = 100000 603 | $saturation = 100000 604 | ; Layout config 605 | $offset_x = 100000 606 | $offset_y = 100000 607 | $anchor_x = 100000 608 | $anchor_y = 100000 609 | ; Current state 610 | $loop_stage = 100000 611 | 612 | 613 | ; TILE GROUP WRITER SHADER ------------------------- 614 | 615 | ; Streamlines multiple tiles declaration and property updates both for initialization and runtime 616 | [CustomShaderTileGroupWriter] 617 | ; Load shader and explicitly unbind other shaders for safety 618 | cs = Shaders/tile_group_writer.hlsl 619 | vs = null 620 | ps = null 621 | hs = null 622 | ds = null 623 | gs = null 624 | ; Pass RWBuffers to communicate with the shader 625 | cs-u0 = ResourceClientTemplatesData 626 | cs-u1 = ResourceClientTilesData 627 | ; cs-u7 = ResourceDebugRW 628 | ; Backup IniParams we are about to use 629 | local $bak_x0 = x0 630 | local $bak_y0 = y0 631 | local $bak_z0 = z0 632 | local $bak_x1 = x1 633 | local $bak_y1 = y1 634 | local $bak_x2 = x2 635 | local $bak_y2 = y2 636 | local $bak_x3 = x3 637 | local $bak_y3 = y3 638 | local $bak_z3 = z3 639 | local $bak_w3 = w3 640 | local $bak_x4 = x4 641 | local $bak_y4 = y4 642 | ; Pass data to the shader 643 | x0 = $request_type 644 | y0 = $template_id 645 | z0 = $parent_tile_id 646 | x1 = $first_tile_id 647 | y1 = $last_tile_id 648 | x2 = $create_tiles 649 | y2 = $skip_existing_tiles 650 | x3 = $cols_count 651 | y3 = $rows_count 652 | if $cols_padding == 100000 653 | z3 = $cols_padding 654 | else 655 | z3 = $cols_padding * $screen_scaling 656 | endif 657 | if $rows_padding == 100000 658 | w3 = $rows_padding 659 | else 660 | w3 = $rows_padding * $screen_scaling 661 | endif 662 | x4 = $anchor_x 663 | y4 = $anchor_y 664 | ; Shader requires 1 thread per tile and has thread group size of 64 declared 665 | ; We'll need max_tiles_count / 64 thread groups total to process all the tiles 666 | local $thread_groups_count = $max_tiles_count / 64 667 | ; Run the compute shader 668 | Dispatch = $thread_groups_count, 1, 1 669 | ; Unbind RWBuffers 670 | post cs-u0 = null 671 | post cs-u1 = null 672 | ; Reset variables 673 | run = CommandListResetVarsOfCustomShaderTileGroupWriter 674 | ; Restore IniParams: 675 | post x0 = $bak_x0 676 | post y0 = $bak_y0 677 | post z0 = $bak_z0 678 | post x1 = $bak_x1 679 | post y1 = $bak_y1 680 | post x2 = $bak_x2 681 | post y2 = $bak_y2 682 | post x3 = $bak_x3 683 | post y3 = $bak_y3 684 | post z3 = $bak_z3 685 | post w3 = $bak_w3 686 | post x4 = $bak_x4 687 | post y4 = $bak_y4 688 | 689 | [CommandListResetVarsOfCustomShaderTileGroupWriter] 690 | ; Request config 691 | $request_type = 100000 692 | 693 | $template_id = 100000 694 | $parent_tile_id = 100000 695 | $first_tile_id = 100000 696 | $last_tile_id = 100000 697 | $create_tiles = 100000 698 | $skip_existing_tiles = 100000 699 | $cols_count = 100000 700 | $rows_count = 100000 701 | $cols_padding = 100000 702 | $rows_padding = 100000 703 | $anchor_x = 100000 704 | $anchor_y = 100000 705 | 706 | 707 | ; TILE FEATURES SERVICE SHADER ------------------------- 708 | 709 | ; Handles special (re)actions for all tiles, like hover over, overlays, dragging and so on 710 | ; Simplifies and accelerates common GUI logic that would require tons of STORE calls otherwise 711 | [CustomShaderTileFeaturesService] 712 | ; Load shader and explicitly unbind other shaders for safety 713 | cs = Shaders/tile_features_service.hlsl 714 | vs = null 715 | ps = null 716 | hs = null 717 | ds = null 718 | gs = null 719 | ; Pass RWBuffers to communicate with the shader 720 | cs-u0 = ResourceClientInstanceData 721 | cs-u1 = ResourceClientTilesData 722 | ; cs-u7 = ResourceDebugRW 723 | ; Backup IniParams we are about to use 724 | local $bak_x0 = x0 725 | local $bak_y0 = y0 726 | local $bak_z0 = z0 727 | local $bak_w0 = w0 728 | ; Pass a game window size and cursor relative coords to the shader 729 | run = CommandListPassWindowInfo 730 | ; Shader requires 1 thread per tile and has thread group size of 64 declared 731 | ; We'll need max_tiles_count / 64 thread groups total to process all the tiles 732 | local $thread_groups_count = $max_tiles_count / 64 733 | ; Run the compute shader 734 | Dispatch = $thread_groups_count, 1, 1 735 | ; Unbind RWBuffers 736 | post cs-u0 = null 737 | post cs-u1 = null 738 | ; Restore IniParams: 739 | post x0 = $bak_x0 740 | post y0 = $bak_y0 741 | post z0 = $bak_z0 742 | post w0 = $bak_w0 743 | 744 | 745 | ; TILE POSITION SERVICE SHADER ------------------------- 746 | 747 | ; Updates positions of all tiles based on sizes, offsets, anchors and those of parents 748 | [CustomShaderTilePositionService] 749 | ; Load shader and explicitly unbind other shaders for safety 750 | cs = Shaders/tile_position_service.hlsl 751 | vs = null 752 | ps = null 753 | hs = null 754 | ds = null 755 | gs = null 756 | ; Pass RWBuffers to communicate with the shader 757 | cs-u1 = ResourceClientTilesData 758 | ; cs-u7 = ResourceDebugRW 759 | ; Backup IniParams we are about to use 760 | local $bak_x0 = x0 761 | local $bak_y0 = y0 762 | local $bak_x1 = x1 763 | ; Pass a game window size to the shader 764 | x0 = window_width 765 | y0 = window_height 766 | ; Pass max length of parents chain to process in single pass 767 | x1 = $max_parent_recursion 768 | ; Shader requires 1 thread per tile and has thread group size of 64 declared 769 | ; We'll need max_tiles_count / 64 thread groups total to process all the tiles 770 | local $thread_groups_count = $max_tiles_count / 64 771 | ; Run the compute shader 772 | Dispatch = $thread_groups_count, 1, 1 773 | ; Unbind RWBuffers 774 | post cs-u0 = null 775 | post cs-u1 = null 776 | ; Restore IniParams: 777 | post x0 = $bak_x0 778 | post y0 = $bak_y0 779 | post x1 = $bak_x1 780 | 781 | 782 | ; TILE DRAW SERVICE SHADER ------------------------- 783 | 784 | ; Draws all tiles on screen 785 | [CustomShaderTileDrawService] 786 | ; Load shader and explicitly unbind other shaders for safety 787 | cs = null 788 | vs = Shaders/tile_draw_service.hlsl 789 | ps = Shaders/tile_draw_service.hlsl 790 | hs = null 791 | ds = null 792 | gs = Shaders/tile_draw_service.hlsl 793 | ; Disable front/back face culling so the vertices can be in any rotation 794 | cull = none 795 | ; Use points as the primitive from the vertex shader to the geometry shader 796 | topology = point_list 797 | ; Clear all render + depth targets to avoid compatibility issues 798 | run = BuiltInCommandListUnbindAllRenderTargets 799 | ; Bind the back buffer as a render target. set_viewport ensures that the view 800 | ; port is the size of the buffer so the draw call will work 801 | o0 = set_viewport bb 802 | ; Enable blending images with alpha channel (transparency support) 803 | blend = ADD SRC_ALPHA INV_SRC_ALPHA 804 | ; Pass RWStructuredBuffers as read-only to the geometry shader (t instead of u slot) 805 | gs-t121 = ResourceClientInstanceData 806 | gs-t122 = ResourceClientTilesData 807 | ; Draw images 808 | Draw = $max_layers_count, 0 809 | ; Unbind resources 810 | post gs-t121 = null 811 | post gs-t122 = null 812 | 813 | 814 | ; TILE READER SHADER ------------------------- 815 | 816 | ; Fetches tile properties from RWBuffers to ini variables 817 | [CustomShaderTileReader] 818 | ; Load shader and explicitly unbind other shaders for safety 819 | cs = Shaders/tile_reader.hlsl 820 | vs = null 821 | ps = null 822 | hs = null 823 | ds = null 824 | gs = null 825 | ; Clear output buffer 826 | clear = ResourceTempBuffer 827 | ; Pass RWBuffers to communicate with the shader 828 | cs-t121 = ResourceClientInstanceData 829 | cs-t122 = ResourceClientTilesData 830 | cs-u0 = ResourceTempBuffer 831 | ; cs-u7 = ResourceDebugRW 832 | ; Backup IniParams we are about to use 833 | local $bak_x1 = x1 834 | local $bak_y1 = y1 835 | local $bak_z1 = z1 836 | ; Pass the update data to the shader 837 | x1 = $arg_request_type 838 | y1 = $target_tile_id 839 | z1 = $arg_tile_var_id 840 | ; Run the compute shader 841 | Dispatch = 1, 1, 1 842 | ; Update $return_var temp variable 843 | $return_var = 100000 844 | store = $return_var, ResourceTempBuffer, 33 845 | ; Reset variables 846 | $arg_request_type = 100000 847 | $target_tile_id = 100000 848 | $arg_tile_var_id = 100000 849 | ; Unbind RWBuffers 850 | post cs-t121 = null 851 | post cs-t122 = null 852 | post cs-u0 = null 853 | ; Restore IniParams: 854 | post x1 = $bak_x1 855 | post y1 = $bak_y1 856 | post z1 = $bak_z1 857 | 858 | [CommandListResetVarsOfCustomShaderTileReader] 859 | $arg_request_type = 100000 860 | $target_tile_id = 100000 861 | $arg_tile_var_id = 100000 862 | $return_var = 100000 863 | 864 | 865 | ; RESOURCES ------------------------- 866 | 867 | [ResourceTempBuffer] 868 | type = buffer 869 | format = R32_FLOAT 870 | array = 34 871 | 872 | ; [ResourceDebugRW] 873 | ; type = RWBuffer 874 | ; format = R32G32B32A32_FLOAT 875 | ; array = 128 876 | 877 | [ResourceClientInstanceData] 878 | 879 | [ResourceClientTilesData] 880 | 881 | [ResourceClientTemplatesData] 882 | 883 | 884 | ; EOF ------------------------- 885 | -------------------------------------------------------------------------------- /TileGUI/UserControls.ini: -------------------------------------------------------------------------------- 1 | ; 2 | ; How To Change Key Bindings 3 | ; 4 | ; 1. Find button (i.e. [KeyLeftButtonClick]) 5 | ; 2. Find line below 'Xbox Gamepad Binding', 'Keyboard Binding' or 'Mouse Binding' comment 6 | ; 3. Replace 'key = OLD_KEY_CODE' with 'key = NEW_KEY_CODE' 7 | ; 8 | ; Key Codes: 9 | ; * For Gamepad buttons, use following codes: 10 | ; XB_LEFT_TRIGGER, XB_RIGHT_TRIGGER, 11 | ; XB_LEFT_SHOULDER, XB_RIGHT_SHOULDER, 12 | ; XB_LEFT_THUMB, XB_RIGHT_THUMB, 13 | ; XB_DPAD_UP, XB_DPAD_DOWN, XB_DPAD_LEFT, XB_DPAD_RIGHT, 14 | ; XB_A, XB_B, XB_X, XB_Y, XB_START, XB_BACK, XB_GUIDE 15 | ; * For A-Z and 0-9 on the number row, just use that single character 16 | ; * For everything else (including mouse buttons) use the Virtual Key Code 17 | ; - Virtual Key Codes list: https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes 18 | ; - Usage of 'VK_' prefix is optional, you can specify buttons with or without it 19 | ; 20 | ; Key Combination: 21 | ; * To specify key combination, separate key names with spaces (e.g. "SHIFT ALT Q") 22 | ; 23 | ; Modifiers: 24 | ; * To specify key that should NOT be held for binding to activate use 'NO_' prefix (e.g. "NO_ALT CTRL F1") 25 | ; * To exclude all standard modifiers (Ctrl, Alt, Shift, Windows) use 'NO_MODIFIERS' (e.g. "NO_MODIFIERS VK_LBUTTON") 26 | 27 | 28 | ; Configuration ------------------------- 29 | 30 | [CommandListSetupConfiguration] 31 | ; Affects the Horizontal Speed of Virtual Cursor controlled via Gamepad or Keyboard 32 | ; For reasonable speed keep the value between 0.25 and 2.0 33 | $cursor_sensivity_x = 0.5 34 | ; Affects the Vertical Speed of Virtual Cursor controlled via Gamepad or Keyboard 35 | ; For reasonable speed keep the value between 0.25 and 2.0 36 | $cursor_sensivity_y = 0.5 37 | 38 | 39 | ; General Hotkeys ------------------------- 40 | 41 | ; Action: Toggle (Show/Hide) Mod's GUI 42 | [KeyToggleGUI] 43 | ; Xbox Gamepad Binding: 44 | key = XB_START XB_BACK 45 | ; Keyboard Binding: 46 | key = SHIFT ALT T 47 | ; Mouse Binding: 48 | ; Doesn't have much sense for mouse tbh 49 | ;------------------------------------------ 50 | ; Input Configuration: 51 | type = cycle 52 | $toggle_gui = 0,1 53 | 54 | 55 | ; Suggested Action: Select or Toggle UI element hovered over by cursor 56 | [KeyLeftButtonClick] 57 | ; Xbox Gamepad Binding: 58 | key = XB_X 59 | ; Keyboard Binding: 60 | key = SHIFT ALT Q 61 | ; Mouse Binding: 62 | key = VK_LBUTTON 63 | ;------------------------------------------ 64 | ; Input Configuration: 65 | type = hold 66 | $mouse_left_state = 1 67 | run = CommandListHandleMouseLeft 68 | 69 | 70 | ; Suggested Action: Deselect or Configure UI element hovered over by cursor 71 | [KeyRightButtonClick] 72 | ; Xbox Gamepad Binding: 73 | key = XB_B 74 | ; Keyboard Binding: 75 | key = SHIFT ALT E 76 | ; Mouse Binding: 77 | key = VK_RBUTTON 78 | ;------------------------------------------ 79 | ; Input Configuration: 80 | type = hold 81 | $mouse_right_state = 1 82 | run = CommandListHandleMouseRight 83 | 84 | 85 | ; Suggested Action: Drag or Scroll UI element hovered over by cursor 86 | [KeyMiddleButtonClick] 87 | ; Xbox Gamepad Binding: 88 | key = XB_Y 89 | ; Keyboard Binding: 90 | key = SHIFT ALT R 91 | ; Mouse Binding: 92 | key = VK_MBUTTON 93 | ;------------------------------------------ 94 | ; Input Configuration: 95 | type = hold 96 | $mouse_mid_state = 1 97 | run = CommandListHandleMouseMid 98 | 99 | 100 | ; Suggested Action: Close Child Panel or Go To Previous UI State 101 | [KeyBackwardButtonClick] 102 | ; Xbox Gamepad Binding: 103 | key = XB_BACK 104 | ; Keyboard Binding: 105 | key = SHIFT ALT Z 106 | ; Mouse Binding: 107 | key = VK_XBUTTON1 108 | ;------------------------------------------ 109 | ; Input Configuration: 110 | type = hold 111 | $mouse_backward_state = 1 112 | run = CommandListHandleMouseBackward 113 | 114 | 115 | ; Suggested Action: Open Child Panel or Go To Next UI State 116 | [KeyForwardButtonClick] 117 | ; Xbox Gamepad Binding: 118 | key = XB_START 119 | ; Keyboard Binding: 120 | key = SHIFT ALT X 121 | ; Mouse Binding: 122 | key = VK_XBUTTON2 123 | ;------------------------------------------ 124 | ; Input Configuration: 125 | type = hold 126 | $mouse_forward_state = 1 127 | run = CommandListHandleMouseForward 128 | 129 | 130 | ; Virtual Cursor Hotkeys ------------------------- 131 | 132 | ; Action: Hide Virtual Cursor 133 | [KeyVirtualCursorHide] 134 | ; Xbox Gamepad Binding: 135 | ; Doesn't have much sense for gamepad tbh 136 | ; Keyboard Binding: 137 | key = SHIFT ALT A D 138 | key = SHIFT ALT W S 139 | ;------------------------------------------ 140 | ; Input Configuration: 141 | run = CommandListHideVirtualCursor 142 | 143 | 144 | ; Action: Move Virtual Cursor in LEFT direction 145 | [KeyVirtualCursorLeft] 146 | ; Xbox Gamepad Binding: 147 | key = XB_DPAD_LEFT 148 | ; Keyboard Binding: 149 | key = SHIFT ALT A 150 | ;------------------------------------------ 151 | ; Input Configuration: 152 | type = hold 153 | $arrow_left_state = 1 154 | 155 | 156 | ; Action: Move Virtual Cursor in RIGHT direction 157 | [KeyVirtualCursorRight] 158 | ; Xbox Gamepad Binding: 159 | key = XB_DPAD_RIGHT 160 | ; Keyboard Binding: 161 | key = SHIFT ALT D 162 | ;------------------------------------------ 163 | ; Input Configuration: 164 | type = hold 165 | $arrow_right_state = 1 166 | 167 | 168 | ; Action: Move Virtual Cursor in UP direction 169 | [KeyVirtualCursorUp] 170 | ; Xbox Gamepad Binding: 171 | key = XB_DPAD_UP 172 | ; Keyboard Binding: 173 | key = SHIFT ALT W 174 | ;------------------------------------------ 175 | ; Input Configuration: 176 | type = hold 177 | $arrow_top_state = 1 178 | 179 | 180 | ; Action: Move Virtual Cursor in DOWN direction 181 | [KeyVirtualCursorDown] 182 | ; Edit the line below to change key binding: 183 | key = XB_DPAD_DOWN 184 | ; Keyboard Binding: 185 | key = SHIFT ALT S 186 | ;------------------------------------------ 187 | ; Input Configuration: 188 | type = hold 189 | $arrow_down_state = 1 190 | 191 | 192 | 193 | ;================================================================================================= 194 | ;= DO NOT EDIT THE CODE BELOW IF YOU'RE NOT SURE WHAT YOU'RE DOING!!! 195 | ;================================================================================================= 196 | 197 | ; Constants ------------------------- 198 | 199 | [Constants] 200 | global $initialized = 0 201 | 202 | global $cursor_sensivity_x = 0 203 | global $cursor_sensivity_y = 0 204 | 205 | global $toggle_gui = 0 206 | global $mouse_left_state = 0 207 | global $mouse_left_counter = 1 208 | global $mouse_right_state = 0 209 | global $mouse_right_counter = 1 210 | global $mouse_mid_state = 0 211 | global $mouse_mid_counter = 1 212 | global $mouse_backward_state = 0 213 | global $mouse_backward_counter = 1 214 | global $mouse_forward_state = 0 215 | global $mouse_forward_counter = 1 216 | 217 | global $virtual_cursor_hide_cooldown = 0 218 | global $arrow_left_state = 0 219 | global $arrow_right_state = 0 220 | global $arrow_top_state = 0 221 | global $arrow_down_state = 0 222 | 223 | 224 | ; Present ------------------------- 225 | 226 | [Present] 227 | ; Load configuration values 228 | if $initialized == 0 229 | $initialized = 1 230 | run = CommandListSetupConfiguration 231 | endif 232 | 233 | ; Update states of buttons in TileGUI.ini 234 | ; Button state is encoded in a following way: 235 | ; * Each button press increases counter's absolute value by 1 236 | ; * When button is DOWN (held aka pressed), counter value is positive 237 | ; * When button is UP (released), counter value is negative 238 | ; This way client .ini may easily detect: 239 | ; * Button state changes 240 | ; local $last_mouse_left_state 241 | ; if $last_mouse_left_state != $\TileGUI\mouse_left 242 | ; ; Do something if button state changed 243 | ; endif 244 | ; * Button state 245 | ; if $\TileGUI\mouse_left < 0 246 | ; ; Do something if button is UP 247 | ; else 248 | ; ; Do something if button is DOWN 249 | ; endif 250 | ; * Arbitrary amount of presses within timeframe (i.e. double clicks) 251 | ; local $first_press_time 252 | ; local $first_press_state 253 | ; local $abs_state = ($\TileGUI\mouse_left**2)**(1/2) 254 | ; if time - $first_press_time < 0.500 255 | ; if $abs_state - $first_press_state >= 1 256 | ; ; Do something if left mouse button was pressed 2 times within 500ms interval 257 | ; endif 258 | ; else 259 | ; $first_press_time = time 260 | ; $first_press_state = $abs_state 261 | ; endif 262 | local $prev_mouse_left_state 263 | if $mouse_left_state != $prev_mouse_left_state 264 | $prev_mouse_left_state = $mouse_left_state 265 | if $mouse_left_state == 0 266 | $\TileGUI\mouse_left = -$mouse_left_counter 267 | else 268 | $\TileGUI\mouse_left = $mouse_left_counter 269 | endif 270 | endif 271 | local $prev_mouse_right_state 272 | if $mouse_right_state != $prev_mouse_right_state 273 | $prev_mouse_right_state = $mouse_right_state 274 | if $mouse_right_state == 0 275 | $\TileGUI\mouse_right = -$mouse_right_counter 276 | else 277 | $\TileGUI\mouse_right = $mouse_right_counter 278 | endif 279 | endif 280 | local $prev_mouse_mid_state 281 | if $mouse_mid_state != $prev_mouse_mid_state 282 | $prev_mouse_mid_state = $mouse_mid_state 283 | if $mouse_mid_state == 0 284 | $\TileGUI\mouse_mid = -$mouse_mid_counter 285 | else 286 | $\TileGUI\mouse_mid = $mouse_mid_counter 287 | endif 288 | endif 289 | local $prev_mouse_forward_state 290 | if $mouse_forward_state != $prev_mouse_forward_state 291 | $prev_mouse_forward_state = $mouse_forward_state 292 | if $mouse_forward_state == 0 293 | $\TileGUI\mouse_forward = -$mouse_forward_counter 294 | else 295 | $\TileGUI\mouse_forward = $mouse_forward_counter 296 | endif 297 | endif 298 | local $prev_mouse_backward_state 299 | if $mouse_backward_state != $prev_mouse_backward_state 300 | $prev_mouse_backward_state = $mouse_backward_state 301 | if $mouse_backward_state == 0 302 | $\TileGUI\mouse_backward = -$mouse_backward_counter 303 | else 304 | $\TileGUI\mouse_backward = $mouse_backward_counter 305 | endif 306 | endif 307 | local $prev_toggle_gui 308 | if $toggle_gui != $prev_toggle_gui 309 | $prev_toggle_gui = $toggle_gui 310 | $\TileGUI\toggle_gui = $toggle_gui 311 | endif 312 | 313 | 314 | ; Update Virtual Cursor coords in TileGUI.ini based on pressed arrow buttons 315 | if time > $virtual_cursor_hide_cooldown 316 | if $arrow_left_state == 1 317 | $\TileGUI\virtual_cursor_x = $\TileGUI\virtual_cursor_x - 10 * $cursor_sensivity_x 318 | endif 319 | if $arrow_right_state == 1 320 | $\TileGUI\virtual_cursor_x = $\TileGUI\virtual_cursor_x + 10 * $cursor_sensivity_x 321 | endif 322 | if $arrow_top_state == 1 323 | $\TileGUI\virtual_cursor_y = $\TileGUI\virtual_cursor_y + 10 * $cursor_sensivity_y 324 | endif 325 | if $arrow_down_state == 1 326 | $\TileGUI\virtual_cursor_y = $\TileGUI\virtual_cursor_y - 10 * $cursor_sensivity_y 327 | endif 328 | endif 329 | 330 | 331 | ; Button Handlers ------------------------- 332 | 333 | [CommandListHandleMouseLeft] 334 | $mouse_left_counter = $mouse_left_counter + 1 335 | 336 | 337 | [CommandListHandleMouseRight] 338 | $mouse_right_counter = $mouse_right_counter + 1 339 | 340 | 341 | [CommandListHandleMouseMid] 342 | $mouse_mid_counter = $mouse_mid_counter + 1 343 | 344 | 345 | [CommandListHandleMouseBackward] 346 | $mouse_backward_counter = $mouse_backward_counter + 1 347 | 348 | 349 | [CommandListHandleMouseForward] 350 | $mouse_forward_counter = $mouse_forward_counter + 1 351 | 352 | 353 | [CommandListHideVirtualCursor] 354 | $virtual_cursor_hide_cooldown = time + 1 355 | $\TileGUI\virtual_cursor_x = -1 356 | $\TileGUI\virtual_cursor_y = -1 357 | 358 | 359 | ; EOF ------------------------- 360 | --------------------------------------------------------------------------------