Merge pull request #53976 from nicbn/something-refactor

Makes cameras process transforms instead of reading mob angles
This commit is contained in:
nemvar
2020-10-03 17:51:16 +02:00
committed by GitHub
2 changed files with 56 additions and 28 deletions
+35 -18
View File
@@ -1,3 +1,36 @@
/// 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 not supported.
/matrix/proc/decompose()
var/datum/decompose_matrix/decompose_matrix = new
. = decompose_matrix
decompose_matrix.scale_x = sqrt(a * a + d * d)
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
decompose_matrix.rotation = arctan(cossine, sine)
/matrix/proc/TurnTo(old_angle, new_angle)
. = new_angle - old_angle
Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
@@ -55,30 +88,14 @@
. += f
. += 1
//The X pixel offset of this matrix
///The X pixel offset of this matrix
/matrix/proc/get_x_shift()
. = c
//The Y pixel offset of this matrix
///The Y pixel offset of this matrix
/matrix/proc/get_y_shift()
. = f
/matrix/proc/get_x_skew()
. = b
/matrix/proc/get_y_skew()
. = d
//Skews a matrix in a particular direction
//Missing arguments are treated as no skew in that direction
//As Rotation is defined as a scale+skew, these procs will break any existing rotation
//Unless the result is multiplied against the current matrix
/matrix/proc/set_skew(x = 0, y = 0)
b = x
d = y
/////////////////////
// COLOUR MATRICES //
/////////////////////
@@ -1,5 +1,4 @@
/obj/effect/appearance_clone
var/turn_angle = 0
/obj/effect/appearance_clone/New(loc, atom/A) //Intentionally not Initialize(), to make sure the clone assumes the intended appearance in time for the camera getFlatIcon.
if(istype(A))
@@ -9,9 +8,6 @@
var/atom/movable/AM = A
step_x = AM.step_x
step_y = AM.step_y
if(iscarbon(A))
var/mob/living/carbon/C = A
UNLINT(turn_angle = C.lying_angle) // this is the only place its okay to read lying directly
. = ..()
/obj/item/camera/proc/camera_get_icon(list/turfs, turf/center, psize_x = 96, psize_y = 96, datum/turf_reservation/clone_area, size_x, size_y, total_x, total_y)
@@ -82,14 +78,29 @@
else
for(var/X in sorted) //these are clones
var/obj/effect/appearance_clone/clone = X
var/xo = (clone.x - center.x) * world.icon_size + clone.pixel_x + xcomp
var/yo = (clone.y - center.y) * world.icon_size + clone.pixel_y + ycomp
xo += clone.step_x
yo += clone.step_y
var/icon/img = getFlatIcon(clone, no_anim = TRUE)
if(img)
if(clone.turn_angle) //the cheapest (so best, considering cams don't need to be laggier) way of doing this, considering getFlatIcon doesn't give a snot about transforms.'
img.Turn(clone.turn_angle)
// Center of the image in X
var/xo = (clone.x - center.x) * world.icon_size + clone.pixel_x + xcomp + clone.step_x
// Center of the image in Y
var/yo = (clone.y - center.y) * world.icon_size + clone.pixel_y + ycomp + clone.step_y
if(clone.transform) // getFlatIcon doesn't give a snot about transforms.
var/datum/decompose_matrix/decompose = clone.transform.decompose()
// Scale in X, Y
if(decompose.scale_x != 1 || decompose.scale_y != 1)
var/base_w = img.Width()
var/base_h = img.Height()
img.Scale(base_w * decompose.scale_x, base_h * decompose.scale_y)
xo -= base_w * (decompose.scale_x - 1) / 2
yo -= base_h * (decompose.scale_y - 1) / 2
// Rotation
if(decompose.rotation != 0)
img.Turn(decompose.rotation)
// Shift
xo += decompose.shift_x
yo += decompose.shift_y
res.Blend(img, blendMode2iconMode(clone.blend_mode), xo, yo)
CHECK_TICK