tgui backend

This commit is contained in:
LetterN
2021-10-28 12:51:31 +08:00
parent 853ff1d8ad
commit 49940c373e
110 changed files with 7353 additions and 259 deletions
+65 -38
View File
@@ -4,7 +4,7 @@
var/window_id // window_id is used as the window name for browse and onclose
var/width = 0
var/height = 0
var/atom/ref = null
var/datum/weakref/ref = null
var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id
var/stylesheets[0]
var/scripts[0]
@@ -16,8 +16,8 @@
/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, atom/nref = null)
user = nuser
RegisterSignal(user, COMSIG_PARENT_QDELETING, .proc/user_deleted)
window_id = nwindow_id
if (ntitle)
title = format_text(ntitle)
@@ -26,7 +26,11 @@
if (nheight)
height = nheight
if (nref)
ref = nref
ref = WEAKREF(nref)
/datum/browser/proc/user_deleted(datum/source)
SIGNAL_HANDLER
user = null
/datum/browser/proc/add_head_content(nhead_content)
head_content = nhead_content
@@ -35,7 +39,7 @@
window_options = nwindow_options
/datum/browser/proc/add_stylesheet(name, file)
if(istype(name, /datum/asset/spritesheet))
if (istype(name, /datum/asset/spritesheet))
var/datum/asset/spritesheet/sheet = name
stylesheets["spritesheet_[sheet.name].css"] = "data/spritesheets/[sheet.name]"
else
@@ -94,27 +98,32 @@
"}
/datum/browser/proc/open(use_onclose = TRUE)
if(isnull(window_id)) //null check because this can potentially nuke goonchat
if(isnull(window_id)) //null check because this can potentially nuke goonchat
WARNING("Browser [title] tried to open with a null ID")
to_chat(user, "<span class='userdanger'>The [title] browser you tried to open failed a sanity check! Please report this on github!</span>")
to_chat(user, span_userdanger("The [title] browser you tried to open failed a sanity check! Please report this on github!"))
return
var/window_size = ""
if(width && height)
if (width && height)
window_size = "size=[width]x[height];"
common_asset.send(user)
if(stylesheets.len)
if (stylesheets.len)
SSassets.transport.send_assets(user, stylesheets)
if(scripts.len)
if (scripts.len)
SSassets.transport.send_assets(user, scripts)
user << browse(get_content(), "window=[window_id];[window_size][window_options]")
if(use_onclose)
if (use_onclose)
setup_onclose()
/datum/browser/proc/setup_onclose()
set waitfor = 0 //winexists sleeps, so we don't need to.
for (var/i in 1 to 10)
if (user && winexists(user, window_id))
onclose(user, window_id, ref)
if (user?.client && winexists(user, window_id))
var/atom/send_ref
if(ref)
send_ref = ref.resolve()
if(!send_ref)
ref = null
onclose(user, window_id, send_ref)
break
/datum/browser/proc/close()
@@ -153,11 +162,35 @@
opentime = 0
close()
//designed as a drop in replacement for alert(); functions the same. (outside of needing User specified)
/proc/tgalert(mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000)
/**
* **DEPRECATED: USE tgui_alert(...) INSTEAD**
*
* Designed as a drop in replacement for alert(); functions the same. (outside of needing User specified)
* Arguments:
* * User - The user to show the alert to.
* * Message - The textual body of the alert.
* * Title - The title of the alert's window.
* * Button1 - The first button option.
* * Button2 - The second button option.
* * Button3 - The third button option.
* * StealFocus - Boolean operator controlling if the alert will steal the user's window focus.
* * Timeout - The timeout of the window, after which no responses will be valid.
*/
/proc/tgalert(mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = TRUE, Timeout = 6000)
if (!User)
User = usr
switch(askuser(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout))
if (!istype(User))
if (istype(User, /client))
var/client/client = User
User = client.mob
else
return
// Get user's response using a modal
var/datum/browser/modal/alert/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout)
A.open()
A.wait()
switch(A.selectedbutton)
if (1)
return Button1
if (2)
@@ -197,8 +230,8 @@
.=..()
opentime = 0
/datum/browser/modal/open(use_onclose = 1)
set waitfor = 0
/datum/browser/modal/open(use_onclose)
set waitfor = FALSE
opentime = world.time
if (stealfocus)
@@ -277,7 +310,7 @@
opentime = 0
close()
/proc/presentpicker(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/values, inputtype = "checkbox", width, height, slidecolor)
/proc/presentpicker(mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/values, inputtype = "checkbox", width, height, slidecolor)
if (!istype(User))
if (istype(User, /client/))
var/client/C = User
@@ -290,7 +323,7 @@
if (A.selectedbutton)
return list("button" = A.selectedbutton, "values" = A.valueslist)
/proc/input_bitfield(var/mob/User, title, bitfield, current_value, nwidth = 350, nheight = 350, nslidecolor, allowed_edit_list = null)
/proc/input_bitfield(mob/User, title, bitfield, current_value, nwidth = 350, nheight = 350, nslidecolor, allowed_edit_list = null)
if (!User || !(bitfield in GLOB.bitfields))
return
var/list/pickerlist = list()
@@ -376,13 +409,13 @@
if ("string")
settings["mainsettings"][setting]["value"] = stripped_input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"])
if ("number")
settings["mainsettings"][setting]["value"] = tgui_input_num(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]")
settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]") as num
if ("color")
settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"]) as color
if ("boolean")
settings["mainsettings"][setting]["value"] = tgui_input_list(user, "[settings["mainsettings"][setting]["desc"]]?", "", list("Yes","No"))
settings["mainsettings"][setting]["value"] = (settings["mainsettings"][setting]["value"] == "Yes") ? "No" : "Yes"
if ("ckey")
settings["mainsettings"][setting]["value"] = tgui_input_list(user, "[settings["mainsettings"][setting]["desc"]]?", "", list("none") + GLOB.directory)
settings["mainsettings"][setting]["value"] = input(user, "[settings["mainsettings"][setting]["desc"]]?") in list("none") + GLOB.directory
if (settings["mainsettings"][setting]["callback"])
var/datum/callback/callback = settings["mainsettings"][setting]["callback"]
settings = callback.Invoke(settings)
@@ -401,7 +434,7 @@
opentime = 0
close()
/proc/presentpreflikepicker(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/settings, width, height, slidecolor)
/proc/presentpreflikepicker(mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/settings, width, height, slidecolor)
if (!istype(User))
if (istype(User, /client/))
var/client/C = User
@@ -414,12 +447,6 @@
if (A.selectedbutton)
return list("button" = A.selectedbutton, "settings" = A.settings)
// This will allow you to show an icon in the browse window
// This is added to mob so that it can be used without a reference to the browser object
// There is probably a better place for this...
/mob/proc/browse_rsc_icon(icon, icon_state, dir = -1)
// Registers the on-close verb for a browse window (client/verb/.windowclose)
// this will be called when the close-button of a window is pressed.
//
@@ -427,8 +454,8 @@
// e.g. canisters, timers, etc.
//
// windowid should be the specified window name
// e.g. code is : user << browse(text, "window=fred")
// then use : onclose(user, "fred")
// e.g. code is : user << browse(text, "window=fred")
// then use : onclose(user, "fred")
//
// Optionally, specify the "ref" parameter as the controlled atom (usually src)
// to pass a "close=1" parameter to the atom's Topic() proc for special handling.
@@ -451,18 +478,18 @@
// otherwise, just reset the client mob's machine var.
//
/client/verb/windowclose(atomref as text)
set hidden = TRUE // hide this verb from the user's panel
set name = ".windowclose" // no autocomplete on cmd line
set hidden = TRUE // hide this verb from the user's panel
set name = ".windowclose" // no autocomplete on cmd line
if(atomref!="null") // if passed a real atomref
var/hsrc = locate(atomref) // find the reffed atom
if(atomref!="null") // if passed a real atomref
var/hsrc = locate(atomref) // find the reffed atom
var/href = "close=1"
if(hsrc)
usr = src.mob
src.Topic(href, params2list(href), hsrc) // this will direct to the atom's
return // Topic() proc via client.Topic()
src.Topic(href, params2list(href), hsrc) // this will direct to the atom's
return // Topic() proc via client.Topic()
// no atomref specified (or not found)
// so just reset the user mob's machine var
if(src && src.mob)
if(src?.mob)
src.mob.unset_machine()
@@ -66,7 +66,7 @@
/datum/component/storage/concrete/_insert_physical_item(obj/item/I, override = FALSE)
. = TRUE
var/atom/real_location = real_location()
if(I.loc != real_location && real_location)
if(real_location && I.loc != real_location)
I.forceMove(real_location)
refresh_mob_views()
@@ -95,16 +95,19 @@
return FALSE
/datum/component/storage/concrete/proc/on_contents_del(datum/source, atom/A)
SIGNAL_HANDLER
var/atom/real_location = parent
if(A in real_location)
usr = null
remove_from_storage(A, null)
/datum/component/storage/concrete/proc/on_deconstruct(datum/source, disassembled)
SIGNAL_HANDLER
if(drop_all_on_deconstruct)
do_quick_empty()
/datum/component/storage/concrete/proc/on_break(datum/source, damage_flag)
SIGNAL_HANDLER
if(drop_all_on_break)
do_quick_empty()
if(unlock_on_break)
@@ -131,14 +134,16 @@
var/list/seeing_mobs = can_see_contents()
for(var/mob/M in seeing_mobs)
M.client.screen -= AM
if(ismob(parent.loc) && isitem(AM))
var/obj/item/I = AM
var/mob/M = parent.loc
I.dropped(M)
I.item_flags &= ~IN_STORAGE
I.remove_outline()
if(isitem(AM))
var/obj/item/removed_item = AM
removed_item.item_flags &= ~IN_STORAGE
if(ismob(parent.loc))
var/mob/carrying_mob = parent.loc
removed_item.dropped(carrying_mob, TRUE)
if(new_location)
AM.forceMove(new_location) // exited comsig will handle removal reset.
//Reset the items values
_removal_reset(AM)
AM.forceMove(new_location)
//We don't want to call this if the item is being destroyed
AM.on_exit_storage(src)
else
@@ -147,7 +152,7 @@
refresh_mob_views()
if(isobj(parent))
var/obj/O = parent
O.update_icon()
O.update_appearance()
return TRUE
/datum/component/storage/concrete/proc/slave_can_insert_object(datum/component/storage/slave, obj/item/I, stop_messages = FALSE, mob/M)
@@ -158,7 +163,7 @@
if(. && !prevent_warning)
slave.mob_item_insertion_feedback(usr, M, I)
/datum/component/storage/concrete/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) //Remote is null or the slave datum
/datum/component/storage/concrete/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) //Remote is null or the slave datum
var/datum/component/storage/concrete/master = master()
var/atom/parent = src.parent
var/moved = FALSE
@@ -168,7 +173,7 @@
if(!M.temporarilyRemoveItemFromInventory(I))
return FALSE
else
moved = TRUE //At this point if the proc fails we need to manually move the object back to the turf/mob/whatever.
moved = TRUE //At this point if the proc fails we need to manually move the object back to the turf/mob/whatever.
if(I.pulledby)
I.pulledby.stop_pulling()
if(silent)
@@ -203,7 +208,7 @@
/datum/component/storage/concrete/update_icon()
if(isobj(parent))
var/obj/O = parent
O.update_icon()
O.update_appearance()
for(var/i in slaves)
var/datum/component/storage/slave = i
slave.update_icon()
+29 -29
View File
@@ -418,38 +418,38 @@
return TRUE
/datum/component/storage/proc/mousedrop_onto(datum/source, atom/over_object, mob/M)
SIGNAL_HANDLER
set waitfor = FALSE
. = COMPONENT_NO_MOUSEDROP
if(!ismob(M))
return
if(!over_object)
return
if(ismecha(M.loc)) // stops inventory actions in a mech
return
if(M.incapacitated() || !M.canUseStorage())
return
var/atom/A = parent
if(ismob(M)) //all the check for item manipulation are in other places, you can safely open any storages as anything and its not buggy, i checked
A.add_fingerprint(M)
if(istype(A, /obj/item))
var/obj/item/I = A
I.remove_outline() //Removes the outline when we drag
if(!over_object)
return FALSE
if(ismecha(M.loc)) // stops inventory actions in a mech
return FALSE
// this must come before the screen objects only block, dunno why it wasn't before
if(over_object == M)
user_show_to_mob(M, trigger_on_found = TRUE)
return
if(isrevenant(M))
RevenantThrow(over_object, M, source)
return
if(!M.incapacitated())
if(!istype(over_object, /atom/movable/screen))
dump_content_at(over_object, M)
return
if(A.loc != M)
return
playsound(A, "rustle", 50, 1, -5)
A.do_jiggle()
if(istype(over_object, /atom/movable/screen/inventory/hand))
var/atom/movable/screen/inventory/hand/H = over_object
M.putItemFromInventoryInHandIfPossible(A, H.held_index)
return
A.add_fingerprint(M)
A.add_fingerprint(M)
// this must come before the screen objects only block, dunno why it wasn't before
if(over_object == M)
user_show_to_mob(M, trigger_on_found = TRUE)
if(isrevenant(M))
INVOKE_ASYNC(GLOBAL_PROC, .proc/RevenantThrow, over_object, M, source)
return
if(!istype(over_object, /atom/movable/screen))
INVOKE_ASYNC(src, .proc/dump_content_at, over_object, M)
return
if(A.loc != M)
return
playsound(A, "rustle", 50, TRUE, -5)
A.do_jiggle()
if(istype(over_object, /atom/movable/screen/inventory/hand))
var/atom/movable/screen/inventory/hand/H = over_object
M.putItemFromInventoryInHandIfPossible(A, H.held_index)
return
A.add_fingerprint(M)
/datum/component/storage/proc/user_show_to_mob(mob/M, force = FALSE, trigger_on_found = FALSE)
var/atom/A = parent
+1 -1
View File
@@ -120,7 +120,7 @@ Simple datum which is instanced once per type and is used for every object of sa
return
I.hitsound = item_sound_override
I.usesound = item_sound_override
I.throwhitsound = item_sound_override
I.mob_throw_hit_sound = item_sound_override
// I.mob_throw_hit_sound = item_sound_override
// I.equip_sound = item_sound_override
// I.pickup_sound = item_sound_override