Skip to content

Commit 6744a3a

Browse files
authored
Makes alt-click more responsive and fixes its item handling (ParadiseSS13#31366)
* make alt click inspect responsive and fix a bug * switch to list operation wow
1 parent d153830 commit 6744a3a

2 files changed

Lines changed: 121 additions & 30 deletions

File tree

code/controllers/subsystem/SSstatpanel.dm

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,15 @@ SUBSYSTEM_DEF(statpanels)
112112
for(var/image/target_image as anything in target.images)
113113
if(!target_image.loc || target_image.loc.loc != target_mob.listed_turf || !target_image.override)
114114
continue
115-
overrides += target_image.loc
115+
overrides[target_image.loc] = TRUE
116116

117117
var/list/atoms_to_display = list(target_mob.listed_turf)
118118
for(var/atom/movable/turf_content as anything in target_mob.listed_turf)
119119
if(turf_content.mouse_opacity == MOUSE_OPACITY_TRANSPARENT)
120120
continue
121121
if(turf_content.invisibility > target_mob.see_invisible)
122122
continue
123-
if(turf_content in overrides)
123+
if(overrides[turf_content])
124124
continue
125125
if(turf_content.IsObscured())
126126
continue
@@ -129,6 +129,8 @@ SUBSYSTEM_DEF(statpanels)
129129
/// Set the atoms we're meant to display
130130
var/datum/object_window_info/obj_window = istype(target.obj_window) ? target.obj_window : new(target)
131131
obj_window.atoms_to_show = atoms_to_display
132+
// don't generate icons for stuff the user will not see
133+
obj_window.atoms_to_imagify &= atoms_to_display
132134
refresh_client_obj_view(target, obj_window.min_index, obj_window.max_index)
133135

134136
/datum/controller/subsystem/statpanels/proc/refresh_client_obj_view(client/refresh, min_index = 0, max_index = 30)
@@ -160,6 +162,8 @@ SUBSYSTEM_DEF(statpanels)
160162
var/list/turf_items = list()
161163
var/i = 0
162164
var/client_uid = load_from.UID()
165+
// While an item's icon is being generated, we send no image URL and let the frontend render an empty slot.
166+
var/static/no_image_url = ""
163167
for(var/atom/turf_item as anything in obj_window.atoms_to_show)
164168
// Limit what we send to the client's rendered section.
165169
i++
@@ -169,7 +173,11 @@ SUBSYSTEM_DEF(statpanels)
169173
// First, we fill up the list of refs to display
170174
// If we already have one, just use that
171175
var/existing_image = already_seen[turf_item]
176+
// rows that are still loading are still sent, we just won't send an image, frontend will hotswap it in
172177
if(existing_image == OBJ_IMAGE_LOADING)
178+
var/obj_m5_uid_loading = turf_item.MD5_UID()
179+
load_from.m5_uid_cache[obj_m5_uid_loading] = turf_item.unique_datum_id
180+
turf_items["[i]"] = list("[turf_item.name]", obj_m5_uid_loading, no_image_url, "", client_uid)
173181
continue
174182
// We already have it. Success!
175183

@@ -254,6 +262,10 @@ SUBSYSTEM_DEF(statpanels)
254262
var/client/parent
255263
/// Are we currently tracking a turf?
256264
var/actively_tracking = FALSE
265+
/// Turf we are currently listening to for content changes.
266+
var/turf/tracked_turf
267+
/// Debounce flag for immediate refreshes.
268+
var/pending_turf_refresh = FALSE
257269
/// The minimum index currently sent to the client.
258270
var/min_index = 0
259271
/// The maximum index currently sent to the client.
@@ -264,6 +276,9 @@ SUBSYSTEM_DEF(statpanels)
264276
src.parent = parent
265277

266278
/datum/object_window_info/Destroy(force, ...)
279+
if(tracked_turf)
280+
UnregisterSignal(tracked_turf, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_EXITED, COMSIG_TURF_CHANGE))
281+
tracked_turf = null
267282
atoms_to_show = null
268283
atoms_to_images = null
269284
atoms_to_imagify = null
@@ -303,6 +318,13 @@ SUBSYSTEM_DEF(statpanels)
303318
/datum/object_window_info/proc/start_turf_tracking()
304319
if(actively_tracking)
305320
stop_turf_tracking()
321+
var/turf/new_tracked = parent?.mob?.listed_turf
322+
if(new_tracked)
323+
// We're setting up signals here so updates are instant rather than laggy and slow.
324+
tracked_turf = new_tracked
325+
RegisterSignal(tracked_turf, COMSIG_ATOM_ENTERED, PROC_REF(on_tracked_turf_entered))
326+
RegisterSignal(tracked_turf, COMSIG_ATOM_EXITED, PROC_REF(on_tracked_turf_exited))
327+
RegisterSignal(tracked_turf, COMSIG_TURF_CHANGE, PROC_REF(on_tracked_turf_change))
306328
var/static/list/connections = list(
307329
COMSIG_MOVABLE_MOVED = PROC_REF(on_mob_move),
308330
COMSIG_MOB_LOGOUT = PROC_REF(on_mob_logout),
@@ -312,8 +334,38 @@ SUBSYSTEM_DEF(statpanels)
312334

313335
/datum/object_window_info/proc/stop_turf_tracking()
314336
DeleteComponent(/datum/component/connect_mob_behalf)
337+
if(tracked_turf)
338+
UnregisterSignal(tracked_turf, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_EXITED, COMSIG_TURF_CHANGE))
339+
tracked_turf = null
340+
pending_turf_refresh = FALSE
315341
actively_tracking = FALSE
316342

