Merge pull request #14342 from neersighted/tgui_followup

More tgui fixes and tweaks
This commit is contained in:
tkdrg
2016-01-04 18:39:52 -03:00
39 changed files with 242 additions and 180 deletions
+5 -5
View File
@@ -1232,10 +1232,10 @@ B --><-- A
return L
/atom/proc/contains(var/atom/location)
if(!location)
/atom/proc/contains(var/atom/A)
if(!A)
return 0
for(location, location && location != src, location=location.loc); //semicolon is for the empty statement
for(var/atom/location = A.loc, location, location = location.loc)
if(location == src)
return 1
return 0
return 1
+4 -4
View File
@@ -9,8 +9,8 @@ var/datum/subsystem/tgui/SStgui
can_fire = 1 // This needs to fire before round start.
var/list/open_uis = list() // A list of open UIs, grouped by src_object and ui_key.
var/list/processing_uis = list() // A list of processing UIs, not grouped.
var/basehtml // The HTML template used by new UIs; minus initial data.
var/list/processing_uis = list() // A list of processing UIs, ungrouped.
var/basehtml // The HTML base used for all UIs.
/datum/subsystem/tgui/New()
@@ -19,9 +19,9 @@ var/datum/subsystem/tgui/SStgui
NEW_SS_GLOBAL(SStgui)
/datum/subsystem/tgui/stat_entry()
..("O:[open_uis.len]|P:[processing_uis.len]") // Show how many interfaces we have open/are processing.
..("P:[processing_uis.len]")
/datum/subsystem/tgui/fire() // Process UIs.
/datum/subsystem/tgui/fire()
for(var/thing in processing_uis)
var/datum/tgui/ui = thing
if(ui && ui.user && ui.src_object)
+1 -1
View File
@@ -190,7 +190,7 @@
/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "air_alarm", name, 390, 590)
ui = new(user, src, ui_key, "air_alarm", name, 440, 650)
ui.open()
/obj/machinery/alarm/get_ui_data(mob/user)
+1
View File
@@ -17,6 +17,7 @@
/obj/Destroy()
if(!istype(src, /obj/machinery))
SSobj.processing.Remove(src) // TODO: Have a processing bitflag to reduce on unnecessary loops through the processing lists
SStgui.close_uis(src)
return ..()
/obj/assume_air(datum/gas_mixture/giver)
-4
View File
@@ -35,10 +35,6 @@
return
cmd_admin_pm(href_list["priv_msg"],null)
return
// NanoUI
if(href_list["nano_error"])
src << href_list["nano_error"]
throw EXCEPTION("NanoUI: [href_list["nano_error"]]")
//Logs all hrefs
if(config && config.log_hrefs && href_logfile)
+1 -1
View File
@@ -629,7 +629,7 @@
/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/tgui/ui = null, force_open = 0)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "apc", name, 460, 520)
ui = new(user, src, ui_key, "apc", name, 535, 515)
ui.open()
/obj/machinery/power/apc/get_ui_data(mob/user)
@@ -88,7 +88,7 @@
/obj/machinery/chem_dispenser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "chem_dispenser", name, 550, 700)
ui = new(user, src, ui_key, "chem_dispenser", name, 550, 550)
ui.open()
/obj/machinery/chem_dispenser/get_ui_data()
@@ -129,11 +129,9 @@
switch(action)
if("amount")
amount = round(text2num(params["amount"]), 5) // round to nearest 5
if (amount < 0) // Since the user can actually type the commands himself, some sanity checking
amount = 0
if (amount > 100)
amount = 100
var/amount = text2num(params["amount"])
if(amount in beaker.possible_transfer_amounts)
src.amount = amount
if("dispense")
if(beaker && dispensable_reagents.Find(params["reagent"]))
var/datum/reagents/R = beaker.reagents
+6 -5
View File
@@ -17,7 +17,7 @@
* optional master_ui datum/tgui The parent UI.
* optional state datum/ui_state The state used to determine status.
**/
/atom/movable/proc/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, \
/datum/proc/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, \
force_open = 0, datum/tgui/master_ui = null, \
datum/ui_state/state = default_state)
return -1 // Sorta implemented.
@@ -32,7 +32,7 @@
*
* return list Data to be sent to the UI.
**/
/atom/movable/proc/get_ui_data(mob/user)
/datum/proc/get_ui_data(mob/user)
return list() // Not implemented.
@@ -47,7 +47,7 @@
*
* return bool If the UI should be updated or not.
**/
/atom/movable/proc/ui_act(action, list/params)
/datum/proc/ui_act(action, list/params)
return // Not implemented.
@@ -55,9 +55,10 @@
* private
*
* The UI's host object (usually src_object).
* Used internally by ui_state(s).
* This allows modules/datums to have the UI attached to them,
* and be a part of another object.
**/
/atom/proc/ui_host()
/datum/proc/ui_host()
return src
/**
+1 -1
View File
@@ -6,7 +6,7 @@
/var/global/datum/ui_state/admin_state/admin_state = new()
/datum/ui_state/admin_state/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/admin_state/can_use_topic(src_object, mob/user)
if(check_rights_for(user.client, R_ADMIN))
return UI_INTERACTIVE
return UI_CLOSE
+1 -1
View File
@@ -6,7 +6,7 @@
/var/global/datum/ui_state/conscious_state/conscious_state = new()
/datum/ui_state/conscious_state/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/conscious_state/can_use_topic(src_object, mob/user)
if(user.stat == CONSCIOUS)
return UI_INTERACTIVE
return UI_CLOSE
+1 -1
View File
@@ -6,7 +6,7 @@
/var/global/datum/ui_state/contained_state/contained_state = new()
/datum/ui_state/contained_state/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/contained_state/can_use_topic(atom/src_object, mob/user)
if(!src_object.contains(user))
return UI_CLOSE
return user.shared_ui_interaction(src_object)
+2 -2
View File
@@ -1,12 +1,12 @@
/**
* tgui state: deep_inventory_state
*
* Checks that the src_object is in the user's fist-level (backpack, webbing, etc) inventory.
* Checks that the src_object is in the user's deep (backpack, box, toolbox, etc) inventory.
**/
/var/global/datum/ui_state/deep_inventory_state/deep_inventory_state = new()
/datum/ui_state/deep_inventory_state/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/deep_inventory_state/can_use_topic(src_object, mob/user)
if(!user.contains(src_object))
return UI_CLOSE
return user.shared_ui_interaction(src_object)
+10 -10
View File
@@ -6,20 +6,20 @@
/var/global/datum/ui_state/default/default_state = new()
/datum/ui_state/default/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/default/can_use_topic(src_object, mob/user)
return user.default_can_use_topic(src_object) // Call the individual mob-overriden procs.
/mob/proc/default_can_use_topic(atom/movable/src_object)
/mob/proc/default_can_use_topic(src_object)
return UI_CLOSE // Don't allow interaction by default.
/mob/living/default_can_use_topic(atom/movable/src_object)
/mob/living/default_can_use_topic(src_object)
. = shared_ui_interaction(src_object)
if(. > UI_CLOSE)
. = min(., shared_living_ui_distance(src_object)) // Check the distance...
if(. > UI_CLOSE && loc)
. = min(., loc.contents_ui_distance(src_object, src)) // Check the distance...
if(. == UI_INTERACTIVE) // Non-human living mobs can only look, not touch.
return UI_UPDATE
/mob/living/carbon/human/default_can_use_topic(atom/movable/src_object)
/mob/living/carbon/human/default_can_use_topic(src_object)
. = shared_ui_interaction(src_object)
if(. > UI_CLOSE)
. = min(., shared_living_ui_distance(src_object)) // Check the distance...
@@ -27,7 +27,7 @@
if(prob(getBrainLoss()))
return UI_UPDATE
/mob/living/silicon/robot/default_can_use_topic(atom/movable/src_object)
/mob/living/silicon/robot/default_can_use_topic(src_object)
. = shared_ui_interaction(src_object)
if(. <= UI_DISABLED)
return
@@ -37,7 +37,7 @@
return UI_INTERACTIVE
return UI_DISABLED // Otherwise they can keep the UI open.
/mob/living/silicon/ai/default_can_use_topic(atom/movable/src_object)
/mob/living/silicon/ai/default_can_use_topic(src_object)
. = shared_ui_interaction(src_object)
if(. < UI_INTERACTIVE)
return
@@ -47,12 +47,12 @@
return UI_INTERACTIVE
return UI_CLOSE
/mob/living/simple_animal/drone/default_can_use_topic(atom/movable/src_object)
/mob/living/simple_animal/drone/default_can_use_topic(src_object)
. = shared_ui_interaction(src_object)
if(. > UI_CLOSE)
. = min(., shared_living_ui_distance(src_object)) // Drones can only use things they're near.
/mob/living/silicon/pai/default_can_use_topic(atom/movable/src_object)
/mob/living/silicon/pai/default_can_use_topic(src_object)
// pAIs can only use themselves and the owner's radio.
if((src_object == src || src_object == radio) && !stat)
return UI_INTERACTIVE
+3 -3
View File
@@ -6,15 +6,15 @@
/var/global/datum/ui_state/hands_state/hands_state = new()
/datum/ui_state/hands_state/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/hands_state/can_use_topic(src_object, mob/user)
. = user.shared_ui_interaction(src_object)
if(. > UI_CLOSE)
return min(., user.hands_can_use_topic(src_object))
/mob/proc/hands_can_use_topic(atom/movable/src_object)
/mob/proc/hands_can_use_topic(src_object)
return UI_CLOSE
/mob/living/hands_can_use_topic(atom/movable/src_object)
/mob/living/hands_can_use_topic(src_object)
if(src_object in get_both_hands(src))
return UI_INTERACTIVE
return UI_CLOSE
+1 -1
View File
@@ -6,7 +6,7 @@
/var/global/datum/ui_state/inventory_state/inventory_state = new()
/datum/ui_state/inventory_state/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/inventory_state/can_use_topic(src_object, mob/user)
if(!(src_object in user))
return UI_CLOSE
return user.shared_ui_interaction(src_object)
+5 -5
View File
@@ -6,21 +6,21 @@
/var/global/datum/ui_state/notcontained_state/notcontained_state = new()
/datum/ui_state/notcontained_state/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/notcontained_state/can_use_topic(atom/src_object, mob/user)
. = user.shared_ui_interaction(src_object)
if(. > UI_CLOSE)
return min(., user.notcontained_can_use_topic(src_object))
/mob/proc/notcontained_can_use_topic(atom/movable/src_object)
/mob/proc/notcontained_can_use_topic(src_object)
return UI_CLOSE
/mob/living/notcontained_can_use_topic(atom/movable/src_object)
/mob/living/notcontained_can_use_topic(atom/src_object)
if(src_object.contains(src))
return UI_CLOSE // Close if we're inside it.
return default_can_use_topic(src_object)
/mob/living/silicon/notcontained_can_use_topic(atom/movable/src_object)
/mob/living/silicon/notcontained_can_use_topic(src_object)
return default_can_use_topic(src_object) // Silicons use default bevhavior.
/mob/living/simple_animal/drone/notcontained_can_use_topic(atom/movable/src_object)
/mob/living/simple_animal/drone/notcontained_can_use_topic(src_object)
return default_can_use_topic(src_object) // Drones use default bevhavior.
+4 -4
View File
@@ -6,16 +6,16 @@
/var/global/datum/ui_state/physical/physical_state = new()
/datum/ui_state/physical/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/physical/can_use_topic(src_object, mob/user)
. = user.shared_ui_interaction(src_object)
if(. > UI_CLOSE)
return min(., user.physical_can_use_topic(src_object))
/mob/proc/physical_can_use_topic(atom/movable/src_object)
/mob/proc/physical_can_use_topic(src_object)
return UI_CLOSE
/mob/living/physical_can_use_topic(atom/movable/src_object)
/mob/living/physical_can_use_topic(src_object)
return shared_living_ui_distance(src_object)
/mob/living/silicon/physical_can_use_topic(atom/movable/src_object)
/mob/living/silicon/physical_can_use_topic(src_object)
return max(UI_UPDATE, shared_living_ui_distance(src_object)) // Silicons can always see.
+1 -1
View File
@@ -6,7 +6,7 @@
/var/global/datum/ui_state/self_state/self_state = new()
/datum/ui_state/self_state/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/self_state/can_use_topic(src_object, mob/user)
if(src_object != user)
return UI_CLOSE
return user.shared_ui_interaction(src_object)
+10 -10
View File
@@ -7,14 +7,14 @@
/**
* public
*
* Checks if a user can use src_object's UI, under the given state.
* 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.
**/
/atom/proc/ui_state(mob/user, datum/ui_state/state)
/datum/proc/ui_status(mob/user, datum/ui_state/state)
var/src_object = ui_host()
if(istype(user, /mob/dead/observer)) // Special-case ghosts.
@@ -31,12 +31,12 @@
* 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 atom/movable The object which owns the UI.
* 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/ui_state/proc/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_state/proc/can_use_topic(src_object, mob/user)
return UI_CLOSE // Don't allow interaction by default.
@@ -47,7 +47,7 @@
*
* return UI_state The state of the UI.
**/
/mob/proc/shared_ui_interaction(atom/movable/src_object)
/mob/proc/shared_ui_interaction(src_object)
if(!client || stat) // Close UIs if mindless or dead/unconcious.
return UI_CLOSE
// Update UIs if incapicitated but concious.
@@ -55,19 +55,19 @@
return UI_UPDATE
return UI_INTERACTIVE
/mob/living/carbon/human/shared_ui_interaction(atom/movable/src_object)
/mob/living/carbon/human/shared_ui_interaction(src_object)
// If we have telekinesis and remain close enough, allow interaction.
if(dna.check_mutation(TK))
if(tkMaxRangeCheck(src, src_object))
return UI_INTERACTIVE
return ..()
/mob/living/silicon/ai/shared_ui_interaction(atom/movable/src_object)
/mob/living/silicon/ai/shared_ui_interaction(src_object)
if(lacks_power()) // Close UIs if the AI is unpowered.
return UI_CLOSE
return ..()
/mob/living/silicon/robot/shared_ui_interaction(atom/movable/src_object)
/mob/living/silicon/robot/shared_ui_interaction(src_object)
if(cell.charge <= 0) // Close UIs if the Borg is unpowered.
return UI_CLOSE
if(lockcharge) // Disable UIs if the Borg is locked.
@@ -81,12 +81,12 @@
* Really only used for checks outside the context of a mob.
* Otherwise, use shared_living_ui_distance().
*
* required src_object atom/movable The object which owns the UI.
* 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_ui_distance(atom/movable/src_object, mob/living/user)
/atom/proc/contents_ui_distance(src_object, mob/living/user)
return user.shared_living_ui_distance(src_object) // Just call this mob's check.
/**
+1 -1
View File
@@ -6,7 +6,7 @@
/var/global/datum/ui_state/z_state/z_state = new()
/datum/ui_state/z_state/can_use_topic(atom/movable/src_object, mob/user)
/datum/ui_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))
+13 -13
View File
@@ -10,7 +10,7 @@
* Get a open UI given a user, src_object, and ui_key and try to update it with data.
*
* required user mob The mob who opened/is using the UI.
* required src_object atom/movable The object which owns the UI.
* required src_object datum The object/datum which owns the UI.
* required ui_key string The ui_key of the UI.
* optional ui datum/tgui The UI to be updated, if it exists.
* optional data list The data to update the UI with, if it exists.
@@ -18,7 +18,7 @@
*
* return datum/tgui The found UI.
**/
/datum/subsystem/tgui/proc/try_update_ui(mob/user, atom/movable/src_object, ui_key, datum/tgui/ui, \
/datum/subsystem/tgui/proc/try_update_ui(mob/user, datum/src_object, ui_key, datum/tgui/ui, \
list/data = null, force_open = 0)
if(!data)
data = src_object.get_ui_data(user)
@@ -41,12 +41,12 @@
* Get a open UI given a user, src_object, and ui_key.
*
* required user mob The mob who opened/is using the UI.
* required src_object atom/movable The object which owns the UI.
* required src_object datum The object/datum which owns the UI.
* required ui_key string The ui_key of the UI.
*
* return datum/tgui The found UI.
**/
/datum/subsystem/tgui/proc/get_open_ui(mob/user, atom/movable/src_object, ui_key)
/datum/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object, ui_key)
var/src_object_key = "\ref[src_object]"
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return null // No UIs open.
@@ -64,11 +64,11 @@
*
* Update all UIs attached to src_object.
*
* required src_object atom/movable The object which owns the UIs.
* required src_object datum The object/datum which owns the UIs.
*
* return int The number of UIs updated.
**/
/datum/subsystem/tgui/proc/update_uis(atom/movable/src_object)
/datum/subsystem/tgui/proc/update_uis(datum/src_object)
var/src_object_key = "\ref[src_object]"
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0 // Couldn't find any UIs for this object.
@@ -86,11 +86,11 @@
*
* Close all UIs attached to src_object.
*
* required src_object atom/movable The object which owns the UIs.
* required src_object datum The object/datum which owns the UIs.
*
* return int The number of UIs closed.
**/
/datum/subsystem/tgui/proc/close_uis(atom/movable/src_object)
/datum/subsystem/tgui/proc/close_uis(datum/src_object)
var/src_object_key = "\ref[src_object]"
if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0 // Couldn't find any UIs for this object.
@@ -109,12 +109,12 @@
* Update all UIs belonging to a user.
*
* required user mob The mob who opened/is using the UI.
* optional src_object atom/movable If provided, only update UIs belonging this atom.
* optional src_object datum If provided, only update UIs belonging this src_object.
* optional ui_key string If provided, only update UIs with this UI key.
*
* return int The number of UIs updated.
**/
/datum/subsystem/tgui/proc/update_user_uis(mob/user, atom/movable/src_object = null, ui_key = null)
/datum/subsystem/tgui/proc/update_user_uis(mob/user, datum/src_object = null, ui_key = null)
if(isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
return 0 // Couldn't find any UIs for this user.
@@ -131,12 +131,12 @@
* Close all UIs belonging to a user.
*
* required user mob The mob who opened/is using the UI.
* optional src_object atom/movable If provided, only update UIs belonging this atom.
* optional ui_key string If provided, only update UIs with this UI key.
* optional src_object datum If provided, only close UIs belonging this src_object.
* optional ui_key string If provided, only close UIs with this UI key.
*
* return int The number of UIs closed.
**/
/datum/subsystem/tgui/proc/close_user_uis(mob/user, atom/movable/src_object = null, ui_key = null)
/datum/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object = null, ui_key = null)
if(isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
return 0 // Couldn't find any UIs for this user.
+56 -28
View File
@@ -9,7 +9,7 @@
**/
/datum/tgui
var/mob/user // The mob who opened/is using the UI.
var/atom/movable/src_object // The object which owns the UI.
var/datum/src_object // The object which owns the UI.
var/title // The title of te UI.
var/ui_key // The ui_key of the UI. This allows multiple UIs for one src_object.
var/window_id // The window_id for browse() and onclose().
@@ -40,7 +40,7 @@
* Create a new UI.
*
* required user mob The mob who opened/is using the UI.
* required src_object atom/movable The object which owns 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.
@@ -52,7 +52,7 @@
*
* return datum/tgui The requested UI.
**/
/datum/tgui/New(mob/user, atom/movable/src_object, ui_key, interface, \
/datum/tgui/New(mob/user, datum/src_object, ui_key, interface, \
title, width = 0, height = 0, \
atom/ref = null, datum/tgui/master_ui = null, \
datum/ui_state/state = default_state)
@@ -89,12 +89,13 @@
* optional data list The data to intialize the UI with.
**/
/datum/tgui/proc/open(list/data = null)
set waitfor = 0 // Don't wait on sleep()s.
if(!user.client)
return // Bail if there is no client.
update_status(push = 0) // Update the window status.
if(status == UI_CLOSE)
return // Bail if we should close.
return // Bail if we're not supposed to open.
if(!initial_data)
if(!data) // If we don't have initial_data and data was not passed, get data from the src_object.
@@ -105,7 +106,11 @@
if(width && height) // If we have a width and height, use them.
window_size = "size=[width]x[height];"
user << browse(get_html(), "window=[window_id];[window_size][list2params(window_options)]") // Open the window.
var/debugable = check_rights_for(user.client, R_DEBUG)
user << browse(get_html(debugable), "window=[window_id];[window_size][list2params(window_options)]") // Open the window.
if(!debugable)
sleep(1)
user << output(url_encode(get_json(initial_data)), "[window_id].browser:initialize") // If the window is not debugable (JSON not inlined), send the JSON.
winset(user, window_id, "on-close=\"uiclose \ref[src]\"") // Instruct the client to signal UI when the window is closed.
SStgui.on_open(src)
@@ -135,6 +140,9 @@
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
/**
* public
@@ -192,11 +200,18 @@
*
* Generate HTML for this UI.
*
* optional bool inline If the JSON should be inlined into the HTML (for debugging).
*
* return string UI HTML output.
**/
/datum/tgui/proc/get_html()
// Poplate HTML with JSON.
return replacetextEx(SStgui.basehtml, "{}", get_json(initial_data))
/datum/tgui/proc/get_html(var/inline)
var/html
// Poplate HTML with JSON if we're supposed to inline.
if(inline)
html = replacetextEx(SStgui.basehtml, "{}", get_json(initial_data))
else
html = SStgui.basehtml
return html
/**
* private
@@ -207,20 +222,20 @@
**/
/datum/tgui/proc/get_config_data()
var/list/config_data = list(
"title" = title,
"status" = status,
"style" = style,
"interface" = interface,
"fancy" = user.client.prefs.tgui_fancy,
"locked" = user.client.prefs.tgui_lock,
"window" = window_id,
"ref" = "\ref[src]",
"user" = list(
"name" = user.name,
"ref" = "\ref[user]"
"title" = title,
"status" = status,
"style" = style,
"interface" = interface,
"fancy" = user.client.prefs.tgui_fancy,
"locked" = user.client.prefs.tgui_lock,
"window" = window_id,
"ref" = "\ref[src]",
"user" = list(
"name" = user.name,
"ref" = "\ref[user]"
),
"srcObject" = list(
"name" = src_object.name,
"srcObject" = list(
"name" = "[src_object]",
"ref" = "\ref[src_object]"
)
)
@@ -240,6 +255,7 @@
json_data["config"] = get_config_data()
if(!isnull(data))
json_data["data"] = data
json_data["adata"] = data
// Generate the JSON; replace bad characters.
var/json = JSON.stringify(json_data)
@@ -262,6 +278,18 @@
var/action = href_list["action"] // Pull the action out.
href_list -= "action"
// Handle any special actions.
switch(action)
if("tgui:ie")
user << link("http://windows.microsoft.com/en-us/internet-explorer/download-ie")
return
if("tgui:fancy")
user.client.prefs.tgui_fancy = TRUE
return
if("tgui:nofrills")
user.client.prefs.tgui_fancy = FALSE
return
var/update = src_object.ui_act(action, href_list, state) // Call ui_act() on the src_object.
if(src_object && update)
SStgui.update_uis(src_object) // If we have a src_object and its ui_act() told us to update.
@@ -297,8 +325,8 @@
if(status <= UI_DISABLED && !force)
return // Cannot update UI, we have no visibility.
// Send the new JSON to the recieveUpdate() Javascript function.
user << output(url_encode(get_json(data)), "[window_id].browser:receiveUpdate")
// Send the new JSON to the update() Javascript function.
user << output(url_encode(get_json(data)), "[window_id].browser:update")
/**
@@ -320,14 +348,14 @@
* optional push bool Push an update to the UI (an update is always sent for UI_DISABLED).
**/
/datum/tgui/proc/update_status(push = 0)
var/new_status = src_object.ui_state(user, state)
var/obj/host = src_object.ui_host()
var/status = host.ui_status(user, state)
if(master_ui)
new_status = min(new_status, master_ui.status)
status = min(status, master_ui.status)
if(new_status == UI_CLOSE)
set_status(status, push)
if(status == UI_CLOSE)
close()
else
set_status(new_status, push)
/**
* private
+1
View File
@@ -0,0 +1 @@
assets/* binary
+1 -1
View File
File diff suppressed because one or more lines are too long
+9 -9
View File
File diff suppressed because one or more lines are too long
+5 -5
View File
@@ -3,7 +3,7 @@
"private": true,
"dependencies": {
"aliasify": "~1.8.0",
"autoprefixer": "~6.2.2",
"autoprefixer": "~6.2.3",
"browserify": "~12.0.1",
"browserify-resolutions": "~1.0.6",
"coffee-script": "~1.10.0",
@@ -14,7 +14,7 @@
"es5-shim": "~4.4.1",
"gulp": "github:gulpjs/gulp#4.0",
"gulp-bytediff": "~1.0.0",
"gulp-cssnano": "~2.0.0",
"gulp-cssnano": "~2.0.1",
"gulp-if": "~2.0.0",
"gulp-load-plugins": "~1.1.0",
"gulp-postcss": "~6.0.1",
@@ -25,10 +25,10 @@
"gulp-uglify": "~1.5.1",
"hexa-color-regex": "~1.0.0",
"html5shiv": "~3.7.3",
"ie8": "~0.2.9",
"ie8": "~0.2.11",
"minimist": "1.2.0",
"pleeease-filters": "~2.0.0",
"postcss": "~5.0.13",
"postcss": "~5.0.14",
"postcss-color-rgba-fallback": "2.2.0",
"postcss-colorblind": "~0.4.0",
"postcss-filter-gradient": "~0.2.1",
@@ -41,7 +41,7 @@
"require-globify": "~1.3.0",
"stylus": "~0.53.0",
"through2": "~2.0.0",
"webfontloader": "~1.6.16"
"webfontloader": "~1.6.20"
},
"aliasify": {
"aliases": {
+6 -5
View File
@@ -5,7 +5,7 @@ constants = require "../constants"
component.exports =
computed:
clickable: ->
if @get("enabled") && not @get "state" then true
if @get("enabled") and not @get("state") then true
else false
enabled: ->
if @get("config.status") is constants.UI_INTERACTIVE then true
@@ -19,16 +19,17 @@ component.exports =
else "#{state}"
else "disabled"
oninit: ->
@on "act", (event) ->
@on "press", (event) ->
event.node.blur()
{action, params} = @get()
action = @get "action"
params = @get "params"
byond.act @get("config.ref"), action, params if action?
</script>
<span class='button {{styles}} {{#grid}}gridable{{/}}'
unselectable='true'
unselectable='on'
{{#clickable}}tabindex='0'{{/}}
on-click-enter='{{#clickable}}act{{/}}'>
on-click-enter='{{#clickable}}press{{/}}'>
{{#if icon}}
<i class='fa fa-{{icon}}'></i>
{{/if}}
+3 -1
View File
@@ -2,7 +2,9 @@
{{#if title}}
<header>
<h3>{{title}}</h3>
{{#if button}}{{yield button}}{{/if}}
{{#if button}}
<div class='buttonRight'>{{yield button}}</div>
{{/if}}
</header>
{{/if}}
<article>
+33
View File
@@ -0,0 +1,33 @@
<script type='text/coffeescript'>
component.exports =
data:
userAgent: navigator.userAgent
computed:
ie: ->
return document.documentMode if document.documentMode
for version in [11..6]
div = document.createElement "div"
div.innerHTML = "<!--[if IE " + version + "]><span></span><![endif]-->"
return version if div.getElementsByTagName("span").length
return undefined
oninit: ->
@on "debug", -> @toggle "debug"
</script>
{{#if config.fancy && ie && ie <= 8}}
<ui-notice>
<span>You have an old (&lt;= 8) version of Internet Explorer installed. Please upgrade to the latest available version of IE.</span><br/>
<span>To upgrade, please click 'Check For Upgrades' below to download the latest available version from Microsoft.</span><br/>
<span>Otherwise, if you are unable (XP/Wine) or unwilling to upgrade past IE8, please click 'No Frills' below to disable incompatible features (and this message).</span>
<hr/>
<ui-button icon='internet-explorer' action='tgui:ie'>Check For Upgrades</ui-button>
<ui-button icon='close' action='tgui:nofrills'>No Frills</ui-button>
<ui-button icon='bug' on-press='debug'>Debug Info</ui-button>
{{#if debug}}
<hr/>
<span>Detected: IE{{ie}}</span><br/>
<span>User Agent: {{userAgent}}</span>
{{/if}}
</ui-notice>
{{/if}}
+2
View File
@@ -3,6 +3,7 @@ byond = require "./byond"
module.exports =
drag: (ractive, event) ->
event.preventDefault()
lock = (x, y) ->
if x < 0 # Left
x = 0
@@ -23,6 +24,7 @@ module.exports =
ractive.set x: event.screenX, y: event.screenY
resize: (ractive, event) ->
event.preventDefault()
sane = (x, y) ->
x = Math.clamp x, 100, screen.width
y = Math.clamp y, 100, screen.height
@@ -20,9 +20,9 @@
</ui-section>
<ui-section label='Filters'>
<ui-button icon='{{filter_co2 ? "check-square-o" : "square-o"}}' style='{{filter_co2 ? "selected" : null}}'
action='co2_scrub' params='{"id_tag": "{{id_tag}}", "val": {{+!filter_co2}}}'>Oxygen</ui-button>
action='co2_scrub' params='{"id_tag": "{{id_tag}}", "val": {{+!filter_co2}}}'>CO2</ui-button>
<ui-button icon='{{filter_n2o ? "check-square-o" : "square-o"}}' style='{{filter_n2o ? "selected" : null}}'
action='n2o_scrub' params='{"id_tag": "{{id_tag}}", "val": {{+!filter_n2o}}}'>Nitrogen</ui-button>
action='n2o_scrub' params='{"id_tag": "{{id_tag}}", "val": {{+!filter_n2o}}}'>N2O</ui-button>
<ui-button icon='{{filter_toxins ? "check-square-o" : "square-o"}}' style='{{filter_toxins ? "selected" : null}}'
action='tox_scrub' params='{"id_tag": "{{id_tag}}", "val": {{+!filter_toxins}}}'>Plasma</ui-button>
</ui-section>
@@ -1,6 +1,6 @@
<ui-display title='Air Status'>
{{#if data.environment_data}}
{{#each data.environment_data}}
{{#each adata.environment_data}}
<ui-section label='{{name}}'>
<span class='{{danger_level == 2 ? "bad" : danger_level == 1 ? "average" : "good"}}'>
{{Math.fixed(value, 2)}}{{unit}}
@@ -13,19 +13,18 @@
</span>
</ui-section>
<ui-section label='Area Status'>
<span class='{{data.atmos_alarm || data.fire_alarm ? "bad bold" : "good"}}'>
<span class='{{data.atmos_alarm || data.fire_alarm ? "bad bold" : "good"}}'>
{{data.atmos_alarm ? "Atmosphere Alarm" : fire_alarm ? "Fire Alarm" : "Nominal"}}
</span>
</ui-section>
{{else}}
<ui-section>
<span class='bad bold'>Warning: Cannot obtain air sample for analysis.</span>
<ui-section label='Warning'>
<span class='bad bold'>Cannot obtain air sample for analysis.</span>
</ui-section>
{{/if}}
{{#if data.emagged}}
<hr/>
<ui-section>
<span class='bad bold'>Warning: Safety measures offline. Device may exhibit abnormal behavior.</span>
<ui-section label='Warning'>
<span class='bad bold'>Safety measures offline. Device may exhibit abnormal behavior.</span>
</ui-section>
{{/if}}
</ui-display>
+10 -16
View File
@@ -1,16 +1,14 @@
<ui-display title='Power'>
<ui-display title='Status'>
<ui-section label='Energy'>
<ui-bar min='0' max='{{data.maxEnergy}}' value='{{data.energy}}'>{{Math.fixed(adata.energy)}} Units</ui-bar>
</ui-section>
{{#if data.beakerTransferAmounts}}
<ui-section label='Amount'>
{{#each data.beakerTransferAmounts}}
<ui-button icon='plus' state='{{data.amount == . ? "selected" : null}}' action='amount' params='{"amount": {{.}}}'>{{.}}</ui-button>
{{/each}}
</ui-section>
{{/if}}
</ui-display>
<ui-display title='Dispense'>
<ui-display title='Dispense' button>
{{#partial button}}
{{#each data.beakerTransferAmounts}}
<ui-button icon='plus' state='{{data.amount == . ? "selected" : null}}' action='amount' params='{"amount": {{.}}}'>{{.}}</ui-button>
{{/each}}
{{/partial}}
<ui-section>
{{#each data.chemicals}}
<ui-button grid icon='tint' action='dispense' params='{"reagent": "{{id}}"}'>{{title}}</ui-button>
@@ -19,15 +17,11 @@
</ui-display>
<ui-display title='Beaker' button>
{{#partial button}}
{{#each data.beakerTransferAmounts}}
<ui-button icon='minus' action='remove' params='{"amount": {{.}}}'>{{.}}</ui-button>
{{/each}}
<ui-button icon='eject' state='{{data.isBeakerLoaded ? null : "disabled"}}' action='eject'>Eject</ui-button>
{{/partial}}
{{#if data.beakerTransferAmounts}}
<ui-section label='Remove'>
{{#each data.beakerTransferAmounts}}
<ui-button icon='minus' action='remove' params='{"amount": {{.}}}'>{{.}}</ui-button>
{{/each}}
</ui-section>
{{/if}}
<ui-section label='Contents'>
{{#if data.isBeakerLoaded}}
<span>{{Math.round(adata.beakerCurrentVolume)}}/{{data.beakerMaxVolume}} Units</span>
+12 -13
View File
@@ -6,24 +6,23 @@ require "./math"
Ractive = require "ractive"
# Set Ractive debug mode based on if we're minified or not.
Ractive.DEBUG = /minified/.test (minified) ->
Ractive.DEBUG = /minified/.test (minified) -> # Set Ractive debug mode based on if we're minified or not.
WebFont = require "webfontloader"
# Load FontAwesome asynchronously from CDNJS.
WebFont.load
WebFont.load # Load FontAwesome asynchronously from CDNJS.
custom:
families: ["FontAwesome"]
urls: ["https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css"]
testStrings:
FontAwesome: "\uf240"
tgui = require "./tgui"
# Create the UI; this is just a Ractive component.
window.tgui = new tgui
el: "#container"
data: ->
data = JSON.parse document.getElementById("data").textContent # Load initial data from the server.
alert "Initial data did not load correctly." if not data? or not (data.data? and data.config?)
data.adata = data.data # Spoof animated data as this is the first load.
data
tgui = require "./tgui.ract"
window.initialize = (dataString) -> # So we can get data inline or from the server.
return if window.tgui # Just incase we get called again; only do this once.
window.tgui = new tgui # Create the UI; this is just a Ractive component.
el: "#container" # Attach the UI to the existing container div.
data: -> data = JSON.parse dataString # Load initial data from the server.
holder = document.getElementById "data"
if holder.textContent != "{}" # If the JSON was inlined, load it.
window.initialize(holder.textContent)
+7 -2
View File
@@ -1,7 +1,9 @@
<link rel='ractive' href='./components/resize.ract'>
<link rel='ractive' href='./components/titlebar.ract'>
<link rel='ractive' href='./components/warnings.ract'>
<script type='text/coffeescript'>
byond = require "./byond"
dragresize = require "./dragresize"
component.exports =
@@ -27,10 +29,10 @@ component.exports =
oninit: ->
@on "titlebar.drag", -> @toggle "drag"; false
@on "resize.resize", -> @toggle "resize"; false
window.addEventListener "mousemove", (event) =>
document.addEventListener "mousemove", (event) =>
if @get "drag" then dragresize.drag(@, event)
else if @get "resize" then dragresize.resize(@, event)
window.addEventListener "mouseup", (event) =>
document.addEventListener "mouseup", (event) =>
if drag = @get "drag" then @set "drag"
if resize = @get "resize" then @set "resize"
if drag or resize then @set "x"; @set "y"
@@ -42,10 +44,13 @@ component.exports =
if newkey?
@el.classList.add newkey
document.body.classList.add newkey
oncomplete: ->
byond.winset "mapwindow.map", "focus", true # Give focus back to the map.
</script>
<titlebar>{{{config.title}}}</titlebar>
<main>
<warnings/>
<interface/>
</main>
<resize/>
+1 -1
View File
@@ -15,7 +15,7 @@ div.display
border-bottom: 2px solid colors.rule
.button
.buttonRight
position: absolute
bottom: 6px
right: 4px
+3
View File
@@ -25,3 +25,6 @@ div.notice
.label
color: colors.textinverse
hr
background-color: colors.border
+1 -1
View File
@@ -13,5 +13,5 @@ $fontReset
font-style: italic
// Make 'unselectable' text unselectable on all browsers.
[unselectable]
[unselectable=on]
user-select: none
+9 -10
View File
@@ -3,22 +3,21 @@
<head>
<meta charset='utf-8'/>
<meta http-equiv='X-UA-Compatible' content='IE=edge'/>
<script type='text/javascript'>
var data;
function receiveUpdate(dataString) {
data = JSON.parse(dataString);
if (typeof tgui !== 'undefined') {
tgui.set("config", data.config);
<script>
var update = function (dataString) {
var data = JSON.parse(dataString);
if (window.tgui) {
window.tgui.set("config", data.config);
if (typeof data.data !== 'undefined') {
tgui.set("data", data.data);
tgui.animate("adata", data.data);
window.tgui.set("data", data.data);
window.tgui.animate("adata", data.adata);
}
}
};
</script>
<link rel='stylesheet' type='text/css' href='tgui.css'/>
<link rel='stylesheet' href='tgui.css'/>
<script id='data' type='application/json'>{}</script>
<script defer type='text/javascript' src='tgui.js'></script>
<script defer src='tgui.js'></script>
</head>
<body>
<div id='container' class='container'>