From efa53a27d82e12f570fa9137ac588eba28bf2921 Mon Sep 17 00:00:00 2001 From: Nicolas Nattis Date: Fri, 25 Sep 2020 18:08:29 -0300 Subject: [PATCH 1/7] Makes cameras process transforms instead of reading mob angles --- code/__HELPERS/matrices.dm | 41 +++++++++++-------- .../camera/camera_image_capturing.dm | 23 ++++++++--- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices.dm index e12d753d20f..0cb19e9c0f4 100644 --- a/code/__HELPERS/matrices.dm +++ b/code/__HELPERS/matrices.dm @@ -55,30 +55,35 @@ . += f . += 1 -//The X pixel offset of this matrix +///The X scale of the matrix +/matrix/proc/get_x_scale() + return sqrt(a * a + d * d) + +///The Y scale of the matrix +/matrix/proc/get_y_scale() + return sqrt(b * b + e * e) + +/// Gets the rotation of the matrix, in degrees. +/// Will produce correct results if the matrix is only being translated, scaled +/// and rotated. Otherwise this is a best attempt. +/matrix/proc/get_rotation() + var/xs = get_x_scale() + var/ys = get_y_scale() + if(!xs || !ys) + return 0 + // If only translated, scaled and rotated, a/xs == e/ys and -d/xs == b/xy + var/cossine = (a/xs + e/ys) / 2 + var/sine = (b/ys - d/xs) / 2 + return arctan(cossine, sine) + +///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 // ///////////////////// diff --git a/code/modules/photography/camera/camera_image_capturing.dm b/code/modules/photography/camera/camera_image_capturing.dm index 63a2b810355..9db5dd06e7d 100644 --- a/code/modules/photography/camera/camera_image_capturing.dm +++ b/code/modules/photography/camera/camera_image_capturing.dm @@ -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) @@ -88,8 +84,23 @@ 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) + if(clone.transform) // getFlatIcon doesn't give a snot about transforms.' + var/sx = clone.transform.get_x_scale() + var/sy = clone.transform.get_y_scale() + if(sx != 1 || sy != 1) + var/wi = img.Width() * sx + var/he = img.Width() * sx + img.Scale(wi, he) + img.Shift(WEST, wi / 2, wrap=1) + img.Shift(SOUTH, he / 2, wrap=1) + if(clone.transform.get_rotation() != 0) + img.Turn(clone.transform.get_rotation()) + var/dx = clone.transform.get_x_shift() + if(dx != 0) + img.Shift(EAST, dx, wrap=1) + var/dy = clone.transform.get_y_shift() + if(dy != 0) + img.Shift(NORTH, dy, wrap=1) res.Blend(img, blendMode2iconMode(clone.blend_mode), xo, yo) CHECK_TICK From 28258332ac37f1845f270f3f70f568e042e80578 Mon Sep 17 00:00:00 2001 From: Nicolas Nattis Date: Fri, 25 Sep 2020 18:27:57 -0300 Subject: [PATCH 2/7] Fixes shifting --- .../camera/camera_image_capturing.dm | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/code/modules/photography/camera/camera_image_capturing.dm b/code/modules/photography/camera/camera_image_capturing.dm index 9db5dd06e7d..09e884a3ed6 100644 --- a/code/modules/photography/camera/camera_image_capturing.dm +++ b/code/modules/photography/camera/camera_image_capturing.dm @@ -78,29 +78,22 @@ 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/xo = (clone.x - center.x) * world.icon_size + clone.pixel_x + xcomp + clone.step_x + var/yo = (clone.y - center.y) * world.icon_size + clone.pixel_y + ycomp + clone.step_y + if(clone.transform) + xo -= world.icon_size * (clone.transform.get_x_scale() - 1) / 2 + yo -= world.icon_size * (clone.transform.get_y_scale() - 1) / 2 + xo += clone.transform.get_x_shift() + yo += clone.transform.get_x_shift() var/icon/img = getFlatIcon(clone, no_anim = TRUE) if(img) if(clone.transform) // getFlatIcon doesn't give a snot about transforms.' var/sx = clone.transform.get_x_scale() var/sy = clone.transform.get_y_scale() if(sx != 1 || sy != 1) - var/wi = img.Width() * sx - var/he = img.Width() * sx - img.Scale(wi, he) - img.Shift(WEST, wi / 2, wrap=1) - img.Shift(SOUTH, he / 2, wrap=1) + img.Scale(img.Width() * sx, img.Height() * sy) if(clone.transform.get_rotation() != 0) img.Turn(clone.transform.get_rotation()) - var/dx = clone.transform.get_x_shift() - if(dx != 0) - img.Shift(EAST, dx, wrap=1) - var/dy = clone.transform.get_y_shift() - if(dy != 0) - img.Shift(NORTH, dy, wrap=1) res.Blend(img, blendMode2iconMode(clone.blend_mode), xo, yo) CHECK_TICK From fb5ddaa8d2edbf257d629c8fc9a440dfe4a015ce Mon Sep 17 00:00:00 2001 From: Nicolas Nattis Date: Fri, 25 Sep 2020 18:31:47 -0300 Subject: [PATCH 3/7] . --- code/modules/photography/camera/camera_image_capturing.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/modules/photography/camera/camera_image_capturing.dm b/code/modules/photography/camera/camera_image_capturing.dm index 09e884a3ed6..40f9aaa2ad2 100644 --- a/code/modules/photography/camera/camera_image_capturing.dm +++ b/code/modules/photography/camera/camera_image_capturing.dm @@ -92,8 +92,9 @@ var/sy = clone.transform.get_y_scale() if(sx != 1 || sy != 1) img.Scale(img.Width() * sx, img.Height() * sy) - if(clone.transform.get_rotation() != 0) - img.Turn(clone.transform.get_rotation()) + var/rx = clone.transform.get_rotation() + if(rx != 0) + img.Turn(rx) res.Blend(img, blendMode2iconMode(clone.blend_mode), xo, yo) CHECK_TICK From ef152036c0e45f34eb9387b93f0b6950a17f7351 Mon Sep 17 00:00:00 2001 From: Nicolas Nattis Date: Fri, 2 Oct 2020 14:15:57 -0300 Subject: [PATCH 4/7] nemvar sugestion --- .../camera/camera_image_capturing.dm | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/code/modules/photography/camera/camera_image_capturing.dm b/code/modules/photography/camera/camera_image_capturing.dm index 40f9aaa2ad2..b6e81ec2202 100644 --- a/code/modules/photography/camera/camera_image_capturing.dm +++ b/code/modules/photography/camera/camera_image_capturing.dm @@ -78,23 +78,26 @@ 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 + clone.step_x - var/yo = (clone.y - center.y) * world.icon_size + clone.pixel_y + ycomp + clone.step_y - if(clone.transform) - xo -= world.icon_size * (clone.transform.get_x_scale() - 1) / 2 - yo -= world.icon_size * (clone.transform.get_y_scale() - 1) / 2 - xo += clone.transform.get_x_shift() - yo += clone.transform.get_x_shift() var/icon/img = getFlatIcon(clone, no_anim = TRUE) if(img) + // 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/sx = clone.transform.get_x_scale() var/sy = clone.transform.get_y_scale() if(sx != 1 || sy != 1) img.Scale(img.Width() * sx, img.Height() * sy) + xo -= world.icon_size * (sx - 1) / 2 + yo -= world.icon_size * (sy - 1) / 2 var/rx = clone.transform.get_rotation() if(rx != 0) img.Turn(rx) + xo += clone.transform.get_x_shift() + yo += clone.transform.get_x_shift() + res.Blend(img, blendMode2iconMode(clone.blend_mode), xo, yo) CHECK_TICK From b0bac2ea642ab9074b2a76ea39f078f0d4b418d6 Mon Sep 17 00:00:00 2001 From: Nicolas Nattis Date: Fri, 2 Oct 2020 14:19:24 -0300 Subject: [PATCH 5/7] some improvement maybe --- code/modules/photography/camera/camera_image_capturing.dm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/code/modules/photography/camera/camera_image_capturing.dm b/code/modules/photography/camera/camera_image_capturing.dm index b6e81ec2202..7f7caa0bfee 100644 --- a/code/modules/photography/camera/camera_image_capturing.dm +++ b/code/modules/photography/camera/camera_image_capturing.dm @@ -89,9 +89,11 @@ var/sx = clone.transform.get_x_scale() var/sy = clone.transform.get_y_scale() if(sx != 1 || sy != 1) - img.Scale(img.Width() * sx, img.Height() * sy) - xo -= world.icon_size * (sx - 1) / 2 - yo -= world.icon_size * (sy - 1) / 2 + var/base_w = img.Width() + var/base_h = img.Height() + img.Scale(base_w * sx, base_h * sy) + xo -= base_w * (sx - 1) / 2 + yo -= base_h * (sy - 1) / 2 var/rx = clone.transform.get_rotation() if(rx != 0) img.Turn(rx) From 8d2db7eeeec3b684939d563db22bef2036f3c53d Mon Sep 17 00:00:00 2001 From: Nicolas Nattis Date: Fri, 2 Oct 2020 14:34:32 -0300 Subject: [PATCH 6/7] Improves code --- code/__HELPERS/matrices.dm | 52 +++++++++++-------- .../camera/camera_image_capturing.dm | 25 ++++----- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices.dm index 0cb19e9c0f4..3623c09d43b 100644 --- a/code/__HELPERS/matrices.dm +++ b/code/__HELPERS/matrices.dm @@ -1,3 +1,34 @@ +/// 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. +/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,27 +86,6 @@ . += f . += 1 -///The X scale of the matrix -/matrix/proc/get_x_scale() - return sqrt(a * a + d * d) - -///The Y scale of the matrix -/matrix/proc/get_y_scale() - return sqrt(b * b + e * e) - -/// Gets the rotation of the matrix, in degrees. -/// Will produce correct results if the matrix is only being translated, scaled -/// and rotated. Otherwise this is a best attempt. -/matrix/proc/get_rotation() - var/xs = get_x_scale() - var/ys = get_y_scale() - if(!xs || !ys) - return 0 - // If only translated, scaled and rotated, a/xs == e/ys and -d/xs == b/xy - var/cossine = (a/xs + e/ys) / 2 - var/sine = (b/ys - d/xs) / 2 - return arctan(cossine, sine) - ///The X pixel offset of this matrix /matrix/proc/get_x_shift() . = c diff --git a/code/modules/photography/camera/camera_image_capturing.dm b/code/modules/photography/camera/camera_image_capturing.dm index 7f7caa0bfee..95966711a4f 100644 --- a/code/modules/photography/camera/camera_image_capturing.dm +++ b/code/modules/photography/camera/camera_image_capturing.dm @@ -85,20 +85,21 @@ // 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/sx = clone.transform.get_x_scale() - var/sy = clone.transform.get_y_scale() - if(sx != 1 || sy != 1) + 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 * sx, base_h * sy) - xo -= base_w * (sx - 1) / 2 - yo -= base_h * (sy - 1) / 2 - var/rx = clone.transform.get_rotation() - if(rx != 0) - img.Turn(rx) - xo += clone.transform.get_x_shift() - yo += clone.transform.get_x_shift() + 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 From 990d62e4ada9939f32a0f91c9257ba8b2f78762f Mon Sep 17 00:00:00 2001 From: Nicolas Nattis Date: Fri, 2 Oct 2020 14:37:10 -0300 Subject: [PATCH 7/7] Extra doc --- code/__HELPERS/matrices.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices.dm index 3623c09d43b..4b430d9c61c 100644 --- a/code/__HELPERS/matrices.dm +++ b/code/__HELPERS/matrices.dm @@ -15,6 +15,8 @@ /// /// 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