mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
[MIRROR] Action button refactor/rework: Enhanced Dragging [MDB IGNORE] (#12423)
* Action button refactor/rework: Enhanced Dragging * PHEW Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com>
This commit is contained in:
@@ -92,26 +92,26 @@
|
||||
if (LAZYACCESS(modifiers, MIDDLE_CLICK))
|
||||
if (src_object && src_location != over_location)
|
||||
middragtime = world.time
|
||||
middragatom = src_object
|
||||
middle_drag_atom_ref = WEAKREF(src_object)
|
||||
else
|
||||
middragtime = 0
|
||||
middragatom = null
|
||||
middle_drag_atom_ref = null
|
||||
mouseParams = params
|
||||
mouseLocation = over_location
|
||||
mouseObject = over_object
|
||||
mouse_location_ref = WEAKREF(over_location)
|
||||
mouse_object_ref = WEAKREF(over_object)
|
||||
if(selected_target[1] && over_object?.IsAutoclickable())
|
||||
selected_target[1] = over_object
|
||||
selected_target[2] = params
|
||||
if(active_mousedown_item)
|
||||
active_mousedown_item.onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
|
||||
SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEDRAG, src_object, over_object, src_location, over_location, src_control, over_control, params)
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
|
||||
return
|
||||
|
||||
/client/MouseDrop(src_object, over_object, src_location, over_location, src_control, over_control, params)
|
||||
if (middragatom == src_object)
|
||||
/client/MouseDrop(atom/src_object, atom/over_object, atom/src_location, atom/over_location, src_control, over_control, params)
|
||||
if (IS_WEAKREF_OF(src_object, middle_drag_atom_ref))
|
||||
middragtime = 0
|
||||
middragatom = null
|
||||
middle_drag_atom_ref = null
|
||||
..()
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
These defines specificy screen locations. For more information, see the byond documentation on the screen_loc var.
|
||||
|
||||
The short version:
|
||||
|
||||
Everything is encoded as strings because apparently that's how Byond rolls.
|
||||
|
||||
"1,1" is the bottom left square of the user's screen. This aligns perfectly with the turf grid.
|
||||
"1:2,3:4" is the square (1,3) with pixel offsets (+2, +4); slightly right and slightly above the turf grid.
|
||||
Pixel offsets are used so you don't perfectly hide the turf under them, that would be crappy.
|
||||
|
||||
In addition, the keywords NORTH, SOUTH, EAST, WEST and CENTER can be used to represent their respective
|
||||
screen borders. NORTH-1, for example, is the row just below the upper edge. Useful if you want your
|
||||
UI to scale with screen size.
|
||||
|
||||
The size of the user's screen is defined by client.view (indirectly by world.view), in our case "15x15".
|
||||
Therefore, the top right corner (except during admin shenanigans) is at "15,15"
|
||||
*/
|
||||
|
||||
/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5)
|
||||
var/x_off = -(!(i % 2))
|
||||
var/y_off = round((i-1) / 2)
|
||||
return"CENTER+[x_off]:16,SOUTH+[y_off]:5"
|
||||
|
||||
/proc/ui_equip_position(mob/M)
|
||||
var/y_off = round((M.held_items.len-1) / 2) //values based on old equip ui position (CENTER: +/-16,SOUTH+1:5)
|
||||
return "CENTER:-16,SOUTH+[y_off+1]:5"
|
||||
|
||||
/proc/ui_swaphand_position(mob/M, which = 1) //values based on old swaphand ui positions (CENTER: +/-16,SOUTH+1:5)
|
||||
var/x_off = which == 1 ? -1 : 0
|
||||
var/y_off = round((M.held_items.len-1) / 2)
|
||||
return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5"
|
||||
|
||||
//Lower left, persistent menu
|
||||
#define ui_inventory "WEST:6,SOUTH:5"
|
||||
|
||||
//Middle left indicators
|
||||
#define ui_lingchemdisplay "WEST,CENTER-1:15"
|
||||
#define ui_lingstingdisplay "WEST:6,CENTER-3:11"
|
||||
|
||||
//Lower center, persistent menu
|
||||
#define ui_sstore1 "CENTER-5:10,SOUTH:5"
|
||||
#define ui_id "CENTER-4:12,SOUTH:5"
|
||||
#define ui_belt "CENTER-3:14,SOUTH:5"
|
||||
#define ui_back "CENTER-2:14,SOUTH:5"
|
||||
#define ui_storage1 "CENTER+1:18,SOUTH:5"
|
||||
#define ui_storage2 "CENTER+2:20,SOUTH:5"
|
||||
#define ui_combo "CENTER+4:24,SOUTH+1:7" //combo meter for martial arts
|
||||
//SKYRAT EDIT ADDITION BEGIN - ERP_SLOT_SYSTEM
|
||||
#define ui_vagina "WEST+1:8,SOUTH+4:14"
|
||||
#define ui_vagina_down "WEST+1:8,SOUTH+1:8"
|
||||
#define ui_anus "WEST+2:10,SOUTH+4:14"
|
||||
#define ui_anus_down "WEST+2:10,SOUTH+1:8"
|
||||
#define ui_nipples "WEST:6,SOUTH+5:17"
|
||||
#define ui_nipples_down "WEST:6,SOUTH+2:11"
|
||||
#define ui_penis "WEST+1:8,SOUTH+5:17"
|
||||
#define ui_penis_down "WEST+1:8,SOUTH+2:11"
|
||||
#define ui_erp_inventory "WEST:6,SOUTH+1:8"
|
||||
#define ui_erp_inventory_up "WEST:6,SOUTH+4:14"
|
||||
//SKYRAT EDI ADDITION END
|
||||
|
||||
//Lower right, persistent menu
|
||||
#define ui_drop_throw "EAST-1:28,SOUTH+1:7"
|
||||
#define ui_above_movement "EAST-2:26,SOUTH+1:7"
|
||||
#define ui_above_intent "EAST-3:24, SOUTH+1:7"
|
||||
#define ui_movi "EAST-2:26,SOUTH:5"
|
||||
#define ui_acti "EAST-3:24,SOUTH:5"
|
||||
#define ui_combat_toggle "EAST-3:24,SOUTH:5"
|
||||
#define ui_zonesel "EAST-1:28,SOUTH:5"
|
||||
#define ui_acti_alt "EAST-1:28,SOUTH:5" //alternative intent switcher for when the interface is hidden (F12)
|
||||
#define ui_crafting "EAST-4:22,SOUTH:5"
|
||||
#define ui_building "EAST-4:22,SOUTH:21"
|
||||
#define ui_language_menu "EAST-4:6,SOUTH:21"
|
||||
#define ui_skill_menu "EAST-4:22,SOUTH:5"
|
||||
|
||||
//Upper-middle right (alerts)
|
||||
#define ui_alert1 "EAST-1:28,CENTER+5:27"
|
||||
#define ui_alert2 "EAST-1:28,CENTER+4:25"
|
||||
#define ui_alert3 "EAST-1:28,CENTER+3:23"
|
||||
#define ui_alert4 "EAST-1:28,CENTER+2:21"
|
||||
#define ui_alert5 "EAST-1:28,CENTER+1:19"
|
||||
|
||||
//Middle right (status indicators)
|
||||
#define ui_healthdoll "EAST-1:28,CENTER-2:13"
|
||||
#define ui_health "EAST-1:28,CENTER-1:15"
|
||||
#define ui_internal "EAST-1:28,CENTER+1:17"
|
||||
#define ui_mood "EAST-1:28,CENTER:17"
|
||||
#define ui_spacesuit "EAST-1:28,CENTER-4:10"
|
||||
#define ui_stamina "EAST-1:28,CENTER-3:10"
|
||||
|
||||
//Pop-up inventory
|
||||
#define ui_shoes "WEST+1:8,SOUTH:5"
|
||||
#define ui_iclothing "WEST:6,SOUTH+1:7"
|
||||
#define ui_oclothing "WEST+1:8,SOUTH+1:7"
|
||||
#define ui_gloves "WEST+2:10,SOUTH+1:7"
|
||||
#define ui_glasses "WEST:6,SOUTH+3:11"
|
||||
#define ui_mask "WEST+1:8,SOUTH+2:9"
|
||||
#define ui_ears "WEST+2:10,SOUTH+2:9"
|
||||
#define ui_neck "WEST:6,SOUTH+2:9"
|
||||
#define ui_head "WEST+1:8,SOUTH+3:11"
|
||||
|
||||
//Generic living
|
||||
#define ui_living_pull "EAST-1:28,CENTER-3:15"
|
||||
#define ui_living_healthdoll "EAST-1:28,CENTER-1:15"
|
||||
|
||||
//Monkeys
|
||||
#define ui_monkey_head "CENTER-5:13,SOUTH:5"
|
||||
#define ui_monkey_mask "CENTER-4:14,SOUTH:5"
|
||||
#define ui_monkey_neck "CENTER-3:15,SOUTH:5"
|
||||
#define ui_monkey_back "CENTER-2:16,SOUTH:5"
|
||||
|
||||
//Drones
|
||||
#define ui_drone_drop "CENTER+1:18,SOUTH:5"
|
||||
#define ui_drone_pull "CENTER+2:2,SOUTH:5"
|
||||
#define ui_drone_storage "CENTER-2:14,SOUTH:5"
|
||||
#define ui_drone_head "CENTER-3:14,SOUTH:5"
|
||||
|
||||
//Cyborgs
|
||||
#define ui_borg_health "EAST-1:28,CENTER-1:15"
|
||||
#define ui_borg_pull "EAST-2:26,SOUTH+1:7"
|
||||
#define ui_borg_radio "EAST-1:28,SOUTH+1:7"
|
||||
#define ui_borg_intents "EAST-2:26,SOUTH:5"
|
||||
#define ui_borg_lamp "CENTER-3:16, SOUTH:5"
|
||||
#define ui_borg_tablet "CENTER-4:16, SOUTH:5"
|
||||
#define ui_inv1 "CENTER-2:16,SOUTH:5"
|
||||
#define ui_inv2 "CENTER-1 :16,SOUTH:5"
|
||||
#define ui_inv3 "CENTER :16,SOUTH:5"
|
||||
#define ui_borg_module "CENTER+1:16,SOUTH:5"
|
||||
#define ui_borg_store "CENTER+2:16,SOUTH:5"
|
||||
#define ui_borg_camera "CENTER+3:21,SOUTH:5"
|
||||
#define ui_borg_alerts "CENTER+4:21,SOUTH:5"
|
||||
#define ui_borg_language_menu "CENTER+4:19,SOUTH+1:6"
|
||||
// SKYRAT EDIT ADDITION BEGIN - Cyborg PDA
|
||||
#define ui_borg_pda_send "CENTER+5:21,SOUTH:5" // To the right of the alert panel
|
||||
#define ui_borg_pda_log "CENTER+6:21,SOUTH:5"
|
||||
// SKYRAT EDIT ADDITION END
|
||||
|
||||
//Aliens
|
||||
#define ui_alien_health "EAST,CENTER-1:15"
|
||||
#define ui_alienplasmadisplay "EAST,CENTER-2:15"
|
||||
#define ui_alien_queen_finder "EAST,CENTER-3:15"
|
||||
#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"
|
||||
#define ui_alien_language_menu "EAST-4:20,SOUTH:5"
|
||||
|
||||
//AI
|
||||
#define ui_ai_core "SOUTH:6,WEST"
|
||||
#define ui_ai_camera_list "SOUTH:6,WEST+1"
|
||||
#define ui_ai_track_with_camera "SOUTH:6,WEST+2"
|
||||
#define ui_ai_camera_light "SOUTH:6,WEST+3"
|
||||
#define ui_ai_crew_monitor "SOUTH:6,WEST+4"
|
||||
#define ui_ai_crew_manifest "SOUTH:6,WEST+5"
|
||||
#define ui_ai_alerts "SOUTH:6,WEST+6"
|
||||
#define ui_ai_announcement "SOUTH:6,WEST+7"
|
||||
#define ui_ai_shuttle "SOUTH:6,WEST+8"
|
||||
#define ui_ai_state_laws "SOUTH:6,WEST+9"
|
||||
#define ui_ai_pda_send "SOUTH:6,WEST+10"
|
||||
#define ui_ai_pda_log "SOUTH:6,WEST+11"
|
||||
#define ui_ai_take_picture "SOUTH:6,WEST+12"
|
||||
#define ui_ai_view_images "SOUTH:6,WEST+13"
|
||||
#define ui_ai_sensor "SOUTH:6,WEST+14"
|
||||
#define ui_ai_multicam "SOUTH+1:6,WEST+13"
|
||||
#define ui_ai_add_multicam "SOUTH+1:6,WEST+14"
|
||||
#define ui_ai_language_menu "SOUTH+1:8,WEST+11:30"
|
||||
|
||||
//pAI
|
||||
#define ui_pai_software "SOUTH:6,WEST"
|
||||
#define ui_pai_shell "SOUTH:6,WEST+1"
|
||||
#define ui_pai_chassis "SOUTH:6,WEST+2"
|
||||
#define ui_pai_rest "SOUTH:6,WEST+3"
|
||||
#define ui_pai_light "SOUTH:6,WEST+4"
|
||||
#define ui_pai_newscaster "SOUTH:6,WEST+5"
|
||||
#define ui_pai_host_monitor "SOUTH:6,WEST+6"
|
||||
#define ui_pai_crew_manifest "SOUTH:6,WEST+7"
|
||||
#define ui_pai_state_laws "SOUTH:6,WEST+8"
|
||||
#define ui_pai_pda_send "SOUTH:6,WEST+9"
|
||||
#define ui_pai_pda_log "SOUTH:6,WEST+10"
|
||||
#define ui_pai_internal_gps "SOUTH:6,WEST+11"
|
||||
#define ui_pai_take_picture "SOUTH:6,WEST+12"
|
||||
#define ui_pai_view_images "SOUTH:6,WEST+13"
|
||||
#define ui_pai_radio "SOUTH:6,WEST+14"
|
||||
#define ui_pai_language_menu "SOUTH+1:8,WEST+13:31"
|
||||
|
||||
//Ghosts
|
||||
#define ui_ghost_spawners_menu "SOUTH:6,CENTER-3:24"
|
||||
#define ui_ghost_orbit "SOUTH:6,CENTER-2:24"
|
||||
#define ui_ghost_reenter_corpse "SOUTH:6,CENTER-1:24"
|
||||
#define ui_ghost_teleport "SOUTH:6,CENTER:24"
|
||||
#define ui_ghost_pai "SOUTH: 6, CENTER+1:24"
|
||||
#define ui_ghost_minigames "SOUTH: 6, CENTER+2:24"
|
||||
#define ui_ghost_language_menu "SOUTH: 22, CENTER+3:8"
|
||||
|
||||
//Blobbernauts
|
||||
#define ui_blobbernaut_overmind_health "EAST-1:28,CENTER+0:19"
|
||||
|
||||
//Families
|
||||
#define ui_wanted_lvl "NORTH,11"
|
||||
|
||||
//SKYRAT HUD DEFINES BELOW
|
||||
#define ui_ammocounter "EAST-1:28,CENTER-5:9"
|
||||
@@ -2,22 +2,36 @@
|
||||
|
||||
/atom/movable/screen/movable/action_button
|
||||
var/datum/action/linked_action
|
||||
var/datum/hud/our_hud
|
||||
var/actiontooltipstyle = ""
|
||||
screen_loc = null
|
||||
|
||||
var/button_icon_state
|
||||
var/appearance_cache
|
||||
|
||||
/// Where we are currently placed on the hud. SCRN_OBJ_DEFAULT asks the linked action what it thinks
|
||||
var/location = SCRN_OBJ_DEFAULT
|
||||
/// A unique bitflag, combined with the name of our linked action this lets us persistently remember any user changes to our position
|
||||
var/id
|
||||
var/ordered = TRUE //If the button gets placed into the default bar
|
||||
/// A weakref of the last thing we hovered over
|
||||
/// God I hate how dragging works
|
||||
var/datum/weakref/last_hovored_ref
|
||||
|
||||
/atom/movable/screen/movable/action_button/Destroy()
|
||||
if(our_hud)
|
||||
var/mob/viewer = our_hud.mymob
|
||||
our_hud.hide_action(src)
|
||||
viewer?.client?.screen -= src
|
||||
linked_action.viewers -= our_hud
|
||||
viewer.update_action_buttons()
|
||||
our_hud = null
|
||||
linked_action = null
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/movable/action_button/proc/can_use(mob/user)
|
||||
if(linked_action)
|
||||
if(linked_action.owner == user)
|
||||
if(linked_action.viewers[user.hud_used])
|
||||
return TRUE
|
||||
for(var/datum/weakref/reference as anything in linked_action.sharers)
|
||||
if(IS_WEAKREF_OF(user, reference))
|
||||
return TRUE
|
||||
return FALSE
|
||||
else if (isobserver(user))
|
||||
var/mob/dead/observer/O = user
|
||||
@@ -25,41 +39,14 @@
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/atom/movable/screen/movable/action_button/MouseDrop(over_object)
|
||||
if(!can_use(usr))
|
||||
return
|
||||
if((istype(over_object, /atom/movable/screen/movable/action_button) && !istype(over_object, /atom/movable/screen/movable/action_button/hide_toggle)))
|
||||
if(locked)
|
||||
to_chat(usr, span_warning("Action button \"[name]\" is locked, unlock it first."))
|
||||
return
|
||||
var/atom/movable/screen/movable/action_button/B = over_object
|
||||
var/list/actions = usr.actions
|
||||
actions.Swap(actions.Find(src.linked_action), actions.Find(B.linked_action))
|
||||
moved = FALSE
|
||||
ordered = TRUE
|
||||
B.moved = FALSE
|
||||
B.ordered = TRUE
|
||||
usr.update_action_buttons()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/movable/action_button/Click(location,control,params)
|
||||
if (!can_use(usr))
|
||||
return FALSE
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
if(LAZYACCESS(modifiers, SHIFT_CLICK))
|
||||
if(locked)
|
||||
to_chat(usr, span_warning("Action button \"[name]\" is locked, unlock it first."))
|
||||
return TRUE
|
||||
moved = 0
|
||||
usr.update_action_buttons() //redraw buttons that are no longer considered "moved"
|
||||
return TRUE
|
||||
if(LAZYACCESS(modifiers, CTRL_CLICK))
|
||||
locked = !locked
|
||||
to_chat(usr, span_notice("Action button \"[name]\" [locked ? "" : "un"]locked."))
|
||||
if(id && usr.client) //try to (un)remember position
|
||||
usr.client.prefs.action_buttons_screen_locs["[name]_[id]"] = locked ? moved : null
|
||||
var/datum/hud/our_hud = usr.hud_used
|
||||
our_hud.position_action(src, SCRN_OBJ_DEFAULT)
|
||||
return TRUE
|
||||
if(usr.next_click > world.time)
|
||||
return
|
||||
@@ -70,127 +57,105 @@
|
||||
linked_action.Trigger(trigger_flags = trigger_flags)
|
||||
return TRUE
|
||||
|
||||
//Hide/Show Action Buttons ... Button
|
||||
/atom/movable/screen/movable/action_button/hide_toggle
|
||||
name = "Hide Buttons"
|
||||
desc = "Shift-click any button to reset its position, and Control-click it to lock it in place. Alt-click this button to reset all buttons to their default positions."
|
||||
icon = 'icons/hud/actions.dmi'
|
||||
icon_state = "bg_default"
|
||||
var/hidden = FALSE
|
||||
var/hide_icon = 'icons/hud/actions.dmi'
|
||||
var/hide_state = "hide"
|
||||
var/show_state = "show"
|
||||
var/mutable_appearance/hide_appearance
|
||||
var/mutable_appearance/show_appearance
|
||||
|
||||
/atom/movable/screen/movable/action_button/hide_toggle/Initialize(mapload)
|
||||
// Entered and Exited won't fire while you're dragging something, because you're still "holding" it
|
||||
// Very much byond logic, but I want nice behavior, so we fake it with drag
|
||||
/atom/movable/screen/movable/action_button/MouseDrag(atom/over_object, src_location, over_location, src_control, over_control, params)
|
||||
. = ..()
|
||||
var/static/list/icon_cache = list()
|
||||
|
||||
var/cache_key = "[hide_icon][hide_state]"
|
||||
hide_appearance = icon_cache[cache_key]
|
||||
if(!hide_appearance)
|
||||
hide_appearance = icon_cache[cache_key] = mutable_appearance(hide_icon, hide_state)
|
||||
|
||||
cache_key = "[hide_icon][show_state]"
|
||||
show_appearance = icon_cache[cache_key]
|
||||
if(!show_appearance)
|
||||
show_appearance = icon_cache[cache_key] = mutable_appearance(hide_icon, show_state)
|
||||
|
||||
|
||||
/atom/movable/screen/movable/action_button/hide_toggle/Click(location,control,params)
|
||||
if (!can_use(usr))
|
||||
if(!can_use(usr))
|
||||
return
|
||||
if(IS_WEAKREF_OF(over_object, last_hovored_ref))
|
||||
return
|
||||
var/atom/old_object
|
||||
if(last_hovored_ref)
|
||||
old_object = last_hovored_ref?.resolve()
|
||||
else // If there's no current ref, we assume it was us. We also treat this as our "first go" location
|
||||
old_object = src
|
||||
var/datum/hud/our_hud = usr.hud_used
|
||||
our_hud?.generate_landings(src)
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
if(LAZYACCESS(modifiers, SHIFT_CLICK))
|
||||
if(locked)
|
||||
to_chat(usr, span_warning("Action button \"[name]\" is locked, unlock it first."))
|
||||
return TRUE
|
||||
moved = FALSE
|
||||
usr.update_action_buttons(TRUE)
|
||||
return TRUE
|
||||
if(LAZYACCESS(modifiers, CTRL_CLICK))
|
||||
locked = !locked
|
||||
to_chat(usr, span_notice("Action button \"[name]\" [locked ? "" : "un"]locked."))
|
||||
if(id && usr.client) //try to (un)remember position
|
||||
usr.client.prefs.action_buttons_screen_locs["[name]_[id]"] = locked ? moved : null
|
||||
return TRUE
|
||||
if(LAZYACCESS(modifiers, ALT_CLICK))
|
||||
var/buttons_locked = usr.client.prefs.read_preference(/datum/preference/toggle/buttons_locked)
|
||||
for(var/V in usr.actions)
|
||||
var/datum/action/A = V
|
||||
var/atom/movable/screen/movable/action_button/B = A.button
|
||||
B.moved = FALSE
|
||||
if(B.id && usr.client)
|
||||
usr.client.prefs.action_buttons_screen_locs["[B.name]_[B.id]"] = null
|
||||
B.locked = buttons_locked
|
||||
locked = buttons_locked
|
||||
moved = FALSE
|
||||
if(id && usr.client)
|
||||
usr.client.prefs.action_buttons_screen_locs["[name]_[id]"] = null
|
||||
usr.update_action_buttons(TRUE)
|
||||
to_chat(usr, span_notice("Action button positions have been reset."))
|
||||
return TRUE
|
||||
usr.hud_used.action_buttons_hidden = !usr.hud_used.action_buttons_hidden
|
||||
if(old_object)
|
||||
old_object.MouseExited(over_location, over_control, params)
|
||||
|
||||
hidden = usr.hud_used.action_buttons_hidden
|
||||
if(hidden)
|
||||
name = "Show Buttons"
|
||||
else
|
||||
name = "Hide Buttons"
|
||||
update_appearance()
|
||||
usr.update_action_buttons()
|
||||
last_hovored_ref = WEAKREF(over_object)
|
||||
over_object.MouseEntered(over_location, over_control, params)
|
||||
|
||||
/atom/movable/screen/movable/action_button/hide_toggle/AltClick(mob/user)
|
||||
for(var/V in user.actions)
|
||||
var/datum/action/A = V
|
||||
var/atom/movable/screen/movable/action_button/B = A.button
|
||||
B.moved = FALSE
|
||||
if(moved)
|
||||
moved = FALSE
|
||||
user.update_action_buttons(TRUE)
|
||||
to_chat(user, span_notice("Action button positions have been reset."))
|
||||
|
||||
|
||||
/atom/movable/screen/movable/action_button/hide_toggle/proc/InitialiseIcon(datum/hud/owner_hud)
|
||||
var/settings = owner_hud.get_action_buttons_icons()
|
||||
icon = settings["bg_icon"]
|
||||
icon_state = settings["bg_state"]
|
||||
hide_icon = settings["toggle_icon"]
|
||||
hide_state = settings["toggle_hide"]
|
||||
show_state = settings["toggle_show"]
|
||||
update_appearance()
|
||||
|
||||
/atom/movable/screen/movable/action_button/hide_toggle/update_overlays()
|
||||
. = ..()
|
||||
. += hidden ? show_appearance : hide_appearance
|
||||
|
||||
/atom/movable/screen/movable/action_button/MouseEntered(location,control,params)
|
||||
/atom/movable/screen/movable/action_button/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
if(!QDELETED(src))
|
||||
openToolTip(usr,src,params,title = name,content = desc,theme = actiontooltipstyle)
|
||||
openToolTip(usr, src, params, title = name, content = desc, theme = actiontooltipstyle)
|
||||
|
||||
|
||||
/atom/movable/screen/movable/action_button/MouseExited()
|
||||
/atom/movable/screen/movable/action_button/MouseExited(location, control, params)
|
||||
closeToolTip(usr)
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/movable/action_button/MouseDrop(over_object)
|
||||
last_hovored_ref = null
|
||||
if(!can_use(usr))
|
||||
return
|
||||
var/datum/hud/our_hud = usr.hud_used
|
||||
if(over_object == src)
|
||||
our_hud.hide_landings()
|
||||
return
|
||||
if(istype(over_object, /atom/movable/screen/action_landing))
|
||||
var/atom/movable/screen/action_landing/reserve = over_object
|
||||
reserve.hit_by(src)
|
||||
our_hud.hide_landings()
|
||||
save_position()
|
||||
return
|
||||
|
||||
our_hud.hide_landings()
|
||||
if(istype(over_object, /atom/movable/screen/button_palette) || istype(over_object, /atom/movable/screen/palette_scroll))
|
||||
our_hud.position_action(src, SCRN_OBJ_IN_PALETTE)
|
||||
save_position()
|
||||
return
|
||||
if(istype(over_object, /atom/movable/screen/movable/action_button))
|
||||
var/atom/movable/screen/movable/action_button/button = over_object
|
||||
our_hud.position_action_relative(src, button)
|
||||
save_position()
|
||||
return
|
||||
. = ..()
|
||||
our_hud.position_action(src, screen_loc)
|
||||
save_position()
|
||||
|
||||
/atom/movable/screen/movable/action_button/proc/save_position()
|
||||
var/mob/user = our_hud.mymob
|
||||
if(!user?.client)
|
||||
return
|
||||
var/position_info = ""
|
||||
switch(location)
|
||||
if(SCRN_OBJ_FLOATING)
|
||||
position_info = screen_loc
|
||||
if(SCRN_OBJ_IN_LIST)
|
||||
position_info = SCRN_OBJ_IN_LIST
|
||||
if(SCRN_OBJ_IN_PALETTE)
|
||||
position_info = SCRN_OBJ_IN_PALETTE
|
||||
|
||||
user.client.prefs.action_buttons_screen_locs["[name]_[id]"] = position_info
|
||||
|
||||
/atom/movable/screen/movable/action_button/proc/load_position()
|
||||
var/mob/user = our_hud.mymob
|
||||
if(!user)
|
||||
return
|
||||
var/position_info = user.client?.prefs?.action_buttons_screen_locs["[name]_[id]"] || SCRN_OBJ_DEFAULT
|
||||
user.hud_used.position_action(src, position_info)
|
||||
|
||||
/atom/movable/screen/movable/action_button/proc/dump_save()
|
||||
var/mob/user = our_hud.mymob
|
||||
if(!user?.client)
|
||||
return
|
||||
user.client.prefs.action_buttons_screen_locs -= "[name]_[id]"
|
||||
|
||||
/datum/hud/proc/get_action_buttons_icons()
|
||||
. = list()
|
||||
.["bg_icon"] = ui_style
|
||||
.["bg_state"] = "template"
|
||||
|
||||
//TODO : Make these fit theme
|
||||
.["toggle_icon"] = 'icons/hud/actions.dmi'
|
||||
.["toggle_hide"] = "hide"
|
||||
.["toggle_show"] = "show"
|
||||
|
||||
//see human and alien hud for specific implementations.
|
||||
|
||||
/mob/proc/update_action_buttons_icon(status_only = FALSE)
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon(status_only)
|
||||
A.UpdateButtons(status_only)
|
||||
|
||||
//This is the proc used to update all the action buttons.
|
||||
/mob/proc/update_action_buttons(reload_screen)
|
||||
@@ -200,58 +165,243 @@
|
||||
if(hud_used.hud_shown != HUD_STYLE_STANDARD)
|
||||
return
|
||||
|
||||
var/button_number = 0
|
||||
for(var/datum/action/action as anything in actions)
|
||||
var/atom/movable/screen/movable/action_button/button = action.viewers[hud_used]
|
||||
action.UpdateButtons()
|
||||
if(reload_screen)
|
||||
client.screen += button
|
||||
|
||||
if(hud_used.action_buttons_hidden)
|
||||
for(var/datum/action/A in actions)
|
||||
A.button.screen_loc = null
|
||||
if(reload_screen)
|
||||
client.screen += A.button
|
||||
else
|
||||
for(var/datum/action/A in actions)
|
||||
A.UpdateButtonIcon()
|
||||
var/atom/movable/screen/movable/action_button/B = A.button
|
||||
if(B.ordered)
|
||||
button_number++
|
||||
if(B.moved)
|
||||
B.screen_loc = B.moved
|
||||
else
|
||||
B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number)
|
||||
if(reload_screen)
|
||||
client.screen += B
|
||||
|
||||
if(!button_number)
|
||||
hud_used.hide_actions_toggle.screen_loc = null
|
||||
return
|
||||
|
||||
if(!hud_used.hide_actions_toggle.moved)
|
||||
hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1)
|
||||
else
|
||||
hud_used.hide_actions_toggle.screen_loc = hud_used.hide_actions_toggle.moved
|
||||
if(reload_screen)
|
||||
client.screen += hud_used.hide_actions_toggle
|
||||
hud_used.update_our_owner()
|
||||
// This holds the logic for the palette buttons
|
||||
hud_used.palette_actions.refresh_actions()
|
||||
|
||||
/atom/movable/screen/button_palette
|
||||
desc = "<b>Drag</b> buttons to move them<br><b>Shift-click</b> any button to reset it<br><b>Alt-click</b> this to reset all buttons"
|
||||
icon = 'icons/hud/64x16_actions.dmi'
|
||||
icon_state = "screen_gen_palette"
|
||||
screen_loc = ui_action_palette
|
||||
var/datum/hud/our_hud
|
||||
var/expanded = FALSE
|
||||
/// Id of any currently running timers that set our color matrix
|
||||
var/color_timer_id
|
||||
|
||||
/atom/movable/screen/button_palette/Destroy()
|
||||
if(our_hud)
|
||||
our_hud.mymob?.client?.screen -= src
|
||||
our_hud.toggle_palette = null
|
||||
our_hud = null
|
||||
return ..()
|
||||
|
||||
#define AB_MAX_COLUMNS 10
|
||||
/atom/movable/screen/button_palette/Initialize(mapload)
|
||||
. = ..()
|
||||
update_appearance()
|
||||
|
||||
/datum/hud/proc/ButtonNumberToScreenCoords(number) // TODO : Make this zero-indexed for readabilty
|
||||
var/row = round((number - 1)/AB_MAX_COLUMNS)
|
||||
var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
|
||||
/atom/movable/screen/button_palette/proc/set_hud(datum/hud/our_hud)
|
||||
src.our_hud = our_hud
|
||||
refresh_owner()
|
||||
|
||||
var/coord_col = "+[col-1]"
|
||||
var/coord_col_offset = 4 + 2 * col
|
||||
/atom/movable/screen/button_palette/update_name(updates)
|
||||
. = ..()
|
||||
if(expanded)
|
||||
name = "Hide Buttons"
|
||||
else
|
||||
name = "Show Buttons"
|
||||
|
||||
var/coord_row = "[row ? -row : "+0"]"
|
||||
/atom/movable/screen/button_palette/proc/refresh_owner()
|
||||
var/mob/viewer = our_hud.mymob
|
||||
if(viewer.client)
|
||||
viewer.client.screen |= src
|
||||
|
||||
return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:-6"
|
||||
var/list/settings = our_hud.get_action_buttons_icons()
|
||||
var/ui_icon = "[settings["bg_icon"]]"
|
||||
var/list/ui_segments = splittext(ui_icon, ".")
|
||||
var/list/ui_paths = splittext(ui_segments[1], "/")
|
||||
var/ui_name = ui_paths[length(ui_paths)]
|
||||
|
||||
/datum/hud/proc/SetButtonCoords(atom/movable/screen/button,number)
|
||||
var/row = round((number-1)/AB_MAX_COLUMNS)
|
||||
var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
|
||||
var/x_offset = 32*(col-1) + 4 + 2*col
|
||||
var/y_offset = -32*(row+1) + 26
|
||||
icon_state = "[ui_name]_palette"
|
||||
|
||||
var/matrix/M = matrix()
|
||||
M.Translate(x_offset,y_offset)
|
||||
button.transform = M
|
||||
/atom/movable/screen/button_palette/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
show_tooltip(params)
|
||||
|
||||
/atom/movable/screen/button_palette/MouseExited()
|
||||
closeToolTip(usr)
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/button_palette/proc/show_tooltip(params)
|
||||
openToolTip(usr, src, params, title = name, content = desc)
|
||||
|
||||
GLOBAL_LIST_INIT(palette_added_matrix, list(0.4,0.5,0.2,0, 0,1.4,0,0, 0,0.4,0.6,0, 0,0,0,1, 0,0,0,0))
|
||||
GLOBAL_LIST_INIT(palette_removed_matrix, list(1.4,0,0,0, 0.7,0.4,0,0, 0.4,0,0.6,0, 0,0,0,1, 0,0,0,0))
|
||||
|
||||
/atom/movable/screen/button_palette/proc/play_item_added()
|
||||
color_for_now(GLOB.palette_added_matrix)
|
||||
|
||||
/atom/movable/screen/button_palette/proc/play_item_removed()
|
||||
color_for_now(GLOB.palette_removed_matrix)
|
||||
|
||||
/atom/movable/screen/button_palette/proc/color_for_now(list/color)
|
||||
if(color_timer_id)
|
||||
return
|
||||
add_atom_colour(color, TEMPORARY_COLOUR_PRIORITY) //We unfortunately cannot animate matrix colors. Curse you lummy it would be ~~non~~trivial to interpolate between the two valuessssssssss
|
||||
color_timer_id = addtimer(CALLBACK(src, .proc/remove_color, color), 2 SECONDS)
|
||||
|
||||
/atom/movable/screen/button_palette/proc/remove_color(list/to_remove)
|
||||
color_timer_id = null
|
||||
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, to_remove)
|
||||
|
||||
/atom/movable/screen/button_palette/proc/can_use(mob/user)
|
||||
if (isobserver(user))
|
||||
var/mob/dead/observer/O = user
|
||||
return !O.observetarget
|
||||
return TRUE
|
||||
|
||||
/atom/movable/screen/button_palette/Click(location, control, params)
|
||||
if(!can_use(usr))
|
||||
return
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
|
||||
if(LAZYACCESS(modifiers, ALT_CLICK))
|
||||
for(var/datum/action/action as anything in usr.actions) // Reset action positions to default
|
||||
for(var/datum/hud/hud as anything in action.viewers)
|
||||
var/atom/movable/screen/movable/action_button/button = action.viewers[hud]
|
||||
hud.position_action(button, SCRN_OBJ_DEFAULT)
|
||||
to_chat(usr, span_notice("Action button positions have been reset."))
|
||||
return TRUE
|
||||
|
||||
set_expanded(!expanded)
|
||||
|
||||
/atom/movable/screen/button_palette/proc/clicked_while_open(datum/source, atom/target, atom/location, control, params, mob/user)
|
||||
if(istype(target, /atom/movable/screen/movable/action_button) || istype(target, /atom/movable/screen/palette_scroll) || target == src) // If you're clicking on an action button, or us, you can live
|
||||
return
|
||||
set_expanded(FALSE)
|
||||
if(source)
|
||||
UnregisterSignal(source, COMSIG_CLIENT_CLICK)
|
||||
|
||||
/atom/movable/screen/button_palette/proc/set_expanded(new_expanded)
|
||||
var/datum/action_group/our_group = our_hud.palette_actions
|
||||
if(!length(our_group.actions)) //Looks dumb, trust me lad
|
||||
new_expanded = FALSE
|
||||
if(expanded == new_expanded)
|
||||
return
|
||||
|
||||
expanded = new_expanded
|
||||
our_group.refresh_actions()
|
||||
update_appearance()
|
||||
|
||||
if(!usr.client)
|
||||
return
|
||||
|
||||
if(expanded)
|
||||
RegisterSignal(usr.client, COMSIG_CLIENT_CLICK, .proc/clicked_while_open)
|
||||
else
|
||||
UnregisterSignal(usr.client, COMSIG_CLIENT_CLICK)
|
||||
|
||||
closeToolTip(usr) //Our tooltips are now invalid, can't seem to update them in one frame, so here, just close them
|
||||
|
||||
/atom/movable/screen/palette_scroll
|
||||
icon = 'icons/hud/screen_gen.dmi'
|
||||
screen_loc = ui_palette_scroll
|
||||
/// How should we move the palette's actions?
|
||||
/// Positive scrolls down the list, negative scrolls back
|
||||
var/scroll_direction = 0
|
||||
var/datum/hud/our_hud
|
||||
|
||||
/atom/movable/screen/palette_scroll/proc/can_use(mob/user)
|
||||
if (isobserver(user))
|
||||
var/mob/dead/observer/O = user
|
||||
return !O.observetarget
|
||||
return TRUE
|
||||
|
||||
/atom/movable/screen/palette_scroll/proc/set_hud(datum/hud/our_hud)
|
||||
src.our_hud = our_hud
|
||||
refresh_owner()
|
||||
|
||||
/atom/movable/screen/palette_scroll/proc/refresh_owner()
|
||||
var/mob/viewer = our_hud.mymob
|
||||
if(viewer.client)
|
||||
viewer.client.screen |= src
|
||||
|
||||
var/list/settings = our_hud.get_action_buttons_icons()
|
||||
icon = settings["bg_icon"]
|
||||
|
||||
/atom/movable/screen/palette_scroll/Click(location, control, params)
|
||||
if(!can_use(usr))
|
||||
return
|
||||
our_hud.palette_actions.scroll(scroll_direction)
|
||||
|
||||
/atom/movable/screen/palette_scroll/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
openToolTip(usr, src, params, title = name, content = desc)
|
||||
|
||||
/atom/movable/screen/palette_scroll/MouseExited()
|
||||
closeToolTip(usr)
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/palette_scroll/down
|
||||
name = "Scroll Down"
|
||||
desc = "<b>Click</b> on this to scroll the actions above down"
|
||||
icon_state = "scroll_down"
|
||||
scroll_direction = 1
|
||||
|
||||
/atom/movable/screen/palette_scroll/down/Destroy()
|
||||
if(our_hud)
|
||||
our_hud.mymob?.client?.screen -= src
|
||||
our_hud.palette_down = null
|
||||
our_hud = null
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/palette_scroll/up
|
||||
name = "Scroll Up"
|
||||
desc = "<b>Click</b> on this to scroll the actions above up"
|
||||
icon_state = "scroll_up"
|
||||
scroll_direction = -1
|
||||
|
||||
/atom/movable/screen/palette_scroll/up/Destroy()
|
||||
if(our_hud)
|
||||
our_hud.mymob?.client?.screen -= src
|
||||
our_hud.palette_up = null
|
||||
our_hud = null
|
||||
return ..()
|
||||
|
||||
/// Exists so you have a place to put your buttons when you move them around
|
||||
/atom/movable/screen/action_landing
|
||||
name = "Button Space"
|
||||
desc = "<b>Drag and drop</b> a button into this spot<br>to add it to the group"
|
||||
icon = 'icons/hud/screen_gen.dmi'
|
||||
icon_state = "reserved"
|
||||
// We want our whole 32x32 space to be clickable, so dropping's forgiving
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
var/datum/action_group/owner
|
||||
|
||||
/atom/movable/screen/action_landing/Destroy()
|
||||
if(owner)
|
||||
owner.landing = null
|
||||
owner?.owner?.mymob?.client?.screen -= src
|
||||
owner.refresh_actions()
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/action_landing/proc/set_owner(datum/action_group/owner)
|
||||
src.owner = owner
|
||||
refresh_owner()
|
||||
|
||||
/atom/movable/screen/action_landing/proc/refresh_owner()
|
||||
var/datum/hud/our_hud = owner.owner
|
||||
var/mob/viewer = our_hud.mymob
|
||||
if(viewer.client)
|
||||
viewer.client.screen |= src
|
||||
|
||||
var/list/settings = our_hud.get_action_buttons_icons()
|
||||
icon = settings["bg_icon"]
|
||||
|
||||
/// Reacts to having a button dropped on it
|
||||
/atom/movable/screen/action_landing/proc/hit_by(atom/movable/screen/movable/action_button/button)
|
||||
var/datum/hud/our_hud = owner.owner
|
||||
our_hud.position_action(button, owner.location)
|
||||
|
||||
@@ -93,8 +93,13 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
|
||||
/// game (MouseEntered).
|
||||
var/screentip_color
|
||||
|
||||
var/atom/movable/screen/movable/action_button/hide_toggle/hide_actions_toggle
|
||||
var/action_buttons_hidden = FALSE
|
||||
var/atom/movable/screen/button_palette/toggle_palette
|
||||
var/atom/movable/screen/palette_scroll/down/palette_down
|
||||
var/atom/movable/screen/palette_scroll/up/palette_up
|
||||
|
||||
var/datum/action_group/palette/palette_actions
|
||||
var/datum/action_group/listed/listed_actions
|
||||
var/list/floating_actions
|
||||
|
||||
var/atom/movable/screen/healths
|
||||
var/atom/movable/screen/stamina
|
||||
@@ -114,10 +119,12 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
|
||||
ui_style = ui_style2icon(owner.client?.prefs?.read_preference(/datum/preference/choiced/ui_style))
|
||||
erp_ui_style = erp_ui_style2icon(owner.client?.prefs?.read_preference(/datum/preference/choiced/ui_style)) //SKYRAT EDIT - ADDITION - ERP ICONS FIX
|
||||
|
||||
hide_actions_toggle = new
|
||||
hide_actions_toggle.InitialiseIcon(src)
|
||||
if(mymob.client?.prefs)
|
||||
hide_actions_toggle.locked = mymob.client.prefs.read_preference(/datum/preference/toggle/buttons_locked)
|
||||
toggle_palette = new()
|
||||
toggle_palette.set_hud(src)
|
||||
palette_down = new()
|
||||
palette_down.set_hud(src)
|
||||
palette_up = new()
|
||||
palette_up.set_hud(src)
|
||||
|
||||
hand_slots = list()
|
||||
|
||||
@@ -142,7 +149,13 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
|
||||
if(mymob.hud_used == src)
|
||||
mymob.hud_used = null
|
||||
|
||||
QDEL_NULL(hide_actions_toggle)
|
||||
QDEL_NULL(toggle_palette)
|
||||
QDEL_NULL(palette_down)
|
||||
QDEL_NULL(palette_up)
|
||||
QDEL_NULL(palette_actions)
|
||||
QDEL_NULL(listed_actions)
|
||||
QDEL_LIST(floating_actions)
|
||||
|
||||
QDEL_NULL(module_store_icon)
|
||||
QDEL_LIST(static_inventory)
|
||||
|
||||
@@ -184,10 +197,14 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
|
||||
/mob/proc/create_mob_hud()
|
||||
if(!client || hud_used)
|
||||
return
|
||||
hud_used = new hud_type(src)
|
||||
set_hud_used(new hud_type(src))
|
||||
update_sight()
|
||||
SEND_SIGNAL(src, COMSIG_MOB_HUD_CREATED)
|
||||
|
||||
/mob/proc/set_hud_used(datum/hud/new_hud)
|
||||
hud_used = new_hud
|
||||
new_hud.build_action_groups()
|
||||
|
||||
//Version denotes which style should be displayed. blank or 0 means "next version"
|
||||
/datum/hud/proc/show_hud(version = 0, mob/viewmob)
|
||||
if(!ismob(mymob))
|
||||
@@ -196,6 +213,8 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
|
||||
if(!screenmob.client)
|
||||
return FALSE
|
||||
|
||||
// This code is the absolute fucking worst, I want it to go die in a fire
|
||||
// Seriously, why
|
||||
screenmob.client.screen = list()
|
||||
screenmob.client.apply_clickcatcher()
|
||||
|
||||
@@ -221,7 +240,7 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
|
||||
if(infodisplay.len)
|
||||
screenmob.client.screen += infodisplay
|
||||
|
||||
screenmob.client.screen += hide_actions_toggle
|
||||
screenmob.client.screen += toggle_palette
|
||||
|
||||
if(action_intent)
|
||||
action_intent.screen_loc = initial(action_intent.screen_loc) //Restore intent selection to the original position
|
||||
@@ -320,7 +339,6 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
|
||||
|
||||
ui_style = new_ui_style
|
||||
build_hand_slots()
|
||||
hide_actions_toggle.InitialiseIcon(src)
|
||||
|
||||
//SKYRAT EDIT - ADDITION - ERP ICONS FIX
|
||||
|
||||
@@ -334,7 +352,6 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
|
||||
item.icon = new_erp_ui_style
|
||||
|
||||
erp_ui_style = new_erp_ui_style
|
||||
hide_actions_toggle.InitialiseIcon(src)
|
||||
|
||||
//SKYRAT EDIT - ADDITION - ERP ICONS FIX - END
|
||||
|
||||
@@ -384,3 +401,306 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list(
|
||||
|
||||
/datum/hud/proc/update_locked_slots()
|
||||
return
|
||||
|
||||
/datum/hud/proc/position_action(atom/movable/screen/movable/action_button/button, position)
|
||||
if(button.location != SCRN_OBJ_DEFAULT)
|
||||
hide_action(button)
|
||||
switch(position)
|
||||
if(SCRN_OBJ_DEFAULT) // Reset to the default
|
||||
button.dump_save() // Nuke any existing saves
|
||||
position_action(button, button.linked_action.default_button_position)
|
||||
return
|
||||
if(SCRN_OBJ_IN_LIST)
|
||||
listed_actions.insert_action(button)
|
||||
if(SCRN_OBJ_IN_PALETTE)
|
||||
palette_actions.insert_action(button)
|
||||
else // If we don't have it as a define, this is a screen_loc, and we should be floating
|
||||
floating_actions += button
|
||||
button.screen_loc = position
|
||||
position = SCRN_OBJ_FLOATING
|
||||
|
||||
button.location = position
|
||||
|
||||
/datum/hud/proc/position_action_relative(atom/movable/screen/movable/action_button/button, atom/movable/screen/movable/action_button/relative_to)
|
||||
if(button.location != SCRN_OBJ_DEFAULT)
|
||||
hide_action(button)
|
||||
switch(relative_to.location)
|
||||
if(SCRN_OBJ_IN_LIST)
|
||||
listed_actions.insert_action(button, listed_actions.index_of(relative_to))
|
||||
if(SCRN_OBJ_IN_PALETTE)
|
||||
palette_actions.insert_action(button, palette_actions.index_of(relative_to))
|
||||
if(SCRN_OBJ_FLOATING) // If we don't have it as a define, this is a screen_loc, and we should be floating
|
||||
floating_actions += button
|
||||
var/client/our_client = mymob.client
|
||||
if(!our_client)
|
||||
position_action(button, button.linked_action.default_button_position)
|
||||
return
|
||||
button.screen_loc = get_valid_screen_location(relative_to.screen_loc, world.icon_size, our_client.view_size.getView()) // Asks for a location adjacent to our button that won't overflow the map
|
||||
|
||||
button.location = relative_to.location
|
||||
|
||||
/// Removes the passed in action from its current position on the screen
|
||||
/datum/hud/proc/hide_action(atom/movable/screen/movable/action_button/button)
|
||||
switch(button.location)
|
||||
if(SCRN_OBJ_DEFAULT) // Invalid
|
||||
CRASH("We just tried to hide an action buttion that somehow has the default position as its location, you done fucked up")
|
||||
if(SCRN_OBJ_FLOATING)
|
||||
floating_actions -= button
|
||||
if(SCRN_OBJ_IN_LIST)
|
||||
listed_actions.remove_action(button)
|
||||
if(SCRN_OBJ_IN_PALETTE)
|
||||
palette_actions.remove_action(button)
|
||||
button.screen_loc = null
|
||||
|
||||
/// Generates visual landings for all groups that the button is not a memeber of
|
||||
/datum/hud/proc/generate_landings(atom/movable/screen/movable/action_button/button)
|
||||
listed_actions.generate_landing()
|
||||
palette_actions.generate_landing()
|
||||
|
||||
/// Clears all currently visible landings
|
||||
/datum/hud/proc/hide_landings()
|
||||
listed_actions.clear_landing()
|
||||
palette_actions.clear_landing()
|
||||
|
||||
// Updates any existing "owned" visuals, ensures they continue to be visible
|
||||
/datum/hud/proc/update_our_owner()
|
||||
toggle_palette.refresh_owner()
|
||||
palette_down.refresh_owner()
|
||||
palette_up.refresh_owner()
|
||||
listed_actions.update_landing()
|
||||
palette_actions.update_landing()
|
||||
|
||||
/// Ensures all of our buttons are properly within the bounds of our client's view, moves them if they're not
|
||||
/datum/hud/proc/view_audit_buttons()
|
||||
var/our_view = mymob?.client?.view
|
||||
if(!our_view)
|
||||
return
|
||||
listed_actions.check_against_view()
|
||||
palette_actions.check_against_view()
|
||||
for(var/atom/movable/screen/movable/action_button/floating_button as anything in floating_actions)
|
||||
var/list/current_offsets = screen_loc_to_offset(floating_button.screen_loc)
|
||||
// We set the view arg here, so the output will be properly hemm'd in by our new view
|
||||
floating_button.screen_loc = offset_to_screen_loc(current_offsets[1], current_offsets[2], view = our_view)
|
||||
|
||||
/// Generates and fills new action groups with our mob's current actions
|
||||
/datum/hud/proc/build_action_groups()
|
||||
listed_actions = new(src)
|
||||
palette_actions = new(src)
|
||||
floating_actions = list()
|
||||
for(var/datum/action/action as anything in mymob.actions)
|
||||
var/atom/movable/screen/movable/action_button/button = action.viewers[src]
|
||||
if(!button)
|
||||
action.ShowTo(mymob)
|
||||
button = action.viewers[src]
|
||||
position_action(button, button.location)
|
||||
|
||||
/datum/action_group
|
||||
/// The hud we're owned by
|
||||
var/datum/hud/owner
|
||||
/// The actions we're managing
|
||||
var/list/atom/movable/screen/movable/action_button/actions
|
||||
/// The initial vertical offset of our action buttons
|
||||
var/north_offset = 0
|
||||
/// The pixel vertical offset of our action buttons
|
||||
var/pixel_north_offset = 0
|
||||
/// Max amount of buttons we can have per row
|
||||
/// Indexes at 1
|
||||
var/column_max = 0
|
||||
/// How far "ahead" of the first row we start. Lets us "scroll" our rows
|
||||
/// Indexes at 1
|
||||
var/row_offset = 0
|
||||
/// How many rows of actions we can have at max before we just stop hiding
|
||||
/// Indexes at 1
|
||||
var/max_rows = INFINITY
|
||||
/// The screen location we go by
|
||||
var/location
|
||||
/// Our landing screen object
|
||||
var/atom/movable/screen/action_landing/landing
|
||||
|
||||
/datum/action_group/New(datum/hud/owner)
|
||||
..()
|
||||
actions = list()
|
||||
src.owner = owner
|
||||
|
||||
/datum/action_group/Destroy()
|
||||
owner = null
|
||||
QDEL_NULL(landing)
|
||||
QDEL_LIST(actions)
|
||||
return ..()
|
||||
|
||||
/datum/action_group/proc/insert_action(atom/movable/screen/action, index)
|
||||
if(action in actions)
|
||||
if(actions[index] == action)
|
||||
return
|
||||
actions -= action // Don't dupe, come on
|
||||
if(!index)
|
||||
index = length(actions) + 1
|
||||
index = min(length(actions) + 1, index)
|
||||
actions.Insert(index, action)
|
||||
refresh_actions()
|
||||
|
||||
/datum/action_group/proc/remove_action(atom/movable/screen/action)
|
||||
actions -= action
|
||||
refresh_actions()
|
||||
|
||||
/datum/action_group/proc/refresh_actions()
|
||||
|
||||
// We don't use size() here because landings are not canon
|
||||
var/total_rows = ROUND_UP(length(actions) / column_max)
|
||||
total_rows -= max_rows // Lets get the amount of rows we're off from our max
|
||||
row_offset = clamp(row_offset, 0, total_rows) // You're not allowed to offset so far that we have a row of blank space
|
||||
|
||||
var/button_number = 0
|
||||
for(var/atom/movable/screen/button as anything in actions)
|
||||
var/postion = ButtonNumberToScreenCoords(button_number )
|
||||
button.screen_loc = postion
|
||||
button_number++
|
||||
|
||||
if(landing)
|
||||
var/postion = ButtonNumberToScreenCoords(button_number, landing = TRUE) // Need a good way to count buttons off screen, but allow this to display in the right place if it's being placed with no concern for dropdown
|
||||
landing.screen_loc = postion
|
||||
button_number++
|
||||
|
||||
/// Accepts a number represeting our position in the group, indexes at 0 to make the math nicer
|
||||
/datum/action_group/proc/ButtonNumberToScreenCoords(number, landing = FALSE)
|
||||
var/row = round(number / column_max)
|
||||
row -= row_offset // If you're less then 0, you don't get to render, this lets us "scroll" rows ya feel?
|
||||
if(row < 0)
|
||||
return null
|
||||
|
||||
// Could use >= here, but I think it's worth noting that the two start at different places, since row is based on number here
|
||||
if(row > max_rows - 1)
|
||||
if(!landing) // If you're not a landing, go away please. thx
|
||||
return null
|
||||
// We always want to render landings, even if their action button can't be displayed.
|
||||
// So we set a row equal to the max amount of rows + 1. Willing to overrun that max slightly to properly display the landing spot
|
||||
row = max_rows // Remembering that max_rows indexes at 1, and row indexes at 0
|
||||
|
||||
// We're going to need to set our column to match the first item in the last row, so let's set number properly now
|
||||
number = row * column_max
|
||||
|
||||
var/visual_row = row + north_offset
|
||||
var/coord_row = visual_row ? "-[visual_row]" : "+0"
|
||||
|
||||
var/visual_column = number % column_max
|
||||
var/coord_col = "+[visual_column]"
|
||||
var/coord_col_offset = 4 + 2 * (visual_column + 1)
|
||||
return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:-[pixel_north_offset]"
|
||||
|
||||
/datum/action_group/proc/check_against_view()
|
||||
var/owner_view = owner?.mymob?.client?.view
|
||||
if(!owner_view)
|
||||
return
|
||||
// Unlikey as it is, we may have been changed. Want to start from our target position and fail down
|
||||
column_max = initial(column_max)
|
||||
// Convert our viewer's view var into a workable offset
|
||||
var/list/view_size = view_to_pixels(owner_view)
|
||||
|
||||
// We're primarially concerned about width here, if someone makes us 1x2000 I wish them a swift and watery death
|
||||
var/furthest_screen_loc = ButtonNumberToScreenCoords(column_max - 1)
|
||||
var/list/offsets = screen_loc_to_offset(furthest_screen_loc, owner_view)
|
||||
if(offsets[1] > world.icon_size && offsets[1] < view_size[1] && offsets[2] > world.icon_size && offsets[2] < view_size[2]) // We're all good
|
||||
return
|
||||
|
||||
for(column_max in column_max - 1 to 1 step -1) // Yes I could do this by unwrapping ButtonNumberToScreenCoords, but I don't feel like it
|
||||
var/tested_screen_loc = ButtonNumberToScreenCoords(column_max)
|
||||
offsets = screen_loc_to_offset(tested_screen_loc, owner_view)
|
||||
// We've found a valid max length, pack it in
|
||||
if(offsets[1] > world.icon_size && offsets[1] < view_size[1] && offsets[2] > world.icon_size && offsets[2] < view_size[2])
|
||||
break
|
||||
// Use our newly resized column max
|
||||
refresh_actions()
|
||||
|
||||
/// Returns the amount of objects we're storing at the moment
|
||||
/datum/action_group/proc/size()
|
||||
var/amount = length(actions)
|
||||
if(landing)
|
||||
amount += 1
|
||||
return amount
|
||||
|
||||
/datum/action_group/proc/index_of(atom/movable/screen/get_location)
|
||||
return actions.Find(get_location)
|
||||
|
||||
/// Generates a landing object that can be dropped on to join this group
|
||||
/datum/action_group/proc/generate_landing()
|
||||
if(landing)
|
||||
return
|
||||
landing = new()
|
||||
landing.set_owner(src)
|
||||
refresh_actions()
|
||||
|
||||
/// Clears any landing objects we may currently have
|
||||
/datum/action_group/proc/clear_landing()
|
||||
QDEL_NULL(landing)
|
||||
|
||||
/datum/action_group/proc/update_landing()
|
||||
if(!landing)
|
||||
return
|
||||
landing.refresh_owner()
|
||||
|
||||
/datum/action_group/proc/scroll(amount)
|
||||
row_offset += amount
|
||||
refresh_actions()
|
||||
|
||||
/datum/action_group/palette
|
||||
north_offset = 2
|
||||
column_max = 3
|
||||
max_rows = 3
|
||||
location = SCRN_OBJ_IN_PALETTE
|
||||
|
||||
/datum/action_group/palette/insert_action(atom/movable/screen/action, index)
|
||||
. = ..()
|
||||
var/atom/movable/screen/button_palette/palette = owner.toggle_palette
|
||||
palette.play_item_added()
|
||||
|
||||
/datum/action_group/palette/remove_action(atom/movable/screen/action)
|
||||
. = ..()
|
||||
var/atom/movable/screen/button_palette/palette = owner.toggle_palette
|
||||
palette.play_item_removed()
|
||||
if(!length(actions))
|
||||
palette.set_expanded(FALSE)
|
||||
|
||||
/datum/action_group/palette/refresh_actions()
|
||||
var/atom/movable/screen/button_palette/palette = owner.toggle_palette
|
||||
var/atom/movable/screen/palette_scroll/scroll_down = owner.palette_down
|
||||
var/atom/movable/screen/palette_scroll/scroll_up = owner.palette_up
|
||||
|
||||
var/actions_above = round((owner.listed_actions.size() - 1) / owner.listed_actions.column_max)
|
||||
north_offset = initial(north_offset) + actions_above
|
||||
|
||||
palette.screen_loc = ui_action_palette_offset(actions_above)
|
||||
var/action_count = length(owner?.mymob?.actions)
|
||||
var/our_row_count = round((length(actions) - 1) / column_max)
|
||||
if(!action_count)
|
||||
palette.screen_loc = null
|
||||
|
||||
if(palette.expanded && action_count && our_row_count >= max_rows)
|
||||
scroll_down.screen_loc = ui_palette_scroll_offset(actions_above)
|
||||
scroll_up.screen_loc = ui_palette_scroll_offset(actions_above)
|
||||
else
|
||||
scroll_down.screen_loc = null
|
||||
scroll_up.screen_loc = null
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/action_group/palette/ButtonNumberToScreenCoords(number, landing)
|
||||
var/atom/movable/screen/button_palette/palette = owner.toggle_palette
|
||||
if(palette.expanded)
|
||||
return ..()
|
||||
|
||||
if(!landing)
|
||||
return null
|
||||
|
||||
// We only render the landing in this case, so we force it to be the second item displayed (Second rather then first since it looks nicer)
|
||||
// Remember the number var indexes at 0
|
||||
return ..(1 + (row_offset * column_max), landing)
|
||||
|
||||
|
||||
/datum/action_group/listed
|
||||
pixel_north_offset = 6
|
||||
column_max = 10
|
||||
location = SCRN_OBJ_IN_LIST
|
||||
|
||||
/datum/action_group/listed/refresh_actions()
|
||||
. = ..()
|
||||
owner.palette_actions.refresh_actions() // We effect them, so we gotta refresh em
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
//Not tied to the grid, places it's center where the cursor is
|
||||
|
||||
/atom/movable/screen/movable
|
||||
mouse_drag_pointer = 'icons/effects/mouse_pointers/screen_drag.dmi'
|
||||
var/snap2grid = FALSE
|
||||
var/moved = FALSE
|
||||
var/locked = FALSE
|
||||
var/x_off = -16
|
||||
var/y_off = -16
|
||||
|
||||
@@ -21,35 +20,29 @@
|
||||
/atom/movable/screen/movable/snap
|
||||
snap2grid = TRUE
|
||||
|
||||
|
||||
/atom/movable/screen/movable/MouseDrop(over_object, src_location, over_location, src_control, over_control, params)
|
||||
if(locked) //no! I am locked! begone!
|
||||
var/position = mouse_params_to_position(params)
|
||||
if(!position)
|
||||
return
|
||||
|
||||
screen_loc = position
|
||||
|
||||
/// Takes mouse parmas as input, returns a string representing the appropriate mouse position
|
||||
/atom/movable/screen/movable/proc/mouse_params_to_position(params)
|
||||
var/list/modifiers = params2list(params)
|
||||
|
||||
//No screen-loc information? abort.
|
||||
if(!LAZYACCESS(modifiers, SCREEN_LOC))
|
||||
return
|
||||
|
||||
//Split screen-loc up into X+Pixel_X and Y+Pixel_Y
|
||||
var/list/screen_loc_params = splittext(LAZYACCESS(modifiers, SCREEN_LOC), ",")
|
||||
|
||||
//Split X+Pixel_X up into list(X, Pixel_X)
|
||||
var/list/screen_loc_X = splittext(screen_loc_params[1],":")
|
||||
|
||||
//Split Y+Pixel_Y up into list(Y, Pixel_Y)
|
||||
var/list/screen_loc_Y = splittext(screen_loc_params[2],":")
|
||||
|
||||
var/client/our_client = usr.client
|
||||
var/list/offset = screen_loc_to_offset(LAZYACCESS(modifiers, SCREEN_LOC))
|
||||
if(snap2grid) //Discard Pixel Values
|
||||
screen_loc = "[screen_loc_X[1]],[screen_loc_Y[1]]"
|
||||
|
||||
offset[1] = FLOOR(offset[1], world.icon_size) // drops any pixel offset
|
||||
offset[2] = FLOOR(offset[2], world.icon_size) // drops any pixel offset
|
||||
else //Normalise Pixel Values (So the object drops at the center of the mouse, not 16 pixels off)
|
||||
var/pix_X = text2num(screen_loc_X[2]) + x_off
|
||||
var/pix_Y = text2num(screen_loc_Y[2]) + y_off
|
||||
screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]"
|
||||
|
||||
moved = screen_loc
|
||||
|
||||
offset[1] += x_off
|
||||
offset[2] += y_off
|
||||
return offset_to_screen_loc(offset[1], offset[2], our_client?.view)
|
||||
|
||||
//Debug procs
|
||||
/client/proc/test_movable_UI()
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
SIGNAL_HANDLER
|
||||
if(!hud || !hud.mymob.client.view_size) //Might not have been initialized by now
|
||||
return
|
||||
maptext_width = getviewsize(hud.mymob.client.view_size.getView())[1] * world.icon_size
|
||||
maptext_width = view_to_pixels(hud.mymob.client.view_size.getView())[1]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user