Skip to content

Commit f95e240

Browse files
authored
Converts some more things to DMIcon (#3808)
* [PORT] Makes vending use DMIcon where possible, halving the time it takes to make the vending spritesheet Ports tgstation/tgstation#85085 from /tg/station, originally by MrMelbert. * [PORT] Chem master containers use DMIcon Ports tgstation/tgstation#85422 from /tg/station, originally by MTandi. * Loadout shop now uses DMIcon * Properly centers the Sunset Sarsaparilla icon * Fix bodycams showing a loading icon in the sec vendor
1 parent 0352150 commit f95e240

File tree

11 files changed

+127
-75
lines changed

11 files changed

+127
-75
lines changed

code/__HELPERS/icons.dm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1164,7 +1164,7 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)
11641164
if(!istext(icon_path) || !length(icon_path))
11651165
return FALSE
11661166

1167-
var/is_in_icon_folder = findtextEx(icon_path, "icons/")
1167+
var/is_in_icon_folder = findtextEx(icon_path, "icons/") || findtextEx(icon_path, "monkestation/") // STOP PUTTING ICONS IN THE `monkestation/code` FOLDER FFS
11681168
var/is_dmi_file = findtextEx(icon_path, ".dmi")
11691169

11701170
if(is_in_icon_folder && is_dmi_file)

code/modules/asset_cache/assets/vending.dm

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,28 @@
66
var/target_items = list()
77
for(var/obj/machinery/vending/vendor as anything in typesof(/obj/machinery/vending))
88
vendor = new vendor() // It seems `initial(list var)` has nothing. need to make a type.
9-
for(var/each in list(vendor.products, vendor.premium, vendor.contraband))
10-
target_items |= each
9+
target_items |= vendor.products
10+
target_items |= vendor.premium
11+
target_items |= vendor.contraband
1112
qdel(vendor)
1213

1314
// building icons for each item
14-
for (var/k in target_items)
15-
var/atom/item = k
15+
for (var/atom/item as anything in target_items)
1616
if (!ispath(item, /atom))
1717
continue
1818

1919
var/icon_file
20-
if (initial(item.greyscale_colors) && initial(item.greyscale_config))
20+
var/icon_state = initial(item.icon_state)
21+
var/icon_color = initial(item.color)
22+
// GAGS icons must be pregenerated
23+
if(initial(item.greyscale_config) && initial(item.greyscale_colors))
2124
icon_file = SSgreyscale.GetColoredIconByType(initial(item.greyscale_config), initial(item.greyscale_colors))
22-
else
25+
// Colored atoms must be pregenerated
26+
else if(icon_color && icon_state)
2327
icon_file = initial(item.icon)
24-
var/icon_state = initial(item.icon_state)
28+
// Otherwise we can rely on DMIcon, so skip it to save init time
29+
else
30+
continue
2531

2632
if (PERFORM_ALL_TESTS(focus_only/invalid_vending_machine_icon_states))
2733
var/icon_states_list = icon_states(icon_file)
@@ -36,11 +42,10 @@
3642
stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)]([text_ref(icon_state)]), icon_states=[icon_states_string]")
3743
continue
3844

39-
var/icon/I = icon(icon_file, icon_state, SOUTH)
40-
var/c = initial(item.color)
41-
if (!isnull(c) && c != "#FFFFFF")
42-
I.Blend(c, ICON_MULTIPLY)
45+
var/icon/produced = icon(icon_file, icon_state, SOUTH)
46+
if (!isnull(icon_color) && icon_color != COLOR_WHITE)
47+
produced.Blend(icon_color, ICON_MULTIPLY)
4348

4449
var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-")
4550

46-
Insert(imgid, I)
51+
Insert(imgid, produced)

