9 Commits

Author SHA1 Message Date
MrMelbert 750ca9d2ec Two as anything greps (and some other cleanup) (#92974) 2025-09-20 13:44:28 -04:00
itsmeow 23816b8ef2 Bumps rust_g to 4.0.0 / IconForge Improvements (#92333) 2025-07-30 22:51:23 -06:00
Bloop 4250ecb14c Removes a couple of duplicate gag map_icons + fixes the gags_recolorable component + most lootpanel gags previews (#91341)
## About The Pull Request

Turns out there were a couple of black mask subtypes that I missed as
well as a prisoner uniform subtype.

Also fixes some bugs that are not related to the map icon pr to further
improve the situation with GAGS previews.

## Why It's Good For The Game

Smaller .dmis, working previews

## Changelog

🆑
fix: spraycan can now be used to recolor the gi, glow shoes, striped
dress, H.E.C.K. suit
fix: most GAGS items should now be showing up in the lootpanel again
/🆑
2025-06-01 19:44:15 -07:00
Bloop cb51a652a9 Adds automatic GAGS icon generation for mapping and the loadout menu (#90940)
## About The Pull Request

Revival of https://github.com/tgstation/tgstation/pull/86482, which is
even more doable now that we have rustg iconforge generation.

What this PR does:

- Sets up every single GAGS icon in the game to have their own preview
icon autogenerated during compile. This is configurable to not run
during live. The icons are created in `icons/map_icons/..`
- This also has the side effect of providing accurate GAGS icons for
things like the loadout menu. No more having to create your own
previews.


![FOuGL6ofxC](https://github.com/user-attachments/assets/e5414971-7f13-4883-9f7f-a8a212b46fe8)

<details><summary>Mappers rejoice!</summary>


![StrongDMM_1oeMSoRHXT](https://github.com/user-attachments/assets/83dcfe4c-31be-4953-98f3-dff90268bbc4)


![StrongDMM_uyqu3CggPn](https://github.com/user-attachments/assets/7896f99e-2656-40e1-a9da-3a513882365a)

</details>

<details><summary>Uses iconforge so it does not take up much time during
init</summary>


![dreamdaemon_u4Md3Dqwge](https://github.com/user-attachments/assets/17baaff8-5d5e-4a4d-ba8f-9dd548024155)

</details>

---

### Copied from https://github.com/tgstation/tgstation/pull/86482 as
this still applies:

Note for Spriters:

After you've assigned the correct values to vars, you must run the game
through init on your local machine and commit the changes to the map
icon dmi files. Unit tests should catch all cases of forgetting to
assign the correct vars, or not running through init.

Note for Server Operators:

In order to not generate these icons on live I've added a new config
entry which should be disabled on live called GENERATE_ASSETS_IN_INIT in
the config.txt


## Why It's Good For The Game

No more error icons in SDMM and loadout.

## Changelog

🆑
refactor: preview icons for greyscale items are now automatically
generated, meaning you can see GAGS as they actually appear ingame while
mapping or viewing the loadout menu.
/🆑

---------

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
2025-05-24 15:21:02 -07:00
Watermelon914 6c017cf1e1 Refactors subsystems to use dependency-ordering to determine init order. Subsystems can now declare their own dependencies. (#90268)
## About The Pull Request
As the title says.
`init_order` is no more, subsystems ordering now depends on their
declared dependencies.
Subsystems can now declare which other subsystems need to init before
them using a list and the subsystem's typepath
I.e.
```dm
dependencies = list(
    /datum/controller/subsystem/atoms,
    /datum/controller/subsystem/mapping
)
```
The reverse can also be done, if a subsystem must initialize after your
own:
```dm
dependents = list(
    /datum/controller/subsystem/atoms
)
```
Cyclical dependencies are not allowed and will throw an error on
initialization if one is found.
There's also a debug tool to visualize the dependency graph, although
it's a bit basic:

![image](https://github.com/user-attachments/assets/80c854d9-c2a5-4f2f-92db-a031e9a8e257)

Subsystem load ordering can still be controlled using `init_stage`, some
subsystems use this in cases where they must initialize first or last
regardless of dependencies. An error will be thrown if a subsystem has
an `init_stage` before one of their dependencies.

## Why It's Good For The Game
Makes dealing with subsystem dependencies easier, and reduces the chance
of making a dependency error when needing to shift around subsystem
inits.

## Changelog
🆑
refactor: Refactored subsystem initialization
/🆑
2025-04-03 17:04:30 -04:00
itsmeow 93a2b723da IconForge: rust-g GAGS (250x faster edition) (#89590)
## About The Pull Request

Offloads GAGS generation to rust-g IconForge.

**Key Notes**

- The builtin GAGS editor still uses the 'legacy' generation to allow
for debugging.
- Does not support `color_matrix` layer type, which is currently not
used by any GAGS configs. Will do nothing if used.
- Does not support `or` blending mode, which is currently not used by
any GAGS configs. Will error if used.
- Has some 'quirks' compared to BYOND when it comes to mixing icon
states with different dir/frame amounts. BYOND will just silently handle
these and it's basically undefined behavior because what should you
expect BYOND to do? IconForge will spit errors out instead. So this PR
also fixes a few of those cases.

Functions by writing output to `tmp/gags/gags-[...].dmi`, copying that
output into the RSC and assigning the file object to `icon`.

Saves ~1.7s init by reducing worst-case GAGS icon generation from 250ms
to 1ms.

Also optimizes `icon_exists` by using `rustg_dmi_icon_states` for file
icons, saving ~60ms. Would have more savings if not for json_decode as
well as DMI parsing in rust being somewhat slow. Perhaps having
`rustg_dmi_icon_states` share a cache with IconForge could reduce this
cost, however I'd still recommend limiting these tests to unit tests
(https://github.com/tgstation/dev-cycles-initiative/issues/34),
especially for GAGS configs. I'm not sure they're worth 700ms.

Saves another ~400ms by replacing `md5asfile` with `rustg_hash_file` in
`/datum/greyscale_config/proc/Refresh`

Savings are likely even higher when combined with #89478, due to
spritesheets sharing a parsed DMI cache with GAGS. This means GAGS will
spend less time parsing icons synchronously and can generate output
faster. Tracy tests with this combo seem to yield ~2sec savings instead
of ~1.7sec

Total savings: ~2.16sec to ~2.46sec

- Ports https://github.com/BeeStation/BeeStation-Hornet/pull/10455
- Resolves https://github.com/tgstation/dev-cycles-initiative/issues/9



## Why It's Good For The Game

GAGS go zoooom

<details>
<summary>GAGS Working Ingame</summary>


![image](https://github.com/user-attachments/assets/28df25a5-bdf0-4a63-a6cf-b15f85467b23)


![image](https://github.com/user-attachments/assets/6a9dab46-5814-47ea-ad9b-f5ec84a6333d)

</details>

<details>
<summary>GetColoredIconByType</summary>


![image](https://github.com/user-attachments/assets/1698729f-1101-4413-bfb3-0922b389c347)

</details>

<details>
<summary>icon_exists</summary>


![image](https://github.com/user-attachments/assets/9e72c6aa-287f-4ce3-8dbe-9d3bebf3a762)

</details>


<details>
<summary>Refresh</summary>


![image](https://github.com/user-attachments/assets/18c15073-a294-4db6-bdd0-cdc7d8682221)

</details>


## Changelog
🆑
tweak: Optimized GAGS using rust-g IconForge, reducing worst-case
generation time to 1ms
/🆑
2025-03-13 20:59:12 -04:00
itsmeow cc335e7e9e IconForge: rust-g Spritesheet Generation (#89478)
## About The Pull Request

Replaces the asset subsystem's spritesheet generator with a rust-based
implementation (https://github.com/tgstation/rust-g/pull/160).

This is a rough port of
https://github.com/BeeStation/BeeStation-Hornet/pull/10404, but it
includes fixes for some cases I didn't catch that apply on TG.

(FWIW we've been using this system on prod for over a year and
encountered no major issues.)

### TG MAINTAINER NOTE


![image](https://github.com/user-attachments/assets/53bd2b44-9bb5-42d2-b33f-093651edebc0)

### Batched Spritesheets

`/datum/asset/spritesheet_batched`: A version of the spritesheet system
that collects a list of `/datum/universal_icon`s and sends them off to
rustg asynchronously, and the generation also runs on another thread, so
the game doesn't block during realize_spritesheet. The rust generation
is about 10x faster when it comes to actual icon generation, but the
biggest perk of the batched spritesheets is the caching system.

This PR notably does not convert a few things to the new spritesheet
generator.

- Species and antagonist icons in the preferences view because they use
getFlatIcon ~~which can't be converted to universal icons~~.
- Yes, this is still a *massive* cost to init, unfortunately. On Bee, I
actually enabled the 'legacy' cache on prod and development, which you
can see in my PR. That's why I added the 'clear cache' verb and the
`unregister()` procs, because it can force a regeneration at runtime. I
decided not to port this, since I think it would be detrimental to the
large amount of contributors here.
- It is *technically* possible to port parts of this to the uni_icon
system by making a uni_icon version of getFlatIcon. However, some
overlays use runtime-generated icons which are ~~completely unparseable
to IconForge, since they're stored in the RSC and don't exist as files
anywhere~~. This is most noticeable with things like hair (which blend
additively with the hair mask on the server, thus making them invisible
to `get_flat_uni_icon`). It also doesn't help that species and antag
icons will still need to generate a bunch of dummies and delete them to
even verify cache validity.
- It is actually possible to write the RSC icons to the filesystem
(using fcopy) and reference them in IconForge. However, I'm going to
wait on doing this until I port my GAGS implementation because it
requires GAGS to exist on the filesystem as well.

#### Caching

IconForge generates a cache based on the set of icons used, all
transform operations applied, and the source DMIs of each icon used
within the spritesheet. It can compare the hashes and invalidate the
cache automatically if any of these change. This means we can enable
caching on development, and have absolutely no downsides, because if
anything changes, the cache invalidates itself.

The caching has a mean cost of ~5ms and saves a lot of time compared to
generating the spritesheet, even with rust's faster generation. The main
downside is that the cache still requires building the list of icons and
their transforms, then json encoding it to send to rustg.

Here's an abbreviated example of a cache JSON. All of these need to
match for the cache to be valid. `input_hash` contains the transform
definitions for all the sprites in the spritesheet, so if the input to
iconforge changes, that hash catches it. The `sizes` and `sprites` are
loaded into DM.

```json
{
	"input_hash": "99f1bc67d590e000",
	"dmi_hashes": {
		"icons/ui/achievements/achievements.dmi": "771200c75da11c62"
	},
	"sizes": [
		"76x76"
	],
	"sprites": {
		"achievement-rustascend": {
			"size_id": "76x76",
			"position": 1
		}
	},
	"rustg_version": "3.6.0",
	"dm_version": 1
}
```

### Universal Icons

Universal icons are just a collection of DMI, Icon State, and any icon
transformation procs you apply (blends, crops, scales). They can be
convered to DM icons via `to_icon()`. I've included an implementation of
GAGS that produces universal icons, allowing GAGS items to be converted
into them. IconForge can read universal icons and add them to
spritesheets. It's basically just a wrapper that reimplements BYOND icon
procs.

### Other Stuff

Converts some uses of md5asfile within legacy spritesheets to use
rustg_hash_file instead, improving the performance of their generation.

Fixes lizard body markings not showing in previews, and re-adds eyes to
the ethereal color preview. This is a side effect of IconForge having
*much* better error handling than DM icon procs. Invalid stuff that gets
passed around will error instead of silently doing nothing.

Changes the CSS used in legacy spritesheet generation to split
`background: url(...) no-repeat` into separate props. This is necessary
for WebView2, as IE treats these properties differently - adding
`background-color` to an icon object (as seen in the R&D console) won't
work if you don't split these out.

Deletes unused spritesheets and their associated icons (condiments
spritesheet, old PDA spritesheet)

## Why It's Good For The Game

If you press "Character Setup", the 10-13sec of lag is now approximately
0.5-2 seconds.

Tracy profile showing the time spent on get_asset_datum. I pressed the
preferences button during init on both branches. Do note that this was
ran with a smart cache HIT, so no generation occurred.


![image](https://github.com/user-attachments/assets/3efa71ab-972b-4f5a-acab-0892496ef999)

Much lower worst-case for /datum/asset/New (which includes
`create_spritesheets()` and `register()`)


![image](https://github.com/user-attachments/assets/9ad8ceee-7bd6-4c48-b5f3-006520f527ef)

Here's a look at the internal costs from rustg - as you can see
`generate_spritesheet()` is very fast:


![image](https://github.com/user-attachments/assets/e6892c28-8c31-4af5-96d4-501e966d0ce9)

### Comparison for a single spritesheet - chat spritesheet:

**Before**


![image](https://github.com/user-attachments/assets/cbd65787-42ba-4278-a45c-bd3d538da986)

**After**


![image](https://github.com/user-attachments/assets/d750899a-bd07-4b57-80fb-420fcc0ae416)

## Changelog

🆑
fix: Fixed lizard body markings and ethereal feature previews in the
preference menu missing some overlays.
refactor: Optimized spritesheet asset generation greatly using rustg
IconForge, greatly reducing post-initialization lag as well as reducing
init times and saving server computation.
config: Added 'smart' asset caching, for batched rustg IconForge
spritesheets. It is persistent and suitable for use on local, with
automatic invalidation.
add: Added admin verbs - Debug -> Clear Smart/Legacy Asset Cache for
spritesheets.
fix: Fixed R&D console icons breaking on WebView2/516
/🆑
2025-03-03 14:58:27 +01:00
Tastyfish 4733643f39 Clean up subsystem Initialize(), require an explicit result returned, give a formal way to fail (for SSlua) (#69775)
* cleanup SS API, give SSlua a proper way to error out

* New SS_INIT_ system
2022-09-14 23:52:10 -04:00
Emmett Gaines 04dfcc6559 GAGS fix + debug improvements I needed to find it (#60819)
This fix was one hell of a debug journey. Icon.Insert() was the issue here but I'm not sure if it counts as byond bug in this particular case. When you insert a single frame icon, if an existing icon state of the same name exists normally it would be overridden. However different things happen if the icon that gets overridden has multiple frames. I'm not fully sure of the different behaviors but depending on what the icons consisted of you could get animated sprites where every frame was the same or appending frames to animated sprites in strange ways.

This has been fixed by making sure no Inserts are overriding existing icon states so that the strange behavior doesn't have to be dealt with.

The GAGS debug menu has been upgraded a bit on the way to fixing this bug. A toggle to automatically refresh icons when the dmi or json configuration are updated has been added and the step by step preview will only show steps now involved in the creation of the icon state you select.
2021-09-16 23:55:12 +01:00