diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 31f34c5d4c..7e2abebcf9 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -15,7 +15,7 @@ #define LAZYREMOVE(L, I) if(L) { L -= I; if(!length(L)) { L = null; } } #define LAZYADD(L, I) if(!L) { L = list(); } L += I; #define LAZYOR(L, I) if(!L) { L = list(); } L |= I; -#define LAZYFIND(L, V) L ? L.Find(V) : 0 +#define LAZYFIND(L, V) (L ? L.Find(V) : 0) #define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= length(L) ? L[I] : null) : L[I]) : null) #define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V; #define LAZYLEN(L) length(L) diff --git a/code/_onclick/hud/screen_objects/storage.dm b/code/_onclick/hud/screen_objects/storage.dm index 72b2d035a3..1ce1df24c6 100644 --- a/code/_onclick/hud/screen_objects/storage.dm +++ b/code/_onclick/hud/screen_objects/storage.dm @@ -85,21 +85,16 @@ makeItemInactive() /obj/screen/storage/volumetric_box/proc/makeItemInactive() - if(!our_item) - return - our_item.layer = VOLUMETRIC_STORAGE_ITEM_LAYER - our_item.plane = VOLUMETRIC_STORAGE_ITEM_PLANE + return /obj/screen/storage/volumetric_box/proc/makeItemActive() - if(!our_item) - return - our_item.layer = VOLUMETRIC_STORAGE_ACTIVE_ITEM_LAYER //make sure we display infront of the others! - our_item.plane = VOLUMETRIC_STORAGE_ACTIVE_ITEM_PLANE + return /obj/screen/storage/volumetric_box/center icon_state = "stored_continue" var/obj/screen/storage/volumetric_edge/stored_left/left var/obj/screen/storage/volumetric_edge/stored_right/right + var/obj/screen/storage/item_holder/holder var/pixel_size /obj/screen/storage/volumetric_box/center/Initialize(mapload, new_master, our_item) @@ -110,6 +105,9 @@ /obj/screen/storage/volumetric_box/center/Destroy() QDEL_NULL(left) QDEL_NULL(right) + vis_contents.Cut() + if(holder) + QDEL_NULL(holder) return ..() /obj/screen/storage/volumetric_box/center/proc/on_screen_objects() @@ -123,13 +121,36 @@ return pixel_size = pixels cut_overlays() + vis_contents.Cut() //our icon size is 32 pixels. - transform = matrix((pixels - (VOLUMETRIC_STORAGE_BOX_BORDER_SIZE * 2)) / VOLUMETRIC_STORAGE_BOX_ICON_SIZE, 0, 0, 0, 1, 0) + var/multiplier = (pixels - (VOLUMETRIC_STORAGE_BOX_BORDER_SIZE * 2)) / VOLUMETRIC_STORAGE_BOX_ICON_SIZE + transform = matrix(multiplier, 0, 0, 0, 1, 0) + if(our_item) + if(holder) + qdel(holder) + holder = new(null, src, our_item) + holder.transform = matrix(1 / multiplier, 0, 0, 0, 1, 0) + holder.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + holder.appearance_flags &= ~RESET_TRANSFORM + makeItemInactive() + vis_contents += holder left.pixel_x = -((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) - VOLUMETRIC_STORAGE_BOX_BORDER_SIZE right.pixel_x = ((pixels - VOLUMETRIC_STORAGE_BOX_ICON_SIZE) * 0.5) + VOLUMETRIC_STORAGE_BOX_BORDER_SIZE add_overlay(left) add_overlay(right) +/obj/screen/storage/volumetric_box/center/makeItemInactive() + if(!holder) + return + holder.layer = VOLUMETRIC_STORAGE_ITEM_LAYER + holder.plane = VOLUMETRIC_STORAGE_ITEM_PLANE + +/obj/screen/storage/volumetric_box/center/makeItemActive() + if(!holder) + return + holder.our_item.layer = VOLUMETRIC_STORAGE_ACTIVE_ITEM_LAYER //make sure we display infront of the others! + holder.our_item.plane = VOLUMETRIC_STORAGE_ACTIVE_ITEM_PLANE + /obj/screen/storage/volumetric_edge layer = VOLUMETRIC_STORAGE_BOX_LAYER plane = VOLUMETRIC_STORAGE_BOX_PLANE @@ -157,3 +178,20 @@ /obj/screen/storage/volumetric_edge/stored_right icon_state = "stored_end" appearance_flags = APPEARANCE_UI | KEEP_APART | RESET_TRANSFORM + +/obj/screen/storage/item_holder + var/obj/item/our_item + vis_flags = NONE + +/obj/screen/storage/item_holder/Initialize(mapload, new_master, obj/item/I) + . = ..() + our_item = I + vis_contents += I + +/obj/screen/storage/item_holder/Destroy() + vis_contents.Cut() + our_item = null + return ..() + +/obj/screen/storage/item_holder/Click(location, control, params) + return our_item.Click(location, control, params) diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index 2fa5a20d7a..7968caed54 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -47,18 +47,8 @@ var/display_numerical_stacking = FALSE //stack things of the same type and show as a single object with a number. - /// "legacy"/default view mode's storage "boxes" - var/obj/screen/storage/boxes/ui_boxes - /// New volumetric storage display mode's left side - var/obj/screen/storage/left/ui_left - /// New volumetric storage display mode's center 'blocks' - var/obj/screen/storage/continuous/ui_continuous - /// The close button, used in all modes. Frames right side in volumetric mode. - var/obj/screen/storage/close/ui_close - /// Associative list of list(item = screen object) for volumetric storage item screen blocks - var/list/ui_item_blocks - - var/current_maxscreensize + /// Ui objects by person. mob = list(objects) + var/list/ui_by_mob = list() var/allow_big_nesting = FALSE //allow storage objects of the same or greater size. @@ -125,18 +115,16 @@ /datum/component/storage/Destroy() close_all() - QDEL_NULL(ui_boxes) - QDEL_NULL(ui_close) - QDEL_NULL(ui_continuous) - QDEL_NULL(ui_left) - // DO NOT USE QDEL_LIST_ASSOC. - if(ui_item_blocks) - for(var/i in ui_item_blocks) - qdel(ui_item_blocks[i]) //qdel the screen object not the item - ui_item_blocks.Cut() + wipe_ui_objects() LAZYCLEARLIST(is_using) return ..() +/datum/component/storage/proc/wipe_ui_objects() + for(var/i in ui_by_mob) + var/list/objects = ui_by_mob[i] + QDEL_LIST(objects) + ui_by_mob.Cut() + /datum/component/storage/PreTransfer() update_actions() @@ -351,13 +339,6 @@ return master._removal_reset(thing) /datum/component/storage/proc/_remove_and_refresh(datum/source, atom/movable/thing) - if(LAZYACCESS(ui_item_blocks, thing)) - var/obj/screen/storage/volumetric_box/center/C = ui_item_blocks[thing] - for(var/i in can_see_contents()) //runtimes result if mobs can access post deletion. - var/mob/M = i - M.client?.screen -= C.on_screen_objects() - ui_item_blocks -= thing - qdel(C) _removal_reset(thing) // THIS NEEDS TO HAPPEN AFTER SO LAYERING DOESN'T BREAK! refresh_mob_views() @@ -467,14 +448,14 @@ return A.add_fingerprint(M) -/datum/component/storage/proc/user_show_to_mob(mob/M, force = FALSE, ghost = FALSE) +/datum/component/storage/proc/user_show_to_mob(mob/M, force = FALSE) var/atom/A = parent if(!istype(M)) return FALSE A.add_fingerprint(M) if(!force && (check_locked(null, M) || !M.CanReach(parent, view_only = TRUE))) return FALSE - ui_show(M, !ghost) + ui_show(M) /datum/component/storage/proc/mousedrop_receive(datum/source, atom/movable/O, mob/M) if(isitem(O)) @@ -596,7 +577,7 @@ return can_be_inserted(I, silent, M) /datum/component/storage/proc/show_to_ghost(datum/source, mob/dead/observer/M) - return user_show_to_mob(M, TRUE, TRUE) + return user_show_to_mob(M, TRUE) /datum/component/storage/proc/signal_show_attempt(datum/source, mob/showto, force = FALSE) return user_show_to_mob(showto, force) diff --git a/code/datums/components/storage/ui.dm b/code/datums/components/storage/ui.dm index c7ac0d3549..044afa2850 100644 --- a/code/datums/components/storage/ui.dm +++ b/code/datums/components/storage/ui.dm @@ -7,7 +7,7 @@ if(QDELETED(I)) continue if(!.[I.type]) - .[I.type] = new /datum/numbered_display(I, 1) + .[I.type] = new /datum/numbered_display(I, 1, src) else var/datum/numbered_display/ND = .[I.type] ND.number++ @@ -20,6 +20,8 @@ . = list() var/list/accessible_contents = accessible_items() var/adjusted_contents = length(accessible_contents) + var/obj/screen/storage/close/ui_close + var/obj/screen/storage/boxes/ui_boxes //Numbered contents display var/list/datum/numbered_display/numbered_contents @@ -60,12 +62,13 @@ for(var/obj/O in accessible_items()) if(QDELETED(O)) continue - O.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip" - O.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]" + var/obj/screen/storage/item_holder/D = new(null, src, O) + D.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip" + D.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]" O.maptext = "" O.layer = ABOVE_HUD_LAYER O.plane = ABOVE_HUD_PLANE - . += O + . += D cx++ if(cx - screen_start_x >= columns) cx = screen_start_x @@ -78,6 +81,9 @@ */ /datum/component/storage/proc/orient2hud_volumetric(mob/user, maxcolumns) . = list() + var/obj/screen/storage/left/ui_left + var/obj/screen/storage/continuous/ui_continuous + var/obj/screen/storage/close/ui_close // Generate ui_item_blocks for missing ones and render+orient. var/list/atom/contents = accessible_items() @@ -128,14 +134,10 @@ var/first = TRUE var/row = 1 - LAZYINITLIST(ui_item_blocks) - for(var/i in percentage_by_item) I = i var/percent = percentage_by_item[I] - if(!ui_item_blocks[I]) - ui_item_blocks[I] = new /obj/screen/storage/volumetric_box/center(null, src, I) - var/obj/screen/storage/volumetric_box/center/B = ui_item_blocks[I] + var/obj/screen/storage/volumetric_box/center/B = new /obj/screen/storage/volumetric_box/center(null, src, I) var/pixels_to_use = overrun? MINIMUM_PIXELS_PER_ITEM : max(using_horizontal_pixels * percent, MINIMUM_PIXELS_PER_ITEM) var/addrow = FALSE if(CEILING(pixels_to_use, 1) >= FLOOR(horizontal_pixels - current_pixel - VOLUMETRIC_STORAGE_EDGE_PADDING, 1)) @@ -143,25 +145,17 @@ addrow = TRUE // now that we have pixels_to_use, place our thing and add it to the returned list. - B.screen_loc = I.screen_loc = "[screen_start_x]:[round(current_pixel + (pixels_to_use * 0.5) + (first? 0 : VOLUMETRIC_STORAGE_ITEM_PADDING), 1)],[screen_start_y+row-1]:[screen_pixel_y]" + B.screen_loc = "[screen_start_x]:[round(current_pixel + (pixels_to_use * 0.5) + (first? 0 : VOLUMETRIC_STORAGE_ITEM_PADDING), 1)],[screen_start_y+row-1]:[screen_pixel_y]" // add the used pixels to pixel after we place the object current_pixel += pixels_to_use + (first? 0 : VOLUMETRIC_STORAGE_ITEM_PADDING) first = FALSE //apply padding to everything after this // set various things B.set_pixel_size(pixels_to_use) - B.layer = VOLUMETRIC_STORAGE_BOX_LAYER - B.plane = VOLUMETRIC_STORAGE_BOX_PLANE B.name = I.name - I.mouse_opacity = MOUSE_OPACITY_ICON - I.maptext = "" - I.layer = VOLUMETRIC_STORAGE_ITEM_LAYER - I.plane = VOLUMETRIC_STORAGE_ITEM_PLANE - // finally add our things. . += B.on_screen_objects() - . += I // go up a row if needed if(addrow) @@ -185,18 +179,19 @@ /** * Shows our UI to a mob. */ -/datum/component/storage/proc/ui_show(mob/M, set_screen_size = TRUE) +/datum/component/storage/proc/ui_show(mob/M) if(!M.client) return FALSE + if(ui_by_mob[M] || LAZYFIND(is_using, M)) + // something went horribly wrong + // hide first + ui_hide(M) var/list/cview = getviewsize(M.client.view) // in tiles var/maxallowedscreensize = cview[1]-8 - if(set_screen_size) - current_maxscreensize = maxallowedscreensize - else if(current_maxscreensize) - maxallowedscreensize = current_maxscreensize // we got screen size, register signal RegisterSignal(M, COMSIG_MOB_CLIENT_LOGOUT, .proc/on_logout, override = TRUE) + RegisterSignal(M, COMSIG_PARENT_QDELETING, .proc/on_logout, override = TRUE) if(M.active_storage != src) if(M.active_storage) M.active_storage.ui_hide(M) @@ -204,10 +199,14 @@ LAZYOR(is_using, M) if(!M.client?.prefs?.no_tetris_storage && volumetric_ui()) //new volumetric ui bay-style - M.client.screen |= orient2hud_volumetric(M, maxallowedscreensize) + var/list/objects = orient2hud_volumetric(M, maxallowedscreensize) + M.client.screen |= objects + ui_by_mob[M] = objects else //old ui - M.client.screen |= orient2hud_legacy(M, maxallowedscreensize) + var/list/objects = orient2hud_legacy(M, maxallowedscreensize) + M.client.screen |= objects + ui_by_mob[M] = objects return TRUE /** @@ -236,8 +235,10 @@ /datum/component/storage/proc/ui_hide(mob/M) if(!M.client) return TRUE - UnregisterSignal(M, COMSIG_MOB_CLIENT_LOGOUT) - M.client.screen -= list(ui_boxes, ui_close, ui_left, ui_continuous) + get_ui_item_objects_hide(M) + UnregisterSignal(M, list(COMSIG_PARENT_QDELETING, COMSIG_MOB_CLIENT_LOGOUT)) + M.client.screen -= ui_by_mob[M] + var/list/objects = ui_by_mob[M] + QDEL_LIST(objects) if(M.active_storage == src) M.active_storage = null LAZYREMOVE(is_using, M) @@ -250,48 +251,26 @@ var/atom/real_location = real_location() return (storage_flags & STORAGE_LIMIT_VOLUME) && (length(real_location.contents) <= MAXIMUM_VOLUMETRIC_ITEMS) && !display_numerical_stacking -/** - * Gets the ui item objects to ui_hide. - */ -/datum/component/storage/proc/get_ui_item_objects_hide(mob/M) - if(!volumetric_ui() || M.client?.prefs?.no_tetris_storage) - var/atom/real_location = real_location() - return real_location.contents - else - . = list() - for(var/i in ui_item_blocks) - // get both the box and the item - . += ui_item_blocks[i] - . += i - /** * Gets our ui_boxes, making it if it doesn't exist. */ /datum/component/storage/proc/get_ui_boxes() - if(!ui_boxes) - ui_boxes = new(null, src) - return ui_boxes + return new /obj/screen/storage/boxes(null, src) /** * Gets our ui_left, making it if it doesn't exist. */ /datum/component/storage/proc/get_ui_left() - if(!ui_left) - ui_left = new(null, src) - return ui_left + return new /obj/screen/storage/left(null, src) /** * Gets our ui_close, making it if it doesn't exist. */ /datum/component/storage/proc/get_ui_close() - if(!ui_close) - ui_close = new(null, src) - return ui_close + return new /obj/screen/storage/close(null, src) /** * Gets our ui_continuous, making it if it doesn't exist. */ /datum/component/storage/proc/get_ui_continuous() - if(!ui_continuous) - ui_continuous = new(null, src) - return ui_continuous + return new /obj/screen/storage/continuous(null, src) diff --git a/code/datums/numbered_display.dm b/code/datums/numbered_display.dm index 9aa880aa75..fc2035b39f 100644 --- a/code/datums/numbered_display.dm +++ b/code/datums/numbered_display.dm @@ -3,8 +3,8 @@ var/obj/item/sample_object var/number -/datum/numbered_display/New(obj/item/sample, _number = 1) +/datum/numbered_display/New(obj/item/sample, _number = 1, datum/component/storage/parent) if(!istype(sample)) qdel(src) - sample_object = sample + sample_object = new /obj/screen/storage/item_holder(null, parent, sample) number = _number diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi index 60c413c372..95aaf330ce 100644 Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