code/modules/reagents/chemistry/machinery/chem_master.dm

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,6 @@ GLOBAL_LIST_INIT(chem_master_containers, list(
214214
CAT_PATCHES = GLOB.chem_master_containers[CAT_PATCHES],
215215
)
216216

217-
/obj/machinery/chem_master/ui_assets(mob/user)
218-
return list(
219-
get_asset_datum(/datum/asset/spritesheet/chemmaster)
220-
)
221-
222217
/obj/machinery/chem_master/ui_interact(mob/user, datum/tgui/ui)
223218
ui = SStgui.try_update_ui(user, src, ui)
224219
if(!ui)
@@ -232,7 +227,8 @@ GLOBAL_LIST_INIT(chem_master_containers, list(
232227
var/container_data = list()
233228
for(var/obj/item/reagent_containers/container as anything in printable_containers[category])
234229
container_data += list(list(
235-
"icon" = sanitize_css_class_name("[container]"),
230+
"icon" = initial(container.icon),
231+
"icon_state" = initial(container.icon_state),
236232
"ref" = REF(container),
237233
"name" = initial(container.name),
238234
"volume" = initial(container.volume),

code/modules/vending/_vending.dm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,15 @@
11411141
ref = REF(record),
11421142
)
11431143

1144+
var/atom/printed = record.product_path
1145+
// If it's not GAGS and has no innate colors we have to care about, we use DMIcon
1146+
if(ispath(printed, /atom) \
1147+
&& (!initial(printed.greyscale_config) || !initial(printed.greyscale_colors)) \
1148+
&& !initial(printed.color) \
1149+
)
1150+
static_record["icon"] = initial(printed.icon)
1151+
static_record["icon_state"] = initial(printed.icon_state)
1152+
11441153
var/list/category = record.category || default_category
11451154
if (!isnull(category))
11461155
if (!(category["name"] in categories))

monkestation/code/modules/asset_cache/assets/loadout_store.dm

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
if(!store_item::name || !store_item::item_path)
88
continue
99
var/obj/item_type = store_item::item_path
10+
if(!should_generate_icon(item_type))
11+
continue
1012
var/id = sanitize_css_class_name("[item_type]")
1113
if(id_list[id])
1214
continue
13-
var/icon/item_icon = generate_icon_for_item(item_type)
15+
var/icon/item_icon = icon(SSgreyscale.GetColoredIconByType(item_type::greyscale_config, item_type::greyscale_colors), item_type::icon_state)
1416
if(!item_icon)
1517
stack_trace("Failed to generate icon for [item_type]")
1618
continue
@@ -20,29 +22,9 @@
2022
Insert(id, item_icon)
2123
id_list[id] = TRUE
2224

23-
/datum/asset/spritesheet/loadout_store/proc/generate_icon_for_item(obj/item/item) as /icon
24-
RETURN_TYPE(/icon)
25-
var/icon_file = item::icon_preview || item::icon
26-
var/icon_state = item::icon_state_preview || item::icon_state
27-
var/has_gags_config = item::greyscale_config && item::greyscale_colors
28-
var/has_preview_icon = item::icon_preview && item::icon_state_preview
29-
if(has_gags_config && !has_preview_icon) // preview icons take priority over GAGS
30-
var/icon/gags_icon = SSgreyscale.GetColoredIconByType(item::greyscale_config, item::greyscale_colors)
31-
return icon(gags_icon, item::icon_state)
32-
else if(icon_exists(icon_file, icon_state))
33-
var/icon/item_icon = icon(
34-
icon_file,
35-
icon_state,
36-
dir = SOUTH,
37-
frame = 1,
38-
moving = FALSE,
39-
)
40-
return icon(fcopy_rsc(item_icon))
41-
else
42-
var/obj/item/dummy_item = new item
43-
var/icon/flat_icon = getFlatIcon(dummy_item)
44-
if(!flat_icon)
45-
CRASH("Failed to generate any icon for [item]")
46-
var/icon/cached_icon = icon(fcopy_rsc(flat_icon))
47-
qdel(dummy_item)
48-
return cached_icon
25+
/datum/asset/spritesheet/loadout_store/proc/should_generate_icon(obj/item/item)
26+
if(item::icon_preview && item::icon_state_preview)
27+
return FALSE
28+
if(item::greyscale_config && item::greyscale_colors)
29+
return TRUE
30+
return FALSE

monkestation/code/modules/store/store_items/__store.dm

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,16 +182,21 @@ GLOBAL_LIST_EMPTY(all_store_datums)
182182
if(item.hidden)
183183
formatted_list.len--
184184
continue
185+
var/obj/item/item_type = item.item_path
185186
var/list/formatted_item = list(
186187
"name" = item.name,
187188
"path" = item.item_path,
188189
"cost" = item.item_cost,
189-
"desc" = item.item_path::desc,
190-
"icon" = sanitize_css_class_name("[item.item_path]"),
190+
"desc" = item_type::desc,
191191
"job_restricted" = null,
192192
)
193+
if((item_type::icon_preview && item_type::icon_state_preview) || !(item_type::greyscale_config && item_type::greyscale_colors))
194+
formatted_item["icon"] = item_type::icon_preview || item_type::icon
195+
formatted_item["icon_state"] = item_type::icon_state_preview || item_type::icon_state
196+
else
197+
formatted_item["icon"] = sanitize_css_class_name("[item_type]")
193198

194-
var/datum/loadout_item/selected = GLOB.all_loadout_datums[item.item_path]
199+
var/datum/loadout_item/selected = GLOB.all_loadout_datums[item_type]
195200
if(length(selected?.restricted_roles))
196201
formatted_item["job_restricted"] = selected.restricted_roles.Join(", ")
197202

-246 Bytes
Binary file not shown.

tgui/packages/tgui/interfaces/ChemMaster.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import { BooleanLike, classes } from 'common/react';
1+
import { BooleanLike } from 'common/react';
22
import { capitalize } from 'common/string';
33
import { useBackend, useLocalState } from '../backend';
44
import {
55
AnimatedNumber,
66
Box,
77
Button,
8+
DmIcon,
9+
Icon,
810
Section,
911
Table,
1012
NumberInput,
@@ -64,6 +66,7 @@ type Reagent = {
6466

6567
type Container = {
6668
icon: string;
69+
icon_state: string;
6770
ref: string;
6871
name: string;
6972
volume: number;
@@ -366,6 +369,8 @@ const ContainerButton = ({ container, category }) => {
366369
const { act, data } = useBackend<Data>();
367370
const { isPrinting, selectedContainerRef } = data;
368371
const isPillPatch = ['pills', 'patches'].includes(category.name);
372+
const fallback = <Icon m="18px" name="spinner" spin />;
373+
const fallbackPillPatch = <Icon m="10px" name="spinner" spin />;
369374
return (
370375
<Tooltip
371376
key={container.ref}
@@ -385,12 +390,13 @@ const ContainerButton = ({ container, category }) => {
385390
});
386391
}}
387392
>
388-
<Box
389-
m={isPillPatch ? '0' : '8px'}
390-
style={{
391-
transform: 'scale(2)',
392-
}}
393-
className={classes(['chemmaster32x32', container.icon])}
393+
<DmIcon
394+
m={isPillPatch ? '-16px' : '-8px'}
395+
fallback={isPillPatch ? fallbackPillPatch : fallback}
396+
icon={container.icon}
397+
icon_state={container.icon_state}
398+
height="64px"
399+
width="64px"
394400
/>
395401
</Button>
396402
</Tooltip>

tgui/packages/tgui/interfaces/PreferencesMenu/data.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ type LoadoutData = {
195195
type LoadoutItem = {
196196
name: string;
197197
icon: string;
198+
icon_state?: string;
198199
desc: string;
199200
cost: number;
200201
item_path: string;

tgui/packages/tgui/interfaces/StoreManager.tsx

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
import { useBackend, useSharedState } from '../backend';
2-
import { Box, Button, Section, Stack, Tabs, Table } from '../components';
2+
import {
3+
Box,
4+
Button,
5+
DmIcon,
6+
Section,
7+
Stack,
8+
Tabs,
9+
Table,
10+
Icon,
11+
} from '../components';
312
import { PreferencesMenuData } from './PreferencesMenu/data';
413
import { Window } from '../layouts';
514
import { classes } from 'common/react';
@@ -69,13 +78,27 @@ export const StoreManager = (props) => {
6978
backgroundColor={index % 2 === 0 ? '#19181e' : '#16151b'}
7079
>
7180
<Table.Cell>
72-
<Box
73-
inline
74-
verticalAlign="middle"
75-
width={'32px'}
76-
height={'32px'}
77-
className={classes(['loadout_store32x32', item.icon])}
78-
/>
81+
{item.icon && item.icon_state ? (
82+
<DmIcon
83+
icon={item.icon}
84+
icon_state={item.icon_state}
85+
verticalAlign="middle"
86+
height={'32px'}
87+
width={'32px'}
88+
fallback={<Icon name="spinner" size={2} spin />}
89+
/>
90+
) : (
91+
<Box
92+
inline
93+
verticalAlign="middle"
94+
width={'32px'}
95+
height={'32px'}
96+
className={classes([
97+
'loadout_store32x32',
98+
item.icon,
99+
])}
100+
/>
101+
)}
79102
</Table.Cell>
80103
<Table.Cell>
81104
<Button

tgui/packages/tgui/interfaces/Vending.tsx

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useBackend, useLocalState } from 'tgui/backend';
44
import {
55
Box,
66
Button,
7+
DmIcon,
78
Icon,
89
LabeledList,
910
NoticeBox,
@@ -39,6 +40,8 @@ type ProductRecord = {
3940
max_amount: number;
4041
ref: string;
4142
category: string;
43+
icon?: string;
44+
icon_state?: string;
4245
};
4346

4447
type CoinRecord = ProductRecord & {
@@ -242,20 +245,22 @@ const VendingRow = (props) => {
242245
(discount ? redPrice : product.price) > user?.cash);
243246

244247
return (
245-
<Table.Row>
246-
<Table.Cell collapsing>
248+
<Table.Row height="32px">
249+
<Table.Cell collapsing width="36px">
247250
<ProductImage product={product} />
248251
</Table.Cell>
249-
<Table.Cell bold>{capitalizeAll(product.name)}</Table.Cell>
250-
<Table.Cell>
252+
<Table.Cell verticalAlign="middle" bold>
253+
{capitalizeAll(product.name)}
254+
</Table.Cell>
255+
<Table.Cell verticalAlign="middle">
251256
{!!productStock?.colorable && (
252257
<ProductColorSelect disabled={disabled} product={product} />
253258
)}
254259
</Table.Cell>
255-
<Table.Cell collapsing textAlign="right">
260+
<Table.Cell collapsing textAlign="right" verticalAlign="middle">
256261
<ProductStock custom={custom} product={product} remaining={remaining} />
257262
</Table.Cell>
258-
<Table.Cell collapsing textAlign="center">
263+
<Table.Cell collapsing textAlign="center" verticalAlign="middle">
259264
<ProductButton
260265
custom={custom}
261266
disabled={disabled}
@@ -273,13 +278,32 @@ const VendingRow = (props) => {
273278
const ProductImage = (props) => {
274279
const { product } = props;
275280

276-
return product.img ? (
277-
<img src={`data:image/jpeg;base64,${product.img}`} />
278-
) : (
279-
<span className={classes(['vending32x32', product.path])} />
281+
return (
282+
<Box width="32px" height="32px">
283+
{product.img ? (
284+
<img
285+
src={`data:image/jpeg;base64,${product.img}`}
286+
style={{
287+
'vertical-align': 'middle',
288+
}}
289+
/>
290+
) : product.icon && product.icon_state ? (
291+
<DmIcon
292+
icon={product.icon}
293+
icon_state={product.icon_state}
294+
fallback={<Icon name="spinner" size={2} spin />}
295+
/>
296+
) : (
297+
<span
298+
className={classes(['vending32x32', product.path])}
299+
style={{
300+
'vertical-align': 'middle',
301+
}}
302+
/>
303+
)}
304+
</Box>
280305
);
281306
};
282-
283307
/** In the case of customizable items, ie: shoes,
284308
* this displays a color wheel button that opens another window.
285309
*/
@@ -291,6 +315,7 @@ const ProductColorSelect = (props) => {
291315
<Button
292316
icon="palette"
293317
tooltip="Change color"
318+
width="24px"
294319
disabled={disabled}
295320
onClick={() => act('select_colors', { ref: product.ref })}
296321
/>

0 commit comments

Comments
 (0)