Update NanoUI

* Update NanoUI to the latest version, ported from Baystation12
* Update the Air Alarm UI
* Make changes to subsystems and some machines to make the new NanoUI
work
This commit is contained in:
Bjorn Neergaard
2015-11-24 17:25:59 -05:00
parent e68a5b773a
commit 4e5edf396a
79 changed files with 5570 additions and 2783 deletions
+1
View File
@@ -795,6 +795,7 @@ var/list/ai_list = list()
if(stat == 2)
return //won't work if dead
src << "Accessing Subspace Transceiver control..."
if (radio)
radio.interact(src)
+7 -2
View File
@@ -49,7 +49,7 @@
loc = T.loc
if (istype(loc, /area))
//stage = 4
if (!loc.master.power_equip && !is_type_in_list(src.loc,list(/obj/item, /obj/mecha)))
if (lacks_power())
//stage = 5
blindness = 1
@@ -92,7 +92,7 @@
src.see_in_dark = 0
src.see_invisible = SEE_INVISIBLE_LIVING
if (((!loc.master.power_equip) || istype(T, /turf/space)) && !is_type_in_list(src.loc,list(/obj/item, /obj/mecha)))
if (lacks_power())
if (src:aiRestorePowerRoutine==0)
src:aiRestorePowerRoutine = 1
@@ -169,6 +169,11 @@
sleep(50)
theAPC = null
/mob/living/silicon/ai/proc/lacks_power()
var/turf/T = get_turf(src)
var/area/A = get_area(src)
return ((!A.power_equip) || istype(T, /turf/space)) && !is_type_in_list(src.loc, list(/obj/item, /obj/mecha))
/mob/living/silicon/ai/updatehealth()
if(status_flags & GODMODE)
health = maxHealth
+170 -169
View File
@@ -1,4 +1,4 @@
/json_token
json_token
var
value
New(v)
@@ -9,7 +9,7 @@
symbol
eof
/json_reader
json_reader
var
list
string = list("'", "\"")
@@ -20,185 +20,186 @@
i = 1
/json_reader/proc/ScanJson(json)
// scanner
src.json = json
. = new/list()
src.i = 1
while(src.i <= lentext(json))
var/char = get_char()
if(is_whitespace(char))
i++
continue
if(string.Find(char))
. += read_string(char)
else if(symbols.Find(char))
. += new/json_token/symbol(char)
else if(is_digit(char))
. += read_number()
else
. += read_word()
i++
. += new/json_token/eof()
/json_reader/proc/read_word()
var/val = ""
while(i <= lentext(json))
var/char = get_char()
if(is_whitespace(char) || symbols.Find(char))
i-- // let scanner handle this character
return new/json_token/word(val)
val += char
i++
/json_reader/proc/read_string(delim)
var
escape = FALSE
val = ""
while(++i <= lentext(json))
var/char = get_char()
if(escape)
switch(char)
if("\\", "'", "\"", "/", "u")
val += char
proc
// scanner
ScanJson(json)
src.json = json
. = new/list()
src.i = 1
while(src.i <= lentext(json))
var/char = get_char()
if(is_whitespace(char))
i++
continue
if(string.Find(char))
. += read_string(char)
else if(symbols.Find(char))
. += new/json_token/symbol(char)
else if(is_digit(char))
. += read_number()
else
// TODO: support octal, hex, unicode sequences
ASSERT(sequences.Find(char))
val += ascii2text(sequences[char])
else
if(char == delim)
return new/json_token/text(val)
else if(char == "\\")
escape = TRUE
else
. += read_word()
i++
. += new/json_token/eof()
read_word()
var/val = ""
while(i <= lentext(json))
var/char = get_char()
if(is_whitespace(char) || symbols.Find(char))
i-- // let scanner handle this character
return new/json_token/word(val)
val += char
CRASH("Unterminated string.")
i++
/json_reader/proc/read_number()
var/val = ""
var/char = get_char()
while(is_digit(char) || char == "." || lowertext(char) == "e")
val += char
i++
char = get_char()
i-- // allow scanner to read the first non-number character
return new/json_token/number(text2num(val))
read_string(delim)
var
escape = FALSE
val = ""
while(++i <= lentext(json))
var/char = get_char()
if(escape)
switch(char)
if("\\", "'", "\"", "/", "u")
val += char
else
// TODO: support octal, hex, unicode sequences
ASSERT(sequences.Find(char))
val += ascii2text(sequences[char])
else
if(char == delim)
return new/json_token/text(val)
else if(char == "\\")
escape = TRUE
else
val += char
CRASH("Unterminated string.")
/json_reader/proc/check_char()
ASSERT(args.Find(get_char()))
read_number()
var/val = ""
var/char = get_char()
while(is_digit(char) || char == "." || lowertext(char) == "e")
val += char
i++
char = get_char()
i-- // allow scanner to read the first non-number character
return new/json_token/number(text2num(val))
/json_reader/proc/get_char()
return copytext(json, i, i+1)
check_char()
ASSERT(args.Find(get_char()))
/json_reader/proc/is_whitespace(char)
return char == " " || char == "\t" || char == "\n" || text2ascii(char) == 13
get_char()
return copytext(json, i, i+1)
/json_reader/proc/is_digit(char)
var/c = text2ascii(char)
return 48 <= c && c <= 57 || char == "+" || char == "-"
is_whitespace(char)
return char == " " || char == "\t" || char == "\n" || text2ascii(char) == 13
is_digit(char)
var/c = text2ascii(char)
return 48 <= c && c <= 57 || char == "+" || char == "-"
// parser
/json_reader/proc/ReadObject(list/tokens)
src.tokens = tokens
. = new/list()
i = 1
read_token("{", /json_token/symbol)
while(i <= tokens.len)
var/json_token/K = get_token()
check_type(/json_token/word, /json_token/text)
// parser
ReadObject(list/tokens)
src.tokens = tokens
. = new/list()
i = 1
read_token("{", /json_token/symbol)
while(i <= tokens.len)
var/json_token/K = get_token()
check_type(/json_token/word, /json_token/text)
next_token()
read_token(":", /json_token/symbol)
.[K.value] = read_value()
var/json_token/S = get_token()
check_type(/json_token/symbol)
switch(S.value)
if(",")
next_token()
continue
if("}")
next_token()
return
else
die()
get_token()
return tokens[i]
next_token()
read_token(":", /json_token/symbol)
return tokens[++i]
.[K.value] = read_value()
var/json_token/S = get_token()
check_type(/json_token/symbol)
switch(S.value)
if(",")
next_token()
continue
if("}")
next_token()
return
else
die()
/json_reader/proc/get_token()
return tokens[i]
/json_reader/proc/next_token()
return tokens[++i]
/json_reader/proc/read_token(val, type)
var/json_token/T = get_token()
if(!(T.value == val && istype(T, type)))
CRASH("Expected '[val]', found '[T.value]'.")
next_token()
return T
/json_reader/proc/check_type(...)
var/json_token/T = get_token()
for(var/type in args)
if(istype(T, type))
return
CRASH("Bad token type: [T.type].")
/json_reader/proc/check_value(...)
var/json_token/T = get_token()
ASSERT(args.Find(T.value))
/json_reader/proc/read_key()
var/char = get_char()
if(char == "\"" || char == "'")
return read_string(char)
/json_reader/proc/read_value()
var/json_token/T = get_token()
switch(T.type)
if(/json_token/text, /json_token/number)
read_token(val, type)
var/json_token/T = get_token()
if(!(T.value == val && istype(T, type)))
CRASH("Expected '[val]', found '[T.value]'.")
next_token()
return T.value
if(/json_token/word)
next_token()
switch(T.value)
if("true")
return TRUE
if("false")
return FALSE
if("null")
return null
if(/json_token/symbol)
switch(T.value)
if("\[")
return read_array()
if("{")
return ReadObject(tokens.Copy(i))
die()
return T
/json_reader/proc/read_array()
read_token("\[", /json_token/symbol)
. = new/list()
var/list/L = .
while(i <= tokens.len)
// Avoid using Add() or += in case a list is returned.
L.len++
L[L.len] = read_value()
var/json_token/T = get_token()
check_type(/json_token/symbol)
switch(T.value)
if(",")
next_token()
continue
if("]")
next_token()
return
else
die()
next_token()
CRASH("Unterminated array.")
check_type(...)
var/json_token/T = get_token()
for(var/type in args)
if(istype(T, type))
return
CRASH("Bad token type: [T.type].")
check_value(...)
var/json_token/T = get_token()
ASSERT(args.Find(T.value))
read_key()
var/char = get_char()
if(char == "\"" || char == "'")
return read_string(char)
read_value()
var/json_token/T = get_token()
switch(T.type)
if(/json_token/text, /json_token/number)
next_token()
return T.value
if(/json_token/word)
next_token()
switch(T.value)
if("true")
return TRUE
if("false")
return FALSE
if("null")
return null
if(/json_token/symbol)
switch(T.value)
if("\[")
return read_array()
if("{")
return ReadObject(tokens.Copy(i))
die()
read_array()
read_token("\[", /json_token/symbol)
. = new/list()
var/list/L = .
while(i <= tokens.len)
// Avoid using Add() or += in case a list is returned.
L.len++
L[L.len] = read_value()
var/json_token/T = get_token()
check_type(/json_token/symbol)
switch(T.value)
if(",")
next_token()
continue
if("]")
next_token()
return
else
die()
next_token()
CRASH("Unterminated array.")
/json_reader/proc/die(json_token/T)
if(!T) T = get_token()
CRASH("Unexpected token: [T.value].")
die(json_token/T)
if(!T) T = get_token()
CRASH("Unexpected token: [T.value].")
+52 -51
View File
@@ -1,57 +1,58 @@
json_writer
var
use_cache = 0
/json_writer/proc/WriteObject(list/L)
. = "{"
var/i = 1
for(var/k in L)
var/val = L[k]
. += {"\"[k]\":[write(val)]"}
if(i++ < L.len)
. += ","
.+= "}"
proc
WriteObject(list/L)
if(use_cache && L["__json_cache"])
return L["__json_cache"]
/json_writer/proc/write(val)
if(isnum(val))
return num2text(val, 100)
else if(isnull(val))
return "null"
else if(istype(val, /list))
if(is_associative(val))
return WriteObject(val)
else
return write_array(val)
else
. += write_string("[val]")
. = "{"
var/i = 1
for(var/k in L)
var/val = L[k]
. += {"\"[k]\":[write(val)]"}
if(i++ < L.len)
. += ","
. += "}"
/json_writer/proc/write_array(list/L)
. = "\["
for(var/i = 1 to L.len)
. += write(L[i])
if(i < L.len)
. += ","
. += "]"
/json_writer/proc/write_string(txt)
var/static/list/json_escape = list("\\", "\"", "'", "\n")
for(var/targ in json_escape)
var/start = 1
while(start <= lentext(txt))
var/i = findtext(txt, targ, start)
if(!i)
break
if(targ == "\n")
txt = copytext(txt, 1, i) + "\\n" + copytext(txt, i+2)
start = i + 1 // 1 character added
if(targ == "'")
txt = copytext(txt, 1, i) + "`" + copytext(txt, i+1) // apostrophies fuck shit up...
start = i + 1 // 1 character added
write(val)
if(isnum(val))
return num2text(val)
else if(isnull(val))
return "null"
else if(istype(val, /list))
if(is_associative(val))
return WriteObject(val)
else
return write_array(val)
else
txt = copytext(txt, 1, i) + "\\" + copytext(txt, i)
start = i + 2 // 2 characters added
. += write_string("[val]")
return {""[txt]""}
write_array(list/L)
. = "\["
for(var/i = 1 to L.len)
. += write(L[i])
if(i < L.len)
. += ","
. += "]"
/json_writer/proc/is_associative(list/L)
for(var/key in L)
// if the key is a list that means it's actually an array of lists (stupid Byond...)
if(!isnum(key) && !istype(key, /list))
return TRUE
write_string(txt)
var/static/list/json_escape = list("\\" = "\\\\", "\"" = "\\\"", "\n" = "\\n")
for(var/targ in json_escape)
var/start = 1
while(start <= lentext(txt))
var/i = findtext(txt, targ, start)
if(!i)
break
var/lrep = length(json_escape[targ])
txt = copytext(txt, 1, i) + json_escape[targ] + copytext(txt, i + length(targ))
start = i + lrep
return {""[txt]""}
is_associative(list/L)
for(var/key in L)
// if the key is a list that means it's actually an array of lists (stupid Byond...)
if(!isnum(key) && !isnull(L[key]) && !istype(key, /list))
return TRUE
+9 -3
View File
@@ -2,10 +2,16 @@
n_Json v11.3.21
*/
/proc/json2list(json)
proc
json2list(json)
var/static/json_reader/_jsonr = new()
return _jsonr.ReadObject(_jsonr.ScanJson(json))
/proc/list2json(list/L)
list2json(list/L)
var/static/json_writer/_jsonw = new()
return _jsonw.WriteObject(L)
return _jsonw.write(L)
list2json_usecache(list/L)
var/static/json_writer/_jsonw = new()
_jsonw.use_cache = 1
return _jsonw.write(L)
+7
View File
@@ -0,0 +1,7 @@
/*
This state checks that the user is an admin, end of story
*/
/var/global/datum/topic_state/admin_state/admin_state = new()
/datum/topic_state/admin_state/can_use_topic(var/src_object, var/mob/user)
return check_rights(R_ADMIN, 0, user) ? NANO_INTERACTIVE : NANO_CLOSE
+32
View File
@@ -0,0 +1,32 @@
/atom/proc/nano_host()
return src
/atom/proc/CanUseTopic(var/mob/user, var/datum/topic_state/state)
var/src_object = nano_host()
return state.can_use_topic(src_object, user)
/datum/topic_state/proc/href_list(var/mob/user)
return list()
/datum/topic_state/proc/can_use_topic(var/src_object, var/mob/user)
return NANO_CLOSE
/mob/proc/shared_nano_interaction()
if (src.stat || !client)
return NANO_CLOSE // no updates, close the interface
else if (restrained() || lying || stat || stunned || weakened) // TODO: Change to incapaciated() on merge
return NANO_UPDATE // update only (orange visibility)
return NANO_INTERACTIVE
/mob/living/silicon/ai/shared_nano_interaction()
if (lacks_power())
return NANO_CLOSE
return ..()
/mob/living/silicon/robot/shared_nano_interaction()
. = NANO_INTERACTIVE
if (cell.charge <= 0)
return NANO_CLOSE
if (lockcharge)
. = NANO_DISABLED
return min(., ..())
@@ -0,0 +1,7 @@
/*
This state only checks if user is conscious.
*/
/var/global/datum/topic_state/conscious_state/conscious_state = new()
/datum/topic_state/conscious_state/can_use_topic(var/src_object, var/mob/user)
return user.stat == CONSCIOUS ? NANO_INTERACTIVE : NANO_CLOSE
@@ -0,0 +1,18 @@
/*
This state checks if user is somewhere within src_object, as well as the default NanoUI interaction.
*/
/var/global/datum/topic_state/contained_state/contained_state = new()
/datum/topic_state/contained_state/can_use_topic(var/atom/src_object, var/mob/user)
if(!src_object.contains(user))
return NANO_CLOSE
return user.shared_nano_interaction()
/atom/proc/contains(var/atom/location)
if(!location)
return 0
if(location == src)
return 1
return contains(location.loc)
+93
View File
@@ -0,0 +1,93 @@
/var/global/datum/topic_state/default/default_state = new()
/datum/topic_state/default/href_list(var/mob/user)
return list()
/datum/topic_state/default/can_use_topic(var/src_object, var/mob/user)
return user.default_can_use_topic(src_object)
/mob/proc/default_can_use_topic(var/src_object)
return NANO_CLOSE // By default no mob can do anything with NanoUI
/mob/dead/observer/default_can_use_topic()
if(check_rights(R_ADMIN, 0, src))
return NANO_INTERACTIVE // Admins are more equal
return NANO_UPDATE // Ghosts can view updates
/mob/living/silicon/pai/default_can_use_topic(var/src_object)
if((src_object == src || src_object == radio) && !stat)
return NANO_INTERACTIVE
else
return ..()
/mob/living/silicon/robot/default_can_use_topic(var/src_object)
. = shared_nano_interaction()
if(. <= NANO_DISABLED)
return
// robots can interact with things they can see within their view range
if((src_object in view(src)) && get_dist(src_object, src) <= src.client.view)
return NANO_INTERACTIVE // interactive (green visibility)
return NANO_DISABLED // no updates, completely disabled (red visibility)
/mob/living/silicon/robot/syndicate/default_can_use_topic(var/src_object)
. = ..()
if(. != NANO_INTERACTIVE)
return
if(istype(get_area(src), /area/syndicate_mothership) || istype(get_area(src), /area/shuttle/syndicate)) // If elsewhere, they can interact with everything on the syndicate shuttle
return NANO_INTERACTIVE
if(istype(src_object, /obj/machinery)) // Otherwise they can only interact with emagged machinery
var/obj/machinery/Machine = src_object
if(Machine.emagged)
return NANO_INTERACTIVE
return NANO_UPDATE
/mob/living/silicon/ai/default_can_use_topic(var/src_object)
. = shared_nano_interaction()
if(. != NANO_INTERACTIVE)
return
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
// unless it's on the same level as the object it's interacting with.
var/turf/T = get_turf(src_object)
if(!T || !(z == T.z))
return NANO_CLOSE
// If an object is in view then we can interact with it
if(src_object in view(client.view, src))
return NANO_INTERACTIVE
return NANO_CLOSE
//Some atoms such as vehicles might have special rules for how mobs inside them interact with NanoUI.
/atom/proc/contents_nano_distance(var/src_object, var/mob/living/user)
return user.shared_living_nano_distance(src_object)
/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates
return NANO_CLOSE
var/dist = get_dist(src_object, src)
if (dist <= 1)
return NANO_INTERACTIVE // interactive (green visibility)
else if (dist <= 2)
return NANO_UPDATE // update only (orange visibility)
else if (dist <= 4)
return NANO_DISABLED // no updates, completely disabled (red visibility)
return NANO_CLOSE
/mob/living/default_can_use_topic(var/src_object)
. = shared_nano_interaction(src_object)
if(. != NANO_CLOSE)
if(loc)
. = min(., loc.contents_nano_distance(src_object, src))
if(NANO_INTERACTIVE)
return NANO_UPDATE
/mob/living/carbon/human/default_can_use_topic(var/src_object)
. = shared_nano_interaction(src_object)
if(. != NANO_CLOSE)
. = min(., shared_living_nano_distance(src_object))
if(. == NANO_UPDATE && dna.check_mutation(TK)) // If we have telekinesis and remain close enough, allow interaction.
return NANO_INTERACTIVE
@@ -0,0 +1,11 @@
/*
This state checks that the src_object is somewhere in the user's first-level inventory (in hands, on ear, etc.), but not further down (such as in bags).
*/
/var/global/datum/topic_state/inventory_state/inventory_state = new()
/datum/topic_state/inventory_state/can_use_topic(var/src_object, var/mob/user)
if(!(src_object in user))
return NANO_CLOSE
return user.shared_nano_interaction()
@@ -0,0 +1,10 @@
/*
This state checks if src_object is contained anywhere in the user's inventory, including bags, etc.
*/
/var/global/datum/topic_state/deep_inventory_state/deep_inventory_state = new()
/datum/topic_state/deep_inventory_state/can_use_topic(var/src_object, var/mob/user)
if(!user.contains(src_object))
return NANO_CLOSE
return user.shared_nano_interaction()
+18
View File
@@ -0,0 +1,18 @@
/var/global/datum/topic_state/physical/physical_state = new()
/datum/topic_state/physical/can_use_topic(var/src_object, var/mob/user)
. = user.shared_nano_interaction(src_object)
if(. > NANO_CLOSE)
return min(., user.check_physical_distance(src_object))
/mob/proc/check_physical_distance(var/src_object)
return NANO_CLOSE
/mob/dead/observer/check_physical_distance(var/src_object)
return default_can_use_topic(src_object)
/mob/living/check_physical_distance(var/src_object)
return shared_living_nano_distance(src_object)
/mob/living/silicon/check_physical_distance(var/src_object)
return max(NANO_UPDATE, shared_living_nano_distance(src_object))
+9
View File
@@ -0,0 +1,9 @@
/*
This state checks that the src_object is the same the as user
*/
/var/global/datum/topic_state/self_state/self_state = new()
/datum/topic_state/self_state/can_use_topic(var/src_object, var/mob/user)
if(src_object != user)
return NANO_CLOSE
return user.shared_nano_interaction()
+13
View File
@@ -0,0 +1,13 @@
/*
This state checks that the user is on the same Z-level as src_object
*/
/var/global/datum/topic_state/z_state/z_state = new()
/datum/topic_state/z_state/can_use_topic(var/src_object, var/mob/user)
var/turf/turf_obj = get_turf(src_object)
var/turf/turf_usr = get_turf(user)
if(!turf_obj || !turf_usr)
return NANO_CLOSE
return turf_obj.z == turf_usr.z ? NANO_INTERACTIVE : NANO_CLOSE
+10 -2
View File
@@ -33,14 +33,22 @@
* @param user /mob The mob who is interacting with this ui
* @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main")
* @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui
* @param force_open boolean Force the UI to (re)open, even if it's already open
*
* @return nothing
*/
/atom/movable/proc/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null)
/atom/movable/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nano_ui/master_ui = null, var/datum/topic_state/state = default_state)
return
/**
* Used to get data to send to the Nano UI.
*
* @param user /mob The mob who is interacting with this ui
*
* @return list
*/
/atom/movable/proc/get_ui_data(mob/user)
return list()
// Used by the Nano UI SubSystem (/datum/subsystem/nano) to track UIs opened by this mob
// Used by the Nano UI Manager (/datum/nanomanager) to track UIs opened by this mob
/mob/var/list/open_uis = list()
+70 -22
View File
@@ -1,4 +1,4 @@
/**
/**
* Get an open /nanoui ui for the current user, or create a new one.
*
* @param user /mob The mob who opened/owns the ui
@@ -9,7 +9,7 @@
*
* @return /nanoui Returns the new or found ui
*/
/datum/subsystem/nano/proc/push_open_or_new_ui(mob/user, atom/movable/src_object, ui_key, datum/nanoui/ui, template, title, width, height, auto_update)
/datum/subsystem/nano/proc/push_open_or_new_ui(mob/user, atom/movable/src_object, ui_key, datum/nanoui/ui, template, title, width, height, auto_update, var/atom/ref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = default_state)
var/list/data = src_object.get_ui_data(user)
if (!data)
data = list()
@@ -17,7 +17,7 @@
ui = try_update_ui(user, src_object, ui_key, ui, data)
if (isnull(ui))
ui = new /datum/nanoui(user, src_object, ui_key, template, title, width, height)
ui = new/datum/nanoui(user, src_object, ui_key, template, title, width, height, ref, master_ui, state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(auto_update)
@@ -30,17 +30,23 @@
* @param ui_key string A string key used for the ui
* @param ui /datum/nanoui An existing instance of the ui (can be null)
* @param data list The data to be passed to the ui, if it exists
* @param force_open boolean The ui is being forced to (re)open, so close ui if it exists (instead of updating)
*
* @return /nanoui Returns the found ui, for null if none exists
*/
/datum/subsystem/nano/proc/try_update_ui(mob/user, src_object, ui_key, datum/nanoui/ui, data)
/datum/subsystem/nano/proc/try_update_ui(var/mob/user, src_object, ui_key, var/datum/nanoui/ui, data, var/force_open = 0)
if (isnull(ui)) // no ui has been passed, so we'll search for one
{
ui = get_open_ui(user, src_object, ui_key)
}
if (!isnull(ui))
// The UI is already open so push the data to it
ui.push_data(data)
return ui
// The UI is already open
if (!force_open)
ui.push_data(data)
return ui
else
ui.reinitialise(new_initial_data=data)
return ui
return null
@@ -53,17 +59,20 @@
*
* @return /nanoui Returns the found ui, or null if none exists
*/
/datum/subsystem/nano/proc/get_open_ui(mob/user, src_object, ui_key)
/datum/subsystem/nano/proc/get_open_ui(var/mob/user, 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))
//testing("subsystem/nano/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open")
return null
else if (isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list))
//testing("subsystem/nano/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open for this object")
return null
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if (ui.user == user)
return ui
//testing("subsystem/nano/get_open_ui mob [user.name] [src_object:name] [ui_key] - ui not found")
return null
/**
@@ -81,11 +90,31 @@
var/update_count = 0
for (var/ui_key in open_uis[src_object_key])
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user)
if(ui && ui.src_object && ui.user && ui.src_object.nano_host())
ui.process(1)
update_count++
return update_count
/**
* Close all /nanoui uis attached to src_object
*
* @param src_object /obj|/mob The obj or mob which the uis are attached to
*
* @return int The number of uis close
*/
/datum/subsystem/nano/proc/close_uis(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
var/close_count = 0
for (var/ui_key in open_uis[src_object_key])
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user && ui.src_object.nano_host())
ui.close()
close_count++
return close_count
/**
* Update /nanoui uis belonging to user
*
@@ -95,7 +124,7 @@
*
* @return int The number of uis updated
*/
/datum/subsystem/nano/proc/update_user_uis(mob/user, src_object = null, ui_key = null)
/datum/subsystem/nano/proc/update_user_uis(var/mob/user, src_object = null, ui_key = null)
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
return 0 // has no open uis
@@ -116,8 +145,9 @@
*
* @return int The number of uis closed
*/
/datum/subsystem/nano/proc/close_user_uis(mob/user, src_object = null, ui_key = null)
/datum/subsystem/nano/proc/close_user_uis(var/mob/user, src_object = null, ui_key = null)
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
//testing("subsystem/nano/close_user_uis mob [user.name] has no open uis")
return 0 // has no open uis
var/close_count = 0
@@ -126,6 +156,8 @@
ui.close()
close_count++
//testing("subsystem/nano/close_user_uis mob [user.name] closed [open_uis.len] of [close_count] uis")
return close_count
/**
@@ -136,17 +168,18 @@
*
* @return nothing
*/
/datum/subsystem/nano/proc/ui_opened(datum/nanoui/ui)
/datum/subsystem/nano/proc/ui_opened(var/datum/nanoui/ui)
var/src_object_key = "\ref[ui.src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
open_uis[src_object_key] = list(ui.ui_key = list())
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
open_uis[src_object_key][ui.ui_key] = list();
ui.user.open_uis.Add(ui)
ui.user.open_uis |= ui
var/list/uis = open_uis[src_object_key][ui.ui_key]
uis.Add(ui)
processing_uis.Add(ui)
uis |= ui
processing_uis |= ui
//testing("subsystem/nano/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
/**
* Remove a /nanoui ui from the list of open uis
@@ -156,7 +189,7 @@
*
* @return int 0 if no ui was removed, 1 if removed successfully
*/
/datum/subsystem/nano/proc/ui_closed(datum/nanoui/ui)
/datum/subsystem/nano/proc/ui_closed(var/datum/nanoui/ui)
var/src_object_key = "\ref[ui.src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0 // wasn't open
@@ -167,7 +200,11 @@
if(ui.user) // Sanity check in case a user has been deleted (say a blown up borg watching the alarm interface)
ui.user.open_uis.Remove(ui)
var/list/uis = open_uis[src_object_key][ui.ui_key]
return uis.Remove(ui)
uis.Remove(ui)
//testing("subsystem/nano/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
return 1
/**
* This is called on user logout
@@ -179,7 +216,8 @@
*/
//
/datum/subsystem/nano/proc/user_logout(mob/user)
/datum/subsystem/nano/proc/user_logout(var/mob/user)
//testing("subsystem/nano/user_logout user [user.name]")
return close_user_uis(user)
/**
@@ -191,8 +229,10 @@
*
* @return nothing
*/
/datum/subsystem/nano/proc/user_transferred(mob/oldMob, mob/newMob)
if (isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0)
/datum/subsystem/nano/proc/user_transferred(var/mob/oldMob, var/mob/newMob)
//testing("subsystem/nano/user_transferred from mob [oldMob.name] to mob [newMob.name]")
if (!oldMob || isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0)
//testing("subsystem/nano/user_transferred mob [oldMob.name] has no open uis")
return 0 // has no open uis
if (isnull(newMob.open_uis) || !istype(newMob.open_uis, /list))
@@ -206,6 +246,14 @@
return 1 // success
//Send all needed nano ui files to the client
/**
* Sends all nano assets to the client
* This is called on user login
*
* @param client /client The user's client
*
* @return nothing
*/
/datum/subsystem/nano/proc/send_resources(client)
getFilesSlow(client, asset_files)
+90
View File
@@ -0,0 +1,90 @@
// This file is a modified version of https://raw2.github.com/Baystation12/OldCode-BS12/master/code/TakePicture.dm
#define NANOMAP_ICON_SIZE 4
#define NANOMAP_MAX_ICON_DIMENSION 1024
#define NANOMAP_TILES_PER_IMAGE (NANOMAP_MAX_ICON_DIMENSION / NANOMAP_ICON_SIZE)
#define NANOMAP_TERMINALERR 5
#define NANOMAP_INPROGRESS 2
#define NANOMAP_BADOUTPUT 2
#define NANOMAP_SUCCESS 1
#define NANOMAP_WATCHDOGSUCCESS 4
#define NANOMAP_WATCHDOGTERMINATE 3
//Call these procs to dump your world to a series of image files (!!)
//NOTE: Does not explicitly support non 32x32 icons or stuff with large pixel_* values, so don't blame me if it doesn't work perfectly
/client/proc/nanomapgen_DumpImage()
set name = "Generate NanoUI Map"
set category = "Server"
if(holder)
nanomapgen_DumpTile(1, 1, text2num(input(usr,"Enter the Z level to generate")))
/client/proc/nanomapgen_DumpTile(var/startX = 1, var/startY = 1, var/currentZ = 1, var/endX = -1, var/endY = -1)
if (endX < 0 || endX > world.maxx)
endX = world.maxx
if (endY < 0 || endY > world.maxy)
endY = world.maxy
if (currentZ < 0 || currentZ > world.maxz)
usr << "NanoMapGen: <B>ERROR: currentZ ([currentZ]) must be between 1 and [world.maxz]</B>"
sleep(3)
return NANOMAP_TERMINALERR
if (startX > endX)
usr << "NanoMapGen: <B>ERROR: startX ([startX]) cannot be greater than endX ([endX])</B>"
sleep(3)
return NANOMAP_TERMINALERR
if (startY > endX)
usr << "NanoMapGen: <B>ERROR: startY ([startY]) cannot be greater than endY ([endY])</B>"
sleep(3)
return NANOMAP_TERMINALERR
var/icon/Tile = icon(file("nano/mapbase1024.png"))
if (Tile.Width() != NANOMAP_MAX_ICON_DIMENSION || Tile.Height() != NANOMAP_MAX_ICON_DIMENSION)
world.log << "NanoMapGen: <B>ERROR: BASE IMAGE DIMENSIONS ARE NOT [NANOMAP_MAX_ICON_DIMENSION]x[NANOMAP_MAX_ICON_DIMENSION]</B>"
sleep(3)
return NANOMAP_TERMINALERR
world.log << "NanoMapGen: <B>GENERATE MAP ([startX],[startY],[currentZ]) to ([endX],[endY],[currentZ])</B>"
usr << "NanoMapGen: <B>GENERATE MAP ([startX],[startY],[currentZ]) to ([endX],[endY],[currentZ])</B>"
var/count = 0;
for(var/WorldX = startX, WorldX <= endX, WorldX++)
for(var/WorldY = startY, WorldY <= endY, WorldY++)
var/atom/Turf = locate(WorldX, WorldY, currentZ)
var/icon/TurfIcon = new(Turf.icon, Turf.icon_state)
TurfIcon.Scale(NANOMAP_ICON_SIZE, NANOMAP_ICON_SIZE)
Tile.Blend(TurfIcon, ICON_OVERLAY, ((WorldX - 1) * NANOMAP_ICON_SIZE), ((WorldY - 1) * NANOMAP_ICON_SIZE))
count++
if (count % 8000 == 0)
world.log << "NanoMapGen: <B>[count] tiles done</B>"
sleep(1)
var/mapFilename = "nanomap_z[currentZ]-new.png"
world.log << "NanoMapGen: <B>sending [mapFilename] to client</B>"
usr << browse(Tile, "window=picture;file=[mapFilename];display=0")
world.log << "NanoMapGen: <B>Done.</B>"
usr << "NanoMapGen: <B>Done. File [mapFilename] uploaded to your cache.</B>"
if (Tile.Width() != NANOMAP_MAX_ICON_DIMENSION || Tile.Height() != NANOMAP_MAX_ICON_DIMENSION)
return NANOMAP_BADOUTPUT
return NANOMAP_SUCCESS
+224 -134
View File
@@ -6,11 +6,6 @@ nanoui class (or whatever Byond calls classes)
nanoui is used to open and update nano browser uis
**********************************************************/
#define STATUS_INTERACTIVE 2 // GREEN Visability
#define STATUS_UPDATE 1 // ORANGE Visability
#define STATUS_DISABLED 0 // RED Visability
/datum/nanoui
// the user who opened this ui
var/mob/user
@@ -36,20 +31,31 @@ nanoui is used to open and update nano browser uis
var/list/stylesheets = list()
// the list of javascript scripts to use for this ui
var/list/scripts = list()
// the list of templates to use with this ui (usually just one)
// a list of templates which can be used with this ui
var/templates[0]
// the body content for this ui, do not change unless you know what you're doing
// the #mainTemplate div will contain the compiled "main" template html
var/content = "<div id='mainTemplate'></div>"
// the layout key for this ui (this is used on the frontend, leave it as "default" unless you know what you're doing)
var/layout_key = "default"
// this sets whether to re-render the ui layout with each update (default 0, turning on will break the map ui if it's in use)
var/auto_update_layout = 0
// this sets whether to re-render the ui content with each update (default 1)
var/auto_update_content = 1
// the default state to use for this ui (this is used on the frontend, leave it as "default" unless you know what you're doing)
var/state_key = "default"
// show the map ui, this is used by the default layout
var/show_map = 0
// the map z level to display
var/map_z_level = 1
// initial data, containing the full data structure, must be sent to the ui (the data structure cannot be extended later on)
var/list/initial_data[0]
// set to 1 to update the ui automatically every master_controller tick
var/is_auto_updating = 0
// the current status/visibility of the ui
var/status = STATUS_INTERACTIVE
var/status = NANO_INTERACTIVE
// Only allow users with a certain user.stat to get updates. Defaults to 0 (concious)
var/allowed_user_stat = 0 // -1 = ignore, 0 = alive, 1 = unconcious or alive, 2 = dead concious or alive
// Relationship between a master interface and its children. Used in update_status
var/datum/nanoui/master_ui
var/list/datum/nanoui/children = list()
var/datum/topic_state/state = null
/**
* Create a new nanoui instance.
@@ -57,7 +63,7 @@ nanoui is used to open and update nano browser uis
* @param nuser /mob The mob who has opened/owns this ui
* @param nsrc_object /obj|/mob The obj or mob which this ui belongs to
* @param nui_key string A string key to use for this ui. Allows for multiple unique uis on one src_oject
* @param ntemplate string The name of the template file from /nano/templates (e.g. "my_template.tmpl")
* @param ntemplate string The filename of the template file from /nano/templates (e.g. "my_template.tmpl")
* @param ntitle string The title of this ui
* @param nwidth int the width of the ui window
* @param nheight int the height of the ui window
@@ -65,17 +71,22 @@ nanoui is used to open and update nano browser uis
*
* @return /nanoui new nanoui object
*/
/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null)
/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = default_state)
user = nuser
src_object = nsrc_object
ui_key = nui_key
window_id = "[ui_key]\ref[src_object]"
// Add the passed template as the 'main' template, this is required
add_template("main", ntemplate)
src.master_ui = master_ui
if(master_ui)
master_ui.children += src
src.state = state
// add the passed template filename as the "main" template, this is required
add_template("main", ntemplate_filename)
if (ntitle)
title = ntitle
title = sanitize(ntitle)
if (nwidth)
width = nwidth
if (nheight)
@@ -86,15 +97,19 @@ nanoui is used to open and update nano browser uis
add_common_assets()
/**
* Use this proc to add assets which are common to all nano uis
* Use this proc to add assets which are common to (and required by) all nano uis
*
* @return nothing
*/
/datum/nanoui/proc/add_common_assets()
add_script("libraries.min.js") // The jQuery library
add_script("nano_config.js") // The NanoConfig JS, this is used to store configuration values.
add_script("nano_update.js") // The NanoUpdate JS, this is used to receive updates and apply them.
add_script("nano_base_helpers.js") // The NanoBaseHelpers JS, this is used to set up template helpers which are common to all templates
add_script("libraries.min.js") // A JS file comprising of jQuery, doT.js and jQuery Timer libraries (compressed together)
add_script("nano_utility.js") // The NanoUtility JS, this is used to store utility functions.
add_script("nano_template.js") // The NanoTemplate JS, this is used to render templates.
add_script("nano_state_manager.js") // The NanoStateManager JS, it handles updates from the server and passes data to the current state
add_script("nano_state.js") // The NanoState JS, this is the base state which all states must inherit from
add_script("nano_state_default.js") // The NanoStateDefault JS, this is the "default" state (used by all UIs by default), which inherits from NanoState
add_script("nano_base_callbacks.js") // The NanoBaseCallbacks JS, this is used to set up (before and after update) callbacks which are common to all UIs
add_script("nano_base_helpers.js") // The NanoBaseHelpers JS, this is used to set up template helpers which are common to all UIs
add_stylesheet("shared.css") // this CSS sheet is common to all UIs
add_stylesheet("icons.css") // this CSS sheet is common to all UIs
@@ -107,12 +122,15 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/proc/set_status(state, push_update)
if (state != status)
status = state
if (push_update || !status)
push_data(list(), 1) // Update the UI, force the update in case the status is 0
else
status = state
if (state != status) // Only update if it is different
if (status == NANO_DISABLED)
status = state
if (push_update)
update()
else
status = state
if (push_update || status == 0)
push_data(null, 1) // Update the UI, force the update in case the status is 0, data is null so that previous data is used
/**
* Update the status (visibility) of this ui based on the user's status
@@ -121,38 +139,14 @@ nanoui is used to open and update nano browser uis
*
* @return nothing
*/
/datum/nanoui/proc/update_status(push_update = 0)
if (istype(user, /mob/living/silicon/ai))
set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility)
else if (istype(user, /mob/living/silicon/robot))
if (src_object in view(7, user)) // robots can see and interact with things they can see within 7 tiles
set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility)
else
set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility)
else
var/dist = get_dist(src_object, user)
var/isTK = 0
/datum/nanoui/proc/update_status(var/push_update = 0)
var/new_status = src_object.CanUseTopic(user, state)
if(master_ui)
new_status = min(new_status, master_ui.status)
if(ishuman(user))
var/mob/living/carbon/human/H = user
isTK = H.dna.check_mutation(TK)
if (dist > 4 && !isTK)
close()
return
if ((allowed_user_stat > -1) && (user.stat > allowed_user_stat))
set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility)
else if (user.restrained() || user.lying)
set_status(STATUS_UPDATE, push_update) // update only (orange visibility)
else if (!(src_object in view(4, user))) // If the src object is not in visable, set status to 0
set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility)
else if (dist <= 1)
set_status(STATUS_INTERACTIVE, push_update) // interactive (green visibility)
else if (dist <= 2 || isTK)
set_status(STATUS_UPDATE, push_update) // update only (orange visibility)
else if (dist <= 4)
set_status(STATUS_DISABLED, push_update) // no updates, completely disabled (red visibility)
set_status(new_status, push_update)
if(new_status == NANO_CLOSE)
close()
/**
* Set the ui to auto update (every master_controller tick)
@@ -161,8 +155,8 @@ nanoui is used to open and update nano browser uis
*
* @return nothing
*/
/datum/nanoui/proc/set_auto_update(state = 1)
is_auto_updating = state
/datum/nanoui/proc/set_auto_update(nstate = 1)
is_auto_updating = nstate
/**
* Set the initial data for the ui. This is vital as the data structure set here cannot be changed when pushing new updates.
@@ -172,21 +166,43 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/proc/set_initial_data(list/data)
initial_data = add_default_data(data)
initial_data = data
/**
* Add default data to the data being sent to the ui.
* Get config data to sent to the ui.
*
* @param data /list The list of data to be modified
*
* @return /list modified data
* @return /list config data
*/
/datum/nanoui/proc/add_default_data(list/data)
data["ui"] = list(
/datum/nanoui/proc/get_config_data()
var/list/config_data = list(
"title" = title,
"srcObject" = list("name" = src_object.name),
"stateKey" = state_key,
"status" = status,
"autoUpdateLayout" = auto_update_layout,
"autoUpdateContent" = auto_update_content,
"showMap" = show_map,
"mapZLevel" = map_z_level,
"user" = list("name" = user.name)
)
return data
return config_data
/**
* Get data to sent to the ui.
*
* @param data /list The list of general data for this ui (can be null to use previous data sent)
*
* @return /list data to send to the ui
*/
/datum/nanoui/proc/get_send_data(var/list/data)
var/list/config_data = get_config_data()
var/list/send_data = list("config" = config_data)
if (!isnull(data))
send_data["data"] = data
return send_data
/**
* Set the browser window options for this ui
@@ -200,6 +216,7 @@ nanoui is used to open and update nano browser uis
/**
* Add a CSS stylesheet to this UI
* These must be added before the UI has been opened, adding after that will have no effect
*
* @param file string The name of the CSS file from /nano/css (e.g. "my_style.css")
*
@@ -210,6 +227,7 @@ nanoui is used to open and update nano browser uis
/**
* Add a JavsScript script to this UI
* These must be added before the UI has been opened, adding after that will have no effect
*
* @param file string The name of the JavaScript file from /nano/js (e.g. "my_script.js")
*
@@ -219,30 +237,81 @@ nanoui is used to open and update nano browser uis
scripts.Add(file)
/**
* Add a template to this UI
* Add a template for this UI
* Templates are combined with the data sent to the UI to create the rendered view
* Each template needs a div in ui.content to contain the rendered content.
* The div format is '<div id='<templateKey>Template'></div>' where <templateKey> is replaced with the templater's key.
* All UIs are set up by default to use a 'main' template, so only use this proc if you want to add advanced functionality.
* These must be added before the UI has been opened, adding after that will have no effect
*
* @param key string The key name for this template, used to identify the div to render this template into ('<div id='<templateKey>Template'></div>')
* @param file string The name of the template file from /nano/templates (e.g. "my_template.tmpl")
* @param key string The key which is used to reference this template in the frontend
* @param filename string The name of the template file from /nano/templates (e.g. "my_template.tmpl")
*
* @return nothing
*/
/datum/nanoui/proc/add_template(key, file)
templates[key] = file
/datum/nanoui/proc/add_template(key, filename)
templates[key] = filename
/**
* Set the HTML content of the UI
* This should only really be used to add more template divs (see the add_template() proc)
* Set the layout key for use in the frontend Javascript
* The layout key is the basic layout key for the page
* Two files are loaded on the client based on the layout key varable:
* -> a template in /nano/templates with the filename "layout_<layout_key>.tmpl
* -> a CSS stylesheet in /nano/css with the filename "layout_<layout_key>.css
*
* @param ncontent string The new HTML content for this UI
* @param nlayout string The layout key to use
*
* @return nothing
*/
/datum/nanoui/proc/set_content(ncontent)
content = ncontent
/datum/nanoui/proc/set_layout_key(nlayout_key)
layout_key = lowertext(nlayout_key)
/**
* Set the ui to update the layout (re-render it) on each update, turning this on will break the map ui (if it's being used)
*
* @param state int (bool) Set update to 1 or 0 (true/false) (default 0)
*
* @return nothing
*/
/datum/nanoui/proc/set_auto_update_layout(nstate)
auto_update_layout = nstate
/**
* Set the ui to update the main content (re-render it) on each update
*
* @param state int (bool) Set update to 1 or 0 (true/false) (default 1)
*
* @return nothing
*/
/datum/nanoui/proc/set_auto_update_content(nstate)
auto_update_content = nstate
/**
* Set the state key for use in the frontend Javascript
*
* @param nstate_key string The key of the state to use
*
* @return nothing
*/
/datum/nanoui/proc/set_state_key(nstate_key)
state_key = nstate_key
/**
* Toggle showing the map ui
*
* @param nstate_key boolean 1 to show map, 0 to hide (default is 0)
*
* @return nothing
*/
/datum/nanoui/proc/set_show_map(nstate)
show_map = nstate
/**
* Toggle showing the map ui
*
* @param nstate_key boolean 1 to show map, 0 to hide (default is 0)
*
* @return nothing
*/
/datum/nanoui/proc/set_map_z_level(nz)
map_z_level = nz
/**
* Set whether or not to use the "old" on close logic (mainly unset_machine())
@@ -255,80 +324,63 @@ nanoui is used to open and update nano browser uis
on_close_logic = state
/**
* Return the HTML header content for this UI
* Return the HTML for this UI
*
* @return string HTML header content
* @return string HTML for the UI
*/
/datum/nanoui/proc/get_header()
/datum/nanoui/proc/get_html()
// before the UI opens, add the layout files based on the layout key
add_stylesheet("layout_[layout_key].css")
add_template("layout", "layout_[layout_key].tmpl")
var/head_content = ""
for (var/filename in scripts)
head_content += "<script type='text/javascript' src='[filename]'></script> "
for (var/filename in stylesheets)
head_content += "<link rel='stylesheet' type='text/css' href='[filename]'>"
var/templatel_data[0]
for (var/key in templates)
templatel_data[key] = templates[key];
head_content += "<link rel='stylesheet' type='text/css' href='[filename]'> "
var/template_data_json = "{}" // An empty JSON object
if (templatel_data.len > 0)
template_data_json = list2json(templatel_data)
if (templates.len > 0)
template_data_json = list2json(templates)
var/initial_data_json = "{}" // An empty JSON object
if (initial_data.len > 0)
initial_data_json = list2json(initial_data)
var/list/send_data = get_send_data(initial_data)
var/initial_data_json = replacetext(replacetext(list2json_usecache(send_data), "&#34;", "&amp;#34;"), "'", "&#39;")
var/url_parameters_json = list2json(list("src" = "\ref[src]"))
return {"<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
return {"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<head>
<script type='text/javascript'>
function receiveUpdateData(jsonString)
{
// We need both jQuery and NanoUpdate to be able to recieve data
// We need both jQuery and NanoStateManager to be able to recieve data
// At the moment any data received before those libraries are loaded will be lost
if (typeof NanoUpdate != 'undefined' && typeof jQuery != 'undefined')
if (typeof NanoStateManager != 'undefined' && typeof jQuery != 'undefined')
{
NanoUpdate.receiveUpdateData(jsonString);
NanoStateManager.receiveUpdateData(jsonString);
}
}
</script>
[head_content]
</head>
<body scroll=auto data-url-parameters='[url_parameters_json]' data-template-data='[template_data_json]' data-initial-data='[initial_data_json]'>
<div id='uiWrapper'>
[title ? "<div id='uiTitleWrapper'><div id='uiStatusIcon' class='icon24 uiStatusGood'></div><div id='uiTitle'>[title]</div><div id='uiTitleFluff'></div></div>" : ""]
<div id='uiContent'>
<div id='uiNoJavaScript'>Initiating...</div>
"}
/**
* Return the HTML footer content for this UI
*
* @return string HTML footer content
*/
/datum/nanoui/proc/get_footer()
return {"
</div>
<body scroll=auto data-template-data='[template_data_json]' data-url-parameters='[url_parameters_json]' data-initial-data='[initial_data_json]'>
<div id='uiLayout'>
</div>
<noscript>
<div id='uiNoScript'>
<h2>JAVASCRIPT REQUIRED</h2>
<p>Your Internet Explorer's Javascript is disabled (or broken).<br/>
Enable Javascript and then open this UI again.</p>
</div>
</noscript>
</body>
</html>"}
/**
* Return the HTML for this UI
*
* @return string HTML for the UI
*/
/datum/nanoui/proc/get_html()
return {"
[get_header()]
[content]
[get_footer()]
</html>
"}
/**
@@ -337,16 +389,34 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/proc/open()
if(!user.client)
return
var/window_size = ""
if (width && height)
window_size = "size=[width]x[height];"
update_status(0)
if(status == NANO_CLOSE)
return
user << browse(get_html(), "window=[window_id];[window_size][window_options]")
winset(user, "mapwindow.map", "focus=true") // return keyboard focus to map
on_close_winset()
//onclose(user, window_id)
SSnano.ui_opened(src)
/**
* Reinitialise this UI, potentially with a different template and/or initial data
*
* @return nothing
*/
/datum/nanoui/proc/reinitialise(template, new_initial_data)
if(template)
add_template("main", template)
if(new_initial_data)
set_initial_data(new_initial_data)
open()
/**
* Close this UI
*
@@ -356,6 +426,8 @@ nanoui is used to open and update nano browser uis
is_auto_updating = 0
SSnano.ui_closed(src)
user << browse(null, "window=[window_id]")
for(var/datum/nanoui/child in children)
child.close()
/**
* Set the UI window to call the nanoclose verb when the window is closed
@@ -377,26 +449,37 @@ nanoui is used to open and update nano browser uis
*/
/datum/nanoui/proc/push_data(data, force_push = 0)
update_status(0)
if (status == STATUS_DISABLED && !force_push)
if (status == NANO_DISABLED && !force_push)
return // Cannot update UI, no visibility
data = add_default_data(data)
var/list/send_data = get_send_data(data)
//user << list2json(data) // used for debugging
user << output(list2params(list(list2json(data))),"[window_id].browser:receiveUpdateData")
user << output(list2params(list(list2json_usecache(send_data))),"[window_id].browser:receiveUpdateData")
/**
* This Topic() proc is called whenever a user clicks on a link within a Nano UI
* If the UI status is currently STATUS_INTERACTIVE then call the src_object Topic()
* If the UI status is currently NANO_INTERACTIVE then call the src_object Topic()
* If the src_object Topic() returns 1 (true) then update all UIs attached to src_object
*
* @return nothing
*/
/datum/nanoui/Topic(href, href_list)
update_status(0) // update the status
if (status != STATUS_INTERACTIVE || user != usr) // If UI is not interactive or usr calling Topic is not the UI user
if (status != NANO_INTERACTIVE || user != usr) // If UI is not interactive or usr calling Topic is not the UI user
return
if (src_object && src_object.Topic(href, href_list))
// This is used to toggle the nano map ui
var/map_update = 0
if(href_list["showMap"])
set_show_map(text2num(href_list["showMap"]))
map_update = 1
if(href_list["mapZLevel"])
set_map_z_level(text2num(href_list["mapZLevel"]))
map_update = 1
if ((src_object && src_object.Topic(href, href_list, 0, state)) || map_update)
SSnano.update_uis(src_object) // update all UIs attached to src_object
/**
@@ -413,7 +496,14 @@ nanoui is used to open and update nano browser uis
return
if (status && (update || is_auto_updating))
src_object.ui_interact(user, ui_key, src) // Update the UI (update_status() is called whenever a UI is updated)
update() // Update the UI (update_status() is called whenever a UI is updated)
else
update_status(1) // Not updating UI, so lets check here if status has changed
/**
* Update the UI
*
* @return nothing
*/
/datum/nanoui/proc/update(var/force_open = 0)
src_object.ui_interact(user, ui_key, src, force_open, master_ui, state)
+1 -1
View File
@@ -661,7 +661,7 @@
if(!user)
return
ui = SSnano.push_open_or_new_ui(user, src, ui_key, ui, "apc.tmpl", "[area.name] - APC", 520, user.has_unlimited_silicon_privilege ? 465 : 420, 1)
ui = SSnano.push_open_or_new_ui(user, src, ui_key, ui, "apc.tmpl", "[area.name] - APC", 540, user.has_unlimited_silicon_privilege ? 550 : 470, 1)
/obj/machinery/power/apc/get_ui_data(mob/user)
var/list/data = list(