mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-18 02:24:11 +01:00
TGUI-V3 (#13310)
* I need that gitignore file * Temp Commit - DOES NOT COMPILE * THE SHIT WORKS * Readme change * Disposal Unit --> TGUI * mmmm yes CI which may not actually work * New GitIgnore * ITS TGUI-NEXT BABY * Doc update * CI tweak * Chmod * And again * *sigh* * Lets appreciate the irony of me failing CI stages * 0/1 --> True/False * Fixes some update nonsense * CI Update * Lets try this * What about this maybe * NVM is hurting me * I swear to god * A little bit of validation in my life * V3 BABYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY * Fixes * Fixes NaN appearing for a few frames when UIs open * Fixes + Crew Monitor * Corn + Steel + Mochi Fixes * Forgot this * Fixes from stylemistake * Code Change * Adds logout proc * Offline implications + Resizeable crew monitor * Change locate() to locateUID() * Change div --> box
This commit is contained in:
@@ -177,6 +177,12 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
|
||||
|
||||
//DEFINITIONS FOR ASSET DATUMS START HERE.
|
||||
/datum/asset/simple/tgui
|
||||
assets = list(
|
||||
"tgui.bundle.js" = 'tgui/packages/tgui/public/tgui.bundle.js',
|
||||
"tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css'
|
||||
)
|
||||
|
||||
/datum/asset/simple/paper
|
||||
assets = list(
|
||||
"large_stamp-clown.png" = 'icons/paper_icons/large_stamp-clown.png',
|
||||
@@ -344,3 +350,15 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
|
||||
/datum/asset/mob_hunt/send(client)
|
||||
send_asset_list(client, assets, verify)
|
||||
|
||||
// Fontawesome
|
||||
/datum/asset/simple/fontawesome
|
||||
verify = FALSE
|
||||
assets = list(
|
||||
"fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot',
|
||||
"fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff',
|
||||
"fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot',
|
||||
"fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff',
|
||||
"font-awesome.css" = 'html/font-awesome/css/all.min.css',
|
||||
"v4shim.css" = 'html/font-awesome/css/v4-shims.min.css'
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
var/register_alarms = 1
|
||||
var/datum/nano_module/alarm_monitor/all/alarm_monitor
|
||||
var/datum/nano_module/atmos_control/atmos_control
|
||||
var/datum/nano_module/crew_monitor/crew_monitor
|
||||
var/datum/tgui_module/crew_monitor/crew_monitor
|
||||
var/datum/nano_module/law_manager/law_manager
|
||||
var/datum/nano_module/power_monitor/silicon/power_monitor
|
||||
|
||||
@@ -71,8 +71,7 @@
|
||||
/mob/living/silicon/proc/subsystem_crew_monitor()
|
||||
set category = "Subsystems"
|
||||
set name = "Crew Monitor"
|
||||
|
||||
crew_monitor.ui_interact(usr, state = GLOB.self_state)
|
||||
crew_monitor.tgui_interact(usr, state = GLOB.tgui_self_state)
|
||||
|
||||
/****************
|
||||
* Law Manager *
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/mob/Logout()
|
||||
SSnanoui.user_logout(src) // this is used to clean up (remove) this user's Nano UIs
|
||||
SStgui.on_logout(src) // Cleanup any TGUIs the user has open
|
||||
unset_machine()
|
||||
GLOB.player_list -= src
|
||||
log_access_out(src)
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/datum/nano_module/crew_monitor
|
||||
name = "Crew monitor"
|
||||
|
||||
/datum/nano_module/crew_monitor/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
var/turf/T = get_turf(nano_host())
|
||||
if(!T || !is_level_reachable(T.z))
|
||||
to_chat(usr, "<span class='warning'><b>Unable to establish a connection</b>: You're too far away from the station!</span>")
|
||||
return 0
|
||||
if(href_list["track"])
|
||||
if(isAI(usr))
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
var/mob/living/carbon/human/H = locate(href_list["track"]) in GLOB.mob_list
|
||||
if(hassensorlevel(H, SUIT_SENSOR_TRACKING))
|
||||
AI.ai_actual_track(H)
|
||||
return 1
|
||||
|
||||
/datum/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.default_state)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800)
|
||||
|
||||
// adding a template with the key "mapContent" enables the map ui functionality
|
||||
ui.add_template("mapContent", "crew_monitor_map_content.tmpl")
|
||||
// adding a template with the key "mapHeader" replaces the map header content
|
||||
ui.add_template("mapHeader", "crew_monitor_map_header.tmpl")
|
||||
|
||||
ui.open()
|
||||
|
||||
// should make the UI auto-update; doesn't seem to?
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/datum/nano_module/crew_monitor/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
var/turf/T = get_turf(nano_host())
|
||||
|
||||
data["isAI"] = isAI(user)
|
||||
data["crewmembers"] = GLOB.crew_repository.health_data(T)
|
||||
|
||||
return data
|
||||
@@ -237,10 +237,10 @@
|
||||
// ai as human but can't flush
|
||||
/obj/machinery/disposal/attack_ai(mob/user as mob)
|
||||
src.add_hiddenprint(user)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/machinery/disposal/attack_ghost(mob/user as mob)
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
|
||||
// human interact with machine
|
||||
/obj/machinery/disposal/attack_hand(mob/user as mob)
|
||||
@@ -256,46 +256,37 @@
|
||||
|
||||
// Clumsy folks can only flush it.
|
||||
if(user.IsAdvancedToolUser())
|
||||
ui_interact(user)
|
||||
tgui_interact(user)
|
||||
else
|
||||
flush = !flush
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/machinery/disposal/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/disposal/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "disposal_bin.tmpl", "Waste Disposal Unit", 395, 250)
|
||||
ui = new(user, src, ui_key, "DisposalBin", name, 300, 250, master_ui, state)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/disposal/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
|
||||
var/pressure = clamp(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 100)
|
||||
var/pressure_round = round(pressure,1)
|
||||
|
||||
/obj/machinery/disposal/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["isAI"] = isAI(user)
|
||||
data["flushing"] = flush
|
||||
data["mode"] = mode
|
||||
if(mode <= 0)
|
||||
data["pumpstatus"] = "N/A"
|
||||
else if(mode == 1)
|
||||
data["pumpstatus"] = "Pressurizing"
|
||||
else if(mode == 2)
|
||||
data["pumpstatus"] = "Ready"
|
||||
else
|
||||
data["pumpstatus"] = "Idle"
|
||||
data["pressure"] = pressure_round
|
||||
data["pressure"] = round(clamp(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 100),1)
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/disposal/Topic(href, href_list)
|
||||
/obj/machinery/disposal/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(usr.loc == src)
|
||||
to_chat(usr, "<span class='warning'>You cannot reach the controls from inside.</span>")
|
||||
return
|
||||
|
||||
if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1
|
||||
if(mode==-1 && action != "eject") // If the mode is -1, only allow ejection
|
||||
to_chat(usr, "<span class='warning'>The disposal units power is disabled.</span>")
|
||||
return
|
||||
|
||||
@@ -311,21 +302,25 @@
|
||||
return
|
||||
|
||||
if(istype(src.loc, /turf))
|
||||
if(href_list["pump"])
|
||||
if(text2num(href_list["pump"]))
|
||||
mode = 1
|
||||
else
|
||||
mode = 0
|
||||
if(action == "pumpOn")
|
||||
mode = 1
|
||||
update()
|
||||
if(action == "pumpOff")
|
||||
mode = 0
|
||||
update()
|
||||
|
||||
if(!isAI(usr))
|
||||
if(href_list["handle"])
|
||||
flush = text2num(href_list["handle"])
|
||||
if(!issilicon(usr))
|
||||
if(action == "engageHandle")
|
||||
flush = 1
|
||||
update()
|
||||
if(action == "disengageHandle")
|
||||
flush = 0
|
||||
update()
|
||||
|
||||
if(href_list["eject"])
|
||||
if(action == "eject")
|
||||
eject()
|
||||
return
|
||||
|
||||
return TRUE
|
||||
|
||||
// eject the contents of the disposal unit
|
||||
/obj/machinery/disposal/proc/eject()
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* tgui external
|
||||
*
|
||||
* Contains all external tgui declarations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Used to open and update UIs.
|
||||
* If this proc is not implemented properly, the UI will not update correctly.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* optional ui_key string The ui_key of the UI.
|
||||
* optional ui datum/tgui The UI to be updated, if it exists.
|
||||
* optional force_open bool If the UI should be re-opened instead of updated.
|
||||
* optional master_ui datum/tgui The parent UI.
|
||||
* optional state datum/ui_state The state used to determine status.
|
||||
*/
|
||||
|
||||
/datum/proc/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
return FALSE // Not implemented.
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Data to be sent to the UI.
|
||||
* This must be implemented for a UI to work.
|
||||
*
|
||||
* required user mob The mob interacting with the UI.
|
||||
*
|
||||
* return list Data to be sent to the UI.
|
||||
*/
|
||||
/datum/proc/tgui_data(mob/user)
|
||||
return list() // Not implemented.
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Static Data to be sent to the UI.
|
||||
* Static data differs from normal data in that it's large data that should be sent infrequently
|
||||
* This is implemented optionally for heavy uis that would be sending a lot of redundant data
|
||||
* frequently.
|
||||
* Gets squished into one object on the frontend side, but the static part is cached.
|
||||
*
|
||||
* required user mob The mob interacting with the UI.
|
||||
*
|
||||
* return list Statuic Data to be sent to the UI.
|
||||
*/
|
||||
/datum/proc/tgui_static_data(mob/user)
|
||||
return list()
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Forces an update on static data. Should be done manually whenever something happens to change static data.
|
||||
*
|
||||
* required user the mob currently interacting with the ui
|
||||
* optional ui ui to be updated
|
||||
* optional ui_key ui key of ui to be updated
|
||||
*/
|
||||
/datum/proc/update_tgui_static_data(mob/user, datum/tgui/ui, ui_key = "main")
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui)
|
||||
// If there was no ui to update, there's no static data to update either.
|
||||
if(!ui)
|
||||
return
|
||||
ui.push_data(null, tgui_static_data(), TRUE)
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Called on a UI when the UI receieves a href.
|
||||
* Think of this as Topic().
|
||||
*
|
||||
* required action string The action/button that has been invoked by the user.
|
||||
* required params list A list of parameters attached to the button.
|
||||
*
|
||||
* return bool If the UI should be updated or not.
|
||||
*/
|
||||
/datum/proc/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||
// If UI is not interactive or usr calling Topic is not the UI user, bail.
|
||||
if(!ui || ui.status != STATUS_INTERACTIVE)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Called on an object when a tgui object is being created, allowing you to
|
||||
* customise the html
|
||||
* For example: inserting a custom stylesheet that you need in the head
|
||||
*
|
||||
* For this purpose, some tags are available in the html, to be parsed out
|
||||
^ with replacetext
|
||||
* (customheadhtml) - Additions to the head tag
|
||||
*
|
||||
* required html the html base text
|
||||
*/
|
||||
/datum/proc/tgui_base_html(html)
|
||||
return html
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* The UI's host object (usually src_object).
|
||||
* This allows modules/datums to have the UI attached to them,
|
||||
* and be a part of another object.
|
||||
*/
|
||||
/datum/proc/tgui_host(mob/user)
|
||||
return src // Default src.
|
||||
|
||||
/**
|
||||
* global
|
||||
*
|
||||
* Associative list of JSON-encoded shared states that were set by
|
||||
* tgui clients.
|
||||
*/
|
||||
|
||||
/datum/var/list/tgui_shared_states
|
||||
|
||||
/**
|
||||
* global
|
||||
*
|
||||
* Used to track UIs for a mob.
|
||||
*/
|
||||
/mob/var/list/open_tguis = list()
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Called on a UI's object when the UI is closed, not to be confused with
|
||||
* client/verb/uiclose(), which closes the ui window
|
||||
*/
|
||||
/datum/proc/tgui_close(mob/user)
|
||||
|
||||
/**
|
||||
* verb
|
||||
*
|
||||
* Called by UIs when they are closed.
|
||||
* Must be a verb so winset() can call it.
|
||||
*
|
||||
* required uiref ref The UI that was closed.
|
||||
*/
|
||||
/client/verb/tguiclose(uid as text)
|
||||
// Name the verb, and hide it from the user panel.
|
||||
set name = "uiclose"
|
||||
set hidden = TRUE
|
||||
|
||||
// Get the UI based on the ref.
|
||||
var/datum/tgui/ui = locateUID(uid)
|
||||
|
||||
// If we found the UI, close it.
|
||||
if(istype(ui))
|
||||
ui.close()
|
||||
// Unset machine just to be sure.
|
||||
if(src && src.mob)
|
||||
src.mob.unset_machine()
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
TGUI MODULES
|
||||
|
||||
This allows for datum-based TGUIs that can be hooked into objects.
|
||||
This is useful for things such as the power monitor, which needs to exist on a physical console in the world, but also as a virtual device the AI can use
|
||||
|
||||
Code is pretty much ripped verbatim from nano modules, but with un-needed stuff removed
|
||||
*/
|
||||
/datum/tgui_module
|
||||
var/name
|
||||
var/datum/host
|
||||
|
||||
/datum/tgui_module/New(var/host)
|
||||
src.host = host
|
||||
|
||||
/datum/tgui_module/tgui_host()
|
||||
return host ? host : src
|
||||
|
||||
/datum/tgui_module/tgui_close(mob/user)
|
||||
if(host)
|
||||
host.tgui_close(user)
|
||||
@@ -0,0 +1,39 @@
|
||||
/datum/tgui_module/crew_monitor
|
||||
name = "Crew monitor"
|
||||
|
||||
/datum/tgui_module/crew_monitor/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
var/turf/T = get_turf(tgui_host())
|
||||
if(!T || !is_level_reachable(T.z))
|
||||
to_chat(usr, "<span class='warning'><b>Unable to establish a connection</b>: You're too far away from the station!</span>")
|
||||
return FALSE
|
||||
|
||||
switch(action)
|
||||
if("track")
|
||||
if(isAI(usr))
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
var/mob/living/carbon/human/H = locate(params["track"]) in GLOB.mob_list
|
||||
if(hassensorlevel(H, SUIT_SENSOR_TRACKING))
|
||||
AI.ai_actual_track(H)
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/tgui_module/crew_monitor/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
// The 557 may seem random, but its the perfectsize for margins on the nanomap
|
||||
ui = new(user, src, ui_key, "CrewMonitor", name, 1400, 557, master_ui, state)
|
||||
ui.autoupdate = TRUE
|
||||
ui.open()
|
||||
|
||||
|
||||
/datum/tgui_module/crew_monitor/tgui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state)
|
||||
var/data[0]
|
||||
var/turf/T = get_turf(tgui_host())
|
||||
|
||||
data["isAI"] = isAI(user)
|
||||
data["crewmembers"] = GLOB.crew_repository.health_data(T)
|
||||
|
||||
return data
|
||||
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* tgui states
|
||||
*
|
||||
* Base state and helpers for states. Just does some sanity checks, implement a state for in-depth checks.
|
||||
*/
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Checks the UI state for a mob.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* required state datum/ui_state The state to check.
|
||||
*
|
||||
* return UI_state The state of the UI.
|
||||
*/
|
||||
/datum/proc/tgui_status(mob/user, datum/tgui_state/state)
|
||||
var/src_object = tgui_host(user)
|
||||
. = STATUS_CLOSE
|
||||
if(!state)
|
||||
return
|
||||
|
||||
if(isobserver(user))
|
||||
// If they turn on ghost AI control, admins can always interact.
|
||||
if(user.client.advanced_admin_interaction)
|
||||
. = max(., STATUS_INTERACTIVE)
|
||||
|
||||
// Regular ghosts can always at least view if in range.
|
||||
var/clientviewlist = getviewsize(user.client.view)
|
||||
if(get_dist(src_object, user) < max(clientviewlist[1],clientviewlist[2]))
|
||||
. = max(., STATUS_UPDATE)
|
||||
|
||||
// Check if the state allows interaction
|
||||
var/result = state.can_use_topic(src_object, user)
|
||||
. = max(., result)
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Checks if a user can use src_object's UI, and returns the state.
|
||||
* Can call a mob proc, which allows overrides for each mob.
|
||||
*
|
||||
* required src_object datum The object/datum which owns the UI.
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
*
|
||||
* return UI_state The state of the UI.
|
||||
*/
|
||||
/datum/tgui_state/proc/can_use_topic(src_object, mob/user)
|
||||
return STATUS_CLOSE // Don't allow interaction by default.
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Standard interaction/sanity checks. Different mob types may have overrides.
|
||||
*
|
||||
* return UI_state The state of the UI.
|
||||
*/
|
||||
/mob/proc/shared_tgui_interaction(src_object)
|
||||
if(!client) // Close UIs if mindless.
|
||||
return STATUS_CLOSE
|
||||
else if(stat) // Disable UIs if unconcious.
|
||||
return STATUS_DISABLED
|
||||
else if(incapacitated()) // Update UIs if incapicitated but concious.
|
||||
return STATUS_UPDATE
|
||||
return STATUS_INTERACTIVE
|
||||
|
||||
/mob/living/silicon/ai/shared_tgui_interaction(src_object)
|
||||
if(lacks_power()) // Disable UIs if the AI is unpowered.
|
||||
return STATUS_DISABLED
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/shared_tgui_interaction(src_object)
|
||||
if(!cell || cell.charge <= 0 || lockcharge) // Disable UIs if the Borg is unpowered or locked.
|
||||
return STATUS_DISABLED
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Check the distance for a living mob.
|
||||
* Really only used for checks outside the context of a mob.
|
||||
* Otherwise, use shared_living_ui_distance().
|
||||
*
|
||||
* required src_object The object which owns the UI.
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
*
|
||||
* return UI_state The state of the UI.
|
||||
*/
|
||||
/atom/proc/contents_tgui_distance(src_object, mob/living/user)
|
||||
return user.shared_living_tgui_distance(src_object) // Just call this mob's check.
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Distance versus interaction check.
|
||||
*
|
||||
* required src_object atom/movable The object which owns the UI.
|
||||
*
|
||||
* return UI_state The state of the UI.
|
||||
*/
|
||||
/mob/living/proc/shared_living_tgui_distance(atom/movable/src_object, viewcheck = TRUE)
|
||||
if(viewcheck && !(src_object in view(src))) // If the object is obscured, close it.
|
||||
return STATUS_CLOSE
|
||||
|
||||
var/dist = get_dist(src_object, src)
|
||||
if(dist <= 1) // Open and interact if 1-0 tiles away.
|
||||
return STATUS_INTERACTIVE
|
||||
else if(dist <= 2) // View only if 2-3 tiles away.
|
||||
return STATUS_UPDATE
|
||||
else if(dist <= 5) // Disable if 5 tiles away.
|
||||
return STATUS_DISABLED
|
||||
return STATUS_CLOSE // Otherwise, we got nothing.
|
||||
|
||||
/mob/living/carbon/human/shared_living_tgui_distance(atom/movable/src_object)
|
||||
if((TK in mutations) && (get_dist(src, src_object) <= 2))
|
||||
return STATUS_INTERACTIVE
|
||||
return ..()
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* tgui state: admin_state
|
||||
*
|
||||
* Checks that the user is an admin, end-of-story.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_admin_state, /datum/tgui_state/admin_state, new)
|
||||
|
||||
/datum/tgui_state/admin_state/can_use_topic(src_object, mob/user)
|
||||
if(check_rights_for(user.client, R_ADMIN))
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_CLOSE
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
/**
|
||||
* tgui state: always_state
|
||||
*
|
||||
* Always grants the user UI_INTERACTIVE. Period.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_always_state, /datum/tgui_state/always_state, new)
|
||||
|
||||
/datum/tgui_state/always_state/can_use_topic(src_object, mob/user)
|
||||
return STATUS_INTERACTIVE
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* tgui state: conscious_state
|
||||
*
|
||||
* Only checks if the user is conscious.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_conscious_state, /datum/tgui_state/conscious_state, new)
|
||||
|
||||
/datum/tgui_state/conscious_state/can_use_topic(src_object, mob/user)
|
||||
if(user.stat == CONSCIOUS)
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_CLOSE
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* tgui state: contained_state
|
||||
*
|
||||
* Checks that the user is inside the src_object.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_contained_state, /datum/tgui_state/contained_state, new)
|
||||
|
||||
/datum/tgui_state/contained_state/can_use_topic(atom/src_object, mob/user)
|
||||
if(!src_object.contains(user))
|
||||
return STATUS_CLOSE
|
||||
return user.shared_tgui_interaction(src_object)
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* tgui state: deep_inventory_state
|
||||
*
|
||||
* Checks that the src_object is in the user's deep (backpack, box, toolbox, etc) inventory.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_deep_inventory_state, /datum/tgui_state/deep_inventory_state, new)
|
||||
|
||||
/datum/tgui_state/deep_inventory_state/can_use_topic(src_object, mob/user)
|
||||
if(!user.contains(src_object))
|
||||
return STATUS_CLOSE
|
||||
return user.shared_tgui_interaction(src_object)
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* tgui state: default_state
|
||||
*
|
||||
* Checks a number of things -- mostly physical distance for humans and view for robots.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_default_state, /datum/tgui_state/default, new)
|
||||
|
||||
/datum/tgui_state/default/can_use_topic(src_object, mob/user)
|
||||
return user.default_can_use_tgui_topic(src_object) // Call the individual mob-overridden procs.
|
||||
|
||||
/mob/proc/default_can_use_tgui_topic(src_object)
|
||||
return STATUS_CLOSE // Don't allow interaction by default.
|
||||
|
||||
/mob/living/default_can_use_tgui_topic(src_object)
|
||||
. = shared_tgui_interaction(src_object)
|
||||
if(. > STATUS_CLOSE && loc)
|
||||
. = min(., loc.contents_tgui_distance(src_object, src)) // Check the distance...
|
||||
if(. == STATUS_INTERACTIVE) // Non-human living mobs can only look, not touch.
|
||||
return STATUS_UPDATE
|
||||
|
||||
/mob/living/carbon/human/default_can_use_tgui_topic(src_object)
|
||||
. = shared_tgui_interaction(src_object)
|
||||
if(. > STATUS_CLOSE)
|
||||
. = min(., shared_living_tgui_distance(src_object)) // Check the distance...
|
||||
|
||||
/mob/living/silicon/robot/default_can_use_tgui_topic(src_object)
|
||||
. = shared_tgui_interaction(src_object)
|
||||
if(. <= STATUS_DISABLED)
|
||||
return
|
||||
|
||||
// Robots can interact with anything they can see.
|
||||
var/list/clientviewlist = getviewsize(client.view)
|
||||
if((src_object in view(src)) && (get_dist(src, src_object) <= min(clientviewlist[1],clientviewlist[2])))
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_DISABLED // Otherwise they can keep the UI open.
|
||||
|
||||
/mob/living/silicon/ai/default_can_use_tgui_topic(src_object)
|
||||
. = shared_tgui_interaction(src_object)
|
||||
if(. < STATUS_INTERACTIVE)
|
||||
return
|
||||
|
||||
// The AI can interact with anything it can see nearby, or with cameras while wireless control is enabled.
|
||||
if(!control_disabled && can_see(src_object))
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_CLOSE
|
||||
|
||||
/mob/living/simple_animal/default_can_use_tgui_topic(src_object)
|
||||
. = shared_tgui_interaction(src_object)
|
||||
if(. > STATUS_CLOSE)
|
||||
. = min(., shared_living_tgui_distance(src_object)) //simple animals can only use things they're near.
|
||||
|
||||
/mob/living/silicon/pai/default_can_use_tgui_topic(src_object)
|
||||
// pAIs can only use themselves and the owner's radio.
|
||||
if((src_object == src || src_object == radio) && !stat)
|
||||
return STATUS_INTERACTIVE
|
||||
else
|
||||
return ..()
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* tgui state: hands_state
|
||||
*
|
||||
* Checks that the src_object is in the user's hands.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_hands_state, /datum/tgui_state/hands_state, new)
|
||||
|
||||
/datum/tgui_state/hands_state/can_use_topic(src_object, mob/user)
|
||||
. = user.shared_tgui_interaction(src_object)
|
||||
if(. > STATUS_CLOSE)
|
||||
return min(., user.hands_can_use_tgui_topic(src_object))
|
||||
|
||||
/mob/proc/hands_can_use_tgui_topic(src_object)
|
||||
return STATUS_CLOSE
|
||||
|
||||
/mob/living/hands_can_use_tgui_topic(src_object)
|
||||
if(is_in_active_hand(src_object) || is_in_inactive_hand(src_object))
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_CLOSE
|
||||
|
||||
/mob/living/silicon/robot/hands_can_use_tgui_topic(src_object)
|
||||
if(activated(src_object))
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_CLOSE
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
/**
|
||||
* tgui state: human_adjacent_state
|
||||
*
|
||||
* In addition to default checks, only allows interaction for a
|
||||
* human adjacent user.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_human_adjacent_state, /datum/tgui_state/human_adjacent_state, new)
|
||||
|
||||
/datum/tgui_state/human_adjacent_state/can_use_topic(src_object, mob/user)
|
||||
. = user.default_can_use_tgui_topic(src_object)
|
||||
|
||||
var/dist = get_dist(src_object, user)
|
||||
if((dist > 1) || (!ishuman(user)))
|
||||
// Can't be used unless adjacent and human, even with TK
|
||||
. = min(., STATUS_UPDATE)
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* tgui state: inventory_state
|
||||
*
|
||||
* Checks that the src_object is in the user's top-level (hand, ear, pocket, belt, etc) inventory.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_inventory_state, /datum/tgui_state/inventory_state, new)
|
||||
|
||||
/datum/tgui_state/inventory_state/can_use_topic(src_object, mob/user)
|
||||
if(!(src_object in user))
|
||||
return STATUS_CLOSE
|
||||
return user.shared_tgui_interaction(src_object)
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* tgui state: not_incapacitated_state
|
||||
*
|
||||
* Checks that the user isn't incapacitated
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_not_incapacitated_state, /datum/tgui_state/not_incapacitated_state, new)
|
||||
|
||||
/**
|
||||
* tgui state: not_incapacitated_turf_state
|
||||
*
|
||||
* Checks that the user isn't incapacitated and that their loc is a turf
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_not_incapacitated_turf_state, /datum/tgui_state/not_incapacitated_state, new(no_turfs = TRUE))
|
||||
|
||||
/datum/tgui_state/not_incapacitated_state
|
||||
var/turf_check = FALSE
|
||||
|
||||
/datum/tgui_state/not_incapacitated_state/New(loc, no_turfs = FALSE)
|
||||
..()
|
||||
turf_check = no_turfs
|
||||
|
||||
/datum/tgui_state/not_incapacitated_state/can_use_topic(src_object, mob/user)
|
||||
if(user.stat)
|
||||
return STATUS_CLOSE
|
||||
if(user.incapacitated() || (turf_check && !isturf(user.loc)))
|
||||
return STATUS_DISABLED
|
||||
return STATUS_INTERACTIVE
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* tgui state: notcontained_state
|
||||
*
|
||||
* Checks that the user is not inside src_object, and then makes the default checks.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_notcontained_state, /datum/tgui_state/notcontained_state, new)
|
||||
|
||||
/datum/tgui_state/notcontained_state/can_use_topic(atom/src_object, mob/user)
|
||||
. = user.shared_tgui_interaction(src_object)
|
||||
if(. > STATUS_CLOSE)
|
||||
return min(., user.notcontained_can_use_tgui_topic(src_object))
|
||||
|
||||
/mob/proc/notcontained_can_use_tgui_topic(src_object)
|
||||
return STATUS_CLOSE
|
||||
|
||||
/mob/living/notcontained_can_use_tgui_topic(atom/src_object)
|
||||
if(src_object.contains(src))
|
||||
return STATUS_CLOSE // Close if we're inside it.
|
||||
return default_can_use_tgui_topic(src_object)
|
||||
|
||||
/mob/living/silicon/notcontained_can_use_tgui_topic(src_object)
|
||||
return default_can_use_tgui_topic(src_object) // Silicons use default bevhavior.
|
||||
|
||||
/mob/living/simple_animal/drone/notcontained_can_use_tgui_topic(src_object)
|
||||
return default_can_use_tgui_topic(src_object) // Drones use default bevhavior.
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* tgui state: observer_state
|
||||
*
|
||||
* Checks that the user is an observer/ghost.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_observer_state, /datum/tgui_state/observer_state, new)
|
||||
|
||||
/datum/tgui_state/observer_state/can_use_topic(src_object, mob/user)
|
||||
if(isobserver(user))
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_CLOSE
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* tgui state: physical_state
|
||||
*
|
||||
* Short-circuits the default state to only check physical distance.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_physical_state, /datum/tgui_state/physical, new)
|
||||
|
||||
/datum/tgui_state/physical/can_use_topic(src_object, mob/user)
|
||||
. = user.shared_tgui_interaction(src_object)
|
||||
if(. > STATUS_CLOSE)
|
||||
return min(., user.physical_can_use_tgui_topic(src_object))
|
||||
|
||||
/mob/proc/physical_can_use_tgui_topic(src_object)
|
||||
return STATUS_CLOSE
|
||||
|
||||
/mob/living/physical_can_use_tgui_topic(src_object)
|
||||
return shared_living_tgui_distance(src_object)
|
||||
|
||||
/mob/living/silicon/physical_can_use_tgui_topic(src_object)
|
||||
return max(STATUS_UPDATE, shared_living_tgui_distance(src_object)) // Silicons can always see.
|
||||
|
||||
/mob/living/silicon/ai/physical_can_use_tgui_topic(src_object)
|
||||
return STATUS_UPDATE // AIs are not physical.
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* tgui state: self_state
|
||||
*
|
||||
* Only checks that the user and src_object are the same.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_self_state, /datum/tgui_state/self_state, new)
|
||||
|
||||
/datum/tgui_state/self_state/can_use_topic(src_object, mob/user)
|
||||
if(src_object != user)
|
||||
return STATUS_CLOSE
|
||||
return user.shared_tgui_interaction(src_object)
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* tgui state: z_state
|
||||
*
|
||||
* Only checks that the Z-level of the user and src_object are the same.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(tgui_z_state, /datum/tgui_state/z_state, new)
|
||||
|
||||
/datum/tgui_state/z_state/can_use_topic(src_object, mob/user)
|
||||
var/turf/turf_obj = get_turf(src_object)
|
||||
var/turf/turf_usr = get_turf(user)
|
||||
if(turf_obj && turf_usr && turf_obj.z == turf_usr.z)
|
||||
return STATUS_INTERACTIVE
|
||||
return STATUS_CLOSE
|
||||
@@ -0,0 +1,363 @@
|
||||
/**
|
||||
* tgui
|
||||
*
|
||||
* /tg/station user interface library
|
||||
*/
|
||||
|
||||
/**
|
||||
* tgui datum (represents a UI).
|
||||
*/
|
||||
/datum/tgui
|
||||
/// The mob who opened/is using the UI.
|
||||
var/mob/user
|
||||
/// The object which owns the UI.
|
||||
var/datum/src_object
|
||||
/// The title of te UI.
|
||||
var/title
|
||||
/// The ui_key of the UI. This allows multiple UIs for one src_object.
|
||||
var/ui_key
|
||||
/// The window_id for browse() and onclose().
|
||||
var/window_id
|
||||
/// The window width.
|
||||
var/width = 0
|
||||
/// The window height
|
||||
var/height = 0
|
||||
/// The interface (template) to be used for this UI.
|
||||
var/interface
|
||||
/// Update the UI every MC tick.
|
||||
var/autoupdate = TRUE
|
||||
/// If the UI has been initialized yet.
|
||||
var/initialized = FALSE
|
||||
/// The data (and datastructure) used to initialize the UI.
|
||||
var/list/initial_data
|
||||
/// The static data used to initialize the UI.
|
||||
var/list/initial_static_data
|
||||
/// Holder for the json string, that is sent during the initial update
|
||||
var/_initial_update
|
||||
/// The status/visibility of the UI.
|
||||
var/status = STATUS_INTERACTIVE
|
||||
/// Topic state used to determine status/interactability.
|
||||
var/datum/tgui_state/state = null
|
||||
/// The parent UI.
|
||||
var/datum/tgui/master_ui
|
||||
/// Children of this UI.
|
||||
var/list/datum/tgui/children = list()
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Create a new UI.
|
||||
*
|
||||
* required user mob The mob who opened/is using the UI.
|
||||
* required src_object datum The object or datum which owns the UI.
|
||||
* required ui_key string The ui_key of the UI.
|
||||
* required interface string The interface used to render the UI.
|
||||
* optional title string The title of the UI.
|
||||
* optional width int The window width.
|
||||
* optional height int The window height.
|
||||
* optional master_ui datum/tgui The parent UI.
|
||||
* optional state datum/ui_state The state used to determine status.
|
||||
*
|
||||
* return datum/tgui The requested UI.
|
||||
*/
|
||||
/datum/tgui/New(mob/user, datum/src_object, ui_key, interface, title, width = 0, height = 0, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
|
||||
src.user = user
|
||||
src.src_object = src_object
|
||||
src.ui_key = ui_key
|
||||
src.window_id = "[src_object.UID()]-[ui_key]"
|
||||
src.interface = interface
|
||||
|
||||
if(title)
|
||||
src.title = sanitize(title)
|
||||
if(width)
|
||||
src.width = width
|
||||
if(height)
|
||||
src.height = height
|
||||
|
||||
src.master_ui = master_ui
|
||||
if(master_ui)
|
||||
master_ui.children += src
|
||||
src.state = state
|
||||
|
||||
var/datum/asset/tgui_assets = get_asset_datum(/datum/asset/simple/tgui)
|
||||
var/datum/asset/fa = get_asset_datum(/datum/asset/simple/fontawesome)
|
||||
tgui_assets.send(user)
|
||||
fa.send(user)
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Open this UI (and initialize it with data).
|
||||
*/
|
||||
/datum/tgui/proc/open()
|
||||
if(!user.client)
|
||||
return // Bail if there is no client.
|
||||
|
||||
update_status(push = FALSE) // Update the window status.
|
||||
if(status < STATUS_UPDATE)
|
||||
return // Bail if we're not supposed to open.
|
||||
|
||||
|
||||
|
||||
// Build window options
|
||||
var/window_options = "can_minimize=0;auto_format=0;"
|
||||
// If we have a width and height, use them.
|
||||
if(width && height)
|
||||
window_options += "size=[width]x[height];"
|
||||
|
||||
// Remove titlebar and resize handles for a fancy window
|
||||
if(user.client.prefs.nanoui_fancy)
|
||||
window_options += "titlebar=0;can_resize=0;"
|
||||
else
|
||||
window_options += "titlebar=1;can_resize=1;"
|
||||
|
||||
// Generate page html
|
||||
var/html
|
||||
html = SStgui.basehtml
|
||||
// Allow the src object to override the html if needed
|
||||
html = src_object.tgui_base_html(html)
|
||||
// Replace template tokens with important UI data
|
||||
html = replacetextEx(html, "\[tgui:ref]", "[src.UID()]")
|
||||
|
||||
// Open the window.
|
||||
user << browse(html, "window=[window_id];[window_options]")
|
||||
|
||||
// Instruct the client to signal UI when the window is closed.
|
||||
// NOTE: Intentional \ref usage; tgui datums can't/shouldn't
|
||||
// be tagged, so this is an effective unwrap
|
||||
winset(user, window_id, "on-close=\"uiclose [UID()]\"")
|
||||
|
||||
// Pre-fetch initial state while browser is still loading in
|
||||
// another thread
|
||||
if(!initial_data)
|
||||
initial_data = src_object.tgui_data(user)
|
||||
if(!initial_static_data)
|
||||
initial_static_data = src_object.tgui_static_data(user)
|
||||
_initial_update = url_encode(get_json(initial_data, initial_static_data))
|
||||
|
||||
SStgui.on_open(src)
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Reinitialize the UI.
|
||||
* (Possibly with a new interface and/or data).
|
||||
*
|
||||
* optional template string The name of the new interface.
|
||||
* optional data list The new initial data.
|
||||
*/
|
||||
/datum/tgui/proc/reinitialize(interface, list/data, list/static_data)
|
||||
if(interface)
|
||||
src.interface = interface
|
||||
if(data)
|
||||
initial_data = data
|
||||
if(static_data)
|
||||
initial_static_data = static_data
|
||||
open()
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Close the UI, and all its children.
|
||||
*/
|
||||
/datum/tgui/proc/close()
|
||||
user << browse(null, "window=[window_id]") // Close the window.
|
||||
src_object.tgui_close(user)
|
||||
SStgui.on_close(src)
|
||||
for(var/datum/tgui/child in children) // Loop through and close all children.
|
||||
child.close()
|
||||
children.Cut()
|
||||
state = null
|
||||
master_ui = null
|
||||
qdel(src)
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Enable/disable auto-updating of the UI.
|
||||
*
|
||||
* required state bool Enable/disable auto-updating.
|
||||
*/
|
||||
/datum/tgui/proc/set_autoupdate(state = TRUE)
|
||||
autoupdate = state
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Package the data to send to the UI, as JSON.
|
||||
* This includes the UI data and config_data.
|
||||
*
|
||||
* return string The packaged JSON.
|
||||
*/
|
||||
/datum/tgui/proc/get_json(list/data, list/static_data)
|
||||
var/list/json_data = list()
|
||||
|
||||
json_data["config"] = list(
|
||||
"title" = title,
|
||||
"status" = status,
|
||||
"interface" = interface,
|
||||
"fancy" = user.client.prefs.nanoui_fancy,
|
||||
"observer" = isobserver(user),
|
||||
"window" = window_id,
|
||||
"map" = (GLOB.using_map && GLOB.using_map.name) ? GLOB.using_map.name : "Unknown",
|
||||
|
||||
"ref" = "[src.UID()]"
|
||||
)
|
||||
|
||||
if(!isnull(data))
|
||||
json_data["data"] = data
|
||||
if(!isnull(static_data))
|
||||
json_data["static_data"] = static_data
|
||||
|
||||
// Send shared states
|
||||
if(src_object.tgui_shared_states)
|
||||
json_data["shared"] = src_object.tgui_shared_states
|
||||
|
||||
// Generate the JSON.
|
||||
var/json = json_encode(json_data)
|
||||
// Strip #255/improper.
|
||||
json = replacetext(json, "\proper", "")
|
||||
json = replacetext(json, "\improper", "")
|
||||
return json
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Handle clicks from the UI.
|
||||
* Call the src_object's ui_act() if status is UI_INTERACTIVE.
|
||||
* If the src_object's ui_act() returns 1, update all UIs attacked to it.
|
||||
*/
|
||||
/datum/tgui/Topic(href, href_list)
|
||||
if(user != usr)
|
||||
return // Something is not right here.
|
||||
|
||||
var/action = href_list["action"]
|
||||
var/params = href_list; params -= "action"
|
||||
|
||||
switch(action)
|
||||
if("tgui:initialize")
|
||||
user << output(_initial_update, "[window_id].browser:update")
|
||||
initialized = TRUE
|
||||
if("tgui:setSharedState")
|
||||
// Update the window state.
|
||||
update_status(push = FALSE)
|
||||
// Bail if UI is not interactive or usr calling Topic
|
||||
// is not the UI user.
|
||||
if(status != STATUS_INTERACTIVE)
|
||||
return
|
||||
var/key = params["key"]
|
||||
var/value = params["value"]
|
||||
if(!src_object.tgui_shared_states)
|
||||
src_object.tgui_shared_states = list()
|
||||
src_object.tgui_shared_states[key] = value
|
||||
SStgui.update_uis(src_object)
|
||||
if("tgui:setFancy")
|
||||
var/value = text2num(params["value"])
|
||||
user.client.prefs.nanoui_fancy = value
|
||||
if("tgui:log")
|
||||
// Force window to show frills on fatal errors
|
||||
if(params["fatal"])
|
||||
winset(user, window_id, "titlebar=1;can-resize=1;size=600x600")
|
||||
log_message(params["log"])
|
||||
if("tgui:link")
|
||||
user << link(params["url"])
|
||||
|
||||
else
|
||||
// Update the window state.
|
||||
update_status(push = FALSE)
|
||||
// Call tgui_act() on the src_object.
|
||||
if(src_object.tgui_act(action, params, src, state))
|
||||
// Update if the object requested it.
|
||||
SStgui.update_uis(src_object)
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Update the UI.
|
||||
* Only updates the data if update is true, otherwise only updates the status.
|
||||
*
|
||||
* optional force bool If the UI should be forced to update.
|
||||
*/
|
||||
/datum/tgui/process(force = FALSE)
|
||||
var/datum/host = src_object.tgui_host(user)
|
||||
if(!src_object || !host || !user) // If the object or user died (or something else), abort.
|
||||
close()
|
||||
return
|
||||
|
||||
if(status && (force || autoupdate))
|
||||
update() // Update the UI if the status and update settings allow it.
|
||||
else
|
||||
update_status(push = TRUE) // Otherwise only update status.
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Push data to an already open UI.
|
||||
*
|
||||
* required data list The data to send.
|
||||
* optional force bool If the update should be sent regardless of state.
|
||||
*/
|
||||
/datum/tgui/proc/push_data(data, static_data, force = FALSE)
|
||||
// Update the window state.
|
||||
update_status(push = FALSE)
|
||||
// Cannot update UI if it is not set up yet.
|
||||
if(!initialized)
|
||||
return
|
||||
// Cannot update UI, we have no visibility.
|
||||
if(status <= STATUS_DISABLED && !force)
|
||||
return
|
||||
// Send the new JSON to the update() Javascript function.
|
||||
user << output(
|
||||
url_encode(get_json(data, static_data)),
|
||||
"[window_id].browser:update")
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Updates the UI by interacting with the src_object again, which will hopefully
|
||||
* call try_ui_update on it.
|
||||
*
|
||||
* optional force_open bool If force_open should be passed to ui_interact.
|
||||
*/
|
||||
/datum/tgui/proc/update(force_open = FALSE)
|
||||
src_object.tgui_interact(user, ui_key, src, force_open, master_ui, state)
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Update the status/visibility of the UI for its user.
|
||||
*
|
||||
* optional push bool Push an update to the UI (an update is always sent for UI_DISABLED).
|
||||
*/
|
||||
/datum/tgui/proc/update_status(push = FALSE)
|
||||
var/status = src_object.tgui_status(user, state)
|
||||
if(master_ui)
|
||||
status = min(status, master_ui.status)
|
||||
|
||||
set_status(status, push)
|
||||
if(status == STATUS_CLOSE)
|
||||
close()
|
||||
|
||||
/**
|
||||
* private
|
||||
*
|
||||
* Set the status/visibility of the UI.
|
||||
*
|
||||
* required status int The status to set (UI_CLOSE/UI_DISABLED/UI_UPDATE/UI_INTERACTIVE).
|
||||
* optional push bool Push an update to the UI (an update is always sent for UI_DISABLED).
|
||||
*/
|
||||
/datum/tgui/proc/set_status(status, push = FALSE)
|
||||
// Only update if status has changed.
|
||||
if(src.status != status)
|
||||
if(src.status == STATUS_DISABLED)
|
||||
src.status = status
|
||||
if(push)
|
||||
update()
|
||||
else
|
||||
src.status = status
|
||||
// Update if the UI just because disabled, or a push is requested.
|
||||
if(status == STATUS_DISABLED || push)
|
||||
push_data(null, force = TRUE)
|
||||
|
||||
/datum/tgui/proc/log_message(message)
|
||||
log_tgui("[user] ([user.ckey]) using \"[title]\":\n[message]")
|
||||
Reference in New Issue
Block a user