343+
/datum/object_window_info/proc/queue_listedturf_refresh()
344+
if(pending_turf_refresh)
345+
return
346+
pending_turf_refresh = TRUE
347+
// This accumulates all of our updates and does one refresh rather than calling a dozen refreshes when a dozen things change
348+
addtimer(CALLBACK(src, PROC_REF(do_listedturf_refresh)), 1)
349+
350+
/datum/object_window_info/proc/do_listedturf_refresh()
351+
pending_turf_refresh = FALSE
352+
if(!parent?.mob?.listed_turf)
353+
return
354+
// If the user moved away, let the existing adjacency logic close the tab.
355+
SSstatpanels.set_turf_examine_tab(parent, parent.mob)
356+
357+
/datum/object_window_info/proc/on_tracked_turf_entered(atom/source, atom/movable/entered, atom/old_loc)
358+
SIGNAL_HANDLER // COMSIG_ATOM_ENTERED
359+
queue_listedturf_refresh()
360+
361+
/datum/object_window_info/proc/on_tracked_turf_exited(atom/source, atom/movable/exiting, direction)
362+
SIGNAL_HANDLER // COMSIG_ATOM_EXITED
363+
queue_listedturf_refresh()
364+
365+
/datum/object_window_info/proc/on_tracked_turf_change(atom/source)
366+
SIGNAL_HANDLER // COMSIG_TURF_CHANGE
367+
queue_listedturf_refresh()
368+
317369
/datum/object_window_info/proc/on_mob_move(mob/source)
318370
SIGNAL_HANDLER
319371
var/turf/listed = source.listed_turf
@@ -330,7 +382,7 @@ SUBSYSTEM_DEF(statpanels)
330382
SIGNAL_HANDLER
331383
atoms_to_show -= deleted
332384
atoms_to_imagify -= deleted
333-
atoms_to_images -= deleted
385+
atoms_to_images[deleted] = null
334386

335387
/mob/proc/set_listed_turf(turf/new_turf)
336388
listed_turf = new_turf
@@ -347,3 +399,6 @@ SUBSYSTEM_DEF(statpanels)
347399
else
348400
client.stat_panel.send_message("remove_listedturf")
349401
client.obj_window.stop_turf_tracking()
402+
// Don't generate icons when the tab's closed.
403+
client.obj_window.atoms_to_show.Cut()
404+
client.obj_window.atoms_to_imagify.Cut()

html/statbrowser.js

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,12 @@ function listedturf_add_row(table, table_index, true_index) {
381381
turf_incomplete_rows[true_index] = true_index + 1;
382382
}
383383

