Skip to content
This repository has been archived by the owner on Jun 7, 2022. It is now read-only.

Commit

Permalink
[MIRROR] Ports tgui lists (#711)
Browse files Browse the repository at this point in the history
* Ports tgui lists (#3366)

* init

Co-Authored-By: Watermelon914 <37270891+Watermelon914@ users.noreply.github.com>

* adds usage

Co-Authored-By: Watermelon914 <37270891+Watermelon914@ users.noreply.github.com>

* switches more lists to using tgui

* stuffs

* fix lmao

* more stuffs uses the thing

* fix

* fix1

* search

* rebuild

* remove stuffs that don't work

* blegh

* that works?

Co-authored-by: Watermelon914 <37270891+Watermelon914@ users.noreply.github.com>

* Ports tgui lists

Co-authored-by: LatteKat <56778689+jupyterkat@users.noreply.github.com>
Co-authored-by: Watermelon914 <37270891+Watermelon914@ users.noreply.github.com>
  • Loading branch information
3 people committed Mar 27, 2021
1 parent f587944 commit d2f3e1a
Show file tree
Hide file tree
Showing 24 changed files with 454 additions and 32 deletions.
1 change: 1 addition & 0 deletions beestation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -3139,6 +3139,7 @@
#include "code\modules\tgui\external.dm"
#include "code\modules\tgui\states.dm"
#include "code\modules\tgui\tgui.dm"
#include "code\modules\tgui\tgui_input_list.dm"
#include "code\modules\tgui\tgui_window.dm"
#include "code\modules\tgui\states\admin.dm"
#include "code\modules\tgui\states\always.dm"
Expand Down
2 changes: 1 addition & 1 deletion code/__HELPERS/files.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
if(path != root)
choices.Insert(1,"/")

var/choice = input(src,"Choose a file to access:","Download",null) as null|anything in sortList(choices)
var/choice = tgui_input_list(src,"Choose a file to access:","Download",sortList(choices))
switch(choice)
if(null)
return
Expand Down
2 changes: 1 addition & 1 deletion code/__HELPERS/unsorted.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
if(matches.len==1)
chosen = matches[1]
else
chosen = input("Select a type", "Pick Type", matches[1]) as null|anything in sortList(matches)
chosen = tgui_input_list(usr, "Select a type", "Pick Type", sortList(matches))
if(!chosen)
return
chosen = matches[chosen]
Expand Down
2 changes: 1 addition & 1 deletion code/_onclick/hud/ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
if(..())
return
var/mob/living/silicon/ai/AI = usr
var/target_name = input(AI, "Choose who you want to track", "Tracking") as null|anything in AI.trackable_mobs()
var/target_name = tgui_input_list(AI, "Choose who you want to track", "Tracking", AI.trackable_mobs())
AI.ai_camera_track(target_name)

/atom/movable/screen/ai/camera_light
Expand Down
13 changes: 5 additions & 8 deletions code/datums/mind.dm
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@
A.admin_remove(usr)

if (href_list["role_edit"])
var/new_role = input("Select new role", "Assigned role", assigned_role) as null|anything in sortList(get_all_jobs())
var/new_role = tgui_input_list(usr,"Select new role", "Assigned role", sortList(get_all_jobs()))
if (!new_role)
return
assigned_role = new_role
Expand All @@ -411,7 +411,6 @@

else if (href_list["obj_edit"] || href_list["obj_add"])
var/objective_pos //Edited objectives need to keep same order in antag objective list
var/def_value
var/datum/antagonist/target_antag
var/datum/objective/old_objective //The old objective we're replacing/editing
var/datum/objective/new_objective //New objective we're be adding
Expand All @@ -438,7 +437,9 @@
if(1)
target_antag = antag_datums[1]
else
var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", "(new custom antag)") as null|anything in sortList(antag_datums) + "(new custom antag)"
var/datum/antagonist/target = tgui_input_list(usr, "Which antagonist gets the objective:", "Antagonist", sortList(antag_datums) + "(new custom antag)")
if(!target)
target = "(new custom antag)"
if (QDELETED(target))
return
else if(target == "(new custom antag)")
Expand All @@ -449,11 +450,7 @@
if(!GLOB.admin_objective_list)
generate_admin_objective_list()

if(old_objective)
if(old_objective.name in GLOB.admin_objective_list)
def_value = old_objective.name

var/selected_type = input("Select objective type:", "Objective type", def_value) as null|anything in GLOB.admin_objective_list
var/selected_type = tgui_input_list(usr, "Select objective type:", "Objective type", GLOB.admin_objective_list)
selected_type = GLOB.admin_objective_list[selected_type]
if (!selected_type)
return
Expand Down
2 changes: 1 addition & 1 deletion code/datums/mutations/actions.dm
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
if(!length(possible))
to_chat(user,"<span class='warning'>Despite your best efforts, there are no scents to be found on [sniffed]...</span>")
return
tracking_target = input(user, "Choose a scent to remember.", "Scent Tracking") as null|anything in sortNames(possible)
tracking_target = tgui_input_list(user, "Choose a scent to remember.", "Scent Tracking", sortNames(possible))
if(!tracking_target)
if(!old_target)
to_chat(user,"<span class='warning'>You decide against remembering any scents. Instead, you notice your own nose in your peripheral vision. This goes on to remind you of that one time you started breathing manually and couldn't stop. What an awful day that was.</span>")
Expand Down
2 changes: 1 addition & 1 deletion code/game/atoms.dm
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@
if(!valid_id)
to_chat(usr, "<span class='warning'>A reagent with that ID doesn't exist!</span>")
if("Choose from a list")
chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in subtypesof(/datum/reagent)
chosen_id = tgui_input_list(usr, "Choose a reagent to add.", "Choose a reagent.", subtypesof(/datum/reagent))
if("I'm feeling lucky")
chosen_id = pick(subtypesof(/datum/reagent))
if(chosen_id)
Expand Down
7 changes: 1 addition & 6 deletions code/game/gamemodes/objective.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,11 @@ GLOBAL_LIST_EMPTY(objectives)
//Shared by few objective types
/datum/objective/proc/admin_simple_target_pick(mob/admin)
var/list/possible_targets = list("Free objective","Random")
var/def_value
for(var/datum/mind/possible_target in SSticker.minds)
if ((possible_target != src) && ishuman(possible_target.current))
possible_targets += possible_target.current


if(target?.current)
def_value = target.current

var/mob/new_target = input(admin,"Select target:", "Objective target", def_value) as null|anything in sortNames(possible_targets)
var/mob/new_target = tgui_input_list(admin,"Select target:", "Objective target", sortNames(possible_targets))
if (!new_target)
return

Expand Down
2 changes: 1 addition & 1 deletion code/game/machinery/camera/tracking.dm
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

/mob/living/silicon/ai/proc/show_camera_list()
var/list/cameras = get_camera_list()
var/camera = input(src, "Choose which camera you want to view", "Cameras") as null|anything in cameras
var/camera = tgui_input_list(src, "Choose which camera you want to view", "Cameras", cameras)
switchCamera(cameras[camera])

/datum/trackable
Expand Down
2 changes: 1 addition & 1 deletion code/game/machinery/hologram.dm
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ Possible to do for anyone motivated enough:
LAZYADD(callnames[A], I)
callnames -= get_area(src)

var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in sortNames(callnames)
var/result = tgui_input_list(usr, "Choose an area to call", "Holocall", sortNames(callnames))
if(QDELETED(usr) || !result || outgoing_call)
return

Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items/holy_weapons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@
if (initial(rodtype.chaplain_spawnable))
display_names[initial(rodtype.name)] = rodtype

var/choice = input(M,"What theme would you like for your holy weapon?","Holy Weapon Theme") as null|anything in sortList(display_names, /proc/cmp_typepaths_asc)
var/choice = tgui_input_list(M,"What theme would you like for your holy weapon?","Holy Weapon Theme", sortList(display_names, /proc/cmp_typepaths_asc))
if(QDELETED(src) || !choice || M.stat || !in_range(M, src) || M.incapacitated() || reskinned)
return

Expand Down
4 changes: 2 additions & 2 deletions code/modules/mob/living/simple_animal/bot/mulebot.dm
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@
if("destination")
var/new_dest
if(pda)
new_dest = input(user, "Enter Destination:", name, destination) as null|anything in GLOB.deliverybeacontags
new_dest = tgui_input_list(user, "Enter Destination:", name, GLOB.deliverybeacontags)
else
new_dest = params["value"]
if(new_dest)
Expand All @@ -262,7 +262,7 @@
if("sethome")
var/new_home
if(pda)
new_home = input(user, "Enter Home:", name, home_destination) as null|anything in GLOB.deliverybeacontags
new_home = tgui_input_list(user, "Enter Home:", name, GLOB.deliverybeacontags)
else
new_home = params["value"]
if(new_home)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/modular_computers/computers/item/computer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@
var/obj/item/computer_hardware/H = all_components[h]
component_names.Add(H.name)

var/choice = input(user, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in sortList(component_names)
var/choice = tgui_input_list(user, "Which component do you want to uninstall?", "Computer maintenance", sortList(component_names))

if(!choice)
return
Expand Down
2 changes: 1 addition & 1 deletion code/modules/shuttle/assault_pod.dm
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

/obj/item/assault_pod/attack_self(mob/living/user)
var/target_area
target_area = input("Area to land", "Select a Landing Zone", target_area) as null|anything in GLOB.teleportlocs
target_area = tgui_input_list(user, "Area to land", "Select a Landing Zone", GLOB.teleportlocs)
if(!target_area)
return
var/area/picked_area = GLOB.teleportlocs[target_area]
Expand Down
2 changes: 1 addition & 1 deletion code/modules/spells/spell_types/area_teleport.dm
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
var/A = null

if(!randomise_selection)
A = input("Area to teleport to", "Teleport", A) as null|anything in GLOB.teleportlocs
A = tgui_input_list(usr, "Area to teleport to", "Teleport", GLOB.teleportlocs)
else
A = pick(GLOB.teleportlocs)
if(!A)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/surgery/helpers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
if(!available_surgeries.len)
return

var/P = input("Begin which procedure?", "Surgery", null, null) as null|anything in sortList(available_surgeries)
var/P = tgui_input_list(user, "Begin which procedure?", "Surgery", sortList(available_surgeries))
if(P && user && user.Adjacent(M) && (I in user))
var/datum/surgery/S = available_surgeries[P]

Expand Down
184 changes: 184 additions & 0 deletions code/modules/tgui/tgui_input_list.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/**
* Creates a TGUI input list window and returns the user's response.
*
* This proc should be used to create alerts that the caller will wait for a response from.
* Arguments:
* * user - The user to show the input box to.
* * message - The content of the input box, shown in the body of the TGUI window.
* * title - The title of the input box, shown on the top of the TGUI window.
* * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
* * timeout - The timeout of the input box, after which the input box will close and qdel itself. Set to zero for no timeout.
*/
/proc/tgui_input_list(mob/user, message, title, list/buttons, timeout = 0)
if (!user)
user = usr
if(!length(buttons))
return
if (!istype(user))
if (istype(user, /client))
var/client/client = user
user = client.mob
else
return
var/datum/tgui_list_input/input = new(user, message, title, buttons, timeout)
input.ui_interact(user)
input.wait()
if (input)
. = input.choice
qdel(input)

/**
* Creates an asynchronous TGUI input list window with an associated callback.
*
* This proc should be used to create inputs that invoke a callback with the user's chosen option.
* Arguments:
* * user - The user to show the input box to.
* * message - The content of the input box, shown in the body of the TGUI window.
* * title - The title of the input box, shown on the top of the TGUI window.
* * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
* * callback - The callback to be invoked when a choice is made.
* * timeout - The timeout of the input box, after which the menu will close and qdel itself. Set to zero for no timeout.
*/
/proc/tgui_input_list_async(mob/user, message, title, list/buttons, datum/callback/callback, timeout = 60 SECONDS)
if (!user)
user = usr
if(!length(buttons))
return
if (!istype(user))
if (istype(user, /client))
var/client/client = user
user = client.mob
else
return
var/datum/tgui_list_input/async/input = new(user, message, title, buttons, callback, timeout)
input.ui_interact(user)

/**
* # tgui_list_input
*
* Datum used for instantiating and using a TGUI-controlled list input that prompts the user with
* a message and shows a list of selectable options
*/
/datum/tgui_list_input
/// The title of the TGUI window
var/title
/// The textual body of the TGUI window
var/message
/// The list of buttons (responses) provided on the TGUI window
var/list/buttons
/// Buttons (strings specifically) mapped to the actual value (e.g. a mob or a verb)
var/list/buttons_map
/// The button that the user has pressed, null if no selection has been made
var/choice
/// The time at which the tgui_list_input was created, for displaying timeout progress.
var/start_time
/// The lifespan of the tgui_list_input, after which the window will close and delete itself.
var/timeout
/// Boolean field describing if the tgui_list_input was closed by the user.
var/closed

/datum/tgui_list_input/New(mob/user, message, title, list/buttons, timeout)
src.title = title
src.message = message
src.buttons = list()
src.buttons_map = list()

// Gets rid of illegal characters
var/static/regex/whitelistedWords = regex(@{"([^\u0020-\u8000]+)"})

for(var/i in buttons)
var/string_key = whitelistedWords.Replace("[i]", "")

src.buttons += string_key
src.buttons_map[string_key] = i


if (timeout)
src.timeout = timeout
start_time = world.time
QDEL_IN(src, timeout)

/datum/tgui_list_input/Destroy(force, ...)
SStgui.close_uis(src)
QDEL_NULL(buttons)
. = ..()

/**
* Waits for a user's response to the tgui_list_input's prompt before returning. Returns early if
* the window was closed by the user.
*/
/datum/tgui_list_input/proc/wait()
while (!choice && !closed)
stoplag(1)

/datum/tgui_list_input/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ListInput")
ui.open()

/datum/tgui_list_input/ui_close(mob/user)
. = ..()
closed = TRUE

/datum/tgui_list_input/ui_state(mob/user)
return GLOB.always_state

/datum/tgui_list_input/ui_static_data(mob/user)
. = list(
"title" = title,
"message" = message,
"buttons" = buttons
)

/datum/tgui_list_input/ui_data(mob/user)
. = list()
if(timeout)
.["timeout"] = clamp((timeout - (world.time - start_time) - 1 SECONDS) / (timeout - 1 SECONDS), 0, 1)

/datum/tgui_list_input/ui_act(action, list/params)
. = ..()
if (.)
return
switch(action)
if("choose")
if (!(params["choice"] in buttons))
return
choice = buttons_map[params["choice"]]
SStgui.close_uis(src)
return TRUE
if("cancel")
SStgui.close_uis(src)
closed = TRUE
return TRUE

/**
* # async tgui_list_input
*
* An asynchronous version of tgui_list_input to be used with callbacks instead of waiting on user responses.
*/
/datum/tgui_list_input/async
/// The callback to be invoked by the tgui_list_input upon having a choice made.
var/datum/callback/callback

/datum/tgui_list_input/async/New(mob/user, message, title, list/buttons, callback, timeout)
..(user, title, message, buttons, timeout)
src.callback = callback

/datum/tgui_list_input/async/Destroy(force, ...)
QDEL_NULL(callback)
. = ..()

/datum/tgui_list_input/async/ui_close(mob/user)
. = ..()
qdel(src)

/datum/tgui_list_input/async/ui_act(action, list/params)
. = ..()
if (!. || choice == null)
return
callback.InvokeAsync(choice)
qdel(src)

/datum/tgui_list_input/async/wait()
return
Loading

0 comments on commit d2f3e1a

Please sign in to comment.