ID:195017
 
//Title: forceAspectRatio
//Credit to: DarkCampainger
//Contributed by: DarkCampainger
//Special thanks to: Beatmewithastick (for posting the question)

/*
This verb resizes the passed window to the passed aspect ratio, tracking the
window's previous size so it knows if it should grow or shrink. Use this verb
by calling it from the the desired window's Resize command:
forceAspect [window] [aspectRatio]
forceAspect "default" 1.3333

It is recommended that you manually call this verb when the player logs in,
so the system can set up the lastWindowWidth/Height lists and correctly
interpret the user's resize as a grow or shrink.
*/


client
// We track the previous window size to determine if the user is trying to
// shrink or grow the window
var/tmp/lastWindowWidth = list() // Associative list of "window" = width
var/tmp/lastWindowHeight = list() // Associative list of "window" = height

// This verb should be called from the "Resize command" of the window you
// want to constrain. Pass its name and the aspect ratio.
// Example: forceAspect "default" 1.3333
verb/forceAspect(window="default" as text|null, aspect=4/3 as num|null)
var
// Get and parse the width/height of the window's size
size = winget(src, window, "size")
delimiter = findtext(size, "x")
width = text2num(copytext(size, 1, delimiter))
height = text2num(copytext(size, delimiter+1, 0))

// Calculate the counterpart to each dimension that would give the
// desired aspect ratio
heightForWidth = round(width/aspect) // Height based on width
widthForHeight = round(height*aspect) // Width based on height

// Determine if the user is stretching or shrinking the window
var
// Calculate the changes in width/height from the previous window size
changeWidth = (!lastWindowWidth[window] ? 0 \
: width - lastWindowWidth[window])
changeHeight = (!lastWindowHeight[window] ? 0 \
: height - lastWindowHeight[window])

// Take the greatest change, and see if it's an increase or decrease
// For an increase, we assume the user is growing the window
grow = ((abs(changeWidth) > abs(changeHeight)) ? changeWidth : changeHeight) >= 0

// If we're growing to fit and the height deviates the most,
// Or if we're shrinking to fit and the width deviates the most
if((grow && widthForHeight>width) || (!grow && widthForHeight<width))
// Reconstrain the width to the height
width = widthForHeight
else
// Otherwise reconstrain the height to the width
height = heightForWidth

// Store the size so we know next time if they're shrinking or stretching the window
lastWindowWidth[window] = width
lastWindowHeight[window] = height

// Update the window size
winset(src, window, "size='[width]x[height]'")