mirror of
https://github.com/fulpstation/fulpstation.git
synced 2025-12-09 16:09:15 +00:00
Several months worth of updates. --------- Co-authored-by: A miscellaneous Fern <80640114+FernandoJ8@users.noreply.github.com> Co-authored-by: Pepsilawn <reisenrui@gmail.com> Co-authored-by: Ray <64306407+OneAsianTortoise@users.noreply.github.com> Co-authored-by: Cure221 <106662180+Cure221@users.noreply.github.com>
219 lines
7.0 KiB
Plaintext
219 lines
7.0 KiB
Plaintext
/// Datum which stores information about a matrix decomposed with decompose().
|
|
/datum/decompose_matrix
|
|
///?
|
|
var/scale_x = 1
|
|
///?
|
|
var/scale_y = 1
|
|
///?
|
|
var/rotation = 0
|
|
///?
|
|
var/shift_x = 0
|
|
///?
|
|
var/shift_y = 0
|
|
|
|
/// Decomposes a matrix into scale, shift and rotation.
|
|
///
|
|
/// If other operations were applied on the matrix, such as shearing, the result
|
|
/// will not be precise.
|
|
///
|
|
/// Negative scales are now supported. =)
|
|
/matrix/proc/decompose()
|
|
var/datum/decompose_matrix/decompose_matrix = new
|
|
. = decompose_matrix
|
|
var/flip_sign = (a*e - b*d < 0)? -1 : 1 // Det < 0 => only 1 axis is flipped - start doing some sign flipping
|
|
// If both axis are flipped, nothing bad happens and Det >= 0, it just treats it like a 180° rotation
|
|
// If only 1 axis is flipped, we need to flip one direction - in this case X, so we flip a, b and the x scaling
|
|
decompose_matrix.scale_x = sqrt(a * a + d * d) * flip_sign
|
|
decompose_matrix.scale_y = sqrt(b * b + e * e)
|
|
decompose_matrix.shift_x = c
|
|
decompose_matrix.shift_y = f
|
|
if(!decompose_matrix.scale_x || !decompose_matrix.scale_y)
|
|
return
|
|
// If only translated, scaled and rotated, a/xs == e/ys and -d/xs == b/xy
|
|
var/cossine = (a/decompose_matrix.scale_x + e/decompose_matrix.scale_y) / 2
|
|
var/sine = (b/decompose_matrix.scale_y - d/decompose_matrix.scale_x) / 2 * flip_sign
|
|
decompose_matrix.rotation = arctan(cossine, sine) * flip_sign
|
|
|
|
/matrix/proc/TurnTo(old_angle, new_angle)
|
|
return Turn(new_angle - old_angle) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
|
|
|
|
/**
|
|
* Shear the transform on either or both axes.
|
|
* * x - X axis shearing
|
|
* * y - Y axis shearing
|
|
*/
|
|
/matrix/proc/Shear(x, y)
|
|
return Multiply(matrix(1, x, 0, y, 1, 0))
|
|
|
|
//Dumps the matrix data in format a-f
|
|
/matrix/proc/tolist()
|
|
. = list()
|
|
. += a
|
|
. += b
|
|
. += c
|
|
. += d
|
|
. += e
|
|
. += f
|
|
|
|
//Dumps the matrix data in a matrix-grid format
|
|
/*
|
|
a d 0
|
|
b e 0
|
|
c f 1
|
|
*/
|
|
/matrix/proc/togrid()
|
|
. = list()
|
|
. += a
|
|
. += d
|
|
. += 0
|
|
. += b
|
|
. += e
|
|
. += 0
|
|
. += c
|
|
. += f
|
|
. += 1
|
|
|
|
///The X pixel offset of this matrix
|
|
/matrix/proc/get_x_shift()
|
|
. = c
|
|
|
|
///The Y pixel offset of this matrix
|
|
/matrix/proc/get_y_shift()
|
|
. = f
|
|
|
|
///The angle of this matrix
|
|
/matrix/proc/get_angle()
|
|
. = -ATAN2(a,d)
|
|
|
|
/////////////////////
|
|
// COLOUR MATRICES //
|
|
/////////////////////
|
|
|
|
/* Documenting a couple of potentially useful color matrices here to inspire ideas
|
|
// Greyscale - indentical to saturation @ 0
|
|
list(LUMA_R,LUMA_R,LUMA_R,0, LUMA_G,LUMA_G,LUMA_G,0, LUMA_B,LUMA_B,LUMA_B,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
// Color inversion
|
|
list(-1,0,0,0, 0,-1,0,0, 0,0,-1,0, 0,0,0,1, 1,1,1,0)
|
|
|
|
// Sepiatone
|
|
list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0,0,0)
|
|
*/
|
|
|
|
//Changes distance hues have from grey while maintaining the overall lightness. Greys are unaffected.
|
|
//1 is identity, 0 is greyscale, >1 oversaturates colors
|
|
/proc/color_matrix_saturation(value)
|
|
var/inv = 1 - value
|
|
var/R = round(LUMA_R * inv, 0.001)
|
|
var/G = round(LUMA_G * inv, 0.001)
|
|
var/B = round(LUMA_B * inv, 0.001)
|
|
|
|
return list(R + value,R,R,0, G,G + value,G,0, B,B,B + value,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
//Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting greys
|
|
//0 is identity, 120 moves reds to greens, 240 moves reds to blues
|
|
/proc/color_matrix_rotate_hue(angle)
|
|
var/sin = sin(angle)
|
|
var/cos = cos(angle)
|
|
var/cos_inv_third = 0.333*(1-cos)
|
|
var/sqrt3_sin = sqrt(3)*sin
|
|
return list(
|
|
round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), 0,
|
|
round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), 0,
|
|
round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), 0,
|
|
0,0,0,1,
|
|
0,0,0,0)
|
|
|
|
//These next three rotate values about one axis only
|
|
//x is the red axis, y is the green axis, z is the blue axis.
|
|
/proc/color_matrix_rotate_x(angle)
|
|
var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
|
|
return list(1,0,0,0, 0,cosval,sinval,0, 0,-sinval,cosval,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
/proc/color_matrix_rotate_y(angle)
|
|
var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
|
|
return list(cosval,0,-sinval,0, 0,1,0,0, sinval,0,cosval,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
/proc/color_matrix_rotate_z(angle)
|
|
var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
|
|
return list(cosval,sinval,0,0, -sinval,cosval,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
|
|
//Returns a matrix addition of A with B
|
|
/proc/color_matrix_add(list/A, list/B)
|
|
if(!istype(A) || !istype(B))
|
|
return COLOR_MATRIX_IDENTITY
|
|
if(A.len != 20 || B.len != 20)
|
|
return COLOR_MATRIX_IDENTITY
|
|
var/list/output = list()
|
|
output.len = 20
|
|
for(var/value in 1 to 20)
|
|
output[value] = A[value] + B[value]
|
|
return output
|
|
|
|
//Returns a matrix multiplication of A with B
|
|
/proc/color_matrix_multiply(list/A, list/B)
|
|
if(!istype(A) || !istype(B))
|
|
return COLOR_MATRIX_IDENTITY
|
|
if(A.len != 20 || B.len != 20)
|
|
return COLOR_MATRIX_IDENTITY
|
|
var/list/output = list()
|
|
output.len = 20
|
|
var/x = 1
|
|
var/y = 1
|
|
var/offset = 0
|
|
for(y in 1 to 5)
|
|
offset = (y-1)*4
|
|
for(x in 1 to 4)
|
|
output[offset+x] = round(A[offset+1]*B[x] + A[offset+2]*B[x+4] + A[offset+3]*B[x+8] + A[offset+4]*B[x+12]+(y == 5?B[x+16]:0), 0.001)
|
|
return output
|
|
|
|
/**
|
|
* Converts RGB shorthands into RGBA matrices complete of constants rows (ergo a 20 keys list in byond).
|
|
* if return_identity_on_fail is true, stack_trace is called instead of CRASH, and an identity is returned.
|
|
*/
|
|
/proc/color_to_full_rgba_matrix(color, return_identity_on_fail = TRUE)
|
|
if(!color)
|
|
return COLOR_MATRIX_IDENTITY
|
|
if(istext(color))
|
|
var/list/L = rgb2num(color)
|
|
if(!L)
|
|
var/message = "Invalid/unsupported color ([color]) argument in color_to_full_rgba_matrix()"
|
|
if(return_identity_on_fail)
|
|
stack_trace(message)
|
|
return COLOR_MATRIX_IDENTITY
|
|
CRASH(message)
|
|
return list(L[1]/255,0,0,0, 0,L[2]/255,0,0, 0,0,L[3]/255,0, 0,0,0,L.len>3?L[4]/255:1, 0,0,0,0)
|
|
if(!islist(color)) //invalid format
|
|
CRASH("Invalid/unsupported color ([color]) argument in color_to_full_rgba_matrix()")
|
|
var/list/L = color
|
|
switch(L.len)
|
|
if(3 to 5) // row-by-row hexadecimals
|
|
. = list()
|
|
for(var/a in 1 to L.len)
|
|
var/list/rgb = rgb2num(L[a])
|
|
for(var/b in rgb)
|
|
. += b/255
|
|
if(length(rgb) % 4) // RGB has no alpha instruction
|
|
. += a != 4 ? 0 : 1
|
|
if(L.len < 4) //missing both alphas and constants rows
|
|
. += list(0,0,0,1, 0,0,0,0)
|
|
else if(L.len < 5) //missing constants row
|
|
. += list(0,0,0,0)
|
|
if(9 to 12) //RGB
|
|
. = list(L[1],L[2],L[3],0, L[4],L[5],L[6],0, L[7],L[8],L[9],0, 0,0,0,1)
|
|
for(var/b in 1 to 3) //missing constants row
|
|
. += L.len < 9+b ? 0 : L[9+b]
|
|
. += 0
|
|
if(16 to 20) // RGBA
|
|
. = L.Copy()
|
|
if(L.len < 20) //missing constants row
|
|
for(var/b in 1 to 20-L.len)
|
|
. += 0
|
|
else
|
|
var/message = "Invalid/unsupported color (list of length [L.len]) argument in color_to_full_rgba_matrix()"
|
|
if(return_identity_on_fail)
|
|
stack_trace(message)
|
|
return COLOR_MATRIX_IDENTITY
|
|
CRASH(message)
|