overhauls rendering + redoes some of widescreen/dynamic sizing + misc fixes (#4668)

Co-authored-by: VM_USER <VM_USER>
This commit is contained in:
silicons
2022-11-17 17:31:54 -06:00
committed by GitHub
co-authored by VM_USER <VM_USER>
parent 798902257c
commit bc5e0940a2
50 changed files with 1475 additions and 754 deletions
+3
View File
@@ -79,6 +79,7 @@
#include "code\__DEFINES\shields.dm"
#include "code\__DEFINES\shuttle.dm"
#include "code\__DEFINES\shuttles.dm"
#include "code\__DEFINES\skin.dm"
#include "code\__DEFINES\sonar.dm"
#include "code\__DEFINES\spaceman_dmm.dm"
#include "code\__DEFINES\spans.dm"
@@ -4210,6 +4211,8 @@
#include "interface\interface.dm"
#include "interface\stylesheet.dm"
#include "interface\skin.dmf"
#include "interface\menus\_menus.dm"
#include "interface\menus\main.dm"
#include "maps\Generic\death_triggers.dm"
#include "maps\Generic\map_data.dm"
#include "maps\Generic\misc.dm"
+2 -2
View File
@@ -50,10 +50,10 @@ What is the naming convention for planes or layers?
/// Reserved for use in space/parallax
#define PARALLAX_PLANE -90
/// everything layering below
#define PARALLAX_VIS_LAYER_BELOW -10000
#define PARALLAX_VIS_LAYER_BELOW -100
#define PARALLAX_LAYER_CENTER 0
/// ditto
#define PARALLAX_VIS_LAYER_ABOVE 10000
#define PARALLAX_VIS_LAYER_ABOVE 100
///For the Looking Glass holodecks
#define PLANE_LOOKINGGLASS -77
///For the Looking Glass holodecks
+54
View File
@@ -0,0 +1,54 @@
//? WINCLONE IDs; NO SKIN CONTROL MAY HAVE THESE IDs, OR WINCLONE WILL NOT CREATE "NAKED" CONTROLS OF THIS TYPE!
#define SKIN_ID_ABSTRACT_MENU "menu"
#define SKIN_ID_ABSTRACT_WINDOW "window"
#define SKIN_ID_ABSTRACT_PANE "pane"
#define SKIN_ID_ABSTRACT_MACRO "macro"
//? SKIN ELEMENT IDS; MAKE SURE TO UPDATE THESE WHEN CHANGING SKIN.DMF.
//! Window IDs
/// main game window
#define SKIN_WINDOW_ID_MAIN "mainwindow"
//! Map IDs
/// main game viewport
#define SKIN_MAP_ID_VIEWPORT "mapwindow.map"
//! Splitter IDs
/// main window split
#define SKIN_SPLITTER_ID_MAIN "mainwindow.split"
//? Dynamic skin IDs used by code-generated elements
//? button groups MUST have unique ids to all skin elements!
// TOP LEVEL MENU //
#define SKIN_ID_MAIN_MENU "menu_main"
// what it attaches to
#define SKIN_ID_MAIN_MENU_ATTACH_TO "mainwindow"
// categories
#define SKIN_ID_MENU_CATEGORY_FILE "menu_file"
#define SKIN_ID_MENU_CATEGORY_ZOOM "menu_zoom"
#define SKIN_ID_MENU_CATEGORY_SCALING "menu_scaling"
#define SKIN_ID_MENU_CATEGORY_HELP "menu_help"
// groups
#define SKIN_BUTTON_GROUP_MAP_ZOOM "group_map_zoom"
#define SKIN_BUTTON_GROUP_MAP_SCALING "group_map_scaling"
#define SKIN_BUTTON_GROUP_MAP_WIDESCREEN "group_map_widescreen"
// buttons - file
#define SKIN_ID_MENU_BUTTON_SCREENSHOT "menubutton_screenshot"
#define SKIN_ID_MENU_BUTTON_SCREENSHOT_QUICK "menubutton_screenshot_quick"
#define SKIN_ID_MENU_BUTTON_RECONNECT "menubutton_reconnect"
#define SKIN_ID_MENU_BUTTON_PING "menubutton_ping"
#define SKIN_ID_MENU_BUTTON_QUIT "menubutton_quit"
// buttons - size
#define SKIN_ID_MENU_BUTTON_STRETCH_TO_FIT "menubutton_stretchtofit"
#define SKIN_ID_MENU_BUTTON_STRETCH_NO_LETTERBOX "menubutton_stretchtofill"
#define SKIN_ID_MENU_BUTTON_FOR_RESOLUTION(resolution) "menubutton_[resolution]x[resolution]"
#define SKIN_ID_MENU_BUTTON_WIDESCREEN_ENABLED "menubutton_widescreen_on"
#define SKIN_ID_MENU_BUTTON_WIDESCREEN_DISABLED "menubutton_widescreen_off"
#define SKIN_ID_MENU_BUTTON_AUTO_FIT_VIEWPORT "menubutton_auto_fit_viewport"
#define SKIN_ID_MENU_BUTTON_FIT_VIEWPORT "menubutton_fit_viewport"
// buttons - scaling
#define SKIN_ID_MENU_BUTTON_NEAREST_NEIGHBOR "menubutton_scale_distort"
#define SKIN_ID_MENU_BUTTON_POINT_SAMPLE "menubutton_scale_normal"
#define SKIN_ID_MENU_BUTTON_BILINEAR "menubutton_scale_blur"
// buttons - help
#define SKIN_ID_MENU_BUTTON_ADMINHELP "menubutton_adminhelp"
-170
View File
@@ -1,167 +1,3 @@
/**
* This is intended to be a full wrapper. DO NOT directly modify its values.
* Container for client viewsize.
*/
/datum/view_data
/// Width offset to apply to the default view string if we're not supressed for some reason.
var/width = 0
/// Height offset to apply to the default view string, see above.
var/height = 0
/**
* This client's current "default" view, in the format "WidthxHeight".
* We add/remove from this when we want to change their window size.
*/
var/default = ""
/**
* This client's current zoom level, if it's not being supressed.
* If it's 0, we autoscale to the size of the window. Otherwise it's treated as the ratio between
* the pixels on the map and output pixels. Only looks proper nice in increments of whole numbers (iirc).
* Stored here so other parts of the code have a non blocking way of getting a user's functional zoom.
*/
var/zoom = 0
/**
* If the view is currently being supressed by some other "monitor".
* For when you want to own the client's eye without fucking with their viewport.
* Doesn't make sense for a binocoler to effect your view in a camera console.
*/
var/is_suppressed = FALSE
/// The client that owns this view packet.
var/client/chief = null
/datum/view_data/New(client/owner, view_string)
default = view_string
chief = owner
apply()
/datum/view_data/proc/setDefault(string)
default = string
apply()
/datum/view_data/proc/safeApplyFormat()
if(isZooming())
assertFormat()
return
resetFormat()
/// T-Pose
/datum/view_data/proc/assertFormat()
// if(!is_preference_enabled(/datum/client_preference/scaling_viewport))
// return
// winset(chief, "mapwindow.map", "zoom=0")
// We're using icon dropdown instead
/// Cuck
/datum/view_data/proc/resetFormat()
// if(!is_preference_enabled(/datum/client_preference/scaling_viewport))
// return
// winset(chief, "mapwindow.map", "zoom=[chief.prefs.pixel_size]")
// We're using icon dropdown instead
/datum/view_data/proc/setZoomMode()
// if(!is_preference_enabled(/datum/client_preference/scaling_viewport))
// return
// winset(chief, "mapwindow.map", "zoom-mode=[chief.prefs.scaling_method]")
// We're using icon dropdown instead
/datum/view_data/proc/isZooming()
return (width || height)
/datum/view_data/proc/resetToDefault()
width = 0
height = 0
apply()
/datum/view_data/proc/add(toAdd)
width += toAdd
height += toAdd
apply()
/datum/view_data/proc/addTo(toAdd)
var/list/shitcode = getviewsize(toAdd)
width += shitcode[1]
height += shitcode[2]
apply(toAdd)
/datum/view_data/proc/setTo(toAdd)
/**
* Backward compatability to account.
* For a change in how sizes get calculated. we used to include world.view in
* This, but it was jank, so I had to move it.
*/
var/list/shitcode = getviewsize(toAdd)
width = shitcode[1]
height = shitcode[2]
apply(toAdd)
/datum/view_data/proc/setBoth(wid, hei)
width = wid
height = hei
apply()
/datum/view_data/proc/setWidth(wid)
width = wid
apply()
/datum/view_data/proc/setHeight(hei)
width = hei
apply()
/datum/view_data/proc/addToWidth(toAdd)
width += toAdd
apply()
/datum/view_data/proc/addToHeight(screen, toAdd)
height += toAdd
apply()
/datum/view_data/proc/apply(forced)
if(!chief.is_preference_enabled(/datum/client_preference/scaling_viewport) && !forced)
return
chief.change_view(getView(), forced)
safeApplyFormat()
if(chief.prefs.auto_fit_viewport)
chief.fit_viewport()
/datum/view_data/proc/supress()
is_suppressed = TRUE
apply()
/datum/view_data/proc/unsupress()
is_suppressed = FALSE
apply()
/datum/view_data/proc/getView()
var/list/temp = getviewsize(default)
if(is_suppressed)
return "[temp[1]]x[temp[2]]"
return "[width + temp[1]]x[height + temp[2]]"
/datum/view_data/proc/zoomIn()
resetToDefault()
animate(chief, pixel_x = 0, pixel_y = 0, 0, FALSE, LINEAR_EASING, ANIMATION_END_NOW)
/datum/view_data/proc/zoomOut(radius = 0, offset = 0, direction = FALSE)
if(direction)
var/_x = 0
var/_y = 0
switch(direction)
if(NORTH)
_y = offset
if(EAST)
_x = offset
if(SOUTH)
_y = -offset
if(WEST)
_x = -offset
animate(chief, pixel_x = world.icon_size*_x, pixel_y = world.icon_size*_y, 0, FALSE, LINEAR_EASING, ANIMATION_END_NOW)
// Ready for this one?
setTo(radius)
/*
/proc/getScreenSize(widescreen)
if(widescreen)
return CONFIG_GET(string/default_view)
return CONFIG_GET(string/default_view_square)
*/
/proc/getviewsize(view)
if(isnum(view))
var/totalviewrange = 1 + 2 * view
@@ -169,9 +5,3 @@
else
var/list/viewrangelist = splittext(view,"x")
return list(text2num(viewrangelist[1]), text2num(viewrangelist[2]))
/proc/in_view_range(mob/user, atom/A)
var/list/view_range = getviewsize(user.client.view)
var/turf/source = get_turf(user)
var/turf/target = get_turf(A)
return ISINRANGE(target.x, source.x - view_range[1], source.x + view_range[1]) && ISINRANGE(target.y, source.y - view_range[1], source.y + view_range[1])
+9
View File
@@ -24,3 +24,12 @@ var/world_log_redirected = FALSE
/datum/world_log_shunter/New()
world.ensure_logging_active()
//! Debugging
var/datum/world_debug_enabler/world_debug_enabler = new
/datum/world_debug_enabler/New()
var/debug_server = world.GetConfig("env", "AUXTOOLS_DEBUG_DLL")
if (debug_server)
call(debug_server, "auxtools_init")()
enable_debugging()
+37 -38
View File
@@ -6,6 +6,7 @@
adjacency code.
*/
// todo: unify with normal click procs
/mob/living/silicon/robot/ClickOn(var/atom/A, var/params)
if(world.time <= next_click)
return
@@ -15,23 +16,23 @@
build_click(src, client.buildmode, params, A)
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
var/list/unpacked_params = params2list(params)
if(unpacked_params["shift"] && unpacked_params["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["shift"] && modifiers["middle"])
if(unpacked_params["shift"] && unpacked_params["middle"])
ShiftMiddleClickOn(A)
return
if(modifiers["middle"])
if(unpacked_params["middle"])
MiddleClickOn(A)
return
if(modifiers["shift"])
if(unpacked_params["shift"])
ShiftClickOn(A)
return
if(modifiers["alt"]) // alt and alt-gr (rightalt)
if(unpacked_params["alt"]) // alt and alt-gr (rightalt)
AltClickOn(A)
return
if(modifiers["ctrl"])
if(unpacked_params["ctrl"])
CtrlClickOn(A)
return
@@ -58,49 +59,47 @@
return
*/
var/obj/item/W = get_active_held_item()
//? Grab click semantics
var/obj/item/I = get_active_held_item()
//? Core cyborg code
// Cyborgs have no range-checking unless there is item use
if(!W)
if(!I)
if(bolt && !bolt.malfunction && A.loc != module)
return
A.add_hiddenprint(src)
A.attack_robot(src)
return
// buckled cannot prevent machine interlinking but stops arm movement
if( buckled )
//? Handle special cases
if(I == A)
// attack_self
I.attack_self(src)
// todo: refactor
trigger_aiming(TARGET_CAN_CLICK)
return
if(W == A)
//? check if we can click from our current location
var/ranged_generics_allowed = loc?.AllowClick(src, A, I)
W.attack_self(src)
return
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc in contents)
if(A == loc || (A in loc) || (A in contents))
// No adjacency checks
var/resolved = A.attackby(W, src, params)
if(!resolved && A && W)
W.afterattack(A,src,1,params)
return
if(!isturf(loc))
return
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc))
if(isturf(A) || isturf(A.loc))
if(A.Adjacent(src)) // see adjacent.dm
var/resolved = A.attackby(W, src, params)
if(!resolved && A && W)
W.afterattack(A, src, 1, params)
return
if(Reachability(A, null, I?.reach, I))
//? attempt melee attack chain
if(I)
I.melee_attack_chain(A, src, CLICKCHAIN_HAS_PROXIMITY, unpacked_params)
else
W.afterattack(A, src, 0, params)
return
return
melee_attack_chain(A, CLICKCHAIN_HAS_PROXIMITY, unpacked_params)
// todo: refactor aiming
trigger_aiming(TARGET_CAN_CLICK)
return
else if(ranged_generics_allowed)
//? attempt ranged attack chain
if(I)
I.ranged_attack_chain(A, src, NONE, params)
else
ranged_attack_chain(A, NONE, unpacked_params)
// todo: refactor aiming
trigger_aiming(TARGET_CAN_CLICK)
return
//Middle click cycles through selected modules.
/mob/living/silicon/robot/MiddleClickOn(var/atom/A)
+1 -1
View File
@@ -9,7 +9,7 @@
/atom/movable/screen
name = ""
icon = 'icons/mob/screen1.dmi'
appearance_flags = TILE_BOUND|PIXEL_SCALE|NO_CLIENT_COLOR
appearance_flags = PIXEL_SCALE | NO_CLIENT_COLOR
layer = LAYER_HUD_BASE
plane = PLANE_PLAYER_HUD
var/obj/master = null //A reference to the object in the slot. Grabs or items, generally.
@@ -176,8 +176,6 @@
/mob/Login()
. = ..()
if(client?.is_preference_enabled(/datum/client_preference/scaling_viewport))
INVOKE_ASYNC(client, /client.verb/SetWindowIconSize, client.prefs.icon_size)
if(ability_master)
ability_master.toggle_open(1)
+5 -7
View File
@@ -31,7 +31,9 @@
*/
/atom/movable/screen/click_catcher/proc/UpdateFill(view_size_x, view_size_y)
screen_loc = "1,1 to [view_size_x],[view_size_y]"
var/matrix/transforming = matrix()
transforming.Scale(view_size_x, view_size_y)
transform = transforming
/atom/movable/screen/click_catcher/Click(location, control, params)
var/list/modifiers = params2list(params)
@@ -63,12 +65,8 @@
/**
* Makes a clickcatcher if necessary, and ensures it's fit to our size.
*/
/client/proc/update_clickcatcher(list/view_override)
/client/proc/update_clickcatcher()
if(!click_catcher)
click_catcher = new
screen |= click_catcher
if(view_override)
click_catcher.UpdateFill(view_override[1], view_override[2])
else
var/list/view_list = getviewsize(view)
click_catcher.UpdateFill(view_list[1], view_list[2])
click_catcher.UpdateFill(current_viewport_width, current_viewport_height)
+10
View File
@@ -14,6 +14,16 @@
reload_fullscreen()
client.update_clickcatcher()
INVOKE_ASYNC(client, /client/proc/init_viewport_blocking)
/**
* reloads rendering after screen viewport size change
*/
/mob/proc/refit_rendering()
client?.parallax_holder?.Reset(force = TRUE)
reload_fullscreen()
client?.update_clickcatcher()
/**
* destroys screen rendering. call on mob del
*/
+5 -1
View File
@@ -175,6 +175,8 @@
continue
L.SetView(C.view, TRUE)
. |= L
if(vis_holder)
. |= vis_holder
C.screen |= .
if(!secondary_map)
var/atom/movable/screen/plane_master/parallax_white/PM = locate() in C.screen
@@ -191,6 +193,7 @@
if(QDELETED(C))
return
C.screen -= layers
C.screen -= vis_holder
if(!secondary_map)
var/atom/movable/screen/plane_master/parallax_white/PM = locate() in C.screen
if(PM)
@@ -311,4 +314,5 @@
parallax_holder = new(src)
/atom/movable/screen/parallax_vis
screen_loc = "CENTER,CENTER"
screen_loc = "LEFT,BOTTOM"
icon = null
+1 -1
View File
@@ -5,7 +5,7 @@
plane = PARALLAX_PLANE
screen_loc = "CENTER-7,CENTER-7"
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
appearance_flags = PIXEL_SCALE | KEEP_TOGETHER
appearance_flags = PIXEL_SCALE | KEEP_TOGETHER | TILE_BOUND
// notice - all parallax layers are 15x15 tiles. They roll over every 240 pixels.
/// pixel x/y shift per real x/y
@@ -1,3 +1,30 @@
/datum/config_entry/string/max_viewport_size
default = "19x15"
/datum/config_entry/string/max_viewport_size/ValidateAndSet(str_val)
if(!istext(str_val))
return FALSE
var/list/split = splittext(str_val, "x")
if(length(split) != 2)
return FALSE
var/width = text2num(split[1])
var/height = text2num(split[2])
if(height < 1 || width < 1 || height > 67 || width > 67)
return FALSE
. = ..()
if(!.)
return
config.update_player_viewsize()
/*
/datum/config_entry/string/game_viewport_size
default = "19x15"
/datum/config_entry/string/max_viewport_size/ValidateAndSet(str_val)
. = ..()
*/
//! BYONd world.view is immutable, this config is left here as a todo. If it's still immutable by, say, 516, remove it.
/datum/config_entry/number/starlight
default = 2
@@ -51,13 +78,3 @@
/datum/config_entry/flag/emojis
default = TRUE
/datum/config_entry/number/max_client_view_x
default = 21
min_val = 15
max_val = 50 // Byond (the) limits
/datum/config_entry/number/max_client_view_y
default = 15
min_val = 15
max_val = 50 // Byond (the) limits
+3
View File
@@ -11,3 +11,6 @@
/// The mob the client controls
var/mob/mob
var/current_viewport_width = 15
var/current_viewport_height = 15
+135 -17
View File
@@ -3,6 +3,25 @@
*
* allows managed control of client viewport/eye changes
*
* ! - - - ATTENTION - - -
* ! These datums will modify mob variables.
* ! This can result in AI mobs having inconsistent sight/whatevers
* ! from what they'd usually have after a player enters, and
* ! leaves them.
* ! Mob reset_perspective() should handle most of these cases, but be wary.
*
* ! - - - ATTENTION - - -
* ! View sizes should only be for clients.
* ! Do not read off this for stuff like AI view/target tracking.
*
* ? - - - ATTENTION - - -
* ? We track MAXIMUM view sizes.
* ? Client can resize up/down as needed.
* ? If you want to force a client to a specific size,
* ? regardless of their widescreen setting,
* ? use client.set_temporary_view.
* ? Augmented view will also ignore client prefs on widescreen, *kinda.*
*
* as of right now, perspectives will **trample** the following on every set:
* client.eye
* client.lazy_eye (unimplemented)
@@ -42,11 +61,9 @@
/// sight var
var/sight = SEE_SELF
/// active clients - this is not the same as mobs because a client can be looking somewhere that isn't their mob
var/list/client/clients = list()
var/list/client/clients
/// mobs that are using this - required for clean gcs
var/list/mob/mobs = list()
/// view size
var/view_size
/// when a client logs out of a mob, and it's using us, the mob should reset to its self_perspective
var/reset_on_logout = TRUE
/// see in dark
@@ -54,6 +71,22 @@
/// see_invisible
var/see_invisible = SEE_INVISIBLE_LIVING
//! view size
/// default view; if null, world.view
var/default_view_size
/// view size increase x
var/augment_view_width = 0
/// view size increase y
var/augment_view_height = 0
/// suppression sources
var/list/view_suppression
/// cached view x
var/cached_view_width
/// cached view y
var/cached_view_height
/// view cache needs recompute
var/view_dirty = TRUE
/datum/perspective/Destroy()
KickAll()
ClearMobs()
@@ -73,7 +106,7 @@
return
if(C.using_perspective)
CRASH("client already had perspective")
clients += C
LAZYADD(clients, C)
C.using_perspective = src
SEND_SIGNAL(src, COMSIG_PERSPECTIVE_CLIENT_REGISTER, C)
Apply(C)
@@ -85,7 +118,7 @@
SHOULD_CALL_PARENT(TRUE)
if(!(C in clients))
return
clients -= C
LAZYREMOVE(clients, C)
Remove(C)
// if we're not doing this as part of a switch have them immediately switch to the mob
// oh and make sure they unregister
@@ -100,7 +133,7 @@
* gets all clients viewing us
*/
/datum/perspective/proc/GetClients()
return clients.Copy()
return isnull(clients)? list() : clients.Copy()
/**
* kicks all clients off us
@@ -118,6 +151,7 @@
/**
* registers as a mob's current perspective
* sets mob vars as necessary
*/
/datum/perspective/proc/AddMob(mob/M)
SHOULD_CALL_PARENT(TRUE)
@@ -127,13 +161,20 @@
return
mobs += M
M.using_perspective = src
M.sight = sight
M.see_in_dark = see_in_dark
M.see_invisible = see_invisible
SEND_SIGNAL(src, COMSIG_PERSPECTIVE_MOB_ADD, M)
/**
* unregisters as a mob's current perspective
* resets mob vars to initial() values
*/
/datum/perspective/proc/RemoveMob(mob/M, switching = FALSE)
SHOULD_CALL_PARENT(TRUE)
M.sight = initial(M.sight)
M.see_in_dark = initial(M.see_in_dark)
M.see_invisible = initial(M.see_invisible)
mobs -= M
SEND_SIGNAL(src, COMSIG_PERSPECTIVE_MOB_REMOVE, M, switching)
if(M.using_perspective == src)
@@ -184,11 +225,7 @@
if(changed != C.eye)
C.parallax_holder?.Reset(force = TRUE)
C.perspective = GetEyeMode(C)
C.mob.sight = sight
C.mob.see_in_dark = see_in_dark
C.mob.see_invisible = see_invisible
if(view_size)
C.change_view(view_size, TRUE)
update_view_size(C)
/**
* update all viewers
@@ -294,13 +331,94 @@
for(var/client/C as anything in clients)
C.mob.see_invisible = see_invisible
/datum/perspective/proc/SetViewSize(new_size)
var/change = view_size == new_size
view_size = new_size
if(change)
for(var/client/C as anything in clients)
C.change_view(new_size, TRUE)
//! view size
/**
* Sets our default size.
*
* DO NOT use this in place of augmented.
* User widescreen preferences WILL override this!
*
* Ideally this shouldn't be used at all.
*/
/datum/perspective/proc/set_default_view(size)
if(size == default_view_size)
return
// assert it y'know, works
if(isnum(size))
default_view_size = size
else if(isnull(size))
default_view_size = size
else if(istext(size))
var/list/split = splittext(size, "x")
ASSERT(split.len == 2)
// if the above runtimes, let it so we know who fucked up
default_view_size = size
else
CRASH("What?")
view_dirty = TRUE
update_view_size()
/**
* Sets augmented size ontop of default size.
*
* Currently only supports positive numbers. Numbers apply equally
* to both directions of a dimension.
*/
/datum/perspective/proc/set_augmented_view(width, height)
if(!isnum(height) || !isnum(width))
CRASH("invalid")
// no negative augment values for now
augment_view_height = max(0, height)
augment_view_width = max(0, width)
view_dirty = TRUE
update_view_size()
/datum/perspective/proc/update_view_size(client/C)
if(view_dirty)
recompute_view_size()
if(C)
C.request_viewport_update()
else
for(var/client/_C as anything in clients)
update_view_size(_C)
/datum/perspective/proc/recompute_view_size()
view_dirty = FALSE
if(isnum(default_view_size))
cached_view_height = default_view_size + augment_view_width
cached_view_width = default_view_size + augment_view_height
return
else if(isnull(default_view_size))
cached_view_width = GLOB.max_client_view_x + augment_view_width
cached_view_height = GLOB.max_client_view_y + augment_view_height
return
var/list/parsed = splittext(default_view_size, "x")
if(length(parsed) != 2)
cached_view_width = GLOB.max_client_view_x + augment_view_width
cached_view_height = GLOB.max_client_view_y + augment_view_height
return
cached_view_width = parsed[1] + augment_view_width
cached_view_height = parsed[2] + augment_view_height
/datum/perspective/proc/suppress_view(source)
var/was = LAZYLEN(view_suppression)
LAZYOR(view_suppression, source)
if(!was && LAZYLEN(view_suppression))
view_dirty = TRUE
update_view_size()
/datum/perspective/proc/unsuppress_view(source)
var/was = LAZYLEN(view_suppression)
LAZYREMOVE(view_suppression, source)
if(was && !LAZYLEN(view_suppression))
view_dirty = TRUE
update_view_size()
/datum/perspective/proc/ensure_view_cached()
if(view_dirty)
recompute_view_size()
//! remotes
/datum/perspective/proc/considered_remote(mob/M)
return eye == M
+2 -1
View File
@@ -1,6 +1,7 @@
/atom/movable
layer = OBJ_LAYER
appearance_flags = TILE_BOUND|PIXEL_SCALE|KEEP_TOGETHER
// todo: evaluate if we need TILE_BOUND
SET_APPEARANCE_FLAGS(TILE_BOUND | PIXEL_SCALE)
// todo: kill this (only used for elcetropacks)
var/moved_recently = FALSE
+5
View File
@@ -225,7 +225,12 @@
//causes damage when running into objects
/obj/mecha/combat/fighter/Bump(atom/obstacle)
. = ..()
// this isn't defined becuase this is shitcode anyways and i'm just patching it
// todo: why the fuck are you guys doing snowflake collision code??
if(TIMER_COOLDOWN_CHECK(src, "fighter_collision"))
return
if(istype(obstacle, /obj) || istype(obstacle, /turf))
TIMER_COOLDOWN_START(src, "fighter_collision", 5 SECONDS)
occupant_message("<B><FONT COLOR=red SIZE=+1>Collision Alert!</B></FONT>")
take_damage(20, "brute")
playsound(src, 'sound/effects/grillehit.ogg', 50, 1)
+1 -1
View File
@@ -837,7 +837,7 @@
/obj/mecha/proc/mechstep(direction)
var/current_dir = dir //For strafing
var/result = get_step(src,direction)
if(result && Move(result))
if(result && Move(result, direction))
if(stomp_sound)
playsound(src,stomp_sound,40,1)
handle_equipment_movement()
+2 -2
View File
@@ -363,10 +363,10 @@
src.log_message("Toggled zoom mode.")
src.occupant_message("<font color='[src.zoom?"blue":"red"]'>Zoom mode [zoom?"en":"dis"]abled.</font>")
if(zoom)
myclient.change_view(12, TRUE)
myclient.set_temporary_view(GLOB.max_client_view_x + 5, GLOB.max_client_view_y + 5)
src.occupant << sound('sound/mecha/imag_enh.ogg',volume=50)
else
myclient.change_view("[myclient.last_view_x_dim*2]x[myclient.last_view_y_dim*2]", TRUE) // Reset to default
myclient.reset_temporary_view()
return
+4 -8
View File
@@ -629,11 +629,11 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
else if(!zoom && user.item_by_slot(wornslot) != src && wornslot != FALSE)
to_chat(user, "You need to wear the [devicename] to look through it properly")
cannotzoom = 1
//We checked above if they are a human and returned already if they weren't.
var/mob/living/carbon/human/H = user
if(!zoom && !cannotzoom)
INVOKE_ASYNC(H.client, /client.proc/change_view, viewsize, TRUE) // Reset to default
H.ensure_self_perspective()
H.self_perspective.set_augmented_view(viewsize - 2, viewsize - 2)
zoom = 1
var/tilesize = 32
@@ -652,14 +652,12 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
if (WEST)
H.client.pixel_x = -viewoffset
H.client.pixel_y = 0
H.visible_message("[user] peers through the [zoomdevicename ? "[zoomdevicename] of the [src.name]" : "[src.name]"].")
H.looking_elsewhere = TRUE
H.handle_vision()
else
H.ensure_self_perspective()
H.self_perspective.set_augmented_view(0, 0)
zoom = 0
H.client.pixel_x = 0
@@ -667,8 +665,6 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
H.looking_elsewhere = FALSE
H.handle_vision()
INVOKE_ASYNC(H.client, H.client.is_preference_enabled(/datum/client_preference/scaling_viewport) ? /client.verb/OnResize : /client.proc/change_view, world.view) // Reset to default
if(!cannotzoom)
user.visible_message("[zoomdevicename ? "[user] looks up from the [src.name]" : "[user] lowers the [src.name]"].")
@@ -50,7 +50,7 @@ when portals are shortly lived, or when portals are made to be obvious with spec
opacity = TRUE
plane = TURF_PLANE
layer = ABOVE_TURF_LAYER
appearance_flags = PIXEL_SCALE|KEEP_TOGETHER // Removed TILE_BOUND so things not visible on the other side stay hidden from the viewer.
SET_APPEARANCE_FLAGS(PIXEL_SCALE)
var/obj/effect/map_effect/portal/counterpart = null // The portal line or master that this is connected to, on the 'other side'.
+1 -7
View File
@@ -18,13 +18,6 @@ GLOBAL_LIST(topic_status_cache)
//This happens after the Master subsystem new(s) (it's a global datum)
//So subsystems globals exist, but are not initialised
/world/New()
//! init auxtools
var/debug_server = world.GetConfig("env", "AUXTOOLS_DEBUG_DLL")
if (debug_server)
call(debug_server, "auxtools_init")()
enable_debugging()
// AUXTOOLS_CHECK(AUXTOOLS_YAML)
log_world("World loaded at [TIME_STAMP("hh:mm:ss", FALSE)]!")
var/tempfile = "data/logs/config_error.[GUID()].log" //temporary file used to record errors with loading config, moved to log directory once logging is set
@@ -40,6 +33,7 @@ GLOBAL_LIST(topic_status_cache)
InitTgs()
config.Load(params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
config.update_world_viewsize() //! Since world.view is immutable, we load it here.
//SetupLogs depends on the RoundID, so lets check
//DB schema and set RoundID if we can
@@ -54,6 +54,12 @@
/proc/_ispath(path, type)
return ispath(path, type)
/proc/_json_encode(list/L)
return json_encode(L)
/proc/_json_decode(json)
return json_decode(json)
/proc/_length(E)
return length(E)
@@ -153,9 +159,17 @@
/proc/_sin(X)
return sin(X)
/proc/_list2params(L)
return list2params(L)
/proc/_list_construct(...)
. = args.Copy()
/proc/_list_construct_assoc(...)
. = list()
for(var/i in 1 to (args.len - 1) step 2)
.[args[i]] = args[i+1]
/proc/_list_add(list/L, ...)
if (args.len < 2)
return
+4 -4
View File
@@ -831,11 +831,11 @@ Traitors and the like can also be revived with the previous role mostly intact.
set name = "Change View Range"
set desc = "switches between 1x and custom views"
var/view = src.view
if(view == world.view)
view = input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128)
if(!using_temporary_viewsize)
var/number = input("Select view range:", "FUCK YE", 7) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,34)
set_temporary_view(number * 2 + 1, number * 2 + 1)
else
SetWindowIconSize(prefs.icon_size)
reset_temporary_view()
log_admin("[key_name(usr)] changed their view range to [view].")
//message_admins("<font color=#4F49AF>[key_name_admin(usr)] changed their view range to [view].</font>", 1) //why? removed by order of XSI
+29 -3
View File
@@ -53,6 +53,35 @@
/// the perspective we're currently using
var/datum/perspective/using_perspective
//! Viewport
/// what we *think* their current viewport size is in pixels
var/assumed_viewport_spx
/// what we *think* their current viewport size is in pixels
var/assumed_viewport_spy
/// what we *think* their current viewport zoom is
var/assumed_viewport_zoom
/// what we *think* their current viewport letterboxing setting is
var/assumed_viewport_box
/// current view x - for fast access
var/current_viewport_width
/// current view y - for fast access
var/current_viewport_height
/// if things are manipulating the viewport we don't want other things to touch it
var/viewport_rwlock = TRUE //! default block so we can release it during init_viewport
/// viewport update queued?
var/viewport_queued = FALSE
/// forced temporary view
var/temporary_viewsize_width
/// forced temporary view
var/temporary_viewsize_height
/// temporary view active?
var/using_temporary_viewsize = FALSE
//! menu button statuses
var/list/menu_buttons_checked = list()
//! menu group statuses
var/list/menu_group_status = list()
////////////////
//ADMIN THINGS//
////////////////
@@ -149,6 +178,3 @@
/// If this client has been fully initialized or not
var/fully_created = FALSE
/// datum wrapper for client view
var/datum/view_data/view_size
+58 -41
View File
@@ -151,32 +151,38 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
///////////
/client/New(TopicData)
//! pre-connect-ish
// set appadmin for profiling or it might not work (?) (this is old code we just assume it's here for a reason)
world.SetConfig("APP/admin", ckey, "role=admin")
//var/tdata = TopicData //save this for later use
TopicData = null //Prevent calls to client.Topic from connect
if(connection != "seeker" && connection != "web")//Invalid connection type.
// block client.Topic() calls from connect
TopicData = null
// kick out invalid connections
if(connection != "seeker" && connection != "web")
return null
// kick out guests
if(!config_legacy.guests_allowed && IsGuestKey(key))
alert(src,"This server doesn't allow guest accounts to play. Please go to http://www.byond.com/ and register for a key.","Guest","OK")
del(src)
return
// pre-connect greeting
to_chat(src, "<font color='red'>If the title screen is black, resources are still downloading. Please be patient until the title screen appears.</font>")
// register in globals
GLOB.clients += src
GLOB.directory[ckey] = src
//! Resolve storage datums
// resolve persistent data
persistent = resolve_client_data(ckey)
// todo: move resolve database data up here
// todo: move resolve database data up here but above preferences
// todo: move preferences up here but above persistent
//! Setup user interface
// todo: move top level menu here, for now it has to be under prefs.
// Instantiate tgui panel
tgui_panel = new(src, "browseroutput")
//! Setup admin tooling
GLOB.ahelp_tickets.ClientLogin(src)
SSserver_maint.UpdateHubStatus()
var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins.
//Admin Authorisation
holder = admin_datums[ckey]
@@ -221,6 +227,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
if(!debug_tools_allowed)
world.SetConfig("APP/admin", ckey, null)
//END CITADEL EDIT
// todo: refactor and hoist
//preferences datum - also holds some persistent data for the client (because we may as well keep these datums to a minimum)
prefs = GLOB.preferences_datums[ckey]
if(!prefs)
@@ -228,10 +235,15 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
GLOB.preferences_datums[ckey] = prefs
prefs.client = src
// todo: refactor
prefs.last_ip = address //these are gonna be used for banning
prefs.last_id = computer_id //these are gonna be used for banning
//fps = prefs.clientfps //(prefs.clientfps < 0) ? RECOMMENDED_FPS : prefs.clientfps
// todo: hoist
// build top level menu
GLOB.main_window_menu.setup(src)
var/full_version = "[byond_version].[byond_build ? byond_build : "xxx"]"
log_access("Login: [key_name(src)] from [address ? address : "localhost"]-[computer_id] || BYOND v[full_version]")
/*
@@ -382,6 +394,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
send_resources()
//? Startup rendering
pre_init_viewport()
mob.reload_rendering()
if(prefs.lastchangelog != GLOB.changelog_hash) //bolds the changelog button on the interface so we know there are updates.
@@ -401,8 +415,13 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
if(isnum(account_age) && account_age <= 2)
log_and_message_admins("PARANOIA: [key_name(src)] has a very new BYOND account ([account_age] days).")
//? We are done
// set initialized
initialized = TRUE
// show any migration errors
prefs.auto_flush_errors()
// update our hub label
SSserver_maint.UpdateHubStatus()
//////////////
//DISCONNECT//
@@ -744,40 +763,38 @@ GLOBAL_VAR_INIT(log_clicks, FALSE)
. = ..()
/client/proc/change_view(new_size, forced, translocate)
if(!is_preference_enabled(/datum/client_preference/scaling_viewport))
if (isnull(new_size))
CRASH("change_view called without argument.")
set waitfor = FALSE // to async temporary view
// todo: refactor this, client view changes should be ephemeral.
var/list/L = getviewsize(new_size)
set_temporary_view(L[1], L[2])
if(view == new_size)
// unnecessary
return
/**
* directly sets our view
* you should probably be using perspective datums most of the time instead
* WARNING: this is verbatim; aka, view = 7 is 15 width 15 height, NOT 7x7!
*
* furthermore, this proc is BLOCKING.
*/
/client/proc/set_temporary_view(width, height)
if(!width || !height || width < 0 || height < 0)
reset_temporary_view()
return
using_temporary_viewsize = FALSE
temporary_viewsize_width = width
temporary_viewsize_height = height
request_viewport_update()
/*
if(prefs && !prefs.widescreenpref && new_size == CONFIG_GET(string/default_view))
new_size = CONFIG_GET(string/default_view_square)
*/
view = new_size
mob.reload_rendering()
if(!translocate)
reset_perspective()
else if(!. || forced)
if(!translocate)
reset_perspective()
mob?.reload_fullscreen()
update_clickcatcher()
if(forced)
view = new_size
else
INVOKE_ASYNC(src, /client.verb/OnResize)
/*
mob.reload_fullscreen()
if (isliving(mob))
var/mob/living/M = mob
M.update_damage_hud()
if (prefs.auto_fit_viewport)
addtimer(CALLBACK(src,.verb/fit_viewport,10)) //Delayed to avoid wingets from Login calls.
*/
/**
* resets our temporary view
* you should probably be using perspective datums most of the time instead
*
* furthermore, this proc is BLOCKING
*/
/client/proc/reset_temporary_view()
using_temporary_viewsize = FALSE
temporary_viewsize_height = null
temporary_viewsize_width = null
request_viewport_update()
/**
* switch perspective - null will cause us to shunt our eye to nullspace!
-46
View File
@@ -235,49 +235,3 @@
if(eyeobj)
return eyeobj
return src
/client/verb/fit_viewport()
set name = "Fit Viewport"
set category = "OOC"
set desc = "Fit the width of the map window to match the viewport"
// Fetch the client's aspect ratio
var/view_size = getviewsize(view)
var/aspect_ratio = view_size[1] / view_size[2]
// Calculate desired pixel width using window size and aspect ratio
var/sizes = params2list(winget(src, "mainwindow.split;mapwindow", "size"))
var/map_size = splittext(sizes["mapwindow.size"], "x")
var/height = text2num(map_size[2])
var/desired_width = round(height * aspect_ratio)
if (text2num(map_size[1]) == desired_width)
return // You're already good fam.
var/split_size = splittext(sizes["mainwindow.split.size"], "x")
var/split_width = text2num(split_size[1])
// Calculate and apply our best estimate
// +4 pixels are for the eidth of the splitter's handle
var/pct = 100 * (desired_width + 4) / split_width
winset(src, "mainwindow.split", "splitter=[pct]")
// Apply an ever-lowering offset until we finish or fail
var/delta
for(var/safety in 1 to 10)
var/after_size = winget(src, "mapwindow", "size")
map_size = splittext(after_size, "x")
var/got_width = text2num(map_size[1])
if (got_width == desired_width)
return // Success!
// Calculate a probable delta value based on the diff
else if (isnull(delta))
delta = 100 * (desired_width - got_width) / split_width
// If we overshot, halve the delta and reverse direction
else if ((delta > 0 && got_width > desired_width) || (delta < 0 && got_width < desired_width))
delta = -delta/2
pct += delta
winset(src, "mainwindow.split", "splitter=[pct]")
+388 -63
View File
@@ -1,78 +1,401 @@
GLOBAL_VAR_INIT(lock_client_view_x, null)
GLOBAL_VAR_INIT(lock_client_view_y, null)
GLOBAL_LIST_INIT(valid_icon_sizes, list(32, 48, 64, 72, 96, 128))
// these two variables control max dynamic resize for viewport
GLOBAL_VAR_INIT(max_client_view_x, 19)
GLOBAL_VAR_INIT(max_client_view_y, 15)
// these two variables **reflect** (config updates, not this!) effective default viewsize for view(), range(), etc.
GLOBAL_VAR_INIT(game_view_x, 19)
GLOBAL_VAR_INIT(game_view_y, 15)
// minimum size viewports can be
GLOBAL_VAR_INIT(min_client_view_x, 15)
GLOBAL_VAR_INIT(min_client_view_y, 15)
// these two variables, if set, lock all clients to a certain viewsize no matter what
GLOBAL_VAR(lock_client_view_x)
GLOBAL_VAR(lock_client_view_y)
/datum/preferences
var/icon_size = 64
/client
var/last_view_x_dim = 7
var/last_view_y_dim = 7
/client/verb/SetCozyViewInwards(val as num|text)
set hidden = 1
if(prefs && val != prefs.icon_size)
prefs.icon_size += val
SScharacters.queue_preferences_save(prefs)
winset(src, "mapwindow.map", "icon-size=[prefs.icon_size]")
OnResize()
/client/verb/SetWindowIconSize(val as num|text)
set hidden = 1
winset(src, "mapwindow.map", "icon-size=[val]")
if(prefs && val != prefs.icon_size)
prefs.icon_size = val
SScharacters.queue_preferences_save(prefs)
OnResize()
/client/verb/OnResize()
set hidden = 1
if(!is_preference_enabled(/datum/client_preference/scaling_viewport))
return
var/divisor = text2num(winget(src, "mapwindow.map", "icon-size")) || world.icon_size
if(!isnull(GLOB.lock_client_view_x) && !isnull(GLOB.lock_client_view_y))
last_view_x_dim = GLOB.lock_client_view_x
last_view_y_dim = GLOB.lock_client_view_y
/**
* forces world viewsize; use for config VAS
*/
/datum/controller/configuration/proc/update_world_viewsize()
//! BYONd world.view is immutable, for now we're stuck read-onlying it.
if(isnum(world.view))
GLOB.game_view_x = GLOB.game_view_y = world.view
else
var/winsize_string = winget(src, "mapwindow.map", "size")
last_view_x_dim = GLOB.lock_client_view_x || clamp(ROUND_UP(text2num(winsize_string) / divisor), 15, (CONFIG_GET(number/max_client_view_x)) || (CONFIG_GET(number/max_client_view_x)))
last_view_y_dim = GLOB.lock_client_view_y || clamp(ROUND_UP(text2num(copytext(winsize_string,findtext(winsize_string,"x")+1,0)) / divisor), 15, (CONFIG_GET(number/max_client_view_y)) || 41)
// is text
var/list/viewsize = splittext(world.view, "x")
GLOB.game_view_x = viewsize[1]
GLOB.game_view_y = viewsize[2]
if(last_view_x_dim % 2 == 0)
last_view_x_dim++
if(last_view_y_dim % 2 == 0)
last_view_y_dim++
/**
* forces screensize update; use for config VAS
*/
/datum/controller/configuration/proc/update_player_viewsize()
var/viewsize_raw = CONFIG_GET(string/max_viewport_size)
var/list/viewsize = splittext(viewsize_raw, "x")
GLOB.max_client_view_x = text2num(viewsize[1])
GLOB.max_client_view_y = text2num(viewsize[2])
for(var/check_icon_size in GLOB.valid_icon_sizes)
winset(src, "menu.icon[check_icon_size]", "is-checked=false")
winset(src, "menu.icon[divisor]", "is-checked=true")
//! Core viewport procs
//! These don't obey the read-write lock, and should only be called from the synchronized procs!
view = "[last_view_x_dim]x[last_view_y_dim]"
/**
* populates important vars that things may read early before we sleep
*/
/client/proc/pre_init_viewport()
PRIVATE_PROC(TRUE)
current_viewport_width = GLOB.max_client_view_x
current_viewport_height = GLOB.max_client_view_y
// Reset eye/perspective
reset_perspective()
/* var/last_perspective = perspective
/**
* called on client init to do this without blocking client/New
*/
/client/proc/init_viewport_blocking()
PRIVATE_PROC(TRUE)
fetch_viewport()
refit_viewsize()
// release the initial lock
viewport_rwlock = FALSE
/**
* called to manually update viewport vars since the skin macro is only triggered on resize
*
* return TRUE if changed
*/
/client/proc/fetch_viewport()
PRIVATE_PROC(TRUE)
. = FALSE
// get vars only; they have to manually refit
var/list/got = params2list(winget(src, SKIN_MAP_ID_VIEWPORT, "size;zoom;letterbox"))
var/got_zoom = text2num(got["zoom"]) || 0
var/got_box = (got["letterbox"] == "true")
var/list/split = splittext(got["size"], "x")
var/got_spx
var/got_spy
if(length(split) == 2)
got_spx = text2num(split[1]) || (WORLD_ICON_SIZE * GLOB.game_view_x)
got_spy = text2num(split[2]) || (WORLD_ICON_SIZE * GLOB.game_view_y)
else
stack_trace("fetch_viewport failed to get spx/spy")
got_spx = (WORLD_ICON_SIZE * GLOB.game_view_x)
got_spy = (WORLD_ICON_SIZE * GLOB.game_view_y)
if(got_zoom != assumed_viewport_zoom || got_spx != assumed_viewport_spx || got_spy != assumed_viewport_spy || got_box != assumed_viewport_box)
. = TRUE
assumed_viewport_zoom = got_zoom
assumed_viewport_spx = got_spx
assumed_viewport_spy = got_spy
assumed_viewport_box = got_box
/**
* called to refit our view size as necessary
*
* this is automatically called every time something modifies us
*/
/client/proc/refit_viewsize(no_fit)
PRIVATE_PROC(TRUE)
if(!isnull(GLOB.lock_client_view_x) && !isnull(GLOB.lock_client_view_y))
view = "[GLOB.lock_client_view_x]x[GLOB.lock_client_view_y]"
on_refit_viewsize(GLOB.lock_client_view_x, GLOB.lock_client_view_y, no_fit)
return
if(using_temporary_viewsize)
view = "[temporary_viewsize_width]x[temporary_viewsize_height]"
on_refit_viewsize(temporary_viewsize_width, temporary_viewsize_height, no_fit)
return
var/widescreen = is_widescreen_enabled()
if(!widescreen)
// if not widescreen, we should just force to 15 x 15 and their augmented view
var/width = 15 + (using_perspective.augment_view_width * 2)
var/height = 15 + (using_perspective.augment_view_height * 2)
view = "[width]x[height]"
on_refit_viewsize(width, height, no_fit)
return
var/stretch_to_fit = assumed_viewport_zoom == 0
using_perspective.ensure_view_cached()
var/max_width = using_perspective.cached_view_width
var/max_height = using_perspective.cached_view_height
if(stretch_to_fit)
// option 1: they're stretching to fit
if(assumed_viewport_box)
// fit everything
view = "[max_width]x[max_height]"
on_refit_viewsize(max_width, max_height)
return
// option 2: they're stretching to fit the longest side
else
// todo: handle horizontally-wider view sizes
// for now we only care about horizontal fit
var/stretch_pixel_amount = assumed_viewport_spy / max_height
var/available_width = assumed_viewport_spx / stretch_pixel_amount
available_width = CEILING(available_width, 1)
available_width = clamp(available_width, GLOB.min_client_view_x, max_width)
view = "[available_width]x[max_height]"
on_refit_viewsize(available_width, max_height, no_fit)
return
// option 3: scale as necessary
var/pixels_per_tile = assumed_viewport_zoom * WORLD_ICON_SIZE
var/div_x = assumed_viewport_spx / pixels_per_tile
var/div_y = assumed_viewport_spy / pixels_per_tile
div_x = CEILING(div_x, 1)
div_y = CEILING(div_y, 1)
var/desired_width = clamp(div_x, GLOB.min_client_view_x, max_width)
var/desired_height = clamp(div_y, GLOB.min_client_view_y, max_height)
view = "[desired_width]x[desired_height]"
on_refit_viewsize(desired_width, desired_height, no_fit)
/client/proc/on_refit_viewsize(new_width, new_height, no_fit)
var/changed = (current_viewport_height != new_height) || (current_viewport_width != new_width)
if(changed)
current_viewport_width = new_width
current_viewport_height = new_height
if(!no_fit && is_auto_fit_viewport_enabled())
fit_viewport()
post_refit_viewsize(changed)
/**
* updates everything when our viewport changes
*/
/client/proc/post_refit_viewsize(changed)
if(!changed)
return
// force perspective swap for ??? reasons (???)
var/old_perspective = perspective
perspective = MOB_PERSPECTIVE
if(perspective != last_perspective)
perspective = last_perspective
var/last_eye = eye
eye = mob
if(eye != last_eye)
eye = last_eye
if(mob)
mob.reload_fullscreen() */
update_clickcatcher()
if(old_perspective != perspective)
perspective = old_perspective
// i don't understand the above
mob?.refit_rendering()
/client/verb/force_onresize_view_update()
set name = "Force Client View Update"
/**
* called to fit our viewport to what we **should** have to get our effective view.
*/
/client/proc/fit_viewport()
// by now we already fetched viewport
// figure out how big they want it to be based on their settings
// note: we only care about horizontal because the splitter.. is, well, horizontal.
var/desired_pixel_width
// todo: pref
// maximum % they're willing to have their map
var/maximum_splitter_percent = 80
// splitter intrinsic width
var/assumed_splitter_width = 4
// effective size
var/widescreen = is_widescreen_enabled()
var/effective_view_width
var/effective_view_height
// todo: optimize the shit out of this proc and the view system
if(!isnull(GLOB.lock_client_view_x) && !isnull(GLOB.lock_client_view_y))
effective_view_width = GLOB.lock_client_view_x
effective_view_height = GLOB.lock_client_view_y
else if(widescreen)
effective_view_width = clamp(temporary_viewsize_width || using_perspective.cached_view_width, GLOB.min_client_view_x, 67)
effective_view_height = clamp(temporary_viewsize_height || using_perspective.cached_view_height, GLOB.min_client_view_y, 67)
else
effective_view_width = clamp(temporary_viewsize_width || (15 + (using_perspective.augment_view_width * 2)), GLOB.min_client_view_x, 67)
effective_view_height = clamp(temporary_viewsize_height || (15 + (using_perspective.augment_view_height * 2)), GLOB.min_client_view_y, 67)
if(assumed_viewport_zoom == 0)
// they're stretching to fit; this makes it annoying
var/aspect_ratio = effective_view_width / effective_view_height
// we have to fit everything
// viewport_spy should never change since that's not what the player can drag,
// unless they resize the outer window itself.
desired_pixel_width = assumed_viewport_spy * aspect_ratio
else
// they're not using stretch to fit; this makes it very easy
desired_pixel_width = WORLD_ICON_SIZE * assumed_viewport_zoom * effective_view_width
// grab their screen size (or what counts as it)
var/list/fetching = winget(src, SKIN_SPLITTER_ID_MAIN, "size")
var/list/parsed = splittext(fetching, "x")
var/screen_width = text2num(parsed[1])
// grab what percent we should go to
var/current_percent = min(100 * ((desired_pixel_width + assumed_splitter_width) / screen_width), maximum_splitter_percent)
// initial set
winset(src, SKIN_SPLITTER_ID_MAIN, "splitter=[current_percent]")
// funny method of correcting for misalignments via binary-search-like behavior
var/delta
fetching = winget(src, SKIN_MAP_ID_VIEWPORT, "size")
parsed = splittext(fetching, "x")
var/current_width = text2num(parsed[1])
var/last_width = current_width
if(current_width == desired_pixel_width)
// done
return
// nope, start adjusting
delta = 100 * ((desired_pixel_width - current_width) / screen_width)
for(var/safety in 1 to 10)
current_percent = min(current_percent + delta, maximum_splitter_percent)
winset(src, SKIN_SPLITTER_ID_MAIN, "splitter=[current_percent]")
fetching = winget(src, SKIN_MAP_ID_VIEWPORT, "size")
parsed = splittext(fetching, "x")
current_width = text2num(parsed[1])
// done?
if(current_width == desired_pixel_width)
return
// if we're literally down to a pixel how about like Don't
if(last_width == current_width)
return
last_width = current_width
// keep adjusting
// overshot?
if ((delta > 0 && current_width > desired_pixel_width) || (delta < 0 && current_width < desired_pixel_width))
// reverse in half
delta = -delta / 2
//! Synchronized procs; calling these from outside is fine.
/**
* call this when things change to queue an update
*
* should only be called **in code**, not by the skin!
*
* warning: this proc doesn't refit instantly, it only queues.
* client decides what time is best to refit.
*/
/client/proc/request_viewport_update()
set waitfor = FALSE
if(!viewport_rwlock)
_request_viewport_update()
if(!viewport_queued)
viewport_queued = TRUE
addtimer(CALLBACK(src, .proc/_request_viewport_update), 0)
/**
* call this when things change to queue an update
*
* should only be called **in code**, not by the skin!
*
* blocks until finished
*/
/client/proc/request_viewport_update_blocking()
if(!viewport_rwlock)
_request_viewport_update()
return
if(!viewport_queued)
viewport_queued = TRUE
addtimer(CALLBACK(src, .proc/_request_viewport_update), 0)
UNTIL(!viewport_queued)
// todo : locks are probably bad when working with request fit
/client/proc/_request_viewport_update(no_fit, no_fetch)
PRIVATE_PROC(TRUE)
// if rwlocked, wait; people should be queuing and not calling this directly
UNTIL(!viewport_rwlock)
// clear queued
viewport_queued = FALSE
// lock
viewport_rwlock = TRUE
if(!no_fetch)
fetch_viewport()
// refit size based on viewport
refit_viewsize(no_fit)
// release lock
viewport_rwlock = FALSE
/**
* call this to request a viewport fit
*/
/client/proc/request_viewport_fit(no_recalc)
set waitfor = FALSE
_request_viewport_fit(no_recalc)
/**
* call this to request a viewport fit
* forcefully fits
* blocks until finished
* don't call this from non-buttons because it blocks and
* absolutely can stack and ruin everyone's day.
*/
/client/proc/viewport_fit_blocking(no_recalc)
UNTIL(!viewport_rwlock)
return _request_viewport_fit(no_recalc)
// todo : locks are probably bad when working with request update
/client/proc/_request_viewport_fit(no_recalc)
PRIVATE_PROC(TRUE)
// if viewport is locked, ignore it
if(viewport_rwlock)
return
// acquire lock
viewport_rwlock = TRUE
// just in case because this is called by a lot of things that are too shitcoded to update (like my own code)
fetch_viewport()
// fit viewport
fit_viewport()
// fetch values; we do not trust on-size to trigger
fetch_viewport()
// then refit the viewsize if needed
if(!no_recalc)
refit_viewsize()
// release lock
viewport_rwlock = FALSE
/**
* called directly by the skin when resizing
*
* @params
* - w - width of viewport in pixels
* - h - height of viewport in pixels
* - z - zoom of viewport
* - b - are we letterboxing?
*/
/client/verb/on_viewport(w as text, h as text, z as num, b as num)
set name = ".on_viewport"
set hidden = TRUE
if(viewport_rwlock) // something is fucking around, don't edit for them
return
// get vars
assumed_viewport_spx = text2num(w)
assumed_viewport_spy = text2num(h)
assumed_viewport_zoom = z
assumed_viewport_box = b
// refit
_request_viewport_update(TRUE, TRUE)
/**
* automatically fit their viewport to show everything optimally
*/
/client/verb/user_fit_viewport()
set name = "Fit Viewport"
set category = "OOC"
set desc = "Fit the width of the map window to match the viewport"
request_viewport_fit()
/client/verb/force_map_zoom(n as num)
set name = ".viewport_zoom"
set hidden = TRUE
set src = usr
set category = "Debug"
OnResize()
if(!isnum(n) || n < 0)
to_chat(usr, SPAN_WARNING("invalid number"))
return
if(viewport_rwlock)
to_chat(usr, SPAN_WARNING("Viewport is rwlocked; try again later."))
return
winset(src, SKIN_MAP_ID_VIEWPORT, "zoom=[n]")
assumed_viewport_zoom = n
request_viewport_update(TRUE)
/client/verb/force_map_box(n as num)
set name = ".viewport_box"
set hidden = TRUE
set src = usr
set category = "Debug"
if(viewport_rwlock)
to_chat(usr, SPAN_WARNING("Viewport is rwlocked; try again later."))
return
n = !!n // force bool
winset(src, SKIN_MAP_ID_VIEWPORT, "letterbox=[n? "true" : "false"]")
assumed_viewport_box = n
request_viewport_update(TRUE)
/client/verb/force_onresize_view_update()
set name = ".viewport_update"
set hidden = TRUE
set src = usr
set category = "Debug"
if(viewport_rwlock)
to_chat(usr, SPAN_WARNING("Viewport is rwlocked; try again later."))
return
request_viewport_update()
/client/verb/show_winset_debug_values()
set name = "Show Client View Debug Values"
set name = ".viewport_debug"
set hidden = TRUE
set src = usr
set category = "Debug"
@@ -83,3 +406,5 @@ GLOBAL_LIST_INIT(valid_icon_sizes, list(32, 48, 64, 72, 96, 128))
to_chat(usr, "Icon size: [divisor]")
to_chat(usr, "xDim: [round(text2num(winsize_string) / divisor)]")
to_chat(usr, "yDim: [round(text2num(copytext(winsize_string,findtext(winsize_string,"x")+1,0)) / divisor)]")
to_chat(usr, "server thinks viewport is:[assumed_viewport_spx]/[assumed_viewport_spy]/[assumed_viewport_zoom]/[assumed_viewport_box]")
to_chat(usr, "server thinks view is:[current_viewport_width]x[current_viewport_height]")
+3
View File
@@ -12,3 +12,6 @@
/client/proc/_winshow(window, show)
winshow(src, window, show)
/client/proc/_command(str)
winset(src, null, "command=[str]")
@@ -40,7 +40,7 @@
/obj/map_helper/network_builder/power_cable/build()
if(!network_directions)
return
var/knot = KNOT_FORCED || (KNOT_AUTO && detect_knot())
var/knot = (src.knot == KNOT_FORCED) || ((src.knot == KNOT_AUTO) && detect_knot())
if(knot)
for(var/i in GLOB.cardinal)
if(!(network_directions & i))
@@ -4,6 +4,7 @@
voice_name = "unknown"
icon = 'icons/effects/effects.dmi' //We have an ultra-complex update icons that overlays everything, don't load some stupid random male human
icon_state = "nothing"
SET_APPEARANCE_FLAGS(TILE_BOUND | PIXEL_SCALE | KEEP_TOGETHER)
/// To check if we've need to roll for damage on movement while an item is imbedded in us.
var/embedded_flag
-5
View File
@@ -19,9 +19,6 @@ GLOBAL_DATUM_INIT(lobby_image, /obj/effect/lobby_image, new)
icon_state = known_icon_states[1]
. = ..()
/mob/new_player
var/client/my_client // Need to keep track of this ourselves, since by the time Logout() is called the client has already been nulled
/mob/new_player/Login()
update_Login_details() //handles setting lastKnownIP and computer_id for use by the ban systems as well as checking for multikeying
@@ -37,7 +34,6 @@ GLOBAL_DATUM_INIT(lobby_image, /obj/effect/lobby_image, new)
mind.current = src
loc = null
my_client = client
GLOB.player_list |= src
new_player_panel()
@@ -45,5 +41,4 @@ GLOBAL_DATUM_INIT(lobby_image, /obj/effect/lobby_image, new)
if(client)
handle_privacy_poll()
client.playtitlemusic()
client.is_preference_enabled(/datum/client_preference/scaling_viewport) ? client.OnResize() : client.change_view(world.view)
return ..()
+2 -2
View File
@@ -21,11 +21,11 @@
// check enter
if(!T2.Enter(src, T))
return FALSE
// uh oh, second loop, check exits
for(var/turf/T as anything in locs)
if(!(T in moving_to))
if(!T.Exit(src, get_step(T, stepdir)))
return FALSE
return TRUE
+1
View File
@@ -227,6 +227,7 @@
bottom_turf.plane = src.plane
bottom_turf.color = below.color
bottom_turf.copy_overlays(below)
// todo: zmimic
bottom_turf.appearance_flags = KEEP_TOGETHER
underlays = list(bottom_turf)
+3
View File
@@ -40,6 +40,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/list/character
/// global data
var/list/options
/// data for byond skin - checkboxes and whatnot; this is ENTIRELY synchronized by the skin system.
var/list/skin
//! ## Game Preferences
var/tgui_fancy = TRUE
@@ -252,6 +254,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
load_path(client.ckey)
if(load_preferences())
if(load_character())
load_skin()
sanitize_everything()
player_setup.sanitize_setup()
client.update_movement_keys()
+8
View File
@@ -268,3 +268,11 @@
for(var/key in skipped)
errors?.Add("Skipping key [key] - no datum found.")
return TRUE
//! Skin stuff
/datum/preferences/proc/set_skin_data(key, value)
skin[key] = value
save_skin()
/datum/preferences/proc/get_skin_data(key)
return skin[key]
@@ -293,13 +293,6 @@ var/list/_client_preferences_by_type
disabled_description = "Hide"
enabled_by_default = TRUE
/datum/client_preference/scaling_viewport
description = "Scaling Viewport"
key = "scaling_viewport"
enabled_description = "Show"
disabled_description = "Hide"
enabled_by_default = TRUE
/********************
* Staff Preferences *
********************/
@@ -8,7 +8,7 @@
if(!path)
return FALSE
// check DOS guard
if(world.time < loadprefcooldown) //This is done before checking if the file exists to ensure that the server can't hang on read attempts
if(initialized && world.time < loadprefcooldown) //This is done before checking if the file exists to ensure that the server can't hang on read attempts
if(istype(client))
to_chat(client, "<span class='warning'>You're attempting to load your preferences a little too fast. Wait half a second, then try again.</span>")
return FALSE
@@ -48,7 +48,7 @@
if(!path)
return FALSE
// check DOS guard
if(world.time < saveprefcooldown)
if(initialized && world.time < saveprefcooldown)
if(istype(client))
to_chat(client, "<span class='warning'>You're attempting to save your preferences a little too fast. Wait half a second, then try again.</span>")
return FALSE
@@ -69,12 +69,42 @@
auto_flush_errors()
return TRUE
/datum/preferences/proc/save_skin()
if(!path)
return FALSE
// heyooo no interruptions please
if(initialized)
UNTIL(world.time >= saveprefcooldown)
var/savefile/S = new /savefile(path)
if(!S)
return FALSE
S.cd = "/"
skin = sanitize_islist(skin)
WRITE_FILE(S["skin"], skin)
return TRUE
/datum/preferences/proc/load_skin()
if(!path)
return FALSE
// heyooo no interruptions please
if(initialized)
UNTIL(world.time >= loadprefcooldown)
if(!fexists(path))
return FALSE
var/savefile/S = new /savefile(path)
if(!S)
return FALSE
S.cd = "/"
READ_FILE(S["skin"], skin)
skin = sanitize_islist(skin)
return TRUE
/datum/preferences/proc/load_character(slot)
// todo: storage handler datums...
if(!path)
return FALSE
// check DOS guard
if(world.time < loadcharcooldown)
if(initialized && world.time < loadcharcooldown)
if(istype(client))
to_chat(client, "<span class='warning'>You're attempting to load your character a little too fast. Wait half a second, then try again.</span>")
return FALSE
@@ -134,7 +164,7 @@
if(!path)
return FALSE
// check DOS guard
if(world.time < savecharcooldown)
if(initialized && world.time < savecharcooldown)
if(istype(client))
to_chat(client, "<span class='warning'>You're attempting to save your character a little too fast. Wait half a second, then try again.</span>")
return FALSE
@@ -306,19 +306,6 @@
feedback_add_details("admin_verb","TOHChat")
/client/verb/toggle_scaling_viewport()
set name = "Toggle Scaling Viewport"
set category = "Preferences"
set desc = "Enable/Disable Viewport Scaling."
var/pref_path = /datum/client_preference/scaling_viewport
toggle_preference(pref_path)
SScharacters.queue_preferences_save(prefs)
to_chat(src, "You will now [(is_preference_enabled(/datum/client_preference/scaling_viewport)) ? "see" : "not see"] more...")
is_preference_enabled(/datum/client_preference/scaling_viewport) ? OnResize() : change_view(world.view)
feedback_add_details("admin_verb","TOHChat")
//Toggles for Staff
//Developers
+2 -3
View File
@@ -430,9 +430,8 @@
var/y = text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32
//Calculate the "resolution" of screen based on client's view and world's icon size. This will work if the user can view more tiles than average.
var/list/screenview = user.client? getviewsize(user.client.view) : world.view
var/screenviewX = screenview[1] * world.icon_size
var/screenviewY = screenview[2] * world.icon_size
var/screenviewX = user.client.current_viewport_width * world.icon_size
var/screenviewY = user.client.current_viewport_height * world.icon_size
var/ox = round(screenviewX/2) - user.client.pixel_x //"origin" x
var/oy = round(screenviewY/2) - user.client.pixel_y //"origin" y
+2 -2
View File
@@ -29,8 +29,8 @@
// Regular ghosts can always at least view if in range.
if(user.client)
var/clientviewlist = getviewsize(user.client.view)
if(get_dist(src_object, user) < max(clientviewlist[1], clientviewlist[2]))
// todo: in view range for zooming
if(get_dist(src_object, user) < max(CEILING(user.client.current_viewport_width / 2, 1), CEILING(user.client.current_viewport_height / 2, 1)))
. = max(., UI_UPDATE)
// Check if the state allows interaction
+2 -2
View File
@@ -31,8 +31,8 @@ GLOBAL_DATUM_INIT(default_state, /datum/ui_state/default, new)
return
// Robots can interact with anything they can see.
var/list/clientviewlist = getviewsize(client.view)
if(get_dist(src, src_object) <= min(clientviewlist[1],clientviewlist[2]))
// todo: in view range for zooming
if(get_dist(src, src_object) <= min(CEILING(client.current_viewport_width / 2, 1), CEILING(client.current_viewport_height / 2, 1)))
return UI_INTERACTIVE
return UI_DISABLED // Otherwise they can keep the UI open.
+3 -4
View File
@@ -35,8 +35,7 @@
// Regular ghosts can always at least view if in range.
var/datum/client_interface/client = GET_CLIENT(user)
if(client)
var/clientviewlist = getviewsize(client.view)
if(get_dist(source, user) < max(clientviewlist[1], clientviewlist[2]))
if(get_dist(source, user) < max(client.current_viewport_width, client.current_viewport_height))
return UI_UPDATE
return UI_CLOSE
@@ -74,8 +73,8 @@
/mob/living/silicon/robot/get_ui_access(atom/source)
// Robots can interact with anything they can see.
var/list/clientviewlist = getviewsize(client.view)
if(get_dist(src, source) <= min(clientviewlist[1],clientviewlist[2]))
// todo: in view range for zooming
if(get_dist(src, source) <= min(CEILING(client.current_viewport_width / 2, 1), CEILING(client.current_viewport_height / 2, 1)))
return UI_INTERACTIVE
return UI_DISABLED // Otherwise they can keep the UI open.
+1 -2
View File
@@ -75,8 +75,7 @@ Notes:
params = {"{ "cursor": "[params]", "screenLoc": "[thing.screen_loc]" }"}
//Send stuff to the tooltip
var/view_size = getviewsize(owner.view)
owner << output(list2params(list(params, view_size[1] , view_size[2], "[title][content]", theme, special)), "[control]:tooltip.update")
owner << output(list2params(list(params, owner.current_viewport_width, owner.current_viewport_height, "[title][content]", theme, special)), "[control]:tooltip.update")
//If a hide() was hit while we were showing, run hide() again to avoid stuck tooltips
showing = 0
+7 -4
View File
@@ -1,3 +1,10 @@
## Max distance for clients to view with widescren mode enabled. Maximum: 35 in either dimension.
MAX_VIEWPORT_SIZE 19x15
## Effective distance used for world.view, affects stuff like AI target aquisition. Maximum: 35 in either dimension.
## GAME_VIEWPORT_SIZE 15x19
## AT THE CURRENT TIME, BYOND WORLD.VIEW IS READ-ONLY
## THIS CONFIGURATION IS LEFT HERE AS A TODO.
## Set to 0 to disable holidays (you monster)
ALLOW_HOLIDAYS
@@ -10,7 +17,3 @@ ENGINE_SUBMAP EngineSubmap_RUST 40
ENGINE_SUBMAP EngineSubmap_Tesla 20
## Singulo
ENGINE_SUBMAP EngineSubmap_Singulo 20
## Max distance for clients to view with widescren mode enabled.
MAX_CLIENT_VIEW_X 21
MAX_CLIENT_VIEW_Y 15
+334
View File
@@ -0,0 +1,334 @@
//! skin menus
/**
* dynamic in-code menu system with blackjack and hookers
*/
/datum/skin_menu
/// id - used for both skin and savefiles
var/id
/// id of window to bind to; we will OVERWRITE ANY EXISTING MENU.
var/bind_to
/// category datum types - transformed into datums at runtime
var/list/datum/skin_menu_category/categories
/// during initial build, we will construct groups list, group name associated to button id for default
var/list/button_groups
/datum/skin_menu/New()
init_categories()
/datum/skin_menu/Destroy()
QDEL_LIST(categories)
button_groups = null
return ..()
/datum/skin_menu/proc/init_categories()
button_groups = list()
for(var/i in 1 to categories.len)
if(ispath(categories[i]))
var/path = categories[i]
var/datum/skin_menu_category/C = new path(src)
categories[i] = C
// category will init in /New(), so...
for(var/datum/skin_menu_entry/E as anything in C.entries)
// again let it runtime if it's bad, we WANT it to runtime so integration tests fail
if(E.group)
button_groups |= E.group
if(E.is_default)
button_groups[E.group] = E.id
else
continue // wtf? let it runtime later
// verify
for(var/group in button_groups)
if(!button_groups[group])
stack_trace("no default for group [group]")
/datum/skin_menu/proc/creation_list(client/C)
. = list()
// create categories after
for(var/datum/skin_menu_category/cat as anything in categories)
. |= cat.creation_list(C)
/datum/skin_menu/proc/setup(client/C, load = TRUE)
create_and_bind(C)
if(load)
load_settings(C)
/datum/skin_menu/proc/all_entries()
. = list()
for(var/datum/skin_menu_category/C as anything in categories)
for(var/datum/skin_menu_entry/E as anything in C.entries)
if(istype(C, /datum/skin_menu_entry/spacer))
continue
. += E
/datum/skin_menu/proc/load_settings(client/C)
// let's like, not do that before they load
UNTIL(C.prefs.initialized)
// basically we need to load saved settings, and default if not
for(var/datum/skin_menu_entry/E as anything in all_entries())
if(!E.checkbox || !E.is_saved)
continue // don't care
// don't load groups, they only load enable, not disable
if(E.group)
// we, do, however, want to load *unchecking* it.
winset(C, E.id, "is-checked=false")
continue
// load anything else
var/enabled = C.prefs.skin[E.id]
if(isnull(enabled))
// default
enabled = E.is_default
// save it while we're at it
E.save(C, enabled)
E.load(C, enabled)
// we do need to load groups if possible
for(var/group in button_groups)
var/choice = C.prefs.skin[group]
var/datum/skin_menu_entry/E
if(isnull(choice) || !GLOB.skin_menu_entries[choice])
// default if null or if choice doesn't exist anymore
E = GLOB.skin_menu_entries[button_groups[group]]
// save it while we're at it
E.save(C, TRUE)
else
E = GLOB.skin_menu_entries[choice]
E.load(C, TRUE)
/datum/skin_menu/proc/create_and_bind(client/C)
// menu creation is special
// we must winclone; skin must not have a control named "menu"
winclone(C, SKIN_ID_ABSTRACT_MENU, id)
var/list/creation = creation_list(C)
for(var/id in creation)
winset(C, id, creation[id])
winset(C, bind_to, "menu=[id]")
//! skin menu categories
/datum/skin_menu_category
/// id - used for both skin and savefiles
var/id
/// name
var/name
/// entry datum types - transformed into datums at runtime; insert a null to create a divider
var/list/datum/skin_menu_entry/entries
/// menu we belong to
var/datum/skin_menu/menu
/datum/skin_menu_category/New(datum/skin_menu/menu)
src.menu = menu
init_entries()
/datum/skin_menu_category/Destroy()
QDEL_LIST(entries)
return ..()
/datum/skin_menu_category/proc/init_entries()
for(var/i in 1 to entries.len)
var/path = entries[i]
var/datum/skin_menu_entry/entry
if(isnull(path))
entry = new /datum/skin_menu_entry/spacer(src)
else if(ispath(path))
entry = new path(src)
else
continue // wtf? let it runtime later
entries[i] = entry
/datum/skin_menu_category/proc/creation_list(client/C)
. = list()
// create us first
.[id] = list2params(list(
"parent" = menu.id,
"name" = name,
))
// create our children
for(var/datum/skin_menu_entry/E as anything in entries)
.[E.id] = E.cached_constructor
//! skin menu entries
/// lookup for skin menu entries
GLOBAL_LIST_EMPTY(skin_menu_entries)
/datum/skin_menu_entry
/// id - used for both skin and savefiles
var/id
/// name
var/name
/**
* command to execute; \n to execute multiple.
* this datum will also inject our own command for synchronization automatically.
* generate_command() overrides this.
*/
var/command
/// do we have a button group? checkbox is required for this; we will NOT load disabled for groups!
var/group
/// default enabled for checkable? only one in a group can have this!! infact, only one in a group **MUST** have tihs!!
var/is_default = FALSE
/// checkable?
var/checkbox = FALSE
/// command to execute, if any, when loading prefs if we're checked
var/load_command_enabled
/// command to execute, if any, when loading prefs if we're unchecked
var/load_command_disabled
/// use proc for load command
var/load_command_proc = FALSE
/// default load_command_enabled to command
var/load_command_default = FALSE
/// is saved? only applicable for checkboxes
var/is_saved = TRUE
/// cached creation parameters
var/cached_constructor
/// category we belong to
var/datum/skin_menu_category/category
/datum/skin_menu_entry/New(datum/skin_menu_category/category)
src.category = category
cache_constructor()
if(load_command_default)
load_command_enabled = generate_command(TRUE)
register()
/datum/skin_menu_entry/Destroy()
unregister()
return ..()
/datum/skin_menu_entry/proc/register()
if(GLOB.skin_menu_entries[id])
stack_trace("warning: collision on [id] between [src] and [GLOB.skin_menu_entries[id]]; overwriting...")
GLOB.skin_menu_entries[id] = src
/datum/skin_menu_entry/proc/unregister()
GLOB.skin_menu_entries -= id
/datum/skin_menu_entry/proc/load(client/C, enabled)
if(!checkbox || !is_saved)
return // why do we care?
var/command
if(load_command_proc)
if(enabled)
command = load_command_enabled(C)
else
command = load_command_enabled(C)
else
if(enabled)
command = load_command_enabled
else
command = load_command_disabled
if(command)
C.menu_run_command(command)
if(enabled)
C.menu_buttons_checked[id] = TRUE
if(group)
C.menu_group_status[group] = id
else
C.menu_buttons_checked -= id
// we assume group is taken care of by the other item overwriting it.
winset(C, id, "is-checked=[enabled? "true" : "false"]")
/datum/skin_menu_entry/proc/save(client/C, enabled)
if(!checkbox || !is_saved)
return // we don't care
if(group)
C.prefs.set_skin_data(group, id)
else
C.prefs.set_skin_data(id, enabled)
/**
* called when someone presses us; using usr here is fine as this should only be called from verb anyways!
*/
/datum/skin_menu_entry/proc/pressed(client/C, new_checked)
save(C, new_checked)
if(!checkbox)
return // don't care
if(group && new_checked)
C.menu_group_status[group] = id
else
if(new_checked)
C.menu_buttons_checked[id] = TRUE
else
C.menu_buttons_checked -= id
/datum/skin_menu_entry/proc/load_command_enabled(client/C)
CRASH("why did the proc get called without an override?")
/datum/skin_menu_entry/proc/load_command_disabled(client/C)
CRASH("why did the proc get called without an override?")
/**
* generates our normal command
*
* ! WARNING !
* While loading, you CANNOT use chained commands with \n.
*/
/datum/skin_menu_entry/proc/generate_command(loading)
return command
/**
* should omit id, that'll be set separately
*/
/datum/skin_menu_entry/proc/creation_parameters()
var/list/params = list()
params["parent"] = category.id
params["command"] = ".menutrigger \"[id]\" \[\[is-checked\]\]\n[generate_command()]"
params["name"] = name
if(group)
params["group"] = group
params["is-checked"] = is_default? "true" : "false"
params["can-check"] = checkbox? "true" : "false"
return list2params(params)
/datum/skin_menu_entry/proc/cache_constructor()
cached_constructor = creation_parameters()
/**
* the empty entry used as a spacer
*/
/datum/skin_menu_entry/spacer
id = null
name = null
/// next id
var/static/next_id = 0
/datum/skin_menu_entry/spacer/New()
..()
id = "menubutton_spacer_[++next_id]"
/datum/skin_menu_entry/spacer/register()
return
/datum/skin_menu_entry/spacer/unregister()
return
/datum/skin_menu_entry/spacer/creation_parameters()
return list2params(list(
parent = category.id,
name = ""
))
//! client stuff needed to make this work
/client/verb/menu_button_triggered(id as text, checked as num)
set name = ".menutrigger"
set hidden = TRUE
var/datum/skin_menu_entry/E = GLOB.skin_menu_entries[id]
if(!E)
stack_trace("no entry found for [id], triggered by [src]")
to_chat(usr, SPAN_WARNING("error: no menu entry found; this is a bug. id: [id]"))
return
E.pressed(src, checked)
/**
* gets which button of a group we have selected
*/
/client/proc/menu_group_query(group)
return menu_group_status[group]
/**
* gets if a button is checked
*/
/client/proc/menu_button_checked(id)
return menu_buttons_checked[id]
/**
* executes a command
*/
/client/proc/menu_run_command(str)
winset(src, null, list2params(list("command" = str)))
+229
View File
@@ -0,0 +1,229 @@
GLOBAL_DATUM_INIT(main_window_menu, /datum/skin_menu/main, new)
/datum/skin_menu/main
id = SKIN_ID_MAIN_MENU
bind_to = SKIN_WINDOW_ID_MAIN
categories = list(
/datum/skin_menu_category/main_file,
/datum/skin_menu_category/main_zoom,
/datum/skin_menu_category/main_scaling,
/datum/skin_menu_category/main_help,
)
/datum/skin_menu_category/main_file
id = SKIN_ID_MENU_CATEGORY_FILE
name = "File"
entries = list(
/datum/skin_menu_entry/quick_screenshot,
/datum/skin_menu_entry/screenshot,
/datum/skin_menu_entry/ping,
/datum/skin_menu_entry/reconnect,
/datum/skin_menu_entry/quit,
)
/datum/skin_menu_category/main_zoom
id = SKIN_ID_MENU_CATEGORY_ZOOM
name = "Zoom"
entries = list(
/datum/skin_menu_entry/widescreen/automatic,
/datum/skin_menu_entry/widescreen/legacy,
null,
/datum/skin_menu_entry/auto_fit,
/datum/skin_menu_entry/fit_viewport,
null,
/datum/skin_menu_entry/zoom/stretch_to_fit,
/datum/skin_menu_entry/zoom/stretch_to_fill,
)
/datum/skin_menu_category/main_zoom/init_entries()
. = ..()
var/static/list/auto_sizes = list(
32,
48,
64,
72,
96,
128,
)
for(var/size in auto_sizes)
entries += new /datum/skin_menu_entry/zoom/specific(src, size)
/datum/skin_menu_category/main_scaling
id = SKIN_ID_MENU_CATEGORY_SCALING
name = "Scaling"
entries = list(
/datum/skin_menu_entry/scaling/sharp,
/datum/skin_menu_entry/scaling/normal,
/datum/skin_menu_entry/scaling/blur,
)
/datum/skin_menu_category/main_help
id = SKIN_ID_MENU_CATEGORY_HELP
name = "Help"
entries = list(
/datum/skin_menu_entry/adminhelp,
)
//! file
/datum/skin_menu_entry/quick_screenshot
id = SKIN_ID_MENU_BUTTON_SCREENSHOT_QUICK
name = "Quick Screenshot"
command = ".screenshot auto"
/datum/skin_menu_entry/screenshot
id = SKIN_ID_MENU_BUTTON_SCREENSHOT
name = "Screenshot..."
command = ".screenshot"
/datum/skin_menu_entry/quit
id = SKIN_ID_MENU_BUTTON_QUIT
name = "Quit"
command = ".quit"
/datum/skin_menu_entry/reconnect
id = SKIN_ID_MENU_BUTTON_RECONNECT
name = "Reconnect"
command = ".reconnect"
/datum/skin_menu_entry/ping
id = SKIN_ID_MENU_BUTTON_PING
name = "Ping (legacy chat)"
command = ".ping"
//! zoom
/datum/skin_menu_entry/zoom
group = SKIN_BUTTON_GROUP_MAP_ZOOM
load_command_default = TRUE
checkbox = TRUE
/datum/skin_menu_entry/zoom/pressed(client/C, new_checked)
. = ..()
if(C.is_auto_fit_viewport_enabled())
C.request_viewport_fit()
C.request_viewport_update()
/datum/skin_menu_entry/zoom/load(client/C, enabled)
. = ..()
if(C.is_auto_fit_viewport_enabled())
C.request_viewport_fit()
C.request_viewport_update()
/datum/skin_menu_entry/zoom/stretch_to_fit
name = "Stretch to Fit"
id = SKIN_ID_MENU_BUTTON_STRETCH_TO_FIT
is_default = TRUE
/datum/skin_menu_entry/zoom/stretch_to_fit/generate_command(loading)
if(loading)
return ".winset \"[SKIN_MAP_ID_VIEWPORT].zoom=0;[SKIN_MAP_ID_VIEWPORT].letterbox=true\""
return ".winset \"[SKIN_MAP_ID_VIEWPORT].zoom=0;[SKIN_MAP_ID_VIEWPORT].letterbox=true\"\n.update_viewport"
/datum/skin_menu_entry/zoom/stretch_to_fill
name = "Stretch to Fill"
id = SKIN_ID_MENU_BUTTON_STRETCH_NO_LETTERBOX
/datum/skin_menu_entry/zoom/stretch_to_fill/generate_command(loading)
if(loading)
return ".winset \"[SKIN_MAP_ID_VIEWPORT].zoom=0;[SKIN_MAP_ID_VIEWPORT].letterbox=false\""
return ".winset \"[SKIN_MAP_ID_VIEWPORT].zoom=0;[SKIN_MAP_ID_VIEWPORT].letterbox=false\"\n.update_viewport"
//? the normal sizes are created by main_zoom category
/datum/skin_menu_entry/zoom/specific
/// our pixel size
var/pixel_size
/datum/skin_menu_entry/zoom/specific/New(datum/skin_menu_category/category, pixel_size)
src.pixel_size = pixel_size
src.id = SKIN_ID_MENU_BUTTON_FOR_RESOLUTION(pixel_size)
src.name = "[pixel_size]x[pixel_size]"
..()
/datum/skin_menu_entry/zoom/specific/generate_command(loading)
var/zoom = pixel_size / WORLD_ICON_SIZE
if(loading)
return ".winset \"[SKIN_MAP_ID_VIEWPORT].zoom=[zoom]\""
return ".winset \"[SKIN_MAP_ID_VIEWPORT].zoom=[zoom]\"\n.update_viewport"
//! widescreen
/datum/skin_menu_entry/widescreen
group = SKIN_BUTTON_GROUP_MAP_WIDESCREEN
checkbox = TRUE
/datum/skin_menu_entry/widescreen/pressed(client/C, new_checked)
. = ..()
if(C.is_auto_fit_viewport_enabled())
C.request_viewport_fit()
C.request_viewport_update()
/datum/skin_menu_entry/widescreen/load(client/C, enabled)
. = ..()
if(C.is_auto_fit_viewport_enabled())
C.request_viewport_fit()
C.request_viewport_update()
/datum/skin_menu_entry/widescreen/automatic
id = SKIN_ID_MENU_BUTTON_WIDESCREEN_ENABLED
name = "Automatic Widescreen"
is_default = TRUE
/datum/skin_menu_entry/widescreen/legacy
id = SKIN_ID_MENU_BUTTON_WIDESCREEN_DISABLED
name = "Lock to 15x15 (Legacy)"
/client/proc/is_widescreen_enabled()
return menu_group_query(SKIN_BUTTON_GROUP_MAP_WIDESCREEN) == SKIN_ID_MENU_BUTTON_WIDESCREEN_ENABLED
//! misc zoom
/datum/skin_menu_entry/auto_fit
id = SKIN_ID_MENU_BUTTON_AUTO_FIT_VIEWPORT
name = "Automatically Fit Viewport (EXPERIMENTAL)"
checkbox = TRUE
is_default = FALSE
/datum/skin_menu_entry/auto_fit/load(client/C, enabled)
. = ..()
if(enabled)
C.request_viewport_fit()
/client/proc/is_auto_fit_viewport_enabled()
return menu_button_checked(SKIN_ID_MENU_BUTTON_AUTO_FIT_VIEWPORT)
/datum/skin_menu_entry/fit_viewport
id = SKIN_ID_MENU_BUTTON_FIT_VIEWPORT
name = "Fit Viewport"
/datum/skin_menu_entry/fit_viewport/pressed(client/C, new_checked)
. = ..()
C.request_viewport_fit()
//! scaling
/datum/skin_menu_entry/scaling
group = SKIN_BUTTON_GROUP_MAP_SCALING
checkbox = TRUE
load_command_default = TRUE
var/zoom_mode
/datum/skin_menu_entry/scaling/generate_command(loading)
return ".winset \"[SKIN_MAP_ID_VIEWPORT].zoom-mode=[zoom_mode]\""
/datum/skin_menu_entry/scaling/sharp
id = SKIN_ID_MENU_BUTTON_NEAREST_NEIGHBOR
name = "Nearest Neighbor (Sharp)"
zoom_mode = "distort"
is_default = TRUE
/datum/skin_menu_entry/scaling/normal
id = SKIN_ID_MENU_BUTTON_POINT_SAMPLE
name = "Point Sampling (Normal)"
zoom_mode = "normal"
/datum/skin_menu_entry/scaling/blur
id = SKIN_ID_MENU_BUTTON_BILINEAR
name = "Bilinear (Blurry)"
zoom_mode = "blur"
//! help
/datum/skin_menu_entry/adminhelp
id = SKIN_ID_MENU_BUTTON_ADMINHELP
name = "Admin Help (F1)"
command = "adminhelp"
+32 -270
View File
@@ -1,284 +1,59 @@
macro "default"
menu "menu"
elem
name = "&File"
command = ""
saved-params = "is-checked"
elem
name = "&Quick screenshot\tF2"
command = ".screenshot auto"
category = "&File"
saved-params = "is-checked"
elem
name = "&Save screenshot as...\tShift+F2"
command = ".screenshot"
category = "&File"
saved-params = "is-checked"
elem
name = ""
command = ""
category = "&File"
saved-params = "is-checked"
elem
name = "&Reconnect"
command = ".reconnect"
category = "&File"
saved-params = "is-checked"
elem
name = "&Check ping"
command = ".ping"
category = "&File"
saved-params = "is-checked"
elem
name = "&Quit"
command = ".quit"
category = "&File"
saved-params = "is-checked"
elem
name = "&Size"
command = ""
saved-params = "is-checked"
elem "stretch"
name = "&Round up and lock to size"
command = ".winset \"mapwindow.map.icon-size=0\""
category = "&Size"
is-checked = true
can-check = true
group = "size"
saved-params = "is-checked"
elem "cozyin"
name = "Get Cozy Inwards"
command = "SetCozyViewInwards 8"
category = "&Size"
can-check = false
group = "size"
saved-params = "is-checked"
elem "icon128"
name = "&128x128 (4K)"
command = "SetWindowIconSize 128"
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon96"
name = "&96x96"
command = "SetWindowIconSize 96"
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon72"
name = "&72x72 (Cozy 1080p)"
command = "SetWindowIconSize 72"
category = "&Size"
is-checked = true
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon64"
name = "&64x64 (1080p)"
command = "SetWindowIconSize 64"
category = "&Size"
is-checked = true
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon48"
name = "&48x48"
command = "SetWindowIconSize 48"
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon32"
name = "&32x32"
command = "SetWindowIconSize 32"
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem
name = "&Scaling"
command = ""
saved-params = "is-checked"
elem "ZM"
name = "&Smooth Scaling"
command = ".winset \"zoommode.is-checked=true?map.zoom-mode=normal:map.zoom-mode=distort\""
category = "&Scaling"
is-checked = true
can-check = true
group = "scale"
saved-params = "is-checked"
elem "NN"
name = "&Nearest Neighbor"
command = ".winset \"mapwindow.map.zoom-mode=distort\""
category = "&Scaling"
can-check = true
group = "scale"
saved-params = "is-checked"
elem "PS"
name = "&Point Sampling"
command = ".winset \"mapwindow.map.zoom-mode=normal\""
category = "&Scaling"
can-check = true
group = "scale"
saved-params = "is-checked"
elem "BL"
name = "&Bilinear"
command = ".winset \"mapwindow.map.zoom-mode=blur\""
category = "&Scaling"
can-check = true
group = "scale"
saved-params = "is-checked"
elem
name = "&Help"
command = ""
saved-params = "is-checked"
elem
name = "&Admin help\tF1"
command = "adminhelp"
category = "&Help"
saved-params = "is-checked"
elem
name = "&Hotkeys"
command = "hotkeys-help"
category = "&Help"
saved-params = "is-checked"
window "Telecomms IDE"
elem "Telecomms IDE"
type = MAIN
pos = 281,0
size = 569x582
anchor1 = none
anchor2 = none
background-color = #ffffff
is-visible = false
saved-params = "pos;size;is-minimized;is-maximized"
title = "TCS IDE"
statusbar = false
on-close = "exittcs"
elem "button5"
type = BUTTON
pos = 209,464
size = 70x20
anchor1 = 37,80
anchor2 = 49,83
saved-params = "is-checked"
text = "Clear Memory"
command = "tcsclearmem"
elem "button4"
type = BUTTON
pos = 157,464
size = 52x20
anchor1 = 28,80
anchor2 = 37,83
saved-params = "is-checked"
text = "Revert"
command = "tcsrevert"
elem "button3"
type = BUTTON
pos = 105,464
size = 52x20
anchor1 = 18,80
anchor2 = 28,83
saved-params = "is-checked"
text = "Execute"
command = "tcsrun"
elem "tcserror"
type = OUTPUT
pos = 0,488
size = 566x94
anchor1 = 0,84
anchor2 = 99,100
font-family = "sans-serif"
font-size = 9
saved-params = "max-lines"
elem "button2"
type = BUTTON
pos = 53,464
size = 52x20
anchor1 = 9,80
anchor2 = 18,83
saved-params = "is-checked"
text = "Compile"
command = "tcscompile"
elem "button1"
type = BUTTON
pos = 0,464
size = 53x20
anchor1 = 0,80
anchor2 = 9,83
saved-params = "is-checked"
text = "Apply"
command = "tcssave"
elem "tcscode"
type = INPUT
pos = 0,0
size = 569x464
anchor1 = 0,0
anchor2 = 100,80
font-family = "Courier"
font-size = 10
saved-params = ""
command = "cancel"
multi-line = true
no-command = true
window "mainwindow"
elem "mainwindow"
type = MAIN
pos = 0,0
size = 640x440
anchor1 = none
anchor2 = none
size = 640x480
anchor1 = -1,-1
anchor2 = -1,-1
background-color = none
is-default = true
saved-params = "pos;size;is-minimized;is-maximized"
icon = 'icons\\CS13.png'
macro = "default"
menu = "menu"
on-size = "OnResize"
outer-size = 656x538
inner-size = 640x499
elem "split"
type = CHILD
pos = 3,0
size = 640x440
pos = 0,0
size = 640x480
anchor1 = 0,0
anchor2 = 100,100
background-color = none
saved-params = "splitter"
left = "mapwindow"
right = "infowindow"
is-vert = true
on-size = "OnResize"
elem "asset_cache_browser"
type = BROWSER
pos = 0,0
size = 200x200
anchor1 = none
anchor2 = none
anchor1 = -1,-1
anchor2 = -1,-1
background-color = none
is-visible = false
saved-params = ""
elem "tooltip"
type = BROWSER
pos = 0,0
size = 999x999
anchor1 = none
anchor2 = none
anchor1 = -1,-1
anchor2 = -1,-1
background-color = none
is-visible = false
saved-params = ""
window "mapwindow"
elem "mapwindow"
type = MAIN
pos = 0,0
pos = 281,0
size = 640x480
anchor1 = none
anchor2 = none
anchor1 = -1,-1
anchor2 = -1,-1
saved-params = "pos;size;is-minimized;is-maximized"
is-pane = true
on-size = "OnResize"
elem "map"
type = MAP
pos = 0,0
@@ -287,9 +62,9 @@ window "mapwindow"
anchor2 = 100,100
font-family = "Arial"
font-size = 7
text-color = none
is-default = true
saved-params = "zoom;letterbox;zoom-mode"
saved-params = ""
on-size = ".on_viewport [[width]] [[height]] [[zoom]] [[letterbox]]"
style = ".center { text-align: center; } .maptext { font-family: 'Small Fonts'; font-size: 7px; -dm-text-outline: 1px black; color: white; line-height: 1.1; } .command_headset { font-weight: bold;\tfont-size: 8px; } .small { font-size: 6px; } .big { font-size: 8px; } .reallybig { font-size: 8px; } .extremelybig { font-size: 8px; } .greentext { color: #00FF00; font-size: 7px; } .redtext { color: #FF0000; font-size: 7px; } .clown { color: #FF69Bf; font-size: 7px; font-weight: bold; } .his_grace { color: #15D512; } .hypnophrase { color: #0d0d0d; font-weight: bold; } .yell { font-weight: bold; } .italics { font-size: 6px; }"
window "preferences_window"
@@ -297,8 +72,8 @@ window "preferences_window"
type = MAIN
pos = 281,0
size = 1000x800
anchor1 = none
anchor2 = none
anchor1 = -1,-1
anchor2 = -1,-1
is-visible = false
saved-params = "pos;size;is-minimized;is-maximized"
statusbar = false
@@ -323,20 +98,16 @@ window "infowindow"
type = MAIN
pos = 418,0
size = 640x480
anchor1 = none
anchor2 = none
background-color = none
anchor1 = -1,-1
anchor2 = -1,-1
saved-params = "pos;size;is-minimized;is-maximized"
is-pane = true
outer-size = 662x561
inner-size = 640x505
elem "mediapanel"
type = BROWSER
pos = 88,216
size = 200x200
anchor1 = none
anchor2 = none
background-color = none
anchor1 = -1,-1
anchor2 = -1,-1
is-visible = false
saved-params = ""
elem "info"
@@ -345,7 +116,6 @@ window "infowindow"
size = 640x445
anchor1 = 0,0
anchor2 = 100,100
background-color = none
saved-params = "splitter"
left = "statwindow"
right = "outputwindow"
@@ -356,7 +126,6 @@ window "infowindow"
size = 104x20
anchor1 = 3,0
anchor2 = 19,0
background-color = none
saved-params = "is-checked"
text = "Changelog"
command = "changelog"
@@ -366,7 +135,6 @@ window "infowindow"
size = 100x20
anchor1 = 19,0
anchor2 = 34,0
background-color = none
saved-params = "is-checked"
text = "Rules"
command = "rules"
@@ -376,7 +144,6 @@ window "infowindow"
size = 100x20
anchor1 = 34,0
anchor2 = 50,0
background-color = none
saved-params = "is-checked"
text = "Wiki"
command = "wiki"
@@ -386,7 +153,6 @@ window "infowindow"
size = 100x20
anchor1 = 50,0
anchor2 = 66,0
background-color = none
saved-params = "is-checked"
text = "Forum"
command = "forum"
@@ -396,7 +162,6 @@ window "infowindow"
size = 100x20
anchor1 = 66,0
anchor2 = 81,0
background-color = none
saved-params = "is-checked"
text = "Github"
command = "github"
@@ -406,7 +171,6 @@ window "infowindow"
size = 100x20
anchor1 = 81,0
anchor2 = 97,0
background-color = none
saved-params = "is-checked"
text = "Report Issue"
command = "report-issue"
@@ -416,8 +180,8 @@ window "outputwindow"
type = MAIN
pos = 0,0
size = 640x480
anchor1 = none
anchor2 = none
anchor1 = -1,-1
anchor2 = -1,-1
saved-params = "pos;size;is-minimized;is-maximized"
is-pane = true
elem "browseroutput"
@@ -436,7 +200,6 @@ window "outputwindow"
size = 40x20
anchor1 = 100,100
anchor2 = -1,-1
background-color = none
saved-params = "is-checked"
text = "Chat"
command = ".winset \"saybutton.is-checked=true?input.command=\"!say \\\"\" macrobutton.is-checked=false:input.command=\""
@@ -457,7 +220,6 @@ window "outputwindow"
size = 80x20
anchor1 = 100,100
anchor2 = -1,-1
background-color = none
saved-params = ""
text = "Hotkey Toggle"
command = ".winset \"mainwindow.macro!=macro ? mainwindow.macro=macro hotkey_toggle.is-checked=false input.focus=true : mainwindow.macro=hotkeymode hotkey_toggle.is-checked=true mapwindow.map.focus=true\""
@@ -474,8 +236,8 @@ window "outputwindow"
type = BROWSER
pos = 0,0
size = 200x200
anchor1 = none
anchor2 = none
anchor1 = -1,-1
anchor2 = -1,-1
is-visible = false
saved-params = ""
@@ -484,8 +246,8 @@ window "statwindow"
type = MAIN
pos = 372,0
size = 640x480
anchor1 = none
anchor2 = none
anchor1 = -1,-1
anchor2 = -1,-1
saved-params = "pos;size;is-minimized;is-maximized"
is-pane = true
elem "statbrowser"
+1 -1
View File
@@ -40,7 +40,7 @@
anchored = 1
plane = TURF_PLANE
layer = ABOVE_TURF_LAYER
appearance_flags = PIXEL_SCALE|KEEP_TOGETHER
SET_APPEARANCE_FLAGS(TILE_BOUND)
var/_stair_tag //Make this match another one and they'll connect!
+8 -8
View File
@@ -132,10 +132,10 @@ export const setClientTheme = name => {
// Say, OOC, me Buttons etc.
'saybutton.background-color': COLOR_DARK_BG,
'saybutton.text-color': COLOR_DARK_TEXT,
'oocbutton.background-color': COLOR_DARK_BG,
'oocbutton.text-color': COLOR_DARK_TEXT,
'mebutton.background-color': COLOR_DARK_BG,
'mebutton.text-color': COLOR_DARK_TEXT,
// 'oocbutton.background-color': COLOR_DARK_BG,
// 'oocbutton.text-color': COLOR_DARK_TEXT,
// 'mebutton.background-color': COLOR_DARK_BG,
// 'mebutton.text-color': COLOR_DARK_TEXT,
'asset_cache_browser.background-color': COLOR_DARK_BG,
'asset_cache_browser.text-color': COLOR_DARK_TEXT,
'tooltip.background-color': COLOR_DARK_BG,
@@ -182,10 +182,10 @@ export const setClientTheme = name => {
// Say, OOC, me Buttons etc.
'saybutton.background-color': COLOR_DARK_BG,
'saybutton.text-color': COLOR_DARK_TEXT,
'oocbutton.background-color': COLOR_DARK_BG,
'oocbutton.text-color': COLOR_DARK_TEXT,
'mebutton.background-color': COLOR_DARK_BG,
'mebutton.text-color': COLOR_DARK_TEXT,
// 'oocbutton.background-color': COLOR_DARK_BG,
// 'oocbutton.text-color': COLOR_DARK_TEXT,
// 'mebutton.background-color': COLOR_DARK_BG,
// 'mebutton.text-color': COLOR_DARK_TEXT,
'asset_cache_browser.background-color': COLOR_DARK_BG,
'asset_cache_browser.text-color': COLOR_DARK_TEXT,
'tooltip.background-color': COLOR_DARK_BG,