384-
function listedturf_fill_row(row, item_index) {
384+
function listedturf_render_row(row, item_index) {
385+
// Clear any previous contents so we don't mess up list indices
386+
while (row.firstChild) {
387+
row.removeChild(row.firstChild);
388+
}
389+
385390
let object_info = turfcontents['' + item_index];
386391
if (!object_info) {
387392
return false;
@@ -428,32 +433,46 @@ function listedturf_fill_row(row, item_index) {
428433
cell.appendChild(button);
429434

430435
let img = document.createElement('img');
431-
img.id = object_info[1];
432-
img.src = object_info[2];
433-
img.style.verticalAlign = 'middle';
434-
img.style.width = turf_row_inner_height + 'em';
435-
img.style.height = turf_row_inner_height + 'em';
436-
img.onerror = (function (object_info) {
437-
return function () {
438-
let delay = imageRetryDelay;
439-
if (!turf_image_errors[object_info[3]]) {
440-
turf_image_errors[object_info[3]] = 0;
441-
delay = imageFirstRetryDelay;
442-
}
443-
turf_image_errors[object_info[3]]++;
444-
if (turf_image_errors[object_info[3]] > imageRetryLimit) {
445-
return;
446-
}
447-
448-
Byond.sendMessage('Resend-Asset', object_info[3]);
449-
setTimeout(function () {
450-
// Use the failure count as a cachebreaker to force-reload.
451-
let img = document.getElementById(object_info[1]);
452-
img.src = object_info[2] + '?' + turf_image_errors[object_info[3]];
453-
}, imageRetryDelay);
454-
};
455-
})(object_info);
456-
button.appendChild(img);
436+
if (object_info[2]) {
437+
img.id = object_info[1];
438+
img.src = object_info[2];
439+
img.style.verticalAlign = 'middle';
440+
img.style.width = turf_row_inner_height + 'em';
441+
img.style.height = turf_row_inner_height + 'em';
442+
// Only retry if we got an asset key
443+
if (object_info[3]) {
444+
img.onerror = (function (object_info) {
445+
return function () {
446+
let delay = imageRetryDelay;
447+
if (!turf_image_errors[object_info[3]]) {
448+
turf_image_errors[object_info[3]] = 0;
449+
delay = imageFirstRetryDelay;
450+
}
451+
turf_image_errors[object_info[3]]++;
452+
if (turf_image_errors[object_info[3]] > imageRetryLimit) {
453+
return;
454+
}
455+
456+
Byond.sendMessage('Resend-Asset', object_info[3]);
457+
setTimeout(function () {
458+
// Use the failure count as a cachebreaker to force-reload.
459+
let img = document.getElementById(object_info[1]);
460+
if (img) {
461+
img.src = object_info[2] + '?' + turf_image_errors[object_info[3]];
462+
}
463+
}, delay);
464+
};
465+
})(object_info);
466+
}
467+
button.appendChild(img);
468+
} else {
469+
// If we're missing an image URL just space out the same amount that the image would take up
470+
let spacer = document.createElement('span');
471+
spacer.style.display = 'inline-block';
472+
spacer.style.width = turf_row_inner_height + 'em';
473+
spacer.style.height = turf_row_inner_height + 'em';
474+
button.appendChild(spacer);
475+
}
457476

458477
var label = document.createElement('span');
459478
label.style.marginLeft = '0.5em';
@@ -463,6 +482,22 @@ function listedturf_fill_row(row, item_index) {
463482
return true;
464483
}
465484

485+
function listedturf_fill_row(row, item_index) {
486+
return listedturf_render_row(row, item_index);
487+
}
488+
489+
function listedturf_refresh_visible_rows() {
490+
if (!turf_rows || !turf_rows.initialized) {
491+
return;
492+
}
493+
for (let i = turf_rows.min_row; i < turf_rows.max_row; i++) {
494+
if (turf_rows[i]) {
495+
listedturf_render_row(turf_rows[i], i + 1);
496+
delete turf_incomplete_rows[i];
497+
}
498+
}
499+
}
500+
466501
function listedturf_fill_all() {
467502
for (let i in turf_incomplete_rows) {
468503
let item_index = turf_incomplete_rows[i];
@@ -915,6 +950,7 @@ Byond.subscribeTo('update_listedturf', function (TC) {
915950
turf_size = TC['total'];
916951
if (current_tab == turfname) {
917952
draw_listedturf();
953+
listedturf_refresh_visible_rows();
918954
}
919955
});
920956

0 commit comments

Comments
 (0)