[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:
SkyratBot
2022-04-01 02:38:57 +02:00
committed by GitHub
parent 2f25875974
commit cec72761ac
79 changed files with 1334 additions and 721 deletions

View File

@@ -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
..()

View File

@@ -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"

View File

@@ -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)

View File

@@ -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

View File

@@ -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()

View File

@@ -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]