From 6fe4e922270e681de2f9b40fcf35a9588593ddd9 Mon Sep 17 00:00:00 2001 From: mozi_h Date: Thu, 4 Mar 2021 18:49:17 +0100 Subject: [PATCH] Clipboards: tgui and better functionality (#57289) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Clipboards now use tgui - View / write on paper on the chipboard using an attached pen - Rename paper on the clipboard - Attach a pen by clicking on a clipboard with one - Attach paper by either clicking on a clipboard with some or: - Rapidly attach paper by clicking on paper with the clipboard 🚀 --- code/modules/paperwork/clipboard.dm | 224 +++++++++++++-------- code/modules/paperwork/paper.dm | 25 ++- tgui/packages/tgui/interfaces/Clipboard.js | 107 ++++++++++ 3 files changed, 262 insertions(+), 94 deletions(-) create mode 100644 tgui/packages/tgui/interfaces/Clipboard.js diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm index 326e664b715..9c88473dd22 100644 --- a/code/modules/paperwork/clipboard.dm +++ b/code/modules/paperwork/clipboard.dm @@ -1,3 +1,6 @@ +/** + * Clipboard + */ /obj/item/clipboard name = "clipboard" icon = 'icons/obj/bureaucracy.dmi' @@ -8,119 +11,172 @@ w_class = WEIGHT_CLASS_SMALL throw_speed = 3 throw_range = 7 - var/obj/item/pen/haspen //The stored pen. - var/obj/item/paper/toppaper //The topmost piece of paper. slot_flags = ITEM_SLOT_BELT resistance_flags = FLAMMABLE + /// The stored pen + var/obj/item/pen/pen + /** + * Weakref of the topmost piece of paper + * + * This is used for the paper displayed on the clipboard's icon + * and it is the one attacked, when attacking the clipboard. + * (As you can't organise contents directly in BYOND) + */ + var/datum/weakref/toppaper_ref /obj/item/clipboard/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins putting [user.p_their()] head into the clip of \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") - return BRUTELOSS//the clipboard's clip is very strong. industrial duty. can kill a man easily. + return BRUTELOSS //The clipboard's clip is very strong. Industrial duty. Can kill a man easily. /obj/item/clipboard/Initialize() update_appearance() . = ..() /obj/item/clipboard/Destroy() - QDEL_NULL(haspen) - QDEL_NULL(toppaper) //let movable/Destroy handle the rest + QDEL_NULL(pen) return ..() +/obj/item/clipboard/examine() + . = ..() + if(pen) + . += "Alt-click to remove [pen]." + var/obj/item/paper/toppaper = toppaper_ref?.resolve() + if(toppaper) + . += "Right-click to remove [toppaper]." + +/// Take out the topmost paper +/obj/item/clipboard/proc/remove_paper(obj/item/paper/paper, mob/user) + if(!istype(paper)) + return + paper.forceMove(user.loc) + user.put_in_hands(paper) + to_chat(user, "You remove [paper] from [src].") + var/obj/item/paper/toppaper = toppaper_ref?.resolve() + if(paper == toppaper) + toppaper_ref = null + var/obj/item/paper/newtop = locate(/obj/item/paper) in src + if(newtop && (newtop != paper)) + toppaper_ref = WEAKREF(newtop) + else + toppaper_ref = null + update_icon() + +/obj/item/clipboard/proc/remove_pen(mob/user) + pen.forceMove(user.loc) + user.put_in_hands(pen) + to_chat(user, "You remove [pen] from [src].") + pen = null + update_icon() + +/obj/item/clipboard/AltClick(mob/user) + ..() + if(pen) + remove_pen(user) + /obj/item/clipboard/update_overlays() . = ..() + var/obj/item/paper/toppaper = toppaper_ref?.resolve() if(toppaper) . += toppaper.icon_state . += toppaper.overlays - if(haspen) + if(pen) . += "clipboard_pen" . += "clipboard_over" -/obj/item/clipboard/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/paper)) - if(!user.transferItemToLoc(W, src)) +/obj/item/clipboard/attack_hand(mob/user, list/modifiers) + if(LAZYACCESS(modifiers, RIGHT_CLICK)) + var/obj/item/paper/toppaper = toppaper_ref?.resolve() + remove_paper(toppaper, user) + return TRUE + . = ..() + +/obj/item/clipboard/attackby(obj/item/weapon, mob/user, params) + var/obj/item/paper/toppaper = toppaper_ref?.resolve() + if(istype(weapon, /obj/item/paper)) + //Add paper into the clipboard + if(!user.transferItemToLoc(weapon, src)) return - toppaper = W - to_chat(user, "You clip the paper onto \the [src].") - update_appearance() + toppaper_ref = WEAKREF(weapon) + to_chat(user, "You clip [weapon] onto [src].") + else if(istype(weapon, /obj/item/pen) && !pen) + //Add a pen into the clipboard, attack (write) if there is already one + if(!usr.transferItemToLoc(weapon, src)) + return + pen = weapon + to_chat(usr, "You slot [weapon] into [src].") else if(toppaper) toppaper.attackby(user.get_active_held_item(), user) - update_appearance() - + update_appearance() /obj/item/clipboard/attack_self(mob/user) - var/dat = "Clipboard" - if(haspen) - dat += "Remove Pen

" - else - dat += "Add Pen

" - - //The topmost paper. You can't organise contents directly in byond, so this is what we're stuck with. -Pete - if(toppaper) - var/obj/item/paper/P = toppaper - dat += "Write Remove - [P.name]

" - - for(P in src) - if(P == toppaper) - continue - dat += "Write Remove Move to top - [P.name]
" - user << browse(dat, "window=clipboard") - onclose(user, "clipboard") add_fingerprint(usr) + ui_interact(user) + return +/obj/item/clipboard/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Clipboard") + ui.open() + +/obj/item/clipboard/ui_data(mob/user) + // prepare data for TGUI + var/list/data = list() + data["pen"] = "[pen]" + + var/obj/item/paper/toppaper = toppaper_ref?.resolve() + data["top_paper"] = "[toppaper]" + data["top_paper_ref"] = "[REF(toppaper)]" + + data["paper"] = list() + data["paper_ref"] = list() + for(var/obj/item/paper/paper in src) + if(paper == toppaper) + continue + data["paper"] += "[paper]" + data["paper_ref"] += "[REF(paper)]" + + return data + +/obj/item/clipboard/ui_act(action, params) + . = ..() + if(.) + return -/obj/item/clipboard/Topic(href, href_list) - ..() if(usr.stat != CONSCIOUS || HAS_TRAIT(usr, TRAIT_HANDS_BLOCKED)) return - if(usr.contents.Find(src)) - - if(href_list["pen"]) - if(haspen) - haspen.forceMove(usr.loc) - usr.put_in_hands(haspen) - haspen = null - - if(href_list["addpen"]) - if(!haspen) - var/obj/item/held = usr.get_active_held_item() - if(istype(held, /obj/item/pen)) - var/obj/item/pen/W = held - if(!usr.transferItemToLoc(W, src)) - return - haspen = W - to_chat(usr, "You slot [W] into [src].") - - if(href_list["write"]) - var/obj/item/P = locate(href_list["write"]) in src - if(istype(P)) - if(usr.get_active_held_item()) - P.attackby(usr.get_active_held_item(), usr) - - if(href_list["remove"]) - var/obj/item/P = locate(href_list["remove"]) in src - if(istype(P)) - P.forceMove(usr.loc) - usr.put_in_hands(P) - if(P == toppaper) - toppaper = null - var/obj/item/paper/newtop = locate(/obj/item/paper) in src - if(newtop && (newtop != P)) - toppaper = newtop - else - toppaper = null - - if(href_list["read"]) - var/obj/item/paper/P = locate(href_list["read"]) in src - if(istype(P)) - usr.examinate(P) - - if(href_list["top"]) - var/obj/item/P = locate(href_list["top"]) in src - if(istype(P)) - toppaper = P - to_chat(usr, "You move [P.name] to the top.") - - //Update everything - attack_self(usr) - update_appearance() + switch(action) + // Take the pen out + if("remove_pen") + if(pen) + remove_pen(usr) + . = TRUE + // Take paper out + if("remove_paper") + var/obj/item/paper/paper = locate(params["ref"]) in src + if(istype(paper)) + remove_paper(paper, usr) + . = TRUE + // Look at (or edit) the paper + if("edit_paper") + var/obj/item/paper/paper = locate(params["ref"]) in src + if(istype(paper)) + paper.ui_interact(usr) + update_icon() + . = TRUE + // Move paper to the top + if("move_top_paper") + var/obj/item/paper/paper = locate(params["ref"]) in src + if(istype(paper)) + toppaper_ref = WEAKREF(paper) + to_chat(usr, "You move [paper] to the top.") + update_icon() + . = TRUE + // Rename the paper (it's a verb) + if("rename_paper") + var/obj/item/paper/paper = locate(params["ref"]) in src + if(istype(paper)) + paper.rename() + update_icon() + . = TRUE diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index dc44faefb40..0675632a750 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -124,7 +124,7 @@ H.update_damage_hud() return var/n_name = stripped_input(usr, "What would you like to label the paper?", "Paper Labelling", null, MAX_NAME_LEN) - if((loc == usr && usr.stat == CONSCIOUS)) + if(((loc == usr || istype(loc, /obj/item/clipboard)) && usr.stat == CONSCIOUS)) name = "paper[(n_name ? text("- '[n_name]'") : null)]" add_fingerprint(usr) @@ -161,7 +161,7 @@ // .. or if you cannot read if(!user.can_read(src)) return UI_CLOSE - if(in_contents_of(/obj/machinery/door/airlock)) + if(in_contents_of(/obj/machinery/door/airlock) || in_contents_of(/obj/item/clipboard)) return UI_INTERACTIVE return ..() @@ -251,27 +251,32 @@ var/list/data = list() data["edit_usr"] = "[user]" - var/obj/O = user.get_active_held_item() - if(istype(O, /obj/item/toy/crayon)) - var/obj/item/toy/crayon/PEN = O + var/obj/holding = user.get_active_held_item() + // Use a clipboard's pen, if applicable + if(istype(loc, /obj/item/clipboard)) + var/obj/item/clipboard/clipboard = loc + if(clipboard.pen) + holding = clipboard.pen + if(istype(holding, /obj/item/toy/crayon)) + var/obj/item/toy/crayon/PEN = holding data["pen_font"] = CRAYON_FONT data["pen_color"] = PEN.paint_color data["edit_mode"] = MODE_WRITING data["is_crayon"] = TRUE data["stamp_class"] = "FAKE" data["stamp_icon_state"] = "FAKE" - else if(istype(O, /obj/item/pen)) - var/obj/item/pen/PEN = O + else if(istype(holding, /obj/item/pen)) + var/obj/item/pen/PEN = holding data["pen_font"] = PEN.font data["pen_color"] = PEN.colour data["edit_mode"] = MODE_WRITING data["is_crayon"] = FALSE data["stamp_class"] = "FAKE" data["stamp_icon_state"] = "FAKE" - else if(istype(O, /obj/item/stamp)) + else if(istype(holding, /obj/item/stamp)) var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/paper) - data["stamp_icon_state"] = O.icon_state - data["stamp_class"] = sheet.icon_class_name(O.icon_state) + data["stamp_icon_state"] = holding.icon_state + data["stamp_class"] = sheet.icon_class_name(holding.icon_state) data["edit_mode"] = MODE_STAMPING data["pen_font"] = "FAKE" data["pen_color"] = "FAKE" diff --git a/tgui/packages/tgui/interfaces/Clipboard.js b/tgui/packages/tgui/interfaces/Clipboard.js new file mode 100644 index 00000000000..69f56a26c9c --- /dev/null +++ b/tgui/packages/tgui/interfaces/Clipboard.js @@ -0,0 +1,107 @@ +import { useBackend } from "../backend"; +import { + Box, + Button, + Divider, + LabeledList, + Flex, + Section, +} from "../components"; +import { Window } from "../layouts"; + +export const Clipboard = (props, context) => { + const { act, data } = useBackend(context); + const { pen, top_paper, top_paper_ref, paper, paper_ref } = data; + return ( + + +
+ {pen ? ( + + act("remove_pen")} /> + } + > + {pen} + + + ) : ( + + No pen attached! + + )} +
+ + {top_paper ? ( + + + {top_paper} + + +