module re.math.rect_ext; import std.algorithm.comparison; static import raymath; import re.math; static class RectangleExt { /* based on https://github.com/prime31/Nez/blob/0e97e68bd9df191fb3b893eb69e54238c30fcc80/Nez.Portable/Utils/Extensions/RectangleExt.cs#L184 */ public static Rectangle calculate_bounds(Vector2 position, Vector2 origin, Vector2 scale, float rotation, float width, float height) { if (rotation == 0) { return Rectangle(cast(int)(position.x - (origin.x * scale.x)), cast(int)(position.y - (origin.y * scale.y)), cast(int)(width * scale.x), cast(int)(height * scale.y)); } else { auto tmp1 = Matrix4.init; // set the reference point to world reference taking origin into account auto transform_mat = raymath.MatrixTranslate(-position.x - origin.x, -position.y - origin.y, 0); tmp1 = raymath.MatrixScale(scale.x, scale.y, 1); // scale -> transform_mat = raymath.MatrixMultiply(transform_mat, tmp1); tmp1 = raymath.MatrixRotateZ(rotation); // rotate -> transform_mat = raymath.MatrixMultiply(transform_mat, tmp1); tmp1 = raymath.MatrixTranslate(position.x, position.y, 0); // translate back transform_mat = raymath.MatrixMultiply(transform_mat, tmp1); // get all four corners in world space auto top_left_w = Vector3(position.x, position.y, 0); auto top_right_w = Vector3(position.x + width, position.y, 0); auto btm_left_w = Vector3(position.x, position.y + height, 0); auto btm_right_w = Vector3(position.x + width, position.y + height, 0); // transform the corners into our work space auto top_left = raymath.Vector3Transform(top_left_w, transform_mat); auto top_right = raymath.Vector3Transform(top_right_w, transform_mat); auto btm_left = raymath.Vector3Transform(btm_left_w, transform_mat); auto btm_right = raymath.Vector3Transform(btm_right_w, transform_mat); // find the min and max values so we can concoct our bounding box auto min_x = cast(int) min(top_left.x, btm_right.x, top_right.x, btm_left.x); auto max_x = cast(int) max(top_left.x, btm_right.x, top_right.x, btm_left.x); auto min_y = cast(int) min(top_left.y, btm_right.y, top_right.y, btm_left.y); auto max_y = cast(int) max(top_left.y, btm_right.y, top_right.y, btm_left.y); return Rectangle(min_x, min_y, max_x - min_x, max_y - min_y); } } }